使用 Azure OpenAI 打造自己的 ChatGPT
Posted 晓晨Master
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用 Azure OpenAI 打造自己的 ChatGPT相关的知识,希望对你有一定的参考价值。
一.前言
当今的人工智能技术正在不断发展,越来越多的企业和个人开始探索人工智能在各个领域中的应用。其中,在自然语言处理领域,OpenAI 的 GPT 系列模型成为了研究热点。OpenAI 公司的 ChatGPT 带起了一波 AI 应用的浪潮,一些科技公司都在努力跟进,比如百度的文心一言,Google 的 Bard 以及 Notion AI。就目前体验来说还是 OpenAI ChatGPT 表现最好。
作为 OpenAI 公司的大股东,Microsoft 当然是使用其服务的一等公民,陆续推出了 GitHub Copilot、New Bing、Office 365 Copilot 和 Github Copilot X 等等。目前 Microsoft Azure 是独一家的提供 OpenAI 云服务的云厂商,Azure OpenAI 提供的 API 服务使得构建和部署自己的 ChatGPT 成为了可能。
二.对比
Azure OpenAI 和 OpenAI 官方提供的服务基本是一致的,但是目前前者还是处于预览版的状态,一些功能还没有完全开放。
注意:需要使用 Azure 国际版,点此进行申请
优点:
- 不受地域限制,国内可以直接调用。
- 可以自己上传训练数据进行训练(据说很贵)。
- Azure 多语言 SDK 支持。
- 更适合企业私有化,数据可完全控制删除。
缺点:
- 部分功能未开放,但 ChatGPT 的功能是没问题的。
- 和 OpenAI 官方的 API 标准有差异,无法直接用一些只支持 OpenAI 官方API 的开源项目。
Azure OpenAI 也已经支持 GPT-4 了,需要单独进行申请,博主的申请还没通过本文暂时以 GPT-3.5 进行演示。
三.使用 Auzre OpenAI
1.创建服务
进入 Azure 后,直接搜索 "Azure OpenAI"。
选择你已经申请通过的订阅进行创建。
如果该订阅没有启动则不能创建。
2.创建模型部署
在资源管理->模型部署 选择需要的模型进行创建,每个模型只能创建1个部署。
2.Azure OpenAI Studio
模型创建完成以后,我们可以直接使用 Azure OpenAI Studio 来进行快速的测试。
ChatGPT 测试。
上传自己的数据集。
四.API 调用
在 资源管理->密钥和终结点 可以获取 API 地址以及调用密钥。
查看 API 文档
使用 POSTMAN 进行调用测试。
五.打造自己的 ChatGPT
1.Azure OpenAI Proxy
打造自己的 ChatGPT 推荐直接使用 https://github.com/Chanzhaoyu/chatgpt-web 这个项目。
前面我们说到 API 调用是有差异的,此项目目前还没用直接支持 Azure OpenAI。我尝试修改过这个项目,可以调用了但是有个问题,无法正常的自动结束对话,跟了代码发现有 Bug:
https://github.com/Chanzhaoyu/chatgpt-web -> https://github.com/transitive-bullshit/chatgpt-api -> https://github.com/rexxars/eventsource-parser
最终在 eventsource-parser 这个 package 里,无法适应 Azure OpenAI 返回的结果,做过对比发现 Azure OpenAI 返回的调用最后少了一个换行 \\n
。
最终我便想了个方法,自己实现一个 Proxy 转换 OpenAI 官方 API 标准到 Azure OpenAI 标准,这样就能让 Azure OpenAI 直接对接到任何支持 OpenAI 的任何项目中,并且可以顺便修复上面所说的差异,让 chatgpt-web 直接使用 Azure OpenAI。
项目地址:https://github.com/stulzq/azure-openai-proxy 希望大家点点 star。
2.搭建
最快的方式当然是使用 Docker,以下是 docker compose 脚本:
version: \'3\'
services:
chatgpt-web:
image: chenzhaoyu94/chatgpt-web
ports:
- 3002:3002
environment:
OPENAI_API_KEY: <Auzre OpenAI API Key>
OPENAI_API_BASE_URL: http://azure-openai:8080
AUTH_SECRET_KEY: ""
MAX_REQUEST_PER_HOUR: 1000
TIMEOUT_MS: 60000
depends_on:
- azure-openai
links:
- azure-openai
networks:
- chatgpt-ns
azure-openai:
image: stulzq/azure-openai-proxy
ports:
- 8080:8080
environment:
AZURE_OPENAI_ENDPOINT: <Auzre OpenAI API Endpoint>
AZURE_OPENAI_MODEL_MAPPER: <Auzre OpenAI API Deployment Mapper>
AZURE_OPENAI_API_VER: 2023-03-15-preview
networks:
- chatgpt-ns
networks:
chatgpt-ns:
driver: bridge
启动有 3 个环境变量需要配置:
变量名 | 说明 |
---|---|
OPENAI_API_KEY | Azure 密钥和终结点 里提供的 Key |
AZURE_OPENAI_ENDPOINT | Azure 密钥和终结点 里提供的终结点 |
AZURE_OPENAI_MODEL_MAPPER | Azure 部署模型名称映射到 OpenAI 官方模型名称 |
特别说明一下 AZURE_OPENAI_MODEL_MAPPER
使用 OpenAI 官方标准发起的请求里包含的模型名称是固定的,在这里可以查询,而在 Azure OpenAI 模型部署时是可以自定义名称的,请求 Azure yes需要提供这个部署模型的名称,所以建立了一个映射关系。
比如我在 Azure 部署了一个 gpt-3.5-turbo
模型,我设置的部署名称为:xc-gpt-35
,此时我的设置:
AZURE_OPENAI_MODEL_MAPPER: gpt-3.5-turbo=xc-gpt-35
六.结束
Azure OpenAI 平台为开发人员提供了一个强大的工具,可以轻松地创建和训练 ChatGPT 模型。随着 ChatGPT 技术的不断发展,它将在越来越多的应用场景中发挥重要作用,为人们提供更加智能和个性化的服务和体验。
目前学习.NET Core 最好的教程 .NET Core 官方教程 ASP.NET Core 官方教程
打造自己的ChatGPT:逐字打印的流式处理
接口的延迟
在调用OpenAI的接口时,不免会有很慢的感觉,抛去地理位置上的网络延迟,大量的延迟往往发生在响应生成的过程中。
因此,如果使用同步接口的话,需要等待响应完全生成之后才能最终显示输出结果,虽然在对接微信或者其他需要通过接口请求的应用服务时没什么特别好的处理方案,但是如果是Web应用的话,就可以通过流式处理实现实时的数据返回,从而提升响应的优先级。
后端的流式处理
绝大部分的SDK都已经对OpenAI API的流式响应做了封装,这里以.NET 的Betalgo.OpenAI.GPT3
为例,详细的配置部分不再赘述,可参考其说明文档。
//使用CreateCompletionAsStream获取 completions
var completions = openAIService.Completions.CreateCompletionAsStream(new OpenAI.GPT3.ObjectModels.RequestModels.CompletionCreateRequest
Prompt = BuildPrompt(input.Prompt),
MaxTokens = 100,
Temperature = 0.5f,
TopP = 1,
FrequencyPenalty = 0,
PresencePenalty = 0,
StopAsList = new List<string> "Q:", "A:"
, Models.TextDavinciV3);
//将返回内容直接经过UTF编码写入Response
async Task ResponseWrite(string? text)
if (text == null) return;
await Response.Body.WriteAsync(Encoding.UTF8.GetBytes(text));
await Response.Body.FlushAsync();
//逐个获取 completion的返回,并写入到Response中
await foreach (var completionResponse in completions)
if (completionResponse.Successful)
await ResponseWrite(completionResponse.Choices[0].Text);
else
await ResponseWrite("<ERR>");
if(completionResponse.Error != null)
await ResponseWrite(completionResponse.Error.Code);
await ResponseWrite(completionResponse.Error.Message);
else
await ResponseWrite("<unknow>");
其中最核心的一点就是 ResponseWrite 部分,提前将内容写入到Response的Body中,并进行Flush。
另外需要注意的就是,Action 不能再有返回值(如果是.NET 7 的话,可以返回 Empty),因为已经在Action结束之前向Response写入了内容,再有返回值的话,就会报错。
前端的流式处理
同样的,后端作为流式发送,前端就需要以流式形式接收。
这里不需要使用到EventSource、WebSocket或是其他的实时通讯框架,仅需要使用普通的fetch即可。
async function send()
const input = document.getElementById("input").value;
const output = document.getElementById("output");
output.innerText = "";
const url = "/api/stream";
const data = "Prompt": input ;
//直接获取 Fetch 的response, 无法使用 await的话, Promise的方式也是可以的。
const response = await fetch(url,
method: "POST",
body: JSON.stringify(data),
headers:
"Content-Type": "application/json"
)
//获取UTF8的解码
const encode = new TextDecoder("utf-8");
//获取body的reader
const reader = response.body.getReader();
// 循环读取reponse中的内容
while (true)
const done, value = await reader.read();
if (done)
break;
// 解码内容
const text = encode.decode(value);
// 当获取错误token时,输出错误信息
if (text === "<ERR>")
output.innerText = "Error";
break;
else
// 获取正常信息时,逐字追加输出
output.innerText += text;
fetch获取的response可以,可以通过 response.body.getReader() 获取reader,然后循环获取reader中的响应,根据情况,将响应内容追加到界面上,就实现了逐字打印的效果了。
相关链接
- 以上示例代码,可参见 GPT3_demo
- 想要了解如何理解OpenAI的API,可参考打造自己的ChatGPT:OpenAI 的API接入技巧
- OpenAI 官方对于延迟处理的一些意见improving-latencies
- Dotnet SDK for OpenAI GPT-3 and DALL·E
以上是关于使用 Azure OpenAI 打造自己的 ChatGPT的主要内容,如果未能解决你的问题,请参考以下文章
基于ChatGPT+Python快速打造前后端分离的OpenAI人工智能聊天机器人
企业级 Azure OpenAI ChatGPT 服务发布(国际预览版)