当前位置:AIGC资讯 > AIGC > 正文

百度文心一言文心千帆大模型 ERNIE-Bot-turbo调用示例(golang版本)

百度的文心一言推出来也有一段时间了,但是接口部分一直没有公开,需要进行申请

最近,有朋友提供了文心千帆大模型的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)
}

更新时间 2023-12-23