快速搭建 AI 画图页面

Posted on
小站 网络 Cloudflare | 共 1165 字,阅读约 3 分钟,浏览了

案例

先看下效果吧 AI 图片生成

2023-12-04-IHQAaa3OoTr0

初步准备

要开始这个项目,首先需要:

  • 注册并开通 Cloudflare 账户。
  • 从域名 dashboard 页面获取必要的认证信息,包括 Account ID[1] , 和 用户 API 令牌

调试

当获取了 Account ID 和 Token 之后,就可以开始调试了。

curl -X POST \
  https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/ai/run/@cf/meta/llama-2-7b-chat-int8 \
  -H "Authorization: Bearer {API_TOKEN}" \
  -d '{ "prompt": "Where did the phrase Hello World come from" }'

当正确返回如下类似的字段,说明准备工作已经做好了。

{
  "result": {
    "response": "Hello, World first appeared in 1974 at Bell Labs when Brian Kernighan included it in the C programming language example. It became widely used as a basic test program due to simplicity and clarity. It represents an inviting greeting from a program to the world."
  },
  "success": true,
  "errors": [],
  "messages": []
}

创建 Worker

  • 将如下脚本上传到 Cloudflare Worker或者使用模板创建 2023-12-07-0SQ8wVIYvJA4
  • 在Worker设置中(Settings -> Variables),配置 ACCOUNT_ID 和 BEARER_TOKEN。
  • 测试 Worker:点击 Quick Edit,直接利用 Cloudflare 的内置功能进行接口调试[2][3]
  • 配置自己的 Custom Domains,以便访问更方便。

2023-12-04-dspicCCRr7sf

addEventListener('fetch', event => {
  event.respondWith(handleRequest(event.request))
})

// 主要的请求处理函数
async function handleRequest(request) {

  // 处理 CORS 预检请求
  if (request.method === "OPTIONS") {
    return handleCors();
  }

  return handleChatGPTRequest(request);
}


// 处理 CORS 预检请求的函数
function handleCors() {
  return new Response(null, {
    headers: {
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "POST, OPTIONS"
    }
  });
}

async function handleChatGPTRequest(request) {
  const url = `https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/ai/run/@cf/stabilityai/stable-diffusion-xl-base-1.0	`;

  const headers = {
    "Authorization": `Bearer ${BEARER_TOKEN}`,
    "Content-Type": "application/json"
  };

  const newRequest = new Request(url, {
    method: "POST",
    headers: headers,
    body: request.body
  });

  const response = await fetch(newRequest);
  const newResponse = new Response(response.body, response);
  newResponse.headers.set("Access-Control-Allow-Origin", "*");

  return newResponse;
}   

发布

至此服务已经做好,剩下的就是简单的前端 html 页面了。


<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0, viewport-fit=cover" />
    <title>AI 图片生成</title>
</head>
<link rel="stylesheet" href="https://res.suning.cn/public/v5/common/2.0.0/channel.css">
<style>

</style>

<body style="margin: 20px auto;">
    
    <div class="header" id="chatBox">
        <p class="loading hide ">图片生成中,小水管服务器生成较慢,请喝口水耐心等待。。。</p>
    </div>

    <style>
        .header{
            text-align: center;
        }
        footer{
            position: fixed;
            bottom: 0;
            width: 100%;
            height: 30px;
            line-height: 30px;
            text-align: center;
            color: #999;
            font-size: 12px;
            background-color: #f2f2f2;
            z-index: 9999;
        }

.inputbox {
    position: fixed;
    bottom: 30px;
    left: 0;
    right: 0;
    width: 90%;
    max-width: 1000px;
    margin: 0 auto;
    display: flex;
    align-items: center;
    border: 1px solid rgba(0,0,0,.3);
    padding-right: 12px;
    background: #fff;
    border-radius: 8px
}

.inputbox input{
    flex-grow: 1;
    height: 44px;
    max-height: 100px;
    border: 0;
    outline: none;
    padding: 12px 15px;
    background: transparent;
    font-size: 16px;
    width: 100%;
    font-weight: 700;
    color: #000000b3
}


.btn-send {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 48px;
    height: 32px;
    border-radius: 6px;
    color: #0009;
    background: rgba(0,0,0,.1)
}

