1. 项目概述与核心价值

最近在折腾AI应用开发,发现直接调用OpenAI的官方API虽然稳定,但有时候会遇到一些网络访问上的小麻烦,尤其是在国内网络环境下,或者需要做一些定制化功能的时候。于是,我花了不少时间研究如何搭建一个属于自己的、功能更灵活的ChatGPT API代理。最终,我选择在Cloudflare Workers这个无服务器边缘计算平台上实现,因为它部署简单、全球节点访问快,而且免费额度对于个人开发者来说相当友好。

这个项目本质上是一个运行在Cloudflare全球网络边缘的反向代理。它扮演了一个“中间人”的角色,接收你从客户端(比如你自己的聊天机器人前端、脚本或者支持自定义API的工具)发来的请求,然后帮你转发给真正的ChatGPT API服务端(比如OpenAI官方或者第三方的兼容API),最后再把响应结果原路返回给你。这样做有几个显而易见的好处:首先,它能有效规避一些网络层面的访问限制,让你的应用访问更稳定;其次,你可以在代理层加入自己的逻辑,比如访问控制、请求日志、甚至像这个项目实现的“联网搜索”这样的增强功能;最后,把API密钥放在云端Worker的环境变量里,比直接暴露在前端代码中要安全得多。

这个代理项目特别适合以下几类朋友:一是独立开发者或小团队,想快速搭建一个稳定可用的ChatGPT接口给自己的产品用;二是AI爱好者,希望在不修改客户端代码的情况下,为ChatGPT增加联网搜索等额外能力;三是任何对Cloudflare Workers感兴趣,想通过一个实用项目来学习边缘函数开发的人。接下来,我会详细拆解这个项目的设计思路、部署步骤、使用技巧以及我踩过的一些坑。

2. 核心设计思路与架构解析

2.1 为什么选择Cloudflare Workers?

在决定技术方案时,我对比了几种常见的代理实现方式,比如用Nginx做反向代理、自己买VPS搭Node.js服务,或者使用Serverless框架。最终选择Cloudflare Workers,主要是基于以下几点考量:

1. 极致的性能与低延迟 :Workers运行在Cloudflare全球275个以上的数据中心边缘。这意味着你的请求会由离用户最近的节点处理并转发,大大减少了网络延迟。对于AI对话这种交互式应用,响应速度至关重要,边缘计算的优势非常明显。

2. 真正的无服务器与低成本 :你不需要关心服务器的维护、扩容、安全补丁。Cloudflare Workers提供了慷慨的免费套餐,每天有10万次请求额度,对于个人项目或中小流量应用完全足够。这比租用一台始终在线的VPS要经济得多。

3. 开发部署体验流畅 :整个开发、测试、部署流程可以通过Wrangler命令行工具或在线编辑器完成,非常便捷。代码修改后几乎秒级生效,非常适合快速迭代。

4. 内置的安全与可靠性 :Cloudflare网络天然具备DDoS防护、SSL证书管理等能力,为你的代理服务增加了一层保障。

当然,它也有局限,主要是运行环境和资源限制(如CPU执行时间、内存大小)。但这个项目的代码逻辑清晰,完全在限制范围内,因此是一个绝佳的应用场景。

2.2 代理的核心工作流程

这个Worker脚本的核心逻辑并不复杂,但设计得很巧妙。它主要处理以下几类请求:

  1. 路径路由 :根据请求的URL路径,决定将请求转发到哪个后端服务。
    • /v1/chat/completions : 转发到OpenAI官方的Chat Completions API。
    • /kamiya/v1/chat/completions : 转发到第三方服务 kamiya.dev 提供的兼容API。
  2. 请求预处理
    • 身份验证 :检查请求头中的 Authorization 字段。如果配置了 PASSWORD 环境变量,则验证客户端提供的密钥是否在密码列表中。如果没配置密码,则可能直接将客户端提供的密钥用作后端API的密钥(具体逻辑取决于代码)。
    • 请求体解析与增强 :这是实现“联网搜索”的关键。Worker会解析请求中的消息内容,寻找特定的标记(如 WS[搜索关键词] )。当发现这种标记时,它会调用一个搜索服务(代码中可能是内置或指定的),获取搜索结果,并将这些结果作为新的上下文信息,附加到原有的用户消息之后,再发送给AI模型。这样,模型就能“看到”实时搜索到的信息并据此回答。
    • 流式响应支持 :它完整地处理了OpenAI的流式响应(Server-Sent Events),确保客户端能像连接官方API一样,接收到一个字一个字蹦出来的体验。
  3. 请求转发与响应回传 :将处理后的请求(添加了正确的后端API密钥、修改后的消息体等)发送到真正的ChatGPT API端点,并将响应(无论是普通JSON还是流式数据)原样返回给客户端。

