Skip to content

Commit

Permalink
go: 新增 Raw 请求方式 (#788)
Browse files Browse the repository at this point in the history
* 新增 Raw 请求

* 增加 Go SDK Lite-V 使用示例

* 增加 Go SDK Plugin 使用示例

* Update plugin.md

---------

Co-authored-by: NuODaniel <[email protected]>
  • Loading branch information
Dobiichi-Origami and danielhjz authored Sep 10, 2024
1 parent 0038584 commit 8645d2f
Show file tree
Hide file tree
Showing 12 changed files with 287 additions and 12 deletions.
72 changes: 72 additions & 0 deletions docs/go/how_to_use/plugin.md
Original file line number Diff line number Diff line change
@@ -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": `['\''牛奶的营养成本有哪些<file>浅谈牛奶的营养与消费趋势.docx</file><url>https://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</url>'\'']`,
},
},
"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)
}
```

135 changes: 135 additions & 0 deletions docs/go/how_to_use/use_lite-v_model.md
Original file line number Diff line number Diff line change
@@ -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)
}
```

68 changes: 68 additions & 0 deletions go/qianfan/base_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -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数
Expand All @@ -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"` // 错误码
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
4 changes: 2 additions & 2 deletions go/qianfan/chat_completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions go/qianfan/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion go/qianfan/console_action.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion go/qianfan/embdding.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
4 changes: 2 additions & 2 deletions go/qianfan/requestor.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand All @@ -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)
}

Expand Down
2 changes: 1 addition & 1 deletion go/qianfan/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
2 changes: 1 addition & 1 deletion go/qianfan/text2img.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
Loading

0 comments on commit 8645d2f

Please sign in to comment.