Deno Deploy部署Azure OpenAI代理:零成本解决API兼容问题
1. 项目概述在Deno Deploy上搭建一个免费的Azure OpenAI代理如果你正在折腾各种开源的ChatGPT WebUI项目比如ChatGPT-Next-Web、Lobe Chat或者想在自己的应用里集成GPT能力大概率会遇到一个头疼的问题这些项目默认都对接OpenAI官方的API但你可能因为网络、成本或者企业合规要求更希望使用微软Azure OpenAI服务。直接修改这些项目的后端代码太麻烦而且每次项目更新都可能需要重新适配。我最近就遇到了这个需求并且找到了一个非常优雅的解决方案deno-azure-openai-proxy。这是一个专门部署在Deno Deploy平台上的代理工具它的核心作用就是“翻译”。它接收一个标准的OpenAI API格式的请求然后“悄无声息”地将其转换成Azure OpenAI API的格式再转发给Azure最后把Azure的响应原样返回给你的客户端。整个过程你的前端应用完全无感它依然认为自己是在和OpenAI官方服务器对话。这个方案最吸引我的地方在于它的“零运维”和“零成本”。Deno Deploy是Deno官方提供的边缘计算平台它提供了相当慷慨的免费额度——每天10万次请求。对于个人开发者、小团队或者内部工具来说这几乎等于免费。你不需要操心服务器、域名备案、SSL证书甚至不需要写一行部署脚本点几下鼠标就能获得一个全球可访问的、高性能的API代理端点。接下来我就把自己从部署到调试再到实际应用中的一些心得和踩过的坑完整地分享给你。2. 核心原理与架构设计解析2.1 为什么需要这个代理理解协议差异要明白这个代理的价值首先得搞清楚OpenAI官方API和Azure OpenAI API之间的区别。它们提供的核心能力如GPT-3.5、GPT-4的文本生成虽然同源但访问协议和接口设计上存在关键差异直接导致了不兼容。1. 端点Endpoint与路径结构不同OpenAI官方API请求发送到统一的https://api.openai.com/v1/chat/completions。模型信息通过请求体Body中的model字段指定例如model: gpt-3.5-turbo。Azure OpenAI API请求发送到资源专属的端点格式为https://[你的资源名].openai.azure.com/openai/deployments/[部署名称]/chat/completions?api-version[版本号]。这里部署名称是关键它对应你在Azure门户中为某个模型如GPT-3.5-Turbo创建的具体部署实例。模型信息体现在URL路径里而非请求体中。2. 认证方式不同OpenAI使用统一的Authorization: Bearer sk-xxx头部sk-xxx是你的OpenAI API Key。Azure使用api-key头部其值是你为Azure OpenAI资源生成的密钥。这个密钥是绑定到特定Azure资源的。3. 请求/响应体微调Azure API的请求体和响应体与OpenAI高度相似但为了兼容其平台可能会有一些细微的字段差异或扩展。一个标准的代理需要妥善处理这些差异确保转换无损。这个deno-azure-openai-proxy项目本质上就是一个运行在Deno Deploy边缘节点的轻量级HTTP服务器。它监听你的自定义域名当收到一个OpenAI格式的请求时它会执行以下转换流程解析请求提取出OpenAI请求中的model参数、API KeyBearer Token和请求体。模型映射根据你预设的mapper规则将OpenAI的模型名如gpt-3.5-turbo映射为Azure的部署名称如my-gpt35-deployment。如果没有映射也可以选择透传。重构请求将端点重写为Azure的格式https://{resourceName}.openai.azure.com/openai/deployments/{deploymentName}/chat/completions。将认证头部从Authorization: Bearer sk-xxx替换为api-key: {你的Azure Key}。这里有个技巧代理会直接使用客户端传来的OpenAI API Key作为Azure的api-key这就要求你在客户端填写的“OpenAI Key”实际上就是你的“Azure Key”。这是一种便捷的密钥传递方式。保留或调整请求体并添加Azure所需的API版本查询参数如?api-version2024-02-15-preview。代理转发与响应将重构后的请求转发给Azure OpenAI服务并将Azure的响应包括流式输出的每一个chunk原封不动地返回给客户端。2.2 为什么选择Deno Deploy你可能会有疑问写一个这样的代理用任何云函数AWS Lambda, Vercel Edge Functions, Cloudflare Workers不都能实现吗为什么这个项目选择了Deno Deploy我对比下来认为有几个显著优势1. 网络直连与低延迟这是相对于Cloudflare Workers的一个关键优势。由于一些网络环境配置从国内直接访问Cloudflare Workers的默认域名*.workers.dev有时不稳定或速度慢。Deno Deploy的边缘节点分布广泛其提供的*.deno.dev二级域名在许多地区的连通性表现更好可以实现“直连”这对于保证ChatGPT类应用的实时响应体验至关重要。2. 开发与部署体验极简Deno Deploy与Deno运行时深度集成。这个项目本身就是一个单一的TypeScript文件main.ts。部署时你只需要把这个文件的内容复制过去设置环境变量点一下部署就完成了。无需处理package.json、依赖安装、构建流程真正做到了“一键部署”。这对于快速原型和轻量级服务来说非常友好。3. 慷慨的免费额度Deno Deploy的免费计划每月包含10万次请求和100GiB的带宽。对于代理API这种通常请求和响应体量都不算巨大的应用来说这个额度相当充裕足以支撑个人或小规模团队的使用。4. 原生支持TypeScript和Web标准Deno原生支持TS这意味着代理脚本可以直接用TS编写类型安全开发体验好。同时Deno的API设计紧跟Web标准如fetch编写HTTP代理的代码非常直观和现代。注意Deno Deploy的免费计划适用于生产级应用但需要注意其使用限制。如果请求量巨大可能需要升级到付费计划。不过对于绝大多数代理场景免费额度绰绰有余。3. 从零开始完整部署与配置指南理论讲清楚了我们动手把它部署起来。我会详细拆解每一步并附上我实际操作中总结的要点。3.1 前期准备获取Azure OpenAI资源在部署代理之前你必须先拥有一个可用的Azure OpenAI资源。如果你还没有可以参照以下步骤访问Azure门户登录你的Microsoft Azure账号如果没有需要注册新用户通常有免费额度。创建Azure OpenAI资源在门户中搜索“Azure OpenAI”。点击“创建”选择你的订阅、资源组和区域例如East US。输入资源名称如my-openai-proxy记住这个resourceName后续配置会用到。选择定价层通常选标准层S0即可。完成创建等待几分钟部署完毕。获取密钥与端点进入创建好的资源在“资源管理”-“密钥和终结点”页面。你会看到两个Key密钥1和密钥2任选其一即可后续作为你的api-key和终结点Endpoint格式为https://[resourceName].openai.azure.com/。部署模型在Azure OpenAI Studio中为你需要的模型如gpt-35-turbo,gpt-4创建部署Deployment。给这个部署起一个名字例如gpt35-turbo-prod。这个deployment name是模型映射的关键。3.2 一键部署流程详解推荐项目作者提供了最便捷的“一键部署”按钮这是最快上手的方式。点击部署链接访问项目GitHub主页找到并点击Deploy on Deno按钮或直接访问其指向的Deno Deploy新建项目页面。如果你是首次使用Deno Deploy系统会提示你登录。强烈建议直接使用GitHub账号授权登录这样最方便。创建与配置项目登录后页面会跳转到“Create a New Project”界面URL已经自动填充。你只需要为项目起个名字比如azure-openai-proxy然后点击 “Create” 按钮。几秒钟后项目就会部署成功。此时你会进入该项目的管理面板。设置关键环境变量 这是配置的核心步骤决定了你的代理如何连接到你的Azure资源。在项目面板左侧点击“Settings”然后选择“Environment Variables”。点击“Add Variable”来添加变量。这里我们需要设置两个核心变量RESOURCE_NAME填入你在Azure门户中创建的OpenAI资源名称resourceName例如my-openai-proxy。注意这里只需要名称不需要完整的URL。MAPPER这是模型映射的JSON字符串。格式必须严格遵循。例如你在Azure上部署了名为gpt35-turbo-prod的GPT-3.5-Turbo模型和名为gpt4-innovate的GPT-4模型那么映射应写为{gpt-3.5-turbo: gpt35-turbo-prod, gpt-4: gpt4-innovate}重要提示环境变量中的JSON字符串必须压缩在一行内不能有换行。引号必须使用双引号。这是最容易出错的地方。一个错误的逗号或引号都会导致代理启动失败。可选配置自定义域名默认情况下你的代理会有一个[你的项目名].deno.dev的域名。你可以直接使用它。如果你想绑定自己的域名如api.openai.mycompany.com继续在 “Settings” 的“Domains”部分添加你的自定义域名并按照提示去你的DNS服务商那里添加CNAME记录。这个过程和绑定域名到任何其他云服务类似。3.3 手动部署方法适用于自定义修改如果你想深入研究代码或者未来需要对代理逻辑进行定制比如增加日志、修改请求头那么手动部署并维护一份自己的代码副本是更好的选择。登录与新建访问https://dash.deno.com登录点击 “New Project”。进入Playground编辑器创建项目后在项目概览页找到 “Playground” 区域点击其右侧的 “Play” 图标会打开一个在线的代码编辑器。复制并修改代码打开原项目的main.ts文件在GitHub上复制全部内容。粘贴到Deno Deploy的Playground编辑器中。你可以直接修改代码开头的resourceName和mapper变量而不是通过环境变量设置。例如const resourceName Deno.env.get(RESOURCE_NAME) || “my-openai-proxy”; // 环境变量优先其次用默认值 const mapper JSON.parse(Deno.env.get(“MAPPER”) || ‘{“gpt-3.5-turbo”: “my-gpt35-deploy”}’);这种方式更灵活但要注意如果你后续在Deno Deploy面板修改了环境变量代码中的Deno.env.get会覆盖硬编码的值。保存并部署编辑完成后点击编辑器上方的“Save Deploy”按钮。每次代码修改后都需要执行这一步来发布新版本。设置域名同“一键部署”步骤4。3.4 验证部署是否成功部署完成后如何确认代理工作正常呢最简单的方法是使用curl命令或 Postman 进行一次测试。假设你的代理地址是https://my-proxy.deno.dev你可以发送一个测试请求curl https://my-proxy.deno.dev/v1/chat/completions \ -H “Content-Type: application/json” \ -H “Authorization: Bearer YOUR_AZURE_OPENAI_KEY” \ -d ‘{ “model”: “gpt-3.5-turbo”, “messages”: [{“role”: “user”, “content”: “Hello!”}], “stream”: true }’请注意这里的YOUR_AZURE_OPENAI_KEY应该替换成你从Azure门户获取的Key即api-key。代理会提取这个Bearer Token并将其用作转发给Azure时的api-key头部。如果返回了流式的响应内容或者一个标准的OpenAI格式的JSON错误比如模型未找到都说明代理服务本身已经成功运行正在与Azure后端通信。接下来就可以配置你的客户端应用了。4. 客户端配置与实战应用代理部署并测试通过后就可以让它为你手中的各种ChatGPT客户端服务了。这里以几个流行的开源项目为例讲解配置方法。4.1 配置ChatGPT-Next-WebChatGPT-Next-Web是目前非常流行的自部署ChatGPT WebUI。部署或打开你的ChatGPT-Next-Web实例。进入设置页面通常点击左下角的设置图标。关键配置项接口地址 (API Endpoint)填写你的代理完整地址必须包含/v1路径。例如https://my-proxy.deno.dev/v1。这是很多新手会漏掉的地方OpenAI客户端默认会向{endpoint}/chat/completions发送请求所以我们的代理地址需要定位到v1这一层。API Key这里不要填OpenAI的Key而是填入你的Azure OpenAI Key即前面提到的Key 1或Key 2。因为代理会提取这个Key去请求Azure。模型在模型下拉列表中选择你之前在mapper里配置过的OpenAI模型名例如gpt-3.5-turbo。代理会将其映射到对应的Azure部署。保存设置现在你就可以像使用官方API一样和你的Azure模型对话了。流式响应、历史记录等功能全部正常工作。4.2 配置Lobe ChatLobe Chat是另一个设计出色的开源ChatGPT应用。打开Lobe Chat的设置通常是右上角的齿轮图标。找到 “语言模型” 或 “Provider” 设置部分。选择 “OpenAI” 作为提供商。在配置项中Endpoint同样填写https://my-proxy.deno.dev/v1。API Key填写你的Azure OpenAI Key。模型选择映射过的模型如gpt-3.5-turbo。保存后即可使用。4.3 在自有代码中调用如果你是在自己的应用程序如Python、Node.js后端中调用配置方式同理。Python (使用openai库)示例from openai import OpenAI # 将 base_url 指向你的代理api_key 填入 Azure Key client OpenAI( base_url“https://my-proxy.deno.dev/v1, api_key“your-azure-openai-key-here”, # 这是你的Azure Key ) response client.chat.completions.create( model“gpt-3.5-turbo”, # 使用映射的模型名 messages[{“role”: “user”, “content”: “Hello world”}], streamTrue, ) for chunk in response: # 处理流式输出 print(chunk.choices[0].delta.content or “”, end“”)Node.js示例import OpenAI from ‘openai’; const openai new OpenAI({ baseURL: ‘https://my-proxy.deno.dev/v1, apiKey: ‘your-azure-openai-key-here’, // 这是你的Azure Key }); const stream await openai.chat.completions.create({ model: ‘gpt-3.5-turbo’, messages: [{ role: ‘user’, content: ‘Hello’ }], stream: true, }); for await (const chunk of stream) { process.stdout.write(chunk.choices[0]?.delta?.content || ‘’); }实操心得在配置客户端时最核心的就是理解“地址”和“密钥”的替换逻辑。地址换成你的代理地址v1路径密钥换成你的Azure密钥模型名使用你定义在mapper中的OpenAI标准名称。把握住这三点适配任何客户端都轻而易举。5. 高级配置与故障排查手册即使部署顺利在实际使用中也可能遇到一些问题。下面是我总结的一些常见场景和解决方案。5.1 模型映射Mapper的进阶用法mapper变量是这个代理的灵魂它非常灵活。一对一映射这是最常用的方式将OpenAI模型名映射到Azure部署名。{“gpt-3.5-turbo”: “my-chatgpt35”, “gpt-4”: “my-gpt4”}多别名映射如果你希望客户端使用不同的模型名比如chatgpt-3.5也能指向同一个Azure部署可以这样设置{“gpt-3.5-turbo”: “my-chatgpt35”, “chatgpt-3.5”: “my-chatgpt35”, “gpt-4”: “my-gpt4”}透传模式如果你不想维护映射表或者Azure部署名就是OpenAI模型名可以将mapper设置为一个空对象{}。这样代理会将客户端请求中的model字段值直接用作Azure的deployment名称。这要求你在Azure上创建的部署名称必须与OpenAI模型名完全一致如gpt-3.5-turbo但Azure的命名规则可能不允许包含横杠所以这种方式限制较多。动态映射通过环境变量这是最佳实践。将复杂的JSON映射关系以字符串形式设置在Deno Deploy的环境变量MAPPER中避免修改代码管理更清晰。5.2 支持更多Azure OpenAI API除了基础的聊天补全/chat/completions该代理也支持其他端点例如Embeddings用于文本向量化。请求路径/v1/embeddings会被代理到Azure的/openai/deployments/{deployment}/embeddings。你需要为Embedding模型如text-embedding-ada-002在Azure上创建部署并在mapper中添加映射例如{“text-embedding-ada-002”: “my-embedding-deploy”}。Completions旧版的文本补全接口使用方式类似。代理脚本会根据请求路径自动路由。你只需要确保在Azure上部署了相应的模型并在mapper中配置好即可。5.3 常见错误与排查表错误现象可能原因排查步骤与解决方案401 Authentication ErrorAPI Key错误或缺失。1. 检查客户端配置的API Key是否是你的Azure Key而非OpenAI Key。2. 登录Azure门户确认密钥是否有效、未禁用。3. 在代理项目中检查环境变量RESOURCE_NAME是否正确。404 Model not found模型映射错误或Azure部署不存在。1. 检查客户端请求的model字段值如gpt-3.5-turbo是否存在于你的mapper映射表中。2. 检查mapper中对应的Azure部署名称如my-gpt35是否与你在Azure OpenAI Studio中创建的部署名称完全一致区分大小写。3. 登录Azure OpenAI Studio确认该部署状态为“成功”。400 Bad Request请求格式问题或Azure API版本不兼容。1. 代理脚本内部有默认的api-version。如果Azure服务升级导致旧版本弃用可能需要更新代理代码中的apiVersion变量。检查项目GitHub页面的更新日志。2. 使用curl或 Postman 直接向你的代理发送一个最简单的请求排除客户端代码问题。代理地址返回5xx错误Deno Deploy服务异常或代理代码有Bug。1. 访问Deno Deploy项目面板查看“Logs”页面这里有详细的运行时错误日志是排查的第一手资料。2. 检查MAPPER环境变量的JSON格式是否正确压缩、双引号。3. 尝试重新部署手动部署模式下点击“Save Deploy”。流式响应中断或异常网络问题或客户端处理流的方式与代理不兼容。1. 首先测试非流式请求“stream”: false是否正常以确定问题是否与流式传输相关。2. 查看Deno Deploy的日志看代理在转发流式数据时是否有报错。3. 确保你的客户端代码能够正确处理分块的HTTP响应。自定义域名无法访问DNS配置未生效或Deno Deploy未验证。1. 确认在Deno Deploy的“Domains”设置中你的自定义域名状态是“Verified”。2. 检查你的DNS管理后台CNAME记录是否已正确指向Deno Deploy提供的目标地址如xxx.deno.dev。3. DNS变更全球生效可能需要几分钟到几小时请耐心等待。5.4 性能监控与日志查看Deno Deploy的控制台提供了基本的监控能力Analytics在项目面板可以看到请求次数、带宽用量、错误率等图表方便你了解代理的使用情况和是否接近免费额度上限。Logs这是最重要的调试工具。所有由你的代理代码打印的console.log以及运行时错误都会在这里显示。在开发自定义功能或排查问题时务必善用此功能。你可以在代理代码中关键位置添加日志来跟踪请求的转换过程。6. 安全考量与最佳实践建议将API密钥通过代理暴露在公网上安全是必须考虑的问题。虽然这个代理本身不存储密钥密钥由客户端每次请求带来但仍需注意以下几点限制调用来源CORS目前的代理脚本默认配置了较宽松的CORS策略Access-Control-Allow-Origin: *。在生产环境中如果你能确定前端应用的域名建议修改代码将*替换为你的具体前端域名如https://chat.yourdomain.com以减少被恶意网站跨域调用的风险。使用自定义域名并启用HTTPSDeno Deploy自动提供HTTPS。使用自定义域名不仅更专业也能避免deno.dev域名被某些网络策略屏蔽的风险。管理Azure密钥的权限在Azure门户中为OpenAI资源创建的密钥具有完全访问权限。定期轮换密钥是一个好习惯。如果条件允许可以考虑使用Azure的托管身份Managed Identity等更安全的认证方式但这需要将代理也部署在Azure生态内与当前Deno Deploy方案不符。监控异常请求定期查看Deno Deploy的Analytics和Logs关注是否有异常高频的请求或来自异常IP的访问。虽然免费额度够用但防止滥用总是好的。代码可维护性如果你采用了手动部署并修改了代码建议将你的main.ts版本保存在自己的Git仓库中。这样当原项目有重要更新如支持新的API版本时你可以方便地对比和合并更改。这个deno-azure-openai-proxy项目我用了快半年支撑了几个内部工具和小型项目稳定性非常不错。它完美地解决了我用开源前端对接Azure后端的需求把复杂的协议转换问题封装成了一个透明的服务。最大的体会是对于开发者而言好的工具就应该像这样“开箱即用无需操心”。如果你也受困于OpenAI和Azure API的兼容性问题不妨花十分钟试试这个方案它很可能就是你在寻找的那块“拼图”。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2594951.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!