ai_scheduler/internal/tools/public/coze_express.go

141 lines
3.5 KiB
Go

package public
import (
"ai_scheduler/internal/config"
"ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg"
"ai_scheduler/internal/pkg/utils_ollama"
"context"
"encoding/json"
"fmt"
"github.com/ollama/ollama/api"
"github.com/coze-dev/coze-go"
)
type CozeExpress struct {
cozeApi coze.CozeAPI
config config.ToolConfig
llm *utils_ollama.Client
}
// NewCozeExpress 创建 CozeExpress 实例
func NewCozeExpress(config config.ToolConfig, llm *utils_ollama.Client) *CozeExpress {
return &CozeExpress{
cozeApi: newCozeApi(config),
config: config,
llm: llm,
}
}
// newCozeExpressClient 创建 CozeExpress 客户端
func newCozeExpressApi(config config.ToolConfig) coze.CozeAPI {
authCli := coze.NewTokenAuth(config.APISecret)
cozeApi := coze.NewCozeAPI(authCli, coze.WithBaseURL(config.BaseURL))
return cozeApi
}
// Name 返回工具名称
func (c *CozeExpress) Name() string {
return "coze_express"
}
// Description 返回工具描述
func (c *CozeExpress) Description() string {
return "查询快递物流信息"
}
// Definition 返回工具定义
func (c *CozeExpress) Definition() entitys.ToolDefinition {
return entitys.ToolDefinition{
Type: "function",
Function: entitys.FunctionDef{
Name: c.Name(),
Description: c.Description(),
Parameters: map[string]interface{}{
"type": "object",
"properties": map[string]interface{}{
"express_id": map[string]interface{}{
"type": "string",
"description": "快递单号",
},
},
"required": []string{"express_id"},
},
},
}
}
// Execute 执行查询
func (c *CozeExpress) Execute(ctx context.Context, requireData *entitys.RequireData) error {
var req map[string]interface{}
if err := json.Unmarshal([]byte(requireData.Match.Parameters), &req); err != nil {
return fmt.Errorf("invalid express request: %w", err)
}
if req["express_id"] == "" {
return fmt.Errorf("express_id is required")
}
// 调用 Coze 工作流查询快递物流信息
rsp, err := c.callWorkflow(ctx, req)
if err != nil {
return fmt.Errorf("failed to get real weather: %w", err)
}
err = c.llm.ChatStream(ctx, requireData.Ch, []api.Message{
{
Role: "system",
Content: "你是一个快递查询助手。用户可能会提供快递单号,你需要分析快递单号,根据快递单号查询物流信息并反馈给我",
},
{
Role: "assistant",
Content: fmt.Sprintf("聊天记录:%s", pkg.JsonStringIgonErr(requireData.Histories)),
},
{
Role: "assistant",
Content: fmt.Sprintf("需要分析的快递单号:%s", rsp.Data),
},
{
Role: "user",
Content: requireData.Req.Text,
},
}, c.Name(), "")
if err != nil {
return fmt.Errorf("failed to get express info: %w", err)
}
//entitys.ResText(requireData.Ch, "", rsp.Data)
return nil
}
// CallWorkflow 调用 Coze 工作流
// 参数:
// - ctx: 上下文,用于控制超时和取消
// - workflowId: 工作流 ID
// - params: 工作流参数
// 返回:
// - interface{}: 工作流执行结果
// - error: 错误信息
func (c *CozeExpress) callWorkflow(ctx context.Context, params map[string]interface{}) (*coze.RunWorkflowsResp, error) {
// 准备工作流请求参数
workflowReq := &coze.RunWorkflowsReq{
WorkflowID: c.config.APIKey,
Parameters: params,
}
// 调用工作流
resp, err := c.cozeApi.Workflows.Runs.Create(ctx, workflowReq)
if err != nil {
return nil, fmt.Errorf("工作流调用失败: %w", err)
}
// 处理工作流响应
if resp == nil {
return nil, fmt.Errorf("工作流响应为空")
}
// 返回工作流执行结果
return resp, nil
}