百度的文心一言推出来也有一段时间了,但是接口部分一直没有公开,需要进行申请
最近,有朋友提供了文心千帆大模型的api权限,拿到了必须的参数,现在就来测试一下
下面是使用golang封装的文心千帆 ERNIE-Bot-turbo模型的调用示例
ERNIE-Bot-turbo.go
package lib
import (
"bufio"
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/tidwall/gjson"
"io/ioutil"
"net/http"
"strings"
)
//百度文心一言ERNIE-Bot-turbo
type ErnieBotTurbo struct {
AppId string
ApiKey string
SecretKey string
AccessToken string
}
func NewErnieBotTurbo(appId, apiKey, secretKey string) (*ErnieBotTurbo, error) {
m := &ErnieBotTurbo{
AppId: appId,
ApiKey: apiKey,
SecretKey: secretKey,
}
var err error
m.AccessToken, err = m.GenerateAccessToken()
if err != nil {
return m, err
}
return m, nil
}
//获取access_token
func (this *ErnieBotTurbo) GenerateAccessToken() (string, error) {
url := fmt.Sprintf("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s",
this.ApiKey,
this.SecretKey)
// 创建POST请求
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println("创建请求失败:", err)
return "", err
}
// 发送请求
client := http.Client{}
response, err := client.Do(req)
if err != nil {
fmt.Println("发送请求失败:", err)
return "", err
}
defer response.Body.Close()
// 读取响应
responseBody, err := ioutil.ReadAll(response.Body)
if err != nil {
return "", err
}
accessToken := gjson.Get(string(responseBody), "access_token").String()
if accessToken == "" {
return "", errors.New("获取access_token失败")
}
this.AccessToken = accessToken
return accessToken, nil
}
//流式请求接口
func (this *ErnieBotTurbo) StreamChat(messages []map[string]string) (*bufio.Reader, error) {
url := fmt.Sprintf("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=" + this.AccessToken)
// 构建请求参数
params := map[string]interface{}{
"messages": messages,
"stream": true,
}
// 创建HTTP请求的body
jsonParams, err := json.Marshal(params)
requestBody := bytes.NewBuffer(jsonParams)
// 创建POST请求
req, err := http.NewRequest("POST", url, requestBody)
if err != nil {
fmt.Println("创建请求失败:", err)
return nil, err
}
// 设置请求头
//req.Header.Set("Access", "text/event-stream")
// 发送请求
client := http.Client{}
response, err := client.Do(req)
if err != nil {
fmt.Println("发送请求失败:", err)
return nil, err
}
//defer response.Body.Close()
// 读取响应
// 读取响应体数据
reader := bufio.NewReader(response.Body)
return reader, nil
}
func (this *ErnieBotTurbo) StreamRecv(reader *bufio.Reader) (string, error) {
waitForData:
line, err := reader.ReadString('\n')
if err != nil {
return "", err
}
// 处理每行数据
line = strings.TrimSpace(line)
if line == "" {
goto waitForData
}
// 根据冒号分割每行数据的键值对
parts := strings.SplitN(line, ":", 2)
if len(parts) != 2 {
return "", errors.New("数据格式错误")
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
// 根据键的不同处理不同的字段
switch key {
case "data":
// 设置Event的数据
return value, nil
//case "meta":
// // 解析JSON格式的元数据
// return value, nil
}
goto waitForData
//return "", errors.New("finish")
}
//流式请求接口
func (this *ErnieBotTurbo) Embedding(input []string) (string, error) {
url := fmt.Sprintf("https://aip.baidubce.com/rpc/2.0/ai_custom/v1/wenxinworkshop/embeddings/embedding-v1?access_token=" + this.AccessToken)
// 构建请求参数
params := map[string]interface{}{
"input": input,
}
// 创建HTTP请求的body
jsonParams, err := json.Marshal(params)
requestBody := bytes.NewBuffer(jsonParams)
// 创建POST请求
req, err := http.NewRequest("POST", url, requestBody)
if err != nil {
fmt.Println("创建请求失败:", err)
return "", err
}
// 设置请求头
//req.Header.Set("Access", "text/event-stream")
// 发送请求
client := http.Client{}
response, err := client.Do(req)
if err != nil {
fmt.Println("发送请求失败:", err)
return "", err
}
defer response.Body.Close()
// 读取响应
responseBody, err := ioutil.ReadAll(response.Body)
if err != nil {
return "", err
}
return string(responseBody), nil
}
测试用例,获取access_token是需要进行缓存的,过期时间是二十多天,但是如果使用流式调用聊天接口,接口里获取不到access_token过期的错误码
所以,先每次都调取access_token,目前没看到有频率限制
package lib
import (
"log"
"testing"
)
//测试获取access_token
func TestErnieBotTurboGenerateAccessToken(t *testing.T) {
AppID := "35662533"
APIKey := "Iq1FfkOQIGtMtZqRFxOrvq6T"
SecretKey := "qbzsoFAUSl8UGt1GkGSDSjENtqsjrOTC"
m, err := NewErnieBotTurbo(AppID, APIKey, SecretKey)
log.Println(m.AccessToken, err)
}
//测试流式输出
func TestErnieBotTurboStreamChat(t *testing.T) {
AppID := "xxxx"
APIKey := "xxxxxxx"
SecretKey := "xxxxxxxxxjrOTC"
m, _ := NewErnieBotTurbo(AppID, APIKey, SecretKey)
system := "假设你是一个程序员,你是程序员老狼的数字分身,你擅长计算机互联网程序开发,你的微信:llike620,官网:gofly.v1kf.com。你开发了唯一客服系统,你了解唯一客服系统的各种问题,你的回答应该是简洁的、不要超过50字。你只能根据知识信息回答问题。你绝对不能暴露自己是个"人工智能、大模型、AI、机器人、GPT"。如果用户问题里有自己联系方式,请回复"稍等,我们马上联系您"。请检测问题语种,并用该语种回答问题."
prompt := []map[string]string{{"role": "user", "content": system + "我的问题是:你是谁"}}
res, _ := m.StreamChat(prompt)
for {
str, err := m.StreamRecv(res)
if err != nil {
log.Println(err)
break
}
log.Println(str, err)
}
}
//测试Embedding
func TestErnieBotTurboEmbedding(t *testing.T) {
AppID := "xxxxxxx"
APIKey := "xxxxxxxxxxq6T"
SecretKey := "qxxxxxxxsoFAxxxxxxxxxxxxxxxxxxxC"
m, _ := NewErnieBotTurbo(AppID, APIKey, SecretKey)
prompt := []string{"我的问题是:你是谁"}
res, err := m.Embedding(prompt)
log.Println(res, err)
}