故事背景 前几天上线了自己的 web 终端项目 – https://www.weirdo-terminal.com/
由于后端是通过微信云托管部署的, 导致上线版本无法使用 chatGPT 服务, 啊 – 这样我也就放弃部署了
正好今天, 有位同志在我项目下提了一个问题
我瞬间懵逼, 啊? 我咋没想到, 到官网看了看调用方法, 和 gpt 是差不多的。
那话不多说, 如何快速通过 Node.js 调用文心一言 API , 接下来你就知道咯~~
API 的调用流程如下图所示。
创建一个千帆应用。根据实际需求创建千帆应用,创建成功后,获取AppID、API Key、Secret Key 等信息。
API 授权。对应用的 AppID 进行授权。
获取接口访问凭证 access_token 。根据第1步获取的 API Key 和 Secret Key ,调用获取access_token 接口获取 access_token ,通过 access_token 鉴权调用者身份。
调用API接口。例如调用ERNIE-Bot相关接口,详见API列表 。
登录 登录百度智能云千帆控制台。
注册并登录百度智能云千帆控制台 。
创建应用 创建千帆应用
进入控制台创建应用 。
获取 key 创建应用后,获取AppID、API Key、Secret Key。
上图则是我的 api key 和 secret key
得到 Access Token 这两个值的作用是用来获取 Access Token,Access Token 是调用文心 API 的必需参数。Access Token 是通过将 API Key 和 Secret Key 作为参数请求一个独立的接口得到。本文用 axios 作为 Node 端的网络请求库,下面的函数用来请求接口,拿到 token:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import axios from 'axios' ;const API_KEY = '<API Key>' ;const SECRET_KEY = '<Secret Key>' ;const ACCESS_TOKEN_URL = 'https://aip.baidubce.com/oauth/2.0/token' ;async function fetchAccessToken ( ) { const accessTokenRes = await axios.post (ACCESS_TOKEN_URL , null , { params : { 'grant_type' : 'client_credentials' , 'client_id' : API_KEY , 'client_secret' : SECRET_KEY , }, }); return accessTokenRes.data .access_token ; }
及时更新token Access Token 的有效期是 30 天,需要及时更新,在一个需要持久运行的 Node 应用里,最好把 Access Token 和它对应的生成时间成对记录,以便在 token 过期之前及时更新:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 let accessToken = { expiredTime : 0 , value : '' , };async function getAccessToken ( ) { if (accessToken.value && Date .now () < accessToken.expiredTime ) { return accessToken.value ; } const token = await fetchAccessToken (); accessToken = { expiredTime : Date .now () + 29 * 86400 * 1000 , value : token, }; return token; }
接下来便是重头戏了, 调用文心一言的服务
调用 ERNIT-Bot API 千帆平台上有多个模型的 API 可以调用,不同 API 用到的参数比较类似,这里用最基本的 ERNIT-Bot API 来做示例。
Access Token 和对话信息是唯二的必填参数,前者以 query 的形式传入,后者则是作为 POST 请求体。
下面是一个简单的调用示例:
1 2 3 4 5 6 7 8 9 const CHAT_URL = 'https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/completions' ;async function ask (question ) { const messages = [{ role : 'user' , content : question }] const token = await getAccessToken () const res = await axios.post (CHAT_URL , { messages }, { params : { access_token : token } }) const { data } = res return data }
测试一下
1 2 3 4 5 6 7 async function main ( ) { const question = '我是最帅的!' const res = await ask (question) console .log (res) }main ();
可以看到,返回的内容里不仅包括回答的文本,还包括占用 token 数(与计费相关)、回答是否有被截断的等信息。
实现多轮对话 OpenAI API 多轮对话是通过维护一个固定 conversation id 的形式实现的,文心 API 则有所不同,要实现多轮对话,需要在调用接口时携带上之前所有的提问和回答。比如最开始我们提问了「把我接下来说的话都翻译成英文」,文心回答「好的,我会尽力把您接下来想要表达的内容翻译成英文。请随时告诉我您想要说的话。」,那么我们再一次提问的时候,message 参数就需要是:
1 2 3 4 5 [ { role : 'user' , content : '把我接下来说的话都翻译成英文' }, { role : 'assistant' , content : '好的,我会尽力把您接下来想要表达的内容翻译成英文。请随时告诉我您想要说的话。' }, { role : 'user' , content : '你好,我是一名程序员。' } ]
这里是通过每次加入一条前端传入的对话历史和当前请求的信息, 这样就能成功实现记忆功能
1 2 3 4 5 6 7 8 async function ask (memory, message ) { const token = await getAccessToken () const messages = memory messages.push ({ role : 'user' , content : message }) const res = await axios.post (CHAT_URL , { messages }, { params : { access_token : token } }) const { data } = res return data.result }
下面是前端的请求函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 export const getBotOutput = async (message: string ) => { if (!message) return null let botStore = useBotStore () let { memory } = botStore let res : any = await myAxios.post ('/bot/get' , { message, memory }) res = res.data botStore.addRecord ({ role : 'user' , content : message }) botStore.addRecord ({ role : 'assistant' , content : res }) return res }
这个 res 就是我们获取的值了. 通过模板将回复的内容渲染到页面中即可。
这样便能请求到文心一言服务啦~~
这是我的项目地址 ~~ https://github.com/2WeirDo/weirdo_terminal ~~ 感兴趣的朋友们欢迎star哦~ ⭐⭐⭐