部署企业级ChatGPT,将AI整合进工作

cybozu发表于:2023年07月24日 17:04:46更新于:2023年09月12日 13:44:04

Index

引言

3月份AI应用大爆发催生了国内大量需求。

然而,所有的需求都不可避免得遇到很多非技术性的问题:

  • 部署开源模型的成本巨大,且效果成谜,65B的模型推理应用最少需要130G显存,而微调训练则需要额外添加8倍的资源。

  • ChatGPT官方API不对中国用户开放,且续费无法使用国内信用卡。强行使用存在法律隐患。

  • 企业用户对安全隐私存在更高的要求。


要解决上面问题,允许私有部署的云服务厂商无疑是最佳选择。

微软作为OpenAI的主要投资者之一,早在2021年11月就推出了Azure OpenAI 服务,支持模型的私有部署,并由Azure来提供安全保证。

在定价方面,Azure OpenAI和OpenAI官方一致,且不限制使用中国信用卡付费。

在网络访问层面,Azure的服务并没有被限制。


  caution  注意

  1.本文仅提供技术指导,不提供任何商业服务。
  2.Azure国际版是否存在其他法律风险,请咨询专业法务人士。
  3.截止2023年7月24日,有消息称美国政府准备限制中国公司使用美国云计算服务。到时候Azure OpenAI是否会受到影响,尚未可知。


申请

声明

本文省略申请Azure国际版账号和绑定信用卡的步骤。如若尚未申请,请参照此网页进行。这里将不再赘述。

再次强调:提供OpenAI服务的是国际版Azure,而不是国内版。


申请步骤

截止2023年7月24日,Azure OpenAI服务仅开放企业用户申请,需要在此处进行填表。

所有的信息请以英文如实填写

需要特别注意的事项如下:

1.目前只支持企业邮箱,当前Azure对于企业邮箱的认定规则为:邮箱的域名必须和第12条的Company Website域名一致。

00164be48cfad3c3fd82c903d133971

00164be48f571de103636554e48e843

比如,如果你所在公司的网页为xxx.abc.com,那么你的企业邮箱必须为yy@abc.com。


2.第22条的OpenAI service feature请只选择Text and code models,这个是大语言模型。

00164be4981e2752b564dddc0a586ef

DALL-E 2是OpenAI画图模型。一旦勾选会增加额外的审核流程。


3.第23条的Select your use case(s),需要覆盖你的AI模型的应用场景,请按需选择。

00164be49ca0205addd6597f0d79096


4.提交申请后,你会在10个工作日内收到核审通过的邮件。

00164be4a3d21c33b5d0b32d77033b5

而审核失败的话,则会列出失败原因。

00164be4a6f9c759a15bebd3098311e

可选操作

通过审核后,你可以再申请GPT4模型的部署权限。


部署

获得权限后,我们进入Azure主页,点击创建资源

00164be4bb0682c68b73ff2d814387f

搜索OpenAI,点击创建->Azure OpenAI。

00164be4c12eb5c942dab6ace241796


在自己的订阅下新建一个资源组,区域选择离我们最近的地域,名称随意,定价层选标准的即可。

00164be4cbfbf2db85f45f2f2ce24ed


一直点击下一步。

作为演示,我们使用默认配置,有其他需求的,请按照自己的需求进行定制。


点击服务名称进入详细画面。

00164be4d70097adbc6f86b0eb09af1


点击模型部署,前往部署画面。

00164be4da8a38ce2c1f7eb9580b944


点击管理部署,进入Azure OpenAI Studio。

00164be4e3b53a4c1976c5c9e8901ed

点击新建部署,按需选择gpt模型,添加部署名,按需更改默认值,最后创建。

00164be4eb70c1b46c50698eb69c252

部署成功后,勾选部署模型,点击在操场中打开。

00164be4f07bbbe0e43db32f2cece55

进入调试画面后,点击查看代码。

00164c89e7aa2e0a5cc4745aa82ef71

复制终结点,这些信息会在我们接下来的应用实例中用到。

00164c89efc865088f4e95f72a8ede8

应用

部署

接下来我们将演示一个实际的案例,将ChatGPT服务整合进kintone。

同比环比数据可视化这个Demo为基础,我们为其添加AI分析功能。

源码已上传至Github。请下载到本地。

将之前复制的终结点的值,粘贴到src目录下的index.js

00164c8b577246fccb71cb6642a8b5d

在项目根目录下运行以下指令:

npm i && npm run build


dist目录下的成果物上传到kintone。

我们能看到如下效果:

00164c8b79d0d5d60f35fa34a7ea52d

原理

本质上,目前所有的GPT应用,都是让ChatGPT担任翻译工作。

翻译并不单单是自然语言之间的互译,也包含自然语言到计算机程序、数字到自然语言的翻译。

在上面的案例中,我们利用Prompt Engineering,对GPT的输出内容进行控制

{role: 'system',content: `I want you to act as an ${role} and translator. I can communicate with you in any language you prefer. Based on the data my provide, You will respond to my questions in my chosen language.`,},
{role: 'user',content: `I need a concrete conceptual plan. Use the following data to provide an answer to the question: "${input}"         
//Today is ${new Date().toISOString().slice(0, 10)} and ${datas}`,},


由于Azure的Restful API本身默认是跨域的,我们不需要使用kintone.proxy中转,可以直接用使用fetch。

但是如果我们想做到1个个单词输出的效果,就必须在request中设定steam,也就是SSE。

{
method: 'POST',
mode: 'cors',
headers: { 'api-key': apikey, 'Content-Type': 'application/json' },
body: JSON.stringify({messages: [
      {role: 'system',content: `I want you to act as an ${role} and translator. I can communicate with you in any language you prefer. Based on the data my provide, You will respond to my questions in my chosen language.`,},
      {role: 'user',content: `I need a concrete conceptual plan. Use the following data to provide an answer to the question: "${input}"         //Today is ${new Date().toISOString().slice(0, 10)} and ${datas}         `,},],
max_tokens: 800,
temperature: 0.7,
frequency_penalty: 0,
presence_penalty: 0,
top_p: 0.95,
stream: true,
}

利用微软的@microsoft/fetch-event-source,我们可以简单的在画面上接受SSE的每个message。

onmessage(ev) {
const msg = JSON.parse(ev.data).choices[0]?.delta?.content
if (msg) {
if (!txtel) {
txtel = document.createElement('p')
txtel.className = 'anwser'
el.appendChild(txtel)
}
const word = document.createElement('span')
word.className = 'spantxt'
word.style.animationDelay = `${index * 0.01}s`
word.textContent = msg
txtel.appendChild(word)
index += 1
if (msg.includes('\n')) {
txtel = undefined
}
}
},

最后利用css的animationDelay,将每个单词延迟输出,实现逐字输出的视觉效果。

word.style.animationDelay = `${index * 0.01}s`