【Cloudflare系列教程】部署WTO

Wdraw 2.3 | 二次元API,由WZH团队-Wdraw开发小组开发,目前已开放免费测试

W系列项目交流群:957780885

WTOWdraw to OpenAI ,本帖教程将介绍如何将 wdraw 转为OpenAI格式后直接通过oneapi调用

感谢wbot团队为论坛佬友提供免费API(赞助 wbot),感谢 edwa 佬对代码进行了完善,感谢他们!

该服务仅供测试使用,严禁商用

生成图例

简单上手

第一步,绑定域名

注册cf账号并绑定域名,并提前分配一个二级域名给worker

第二步,配置worker

新建一个worker,覆盖粘贴下面的代码,然后在路由中将二级域名和worker绑定。

woker.js

默认使用Telegraph官方图床,你也可以自建,详参: 【Cloudflare系列教程】利用Pages部署免费Telegraph图床

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

async function handleRequest(request) {
  if (request.method === "OPTIONS") {
    return new Response("", {
      headers: {
        'Access-Control-Allow-Origin': '*',
        "Access-Control-Allow-Headers": '*'
      }, status: 204
    })
  }

  if(/^(https?:\/\/[^\/]*?)\/file\//i.test(request.url)){
    if(request.headers.get("if-modified-since")){
      return new Response("",{status:304,headers:{
        'Access-Control-Allow-Origin': '*',
       "Access-Control-Allow-Headers": '*',
       "Last-Modified":request.headers.get("If-Modified-Since")
    }});
  }

    var img = await fetch(request.url.replace(/^(https?:\/\/[^\/]*?)\//,"https://telegra.ph/"))
    return new Response(img.body,{status:img.status,headers:{
      "content-type":img.headers.get("content-type"),
      'Access-Control-Allow-Origin': '*',
       "Access-Control-Allow-Headers": '*',
       "Last-Modified": (new Date()).toUTCString(),
       "Cache-Control": "public, max-age=31536000"
    }})
  }

  const url = new URL(request.url);
  const search = url.searchParams

  if (!search.get("debug")) {
    if (url.pathname !== "/v1/chat/completions" || request.method !== "POST") {
      return new Response("Not Found or Method Not Allowed", {
        status: 404,
        headers: {
          "Content-Type": "application/json",
          'Access-Control-Allow-Origin': '*',
          "Access-Control-Allow-Headers": '*'
        }
      });
    }
  }

  const authHeader = request.headers.get("Authorization") || "Bearer " + search.get("key");
  if (!authHeader || !authHeader.startsWith("Bearer ")) {
    return new Response("Unauthorized: Missing or invalid Authorization header", {
      status: 401,
      headers: {
        "Content-Type": "application/json",
        'Access-Control-Allow-Origin': '*',
        "Access-Control-Allow-Headers": '*'
      }
    });
  }
  const apiKey = authHeader.slice(7);
  let data;
  try {
    data = await request.json();
  } catch (error) {
    if(!search.get("debug")) return new Response("Bad Request: Invalid JSON", { status: 400 });
    data = {model:"wdraw",messages:[{role:"user",content:search.get("prompt") || "cat"}]}
  }

  if (!data || !data.model || !data.messages || data.messages.length === 0) {
    return new Response("Bad Request: Missing required fields", { status: 400 });
  }

  const prompt = data.messages[data.messages.length - 1].content;
  const apiUrl = `https://aihh.api.ecylt.top/?key=${encodeURIComponent(apiKey)}&prompt=${encodeURIComponent(prompt)}`;

  const currentTimestamp = Math.floor(Date.now() / 1000);
  const uniqueId = `imggen-${currentTimestamp}`;

  try {
    const apiResponse = await fetch(apiUrl);
    if (!apiResponse.ok) {
      throw new Error("Request error: " + apiResponse.status);
    }
    const imageBlob = await apiResponse.blob();
    const formData = new FormData();
    formData.append("file", imageBlob, "image.jpg");

    const uploadResponse = await fetch("https://telegra.ph/upload", {
      method: 'POST',
      body: formData
    });

    if (!uploadResponse.ok) {
      throw new Error("Failed to upload image");
    }
    const uploadResult = await uploadResponse.json();
    const imageUrl = request.url.match(/^(https?:\/\/[^\/]*?)\//)[1] + uploadResult[0].src;

    const responsePayload = {
      id: uniqueId,
      object: "chat.completion.chunk",
      created: currentTimestamp,
      model: "wbot-2.3",
      choices: [
        {
          index: 0,
          delta: {
            content: `![](${imageUrl})`
          },
          finish_reason: "stop"
        }
      ]
    };

    const dataString = JSON.stringify(responsePayload);

    return new Response(`data: ${dataString}\n\n`, {
      status: 200,
      headers: {
        "Content-Type": "text/event-stream",
        'Access-Control-Allow-Origin': '*',
        "Access-Control-Allow-Headers": '*'
      }
    });
  } catch (error) {
    return new Response("Internal Server Error: " + error.message, {
      status: 500,
      headers: {
        "Content-Type": "application/json",
        'Access-Control-Allow-Origin': '*',
        "Access-Control-Allow-Headers": '*'
      }
    });
  }
}

第三步 配置oneapi

在oneapi新建一个自定义渠道,base_url 填 worker 绑定的二级域名,密钥 test,模型 wdraw-2.3

快来试试吧 :rofl:

参考链接

鸣谢

22 个赞

来了,第一

1 个赞

来了,第二

1 个赞

第 3

1 个赞

秀秀秀

1 个赞

6啊

1 个赞

mark

1 个赞

顶顶

1 个赞

WTO有点意思,以为是世贸呢

1 个赞

学习学习

1 个赞

不错 不错

1 个赞

谢谢分享

1 个赞

世贸由我部署

1 个赞

第一眼也以为是世贸……

支持一下

嗅着世贸组织的味道进来了,感谢佬的分享

Σ( ° △ °|||)︴

1 个赞

冷静

1 个赞