这种设计实现了 解耦 可扩展性 。你的客户端代码几乎不需要改动,只需要换一个API地址和密钥(即你设置的密码)。所有复杂的认证、增强逻辑都在云端Worker中完成。

2.3 环境变量配置策略解析

项目通过环境变量来管理敏感信息和配置,这是云函数的最佳实践。这里详细解释一下三个变量的用途和配置技巧:

  • PASSWORD :这是你暴露给 客户端 的密钥。你可以设置一个或多个(用逗号分隔)。客户端在调用你的代理时,需要在 Authorization: Bearer <password> 头中使用这个密码。它的存在不是为了调用OpenAI,而是为了保护你的代理端点不被滥用。即使有人拿到了这个密码,他也不知道你背后真正的OpenAI Key是什么。
  • API_KEY :这是你真实的 OpenAI API密钥 。Worker在向 api.openai.com 转发请求时,会使用这个密钥来替换掉客户端请求中的 Authorization 头。 非常重要: 永远不要把这个密钥直接交给前端或不可信的客户端。在这里,它被安全地存储在Cloudflare的环境变量中。
  • KAMIYA_TOKEN :这是为备用API端点准备的密钥。如果你配置了 /kamiya 路由,并且希望使用 kamiya.dev 的服务,就需要在这里填入他们提供的密钥。

重要安全提示 :在Cloudflare Workers仪表盘设置环境变量时,务必区分“加密”和“明文”。对于 API_KEY KAMIYA_TOKEN 这类高度敏感的密钥,应该使用“加密的文本”方式添加,这样它们在日志和代码中都不会被明文暴露。 PASSWORD 相对可以宽松一些,但出于安全习惯,也建议加密。

3. 从零开始的详细部署指南

3.1 前期准备与工具安装

在开始部署之前,你需要准备好以下几样东西:

  1. 一个Cloudflare账户 :如果你还没有,去Cloudflare官网注册一个,免费计划即可。
  2. 一个域名(可选但推荐) :虽然Cloudflare Workers提供免费的 *.workers.dev 子域名,但使用自己的域名会更专业,也便于管理。你需要将这个域名的DNS托管到Cloudflare。
  3. Node.js与npm环境 :用于安装部署工具。建议安装最新的LTS版本。
  4. OpenAI API密钥 :从OpenAI平台获取。如果你打算使用 kamiya.dev 的服务,也需要去其官网获取相应的令牌。

接下来,安装Cloudflare的命令行部署工具 Wrangler 。打开你的终端(命令行),执行以下命令:

npm install -g wrangler

安装完成后,运行 wrangler login ,按照提示在浏览器中完成对Cloudflare账户的授权。这一步会将你的本地环境与Cloudflare账户关联起来。

3.2 获取与配置项目代码

这个项目的代码托管在GitHub上。你不需要克隆整个仓库,只需要获取核心的JavaScript文件。

  1. 访问项目页面,找到 index.js (源代码,便于阅读和自定义)或 production.js (压缩后的代码,体积更小)。

  2. 将文件内容复制下来,在你本地创建一个新文件,例如命名为 chatgpt-proxy.js ,并将代码粘贴进去。

  3. (关键步骤)初始化Wrangler项目 :在存放 chatgpt-proxy.js 文件的目录下,打开终端,运行:

    wrangler init
    

    这个命令会创建一个 wrangler.toml 配置文件。你可以删除它自动生成的其他文件,只保留这个配置文件和我们刚才创建的JS文件。

  4. 编辑 wrangler.toml 文件 :用文本编辑器打开它,进行如下配置:

    name = "my-chatgpt-proxy" # 给你的Worker起个名字,全局唯一
    main = "chatgpt-proxy.js" # 指定入口文件为我们的JS文件
    compatibility_date = "2024-08-01" # 使用一个较新的兼容日期
    
    [vars]
    # 这里可以定义环境变量,但生产环境建议在Dashboard设置
    # PASSWORD = "your_secret_password_here"
    # API_KEY = "sk-your-real-openai-key"
    
    # 如果你使用自己的域名,需要配置路由
    # [[routes]]
    # pattern = "chatgpt.yourdomain.com/*"
    # zone_name = "yourdomain.com"
    

    注意,我在这里的 [vars] 部分注释掉了环境变量。 我更推荐的做法是,先在本地测试时用这里定义,测试无误后,在部署到生产环境前,删除这里的明文密钥,转而在Cloudflare Dashboard上设置加密的环境变量。 这是避免将密钥意外提交到Git等版本控制系统的最佳实践。

