diff --git a/docs/go/how_to_use/plugin.md b/docs/go/how_to_use/plugin.md
new file mode 100644
index 00000000..bea409ee
--- /dev/null
+++ b/docs/go/how_to_use/plugin.md
@@ -0,0 +1,72 @@
+# 在千帆 Go SDK 中使用插件
+
+# 0. 准备工作
+
+为了使用插件功能,我们需要:
+
+a. 安装千帆 Go SDK
+
+```shell
+go get github.com/baidubce/bce-qianfan-sdk/go/qianfan
+```
+
+b. 导入相关包
+
+```go
+import (
+ "github.com/baidubce/bce-qianfan-sdk/go/qianfan"
+)
+```
+
+c. 设置好百度智能云的 Access Key 和 Secret Key
+
+```shell
+export QIANFAN_ACCESS_KEY=""
+export QIANFAN_SECRET_KEY=""
+```
+
+# 1. 初始化
+
+我们需要先初始化好所需要使用到的千帆 SDK 对象
+
+```
+qianfanClient := qianfan.NewBaseModel()
+```
+
+# 2. 构造插件请求
+
+我们可以使用千帆 Go SDK 提供的接口来自行拼接请求参数,以使用 `ChatFilePlus` 插件为例:
+
+```
+request, _ := qianfan.NewModelRequest(
+ "POST",
+ "/rpc/2.0/ai_custom/v1/wenxinworkshop/erniebot/plugin",
+ qianfan.RawRequest{
+ "messages": []map[string]any{
+ {
+ "role": "user",
+ "content": `['\''牛奶的营养成本有哪些浅谈牛奶的营养与消费趋势.docxhttps://qianfan-doc.bj.bcebos.com/chatfile/%E6%B5%85%E8%B0%88%E7%89%9B%E5%A5%B6%E7%9A%84%E8%90%A5%E5%85%BB%E4%B8%8E%E6%B6%88%E8%B4%B9%E8%B6%8B%E5%8A%BF.docx'\'']`,
+ },
+ },
+ "plugins": []string{
+ "ChatFilePlus",
+ },
+ },
+)
+```
+
+# 3. 发送请求并获取结果
+
+在使用 `BaseModel` 调用 `Do` 进行请求时,返回值是一个代表了响应结果的 `RawResponse` 对象。用户可以使用 `json.Unmarshal` 方法将响应结果反序列化为一个 `map[string]any` 对象,方便后续处理
+
+```
+resp, err := qianfanClient.Do(context.Background(), request)
+if err != nil {
+ fmt.Println(err)
+} else {
+ result := make(map[string]any)
+ json.Unmarshal(resp.Body, &result)
+ fmt.Println(result)
+}
+```
+
diff --git a/docs/go/how_to_use/use_lite-v_model.md b/docs/go/how_to_use/use_lite-v_model.md
new file mode 100644
index 00000000..f820ad86
--- /dev/null
+++ b/docs/go/how_to_use/use_lite-v_model.md
@@ -0,0 +1,135 @@
+# 在千帆 Go SDK 中使用 Lite-V 模型
+
+Lite-V 模型是百度针对多模态场景打造的一款模型。本文将介绍如何在千帆 Go SDK 中使用 Lite-V 模型。
+
+# 0. 准备工作
+
+为了使用 Lite-V 模型,我们需要:
+
+a. 安装千帆 Go SDK 和百度智能云 Bos SDK
+
+```shell
+go get github.com/baidubce/bce-qianfan-sdk/go/qianfan
+go get github.com/baidubce/bce-sdk-go/services/bos
+```
+
+b. 导入相关包
+
+```go
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "image"
+ _ "image/jpeg"
+ "os"
+
+ "github.com/baidubce/bce-qianfan-sdk/go/qianfan"
+ "github.com/baidubce/bce-sdk-go/services/bos"
+)
+```
+
+c. 设置好百度智能云的 Access Key 和 Secret Key 以及相关环境变量
+
+Go:
+```
+var (
+ ak = "" // 百度智能云的 Access Key
+ sk = "" // 百度智能云的 Secret Key
+ bucket = "" // 存储图片的 BOS Bucket
+ bucketImagePath = "" // BOS Bucket 中的图片路径
+ localImagePath = "" // 本地图片的路径
+)
+```
+
+Shell:
+```shell
+export QIANFAN_ACCESS_KEY=""
+export QIANFAN_SECRET_KEY=""
+```
+
+# 1. 初始化
+
+我们需要先初始化好所需要使用到的千帆 SDK 和 Bos SDK 客户端对象
+
+```
+qianfanClient := qianfan.NewBaseModel()
+bosClient, err := bos.NewClient(ak, sk, "")
+if err != nil {
+ panic(err)
+}
+```
+
+# 2. 读取图片并上传到 BOS
+
+为了使用 Lite-V 模型的多模态功能,我们需要将其上传到可被访问的服务之中。并且使用传递 URL 的方式来让 Lite-V 模型来读取该图片
+
+```go
+imageFile, err := os.Open(localImagePath)
+if err != nil {
+ panic(err)
+}
+defer imageFile.Close()
+
+imageConfig, _, err := image.DecodeConfig(imageFile)
+if err != nil {
+ panic(err)
+}
+
+imageHeight := imageConfig.Height
+imageWidth := imageConfig.Width
+
+if _, err = bosClient.PutObjectFromFile(bucket, bucketImagePath, localImagePath, nil); err != nil {
+ panic(err)
+}
+
+url := bosClient.BasicGeneratePresignedUrl(bucket, bucketImagePath, 120)
+```
+
+# 3. 请求 Lite-V 模型
+
+我们可以使用千帆 Go SDK 提供的接口来自行拼接请求参数,实现对 Lite-V 模型的灵活请求,以上面的图片举例:
+
+```
+request, _ := qianfan.NewModelRequest(
+ "POST",
+ "/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/ernie-lite-v",
+ qianfan.RawRequest{
+ "messages": []map[string]any{
+ {
+ "role": "user",
+ "content": []map[string]any{
+ {
+ "type": "image_url",
+ "image_url": map[string]any{
+ "image_width": imageWidth,
+ "image_height": imageHeight,
+ "url": url,
+ },
+ },
+ {
+ "type": "text",
+ "text": "这个图片展示了什么",
+ },
+ },
+ },
+ },
+ },
+)
+```
+
+# 4. 发送请求并获取结果
+
+在使用 `BaseModel` 调用 `Do` 进行请求时,返回值是一个代表了响应结果的 `RawResponse` 对象。用户可以使用 `json.Unmarshal` 方法将响应结果反序列化为一个 `map[string]any` 对象,方便后续处理
+
+```
+resp, err := qianfanClient.Do(context.Background(), request)
+if err != nil {
+ fmt.Println(err)
+} else {
+ result := make(map[string]any)
+ json.Unmarshal(resp.Body, &result)
+ fmt.Println(result)
+}
+```
+
diff --git a/go/qianfan/base_model.go b/go/qianfan/base_model.go
index 958ca1c2..3369342d 100644
--- a/go/qianfan/base_model.go
+++ b/go/qianfan/base_model.go
@@ -32,6 +32,10 @@ type BaseModel struct {
*Requestor // Requstor 作为基类
}
+func NewBaseModel(options ...Option) *BaseModel {
+ return &BaseModel{Requestor: newRequestor(makeOptions(options...))}
+}
+
// 使用量信息
type ModelUsage struct {
PromptTokens int `json:"prompt_tokens"` // 问题tokens数
@@ -44,6 +48,26 @@ type ModelAPIResponse interface {
ClearError()
}
+type RawRequest map[string]any
+
+func (r RawRequest) SetExtra(extra map[string]any) {
+ r["extra"] = extra
+}
+
+func (r RawRequest) GetExtra() map[string]any {
+ extra, ok := r["extra"]
+ if !ok {
+ return make(map[string]any)
+ } else {
+ return extra.(map[string]any)
+ }
+}
+
+type RawResponse struct {
+ baseResponse `json:",omitempty"`
+ ModelAPIError `json:",omitempty"`
+}
+
// API 错误信息
type ModelAPIError struct {
ErrorCode int `json:"error_code"` // 错误码
@@ -179,6 +203,33 @@ func (s *ModelResponseStream) Recv() (*ModelResponse, error) {
return &resp, nil
}
+type RawModelResponseStream struct {
+ *ModelResponseStream
+}
+
+func newRawModelResponseStream(si *streamInternal) (*RawModelResponseStream, error) {
+ s := &RawModelResponseStream{}
+ mrs, err := newModelResponseStream(si)
+ if err != nil {
+ return s, err
+ }
+
+ s.ModelResponseStream = mrs
+ return s, nil
+}
+
+func (s *RawModelResponseStream) Recv() (*RawResponse, error) {
+ var resp RawResponse
+ err := s.streamInternal.Recv(&resp)
+ if err != nil {
+ return nil, err
+ }
+ if err = checkResponseError(&resp); err != nil {
+ return &resp, err
+ }
+ return &resp, nil
+}
+
func checkResponseError(resp ModelAPIResponse) error {
errCode, errMsg := resp.GetError()
if errCode != 0 {
@@ -272,3 +323,20 @@ func isUnsupportedModelError(err error) bool {
}
return false
}
+
+func (m *BaseModel) Do(ctx context.Context, request *QfRequest) (*RawResponse, error) {
+ rawResponse := &RawResponse{}
+ if err := m.requestResource(ctx, request, rawResponse); err != nil {
+ return nil, err
+ }
+ return rawResponse, nil
+}
+
+func (m *BaseModel) Stream(ctx context.Context, request *QfRequest) (*RawModelResponseStream, error) {
+ request.Body["stream"] = true
+ si, err := m.requestStream(ctx, request)
+ if err != nil {
+ return nil, err
+ }
+ return newRawModelResponseStream(si)
+}
diff --git a/go/qianfan/chat_completion.go b/go/qianfan/chat_completion.go
index 07945ceb..6b34cd89 100644
--- a/go/qianfan/chat_completion.go
+++ b/go/qianfan/chat_completion.go
@@ -316,7 +316,7 @@ func (c *ChatCompletion) do(ctx context.Context, request *ChatCompletionRequest)
c.processWithInputLimit(ctx, request, url)
- req, err := newModelRequest("POST", url, request)
+ req, err := NewModelRequest("POST", url, request)
if err != nil {
return nil, err
}
@@ -368,7 +368,7 @@ func (c *ChatCompletion) stream(ctx context.Context, request *ChatCompletionRequ
c.processWithInputLimit(ctx, request, url)
request.SetStream()
- req, err := newModelRequest("POST", url, request)
+ req, err := NewModelRequest("POST", url, request)
if err != nil {
return nil, err
}
diff --git a/go/qianfan/completion.go b/go/qianfan/completion.go
index fc8bafaa..9a9200ff 100644
--- a/go/qianfan/completion.go
+++ b/go/qianfan/completion.go
@@ -145,7 +145,7 @@ func (c *Completion) do(ctx context.Context, request *CompletionRequest) (*Model
if err != nil {
return nil, err
}
- req, err := newModelRequest("POST", url, request)
+ req, err := NewModelRequest("POST", url, request)
if err != nil {
return nil, err
}
@@ -195,7 +195,7 @@ func (c *Completion) stream(ctx context.Context, request *CompletionRequest) (*M
return nil, err
}
request.SetStream()
- req, err := newModelRequest("POST", url, request)
+ req, err := NewModelRequest("POST", url, request)
if err != nil {
return nil, err
}
diff --git a/go/qianfan/console_action.go b/go/qianfan/console_action.go
index 24f67b45..cd39bc87 100644
--- a/go/qianfan/console_action.go
+++ b/go/qianfan/console_action.go
@@ -30,7 +30,7 @@ func (ca *ConsoleAction) Call(ctx context.Context, route string, action string,
reqBody := BaseRequestBody{
Extra: params,
}
- req, err := newConsoleRequest("POST", ca.baseActionUrl(route, action), &reqBody)
+ req, err := NewConsoleRequest("POST", ca.baseActionUrl(route, action), &reqBody)
if err != nil {
logger.Error("new console req error", err)
return nil, err
diff --git a/go/qianfan/embdding.go b/go/qianfan/embdding.go
index 1dee1f9d..4095801b 100644
--- a/go/qianfan/embdding.go
+++ b/go/qianfan/embdding.go
@@ -118,7 +118,7 @@ func (c *Embedding) do(ctx context.Context, request *EmbeddingRequest) (*Embeddi
if err != nil {
return nil, err
}
- req, err := newModelRequest("POST", url, request)
+ req, err := NewModelRequest("POST", url, request)
if err != nil {
return nil, err
}
diff --git a/go/qianfan/requestor.go b/go/qianfan/requestor.go
index f07f50fe..da3eb6a7 100644
--- a/go/qianfan/requestor.go
+++ b/go/qianfan/requestor.go
@@ -97,7 +97,7 @@ type QfRequest struct {
}
// 创建一个用于模型类请求的 Request
-func newModelRequest(method string, url string, body RequestBody) (*QfRequest, error) {
+func NewModelRequest(method string, url string, body RequestBody) (*QfRequest, error) {
return newRequest(modelRequest, method, url, body)
}
@@ -107,7 +107,7 @@ func newAuthRequest(method string, url string, body RequestBody) (*QfRequest, er
}
// 创建一个用于管控类请求的 Request
-func newConsoleRequest(method string, url string, body RequestBody) (*QfRequest, error) {
+func NewConsoleRequest(method string, url string, body RequestBody) (*QfRequest, error) {
return newRequest(consoleRequest, method, url, body)
}
diff --git a/go/qianfan/service.go b/go/qianfan/service.go
index 8d627bd8..30d77503 100644
--- a/go/qianfan/service.go
+++ b/go/qianfan/service.go
@@ -42,7 +42,7 @@ type ServiceListItemVersion struct {
func (service *Service) List(ctx context.Context, request *ServiceListRequest) (*ServiceListResponse, error) {
var s ServiceListResponse
- req, err := newConsoleRequest("POST", serviceListURL, request)
+ req, err := NewConsoleRequest("POST", serviceListURL, request)
if err != nil {
return nil, err
}
diff --git a/go/qianfan/text2img.go b/go/qianfan/text2img.go
index 41128477..4de85a35 100644
--- a/go/qianfan/text2img.go
+++ b/go/qianfan/text2img.go
@@ -121,7 +121,7 @@ func (c *Text2Image) do(ctx context.Context, request *Text2ImageRequest) (*Text2
if err != nil {
return nil, err
}
- req, err := newModelRequest("POST", url, request)
+ req, err := NewModelRequest("POST", url, request)
if err != nil {
return nil, err
}
diff --git a/go/qianfan/tokenizer.go b/go/qianfan/tokenizer.go
index 4d5fa9ac..1daccd00 100644
--- a/go/qianfan/tokenizer.go
+++ b/go/qianfan/tokenizer.go
@@ -87,7 +87,7 @@ func (t *Tokenizer) remoteCountTokensEB(text string, model string) (int, error)
Model: model,
}
- req, err := newModelRequest("POST", modelAPIPrefix+"/tokenizer/erniebot", request)
+ req, err := NewModelRequest("POST", modelAPIPrefix+"/tokenizer/erniebot", request)
if err != nil {
return -1, err
}
diff --git a/go/qianfan/version.go b/go/qianfan/version.go
index fd08a6b7..154c12df 100644
--- a/go/qianfan/version.go
+++ b/go/qianfan/version.go
@@ -26,5 +26,5 @@
package qianfan
// SDK 版本
-const Version = "v0.0.11"
+const Version = "v0.0.12"
const versionIndicator = "qianfan_go_sdk_" + Version