.btn-send:hover {
    cursor: pointer;
    opacity: .85
}
img.list{
    margin: 10px 0;
}
.loading{text-align: center;width:70%;font-size: 16px;position: fixed;top: 50%;left: 50%;transform: translate(-50%,-50%);background: #fff;padding: 10px;border-radius: 5px;}

    </style>
    
    
    <div class="inputbox">
        <input type="text" placeholder="需要输入英文,示例:a cat in a box">
        <div data-v-eddecc8f="" class="btn-send" id="submit-btn">
            <div data-v-eddecc8f="" class="send-view" style="display: flex;"><img data-v-eddecc8f=""
                    src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADEAAAAxCAYAAABznEEcAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFLElEQVR4nNWZWWyVZRCGHzltXUBwA+tWq+KGcUNFQiQmhmCsxL1oXCBq4AKjgnHXCy40NkGNvUADIdEAMbVyIRo1UiVGjSwRk3okiFi0KooVbVxYCqU1k7wnGf/829nbNzmB83e+75+Zb+ad+ebA8MSRwBxgA/ANwwyXAkuBv4FBfdYzDDAamAtscor7z2yGMC4BlgD/RChvnz+BIxhiOBp4AMhKyQFgb4jy6/Xv8wwhTAWWO4V3KvY/liEHnQGLJGvPxldb8aMU619JOVOqA2gGbgJ+0vNP3P9bgONk7PtDIdb3SLFfpdzpwAnAKnca9wPrnAGGx/T9ukorfjzwIPB1iNdrgUN0Kn8pfJYrVDZK/mntY3LbgG4gUwnFRwDTgHagT8rskEcbndyZwFr9/TutGQd0yqD5TrZJck+WW/l6HXlXiNdrnFyt5PYBB4BWYKROLSsDLJw83pFDTKasXt8v5X+W108NkZ8CbJbcl8oTwynAtzL8nsCaBqAfeL3Uyp8ob34vhfqd1zMR1bdVSu7W2pxcg8KpP6IKP6d3GB2X1OsHtLEl20J5MgozgB8l/17ghBqB7TLgzpC1dWKrzUrugnGSPNctRfpkyLSEjevFNrbmD7GQx9kKvT7VhzDcofXzClE847zer422ypixCWvNsFnALq1rV6HyOEeM1QdcH7PXZ+qhLBxTY7zCI3f8+1J6PYczgA+11sJkeojMRUCPit70mL0u0D6L0yhep4TsEL3Zwi3yetCDUaiR/F5Hm6NC5CbqhHbLMXF4Rbqcn+T1F4DfJWwbvyoazAeXuz5okxQNw2SgV9X5ioQ9R+sC9GnSy3v04h4lzpg8lR8VoM1HAkXNY6qU6pUxSZgn3W5PErzVncIbYpO0uNaxVYeauChcBfwrhsoVtyRkgd+AQ9NeRpYoF3rVrFk9iMI4R5u9os24hL9aCWynfWFKA67U/s+mlP/fwq2ujzcKDKLZnVy7DIpDkxJ9Z1JyBtCmEPXNYmocLnrdr5cvFHNZqKxx3eiNKfaaIXq2O8OEPHSoV+1YTZGYqOZsULOdPSp4L0XQZhC3iWZ/UN3IB0/pvddQAhjLPCxvWsWclHLdXTK4K6KLTeoSurU2Li/zxsvyTBT3e9yrWLbcOrmAd92gdxlVlxQTxFw2gYjDXBmwRW16IfhAJ5/UmyWiTh7x/LxWxczoOAzzZWhnCsaK6x4Oir6LNmB1yAXkZj17KGTNAtduHFvEuxdpnzTVPJUBiwMFrEbzn20hCfeLY7G4ljqJ2neJEYsy4O0IA4LUZwUshzF6llVLMajJnU2w88FsrZ1TjAFvaZOlMS3EWBXAd92zSVq3QPnSIpkBVfTTUuqwQS3MyHIakMMKKXiWvs8KKUwNSs4BVd7WhO74Yu1hhbQgtCWEUBCTJW93EMMz+h5Wle1O8rlr9e/TvCmIZTI4rFdLhTVihXymCF+43wZWKXyixoq270w3TAsmv4WgUfdHVBh3uyTM6pOEWhXD3CVsnU4qR89G4RXFYWrHO3UKdhppcQzwonJlQDe9HRFhVjJYmDwaQpkt7oePvC8uyqE3ZcgTlNmAlRENWaObRVnXWihsn6KmemkNWBmRuLnqHtWiN6utPpcqIJPCAMN5+vEv7O8zdSnarjyoKDJuCNAWM36Jwy3uVpe2YlOOC1DcCcQhdwJdqtxVwQpV70IMuKyaBowoUfLZROS1ahiQcUlcqCFT8hiKlQXLXA4UMl1oUghZ4aoaNsqQQn8XflzT8Kol8X8x75k5b0tu7gAAAABJRU5ErkJggg=="
                    style="width: 20px;"></div>
            </div>
        </div>
    </div>
    
    <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <footer>
        <span class="hide" id="busuanzi_container_site_pv">本站总访问量 <span id="busuanzi_value_site_pv"></span> 次</span> · 
        <span>基于 stable-diffusion-xl-base-1.0 模型</span>
    </footer>
    <script>
        var flag = true;
        function clean(msg) {
            if (!msg) {
                alert("内容不能为空!")
                return;
            }
            if (!flag) {
                console.log('不要重复请求!');
                return
            }
            flag = false;
            document.querySelector(".loading").classList.remove("hide");
            fetch(
                `https://ai.1953615.xyz/`,
                {
                    method: "POST",
                    mode: "cors",
                    body: JSON.stringify({

                        "cfg_scale": 7,
                        "clip_guidance_preset": "FAST_BLUE",
                        "height": 512,
                        "width": 512,
                        "sampler": "K_DPM_2_ANCESTRAL",
                        "samples": 1,
                        "steps": 30,

                        "prompt": msg || "a cat in a room",
                    })
                },
            ).then(response => response.blob()).then((d) => {
                flag = true;
                let img = new Image();
                img.src = URL.createObjectURL(d);
                img.className = "list"
                img.onload = () => {
                    document.querySelector("#chatBox").appendChild(img);
                    document.querySelector(".loading").classList.add("hide");
                }
                img.onerror = () => {
                    alert("服务拥堵,请稍后再试。。")
                }

            }).catch((error) => {
                console.error("There has been a problem with your fetch operation:", error);
                alert("服务拥堵,请稍后再试。")
                 document.querySelector(".loading").classList.remove("hide");
            })
        }
        document.querySelector("#submit-btn").addEventListener("click", function (params) {
            clean(document.querySelector("input").value)
        });
    </script>
</body>

</html>

Worker 的服务是跨域的,现在只要把页面发布到自己的服务器上就可以在线访问使用了。

TIPS:服务目前免费不代表以后免费

参考

  • [1] 点击左侧 Workers and Pages,在页面右上方就有 Account ID
📝 评论
评论区加载中,请稍等