3.3 本地开发与测试

在部署到云端之前,强烈建议先在本地进行测试。Wrangler提供了出色的本地开发服务器。

  1. 在项目根目录下,创建一个 .dev.vars 文件。这个文件用于定义本地开发时的环境变量,它不会被提交到版本库。

    # .dev.vars
    PASSWORD="my_test_password"
    API_KEY="sk-your-real-openai-key-for-test"
    
  2. 启动本地开发服务器:

    wrangler dev
    

    终端会输出一个本地地址,通常是 http://localhost:8787

  3. 测试代理功能 :使用 curl 或Postman等工具进行测试。

    • 测试基础代理
      curl http://localhost:8787/v1/chat/completions \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer my_test_password" \
        -d '{
          "model": "gpt-3.5-turbo",
          "messages": [{"role": "user", "content": "你好,世界!"}],
          "stream": false
        }'
      
      你应该能收到一个正常的ChatGPT回复。
    • 测试流式输出 :将请求体中的 "stream": false 改为 true ,你会看到一段段的数据流。
    • 测试联网搜索
      curl http://localhost:8787/v1/chat/completions \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer my_test_password" \
        -d '{
          "model": "gpt-3.5-turbo",
          "messages": [{"role": "user", "content": "告诉我今天的天气。WS[北京 今天 天气]"}],
          "stream": false
        }'
      
      观察响应,看AI的回答是否包含了基于搜索结果的实时信息。

    本地测试能帮你快速验证代码逻辑和环境变量是否正确,避免直接部署到云端后排查困难。

3.4 生产环境部署与配置

本地测试通过后,就可以部署到生产环境了。

  1. 发布Worker :在终端运行以下命令,将你的代码部署到Cloudflare全球网络。

    wrangler deploy
    

    部署成功后,你会得到一个形如 https://my-chatgpt-proxy.<你的子域名>.workers.dev 的访问地址。这就是你的代理API的基础URL。

  2. 配置生产环境变量

    • 登录Cloudflare Dashboard,进入“Workers & Pages”页面。
    • 找到你刚刚部署的Worker( my-chatgpt-proxy )。
    • 点击进入“设置”(Settings) -> “变量”(Variables)。
    • 在“环境变量”部分,添加 PASSWORD API_KEY 等变量。 务必为 API_KEY KAMIYA_TOKEN 选择“加密的文本”
    • 点击“保存”。
  3. 绑定自定义域名(可选)

    • 在Worker的“设置”页面,找到“触发器”(Triggers) -> “自定义域”(Custom Domains)。
    • 点击“添加自定义域”,输入你已托管在Cloudflare的域名,例如 chatgpt-api.yourdomain.com
    • 按照提示完成DNS记录的自动添加。绑定成功后,你就可以通过 https://chatgpt-api.yourdomain.com/v1/... 来访问你的代理了,这比workers.dev的域名更简洁专业。

4. 客户端集成与使用实战

部署好代理后,最关键的一步就是在你的客户端应用中使用它。这里以几种常见场景为例。

4.1 在ChatGPT WebUI类工具中配置

许多基于Web的ChatGPT开源前端(如ChatGPT-Next-Web, LibreChat)都支持自定义API地址。

  1. 配置API地址 :在设置页面,找到“API地址”或“Base URL”的配置项。将默认的 https://api.openai.com 替换为你的Worker地址,例如 https://my-chatgpt-proxy.your-subdomain.workers.dev https://chatgpt-api.yourdomain.com
  2. 配置API密钥 :在“API密钥”配置项中,填入你在Worker环境变量里设置的 PASSWORD (访问密码),而不是你的真实OpenAI Key。
  3. 模型列表(可选) :有些前端需要手动配置模型列表。你可以填写 gpt-3.5-turbo, gpt-4 等。如果前端支持从接口自动获取模型列表,但你的代理没有实现 /v1/models 端点,可能会报错。这时你可能需要在前端配置中关闭“自动获取模型”的选项,或者为你的Worker添加一个简单的 /v1/models 路由,返回一个固定的模型列表。

配置完成后,你就可以在前端界面中正常聊天了。当你需要联网搜索时,只需在问题中插入 WS[关键词] 即可。

4.2 在编程中直接调用API

如果你在编写Python、JavaScript等脚本,调用方式与调用官方API几乎无异,只需修改 base_url api_key

Python示例(使用OpenAI官方库):

from openai import OpenAI

# 初始化客户端,指向你的代理
client = OpenAI(
    api_key="your_proxy_password_here", # 填写PASSWORD
    base_url="https://chatgpt-api.yourdomain.com/v1", # 注意这里只到/v1
)

# 发起普通对话
response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "你好!"}],
    stream=False,
)
print(response.choices[0].message.content)

# 发起带联网搜索的对话
search_response = client.chat.completions.create(
    model="gpt-3.5-turbo",
    messages=[{"role": "user", "content": "马斯克最近有什么新闻?WS[Elon Musk news]"}],
    stream=False,
)
print(search_response.choices[0].message.content)

JavaScript/Node.js示例(使用原生fetch):

async function callProxyChatGPT() {
    const response = await fetch('https://chatgpt-api.yourdomain.com/v1/chat/completions', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer your_proxy_password_here` // 填写PASSWORD
        },
        body: JSON.stringify({
            model: 'gpt-3.5-turbo',
            messages: [{ role: 'user', content: '解释一下量子计算。WS[quantum computing basics]' }],
            stream: false // 设为true可处理流式响应
        })
    });

    const data = await response.json();
    console.log(data.choices[0].message.content);
}

callProxyChatGPT();

4.3 联网搜索功能深度使用指南

项目的联网搜索功能是其一大亮点,但使用上有一些细节需要注意:

  • 触发语法 :在用户消息的任何位置插入 WS[搜索查询词] 即可。Worker会识别这个模式,提取括号内的内容进行搜索,并将搜索结果整理后附加到原始消息后。例如:“ 帮我总结一下WS[2024年人工智能大会]的主要议题。
  • 搜索次数限制 :代码中默认设置了限制, 当前提问中最多触发2次搜索 ,并且会 附带上次提问的搜索请求 ,因此 单次回答总共最多进行4次搜索 。这是为了防止滥用和避免Worker执行时间超限。如果你需要更多次搜索,必须修改Worker源代码,找到对应的限制变量(通常是一个计数器或数组长度检查)进行调整。
  • 性能影响 :每一次搜索都意味着Worker需要额外发起一个网络请求到搜索引擎(如Bing或Google的API),等待返回,然后解析结果。这会显著增加整个请求的响应时间,从几百毫秒可能增加到几秒甚至更久。 在要求低延迟的交互场景中慎用
  • 搜索质量 :最终的回答质量高度依赖于底层搜索服务的准确性和Worker对搜索结果的摘要能力。有时搜索结果可能包含无关或过时信息,从而影响AI的回答。对于关键信息,最好能提供更精确的搜索关键词。

5. 高级配置、问题排查与优化

5.1 自定义与扩展

这个Worker项目是一个很好的起点,你可以基于它进行各种自定义:

  1. 修改默认密码和密钥 :直接在Cloudflare Dashboard的环境变量中修改即可,无需改动代码。
  2. 增加新的API提供商 :如果你想接入除了OpenAI和Kamiya之外的其他大模型API(如Anthropic Claude、Google Gemini),可以在代码的请求路由部分添加新的判断分支,并配置对应的环境变量(如 ANTHROPIC_KEY )。
  3. 修改搜索逻辑 :默认的搜索实现可能比较简单。你可以替换成更强大的搜索API(如Serper API、SerpAPI),或者修改结果的处理方式,比如只提取摘要、只取前N条结果等。
  4. 添加请求日志与监控 :在代码开头或结尾添加日志记录,将请求的元信息(时间、IP、模型、Token用量)发送到日志服务(如Cloudflare自身的Workers Analytics、或第三方如Logtail),便于监控使用情况和排查问题。
  5. 实现更复杂的鉴权 :目前的密码鉴权比较简单。你可以集成更复杂的机制,如JWT令牌验证、基于IP的访问限制等。

5.2 常见问题与排查清单

在实际使用中,你可能会遇到以下问题。这里提供一个排查思路:

问题现象 可能原因 排查步骤与解决方案
返回 401 Unauthorized 1. 客户端未提供 Authorization 头。
2. 提供的密码不在 PASSWORD 环境变量列表中。
3. 环境变量未正确加载或Worker未重启。
1. 检查客户端请求头是否包含 Authorization: Bearer <password>
2. 登录Cloudflare Dashboard,确认 PASSWORD 变量值是否正确,密码间用英文逗号分隔,无空格。
3. 在Dashboard上轻微修改并保存环境变量,或重新部署Worker以触发更新。
返回 5xx 错误 (如 524, 500) 1. Worker执行超时(默认10秒)。
2. 后端API(OpenAI)服务不稳定或超时。
3. Worker代码运行时错误。
1. 检查是否进行了过于复杂或耗时的操作(如多次联网搜索)。尝试简化请求。
2. 检查OpenAI服务状态。可以在本地用真实密钥直接调用官方API测试。
3. 查看Cloudflare Dashboard中Worker的“日志”(Logs)页面,查看详细的错误信息。
流式输出中断或不完整 1. 网络连接不稳定。
2. Worker处理流式响应时出现错误。
3. 客户端处理流的方式有问题。
1. 检查网络。
2. 查看Worker日志,看是否有未捕获的异常。
3. 使用 curl 或简单的测试脚本验证代理的流式响应是否正常: curl -N -X POST ... -H \"Accept: text/event-stream\" ...
联网搜索功能不生效 1. 搜索语法错误。
2. 搜索服务不可用或返回错误。
3. 搜索次数已达上限。
1. 确认请求内容中包含了正确的 WS[查询词] 格式,括号为英文半角。
2. 查看Worker日志,搜索请求是否发出,返回状态码是什么。可能需要检查搜索服务API密钥和额度。
3. 检查代码中的搜索限制逻辑。
响应速度非常慢 1. 启用了联网搜索。
2. 模型负载高(如使用GPT-4)。
3. Worker冷启动。
1. 这是搜索功能的预期行为。如非必要,避免使用。
2. 尝试切换到 gpt-3.5-turbo 模型对比。
3. 对于免费Worker,不活跃时会进入“休眠”,首次请求会有冷启动延迟。保持一定频率的请求可以缓解。

5.3 性能优化与成本控制建议

  1. 合理设置超时与重试 :在Worker代码中,当你向后端API(OpenAI)发起 fetch 请求时,可以设置一个合理的超时(例如30秒),并考虑加入简单的重试逻辑(针对网络波动导致的5xx错误),但注意不要触发Cloudflare Worker自身的超时限制(免费版为10秒CPU时间,付费版更长)。
  2. 缓存常用结果 :对于一些通用、不常变的问题,可以考虑使用Cloudflare的KV(键值存储)或Cache API来缓存AI的回复。例如,将“用户问题+模型”作为键,将回复内容作为值缓存一段时间,可以极大减少对OpenAI API的调用,节省成本并提升响应速度。
  3. 监控API用量与成本 :定期查看OpenAI平台的使用仪表盘,监控Token消耗和费用。同时,可以在Worker代码中粗略计算每次请求的Token数(通过分析请求和响应体),并记录到日志中,以便分析。
  4. 使用压缩代码 :项目提供的 production.js 是压缩后的版本,体积更小,加载和执行更快。在生产环境部署时,建议使用这个文件。
  5. 考虑备用路由 :如果 /v1 路由对应的OpenAI API出现故障,可以快速在客户端将请求切换到 /kamiya/v1 路由(如果已配置),实现简单的故障转移。

部署并运行这个ChatGPT代理Worker几个月下来,最大的体会是它将复杂的基础设施问题简化了。你不再需要维护服务器,全球访问速度有保障,还能灵活地加入自己的业务逻辑。对于独立开发者和小型项目来说,这是一个性价比极高的解决方案。当然,它也要求你对Cloudflare Workers和JavaScript有一定的了解,以便在出现问题时能够自主排查和调整。希望这篇详细的指南能帮你顺利搭建起自己的AI代理网关。

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