From 03f6130a6e06a8915026dfb1eb959a3235bd6106 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 22 Sep 2025 09:49:48 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/router.go | 111 ++++++++++++++++++++++++---- internal/data/constant/const.go | 4 +- internal/entitys/types.go | 14 +++- internal/pkg/utils_ollama/ollama.go | 2 +- internal/test/chat_test.go | 23 ++++++ 5 files changed, 133 insertions(+), 21 deletions(-) diff --git a/internal/biz/router.go b/internal/biz/router.go index 1471009..5888c76 100644 --- a/internal/biz/router.go +++ b/internal/biz/router.go @@ -2,18 +2,24 @@ package biz import ( "ai_scheduler/internal/config" + "ai_scheduler/internal/data/constant" errors "ai_scheduler/internal/data/error" "ai_scheduler/internal/data/impl" "ai_scheduler/internal/data/model" "ai_scheduler/internal/entitys" "ai_scheduler/internal/pkg" + "ai_scheduler/internal/pkg/mapstructure" "ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/tools" "ai_scheduler/tmpl/dataTemp" "context" "encoding/json" - "log" + "fmt" + "net/http" + "strings" + "gitea.cdlsxd.cn/self-tools/l_request" + "github.com/gofiber/fiber/v2/log" "github.com/gofiber/websocket/v2" "github.com/tmc/langchaingo/llms" "xorm.io/builder" @@ -41,6 +47,7 @@ func NewAiRouterBiz( hisImpl *impl.ChatImpl, conf *config.Config, utilAgent *utils_ollama.UtilOllama, + ) entitys.RouterService { return &AiRouterService{ //aiClient: aiClient, @@ -91,26 +98,27 @@ func (r *AiRouterService) RouteWithSocket(c *websocket.Conn, req *entitys.ChatSo return errors.SystemError } - toolDefinitions := r.registerTools(task) + //toolDefinitions := r.registerTools(task) //prompt := r.getPrompt(sysInfo, history, req.Text) //意图预测 - //msg, err := r.utilAgent.Llm.Call(context.TODO(), pkg.JsonStringIgonErr(prompt), - // llms.WithTools(toolDefinitions), - // //llms.WithToolChoice(llms.FunctionCallBehaviorAuto), - // llms.WithJSONMode(), - //) - prompt := r.getPromptLLM(sysInfo, history, req.Text) - msg, err := r.utilAgent.Llm.GenerateContent(context.TODO(), prompt, - llms.WithTools(toolDefinitions), - llms.WithToolChoice("tool_name"), + prompt := r.getPromptLLM(sysInfo, history, req.Text, task) + match, err := r.utilAgent.Llm.GenerateContent(context.TODO(), prompt, + //llms.WithTools(toolDefinitions), + //llms.WithToolChoice("tool_name"), llms.WithJSONMode(), ) if err != nil { return errors.SystemError } - - c.WriteMessage(1, []byte(msg.Choices[0].Content)) + log.Info(match) + var matchJson entitys.Match + err = json.Unmarshal([]byte(match.Choices[0].Content), &matchJson) + if err != nil { + return errors.SystemError + } + return r.handleMatch(c, &matchJson, task) + //c.WriteMessage(1, []byte(msg.Choices[0].Content)) // 构建消息 //messages := []entitys.Message{ // { @@ -193,6 +201,76 @@ func (r *AiRouterService) RouteWithSocket(c *websocket.Conn, req *entitys.ChatSo return nil } +func (r *AiRouterService) handleMatch(c *websocket.Conn, matchJson *entitys.Match, tasks []model.AiTask) (err error) { + defer func() { + c.WriteMessage(1, []byte("EOF")) + }() + if !matchJson.IsMatch { + c.WriteMessage(1, []byte(matchJson.Reasoning)) + return + } + var pointTask *model.AiTask + for _, task := range tasks { + if task.Index == matchJson.Index { + pointTask = &task + break + } + } + if pointTask == nil || pointTask.Index == "other" { + return r.handleOtherTask(c, matchJson) + } + var res []byte + switch pointTask.Type { + case constant.TaskTypeApi: + res, err = r.handleApiTask(c, matchJson, pointTask) + default: + return r.handleOtherTask(c, matchJson) + } + + return +} + +func (r *AiRouterService) handleOtherTask(c *websocket.Conn, matchJson *entitys.Match) (err error) { + + c.WriteMessage(1, []byte(matchJson.Reasoning)) + + return +} + +func (r *AiRouterService) handleApiTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (resByte []byte, err error) { + var ( + request l_request.Request + auth = c.Headers("X-Authorization", "") + requestParam map[string]interface{} + ) + err = json.Unmarshal([]byte(matchJson.Parameters), &requestParam) + if err != nil { + return + } + request.Url = strings.ReplaceAll(task.Config, "${authorization}", auth) + for k, v := range requestParam { + task.Config = strings.ReplaceAll(task.Config, "${"+k+"}", fmt.Sprintf("%v", v)) + } + var configData entitys.ConfigData + err = json.Unmarshal([]byte(task.Config), &configData) + if err != nil { + return + } + err = mapstructure.Decode(configData.Do, &request) + if err != nil { + return + } + if len(request.Url) == 0 { + err = errors.NewBusinessErr("00022", "api地址获取失败") + return + } + res, err := request.Send() + if err != nil { + return + } + return res.Content, nil +} + func (r *AiRouterService) getSessionChatHis(sessionId string) (his []model.AiChatHi, err error) { cond := builder.NewCond() @@ -261,7 +339,7 @@ func (r *AiRouterService) getPrompt(sysInfo model.AiSy, history []model.AiChatHi return prompt } -func (r *AiRouterService) getPromptLLM(sysInfo model.AiSy, history []model.AiChatHi, reqInput string) []llms.MessageContent { +func (r *AiRouterService) getPromptLLM(sysInfo model.AiSy, history []model.AiChatHi, reqInput string, tasks []model.AiTask) []llms.MessageContent { var ( prompt = make([]llms.MessageContent, 0) ) @@ -275,6 +353,11 @@ func (r *AiRouterService) getPromptLLM(sysInfo model.AiSy, history []model.AiCha Parts: []llms.ContentPart{ llms.TextPart(pkg.JsonStringIgonErr(r.buildAssistant(history))), }, + }, llms.MessageContent{ + Role: llms.ChatMessageTypeTool, + Parts: []llms.ContentPart{ + llms.TextPart(pkg.JsonStringIgonErr(r.registerTools(tasks))), + }, }, llms.MessageContent{ Role: llms.ChatMessageTypeHuman, Parts: []llms.ContentPart{ diff --git a/internal/data/constant/const.go b/internal/data/constant/const.go index d611d70..19ae774 100644 --- a/internal/data/constant/const.go +++ b/internal/data/constant/const.go @@ -11,6 +11,6 @@ const ( type TaskType int32 const ( - TaskTypeApi ConnStatus = iota + 1 - TaskTypeKnowle + TaskTypeApi = 1 + TaskTypeKnowle = 2 ) diff --git a/internal/entitys/types.go b/internal/entitys/types.go index 13a1f9f..0a3373f 100644 --- a/internal/entitys/types.go +++ b/internal/entitys/types.go @@ -69,9 +69,9 @@ type Tool interface { Execute(ctx context.Context, args json.RawMessage) (interface{}, error) } -// AIClient AI客户端接口 -type AIClient interface { - Chat(ctx context.Context, messages []Message, tools []ToolDefinition) (*ChatResponse, error) +type ConfigData struct { + Param map[string]interface{} `json:"param"` + Do map[string]interface{} `json:"do"` } // Message 消息 @@ -88,7 +88,13 @@ type FuncApi struct { type TaskConfig struct { Param interface{} `json:"param"` } - +type Match struct { + Confidence float64 `json:"confidence"` + Index string `json:"index"` + IsMatch bool `json:"is_match"` + Parameters string `json:"parameters"` + Reasoning string `json:"reasoning"` +} type ChatHis struct { SessionId string `json:"session_id"` Messages []HisMessage `json:"messages"` diff --git a/internal/pkg/utils_ollama/ollama.go b/internal/pkg/utils_ollama/ollama.go index f5546bb..65388a3 100644 --- a/internal/pkg/utils_ollama/ollama.go +++ b/internal/pkg/utils_ollama/ollama.go @@ -18,7 +18,7 @@ func NewUtilOllama(c *config.Config, logger log.AllLogger) *UtilOllama { ollama.WithModel(c.Ollama.Model), ollama.WithHTTPClient(http.DefaultClient), ollama.WithServerURL(getUrl(c)), - ollama.WithKeepAlive("1h"), + ollama.WithKeepAlive("-1s"), ) if err != nil { logger.Fatal(err) diff --git a/internal/test/chat_test.go b/internal/test/chat_test.go index ebd1bda..489eb4f 100644 --- a/internal/test/chat_test.go +++ b/internal/test/chat_test.go @@ -2,8 +2,11 @@ package test import ( "ai_scheduler/internal/entitys" + "ai_scheduler/internal/pkg/mapstructure" "encoding/json" "testing" + + "gitea.cdlsxd.cn/self-tools/l_request" ) func Test_task(t *testing.T) { @@ -12,3 +15,23 @@ func Test_task(t *testing.T) { err := json.Unmarshal([]byte(config), &c) t.Log(err) } + +type configData struct { + Param map[string]interface{} `json:"param"` + Do map[string]interface{} `json:"do"` +} + +func Test_task2(t *testing.T) { + var ( + c l_request.Request + config configData + ) + + configJson := `{"param": {"type": "object", "optional": [], "required": ["order_number"], "properties": {"order_number": {"type": "string", "description": "订单编号/流水号"}}}, "do": {"url": "http://www.baidu.com/${number}", "headers": {"Authorization": "${authorization}"}, "method": "GET"}}` + err := json.Unmarshal([]byte(configJson), &config) + if err != nil { + panic(err) + } + mapstructure.Decode(config.Do, &c) + t.Log(err) +} From b81c9ef137e3665439b8c5b9944703d56521169f Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 22 Sep 2025 11:03:40 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/router.go | 24 +++++++++++++++++++++--- internal/data/constant/const.go | 1 + internal/entitys/types.go | 9 +++++++-- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/internal/biz/router.go b/internal/biz/router.go index 5888c76..0cdc93d 100644 --- a/internal/biz/router.go +++ b/internal/biz/router.go @@ -223,13 +223,31 @@ func (r *AiRouterService) handleMatch(c *websocket.Conn, matchJson *entitys.Matc switch pointTask.Type { case constant.TaskTypeApi: res, err = r.handleApiTask(c, matchJson, pointTask) + case constant.TaskTypeFunc: + ctx := context.TODO() + res, err = r.handleTask(ctx, matchJson, pointTask) default: return r.handleOtherTask(c, matchJson) } - + fmt.Println(res) return } +func (r *AiRouterService) handleTask(c context.Context, matchJson *entitys.Match, task *model.AiTask) (res []byte, err error) { + + var configData entitys.ConfigDataTool + err = json.Unmarshal([]byte(task.Config), &configData) + if err != nil { + return + } + resInterface, err := r.toolManager.ExecuteTool(c, configData.Tool, []byte(matchJson.Parameters)) + if err != nil { + return nil, err + } + + return json.Marshal(resInterface) +} + func (r *AiRouterService) handleOtherTask(c *websocket.Conn, matchJson *entitys.Match) (err error) { c.WriteMessage(1, []byte(matchJson.Reasoning)) @@ -251,12 +269,12 @@ func (r *AiRouterService) handleApiTask(c *websocket.Conn, matchJson *entitys.Ma for k, v := range requestParam { task.Config = strings.ReplaceAll(task.Config, "${"+k+"}", fmt.Sprintf("%v", v)) } - var configData entitys.ConfigData + var configData entitys.ConfigDataHttp err = json.Unmarshal([]byte(task.Config), &configData) if err != nil { return } - err = mapstructure.Decode(configData.Do, &request) + err = mapstructure.Decode(configData.Request, &request) if err != nil { return } diff --git a/internal/data/constant/const.go b/internal/data/constant/const.go index 19ae774..13ef745 100644 --- a/internal/data/constant/const.go +++ b/internal/data/constant/const.go @@ -13,4 +13,5 @@ type TaskType int32 const ( TaskTypeApi = 1 TaskTypeKnowle = 2 + TaskTypeFunc = 3 ) diff --git a/internal/entitys/types.go b/internal/entitys/types.go index 0a3373f..fea6177 100644 --- a/internal/entitys/types.go +++ b/internal/entitys/types.go @@ -69,9 +69,14 @@ type Tool interface { Execute(ctx context.Context, args json.RawMessage) (interface{}, error) } -type ConfigData struct { +type ConfigDataHttp struct { + Param map[string]interface{} `json:"param"` + Request map[string]interface{} `json:"request"` +} + +type ConfigDataTool struct { Param map[string]interface{} `json:"param"` - Do map[string]interface{} `json:"do"` + Tool string `json:"tool"` } // Message 消息 From 32866d59a1f446573ba0ec06d37fa89672cd4166 Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 22 Sep 2025 11:23:28 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/router.go | 84 ++++++--------------------- internal/entitys/types.go | 2 +- internal/tools/manager.go | 88 ++++++++++++++--------------- internal/tools/zltx_order_detail.go | 19 ++++--- 4 files changed, 72 insertions(+), 121 deletions(-) diff --git a/internal/biz/router.go b/internal/biz/router.go index 0cdc93d..45ad515 100644 --- a/internal/biz/router.go +++ b/internal/biz/router.go @@ -15,7 +15,7 @@ import ( "context" "encoding/json" "fmt" - "net/http" + "strings" "gitea.cdlsxd.cn/self-tools/l_request" @@ -203,10 +203,13 @@ func (r *AiRouterService) RouteWithSocket(c *websocket.Conn, req *entitys.ChatSo func (r *AiRouterService) handleMatch(c *websocket.Conn, matchJson *entitys.Match, tasks []model.AiTask) (err error) { defer func() { - c.WriteMessage(1, []byte("EOF")) + if err != nil { + c.WriteMessage(websocket.TextMessage, []byte(err.Error())) + } + c.WriteMessage(websocket.TextMessage, []byte("EOF")) }() if !matchJson.IsMatch { - c.WriteMessage(1, []byte(matchJson.Reasoning)) + c.WriteMessage(websocket.TextMessage, []byte(matchJson.Reasoning)) return } var pointTask *model.AiTask @@ -219,33 +222,32 @@ func (r *AiRouterService) handleMatch(c *websocket.Conn, matchJson *entitys.Matc if pointTask == nil || pointTask.Index == "other" { return r.handleOtherTask(c, matchJson) } - var res []byte + switch pointTask.Type { case constant.TaskTypeApi: - res, err = r.handleApiTask(c, matchJson, pointTask) + err = r.handleApiTask(c, matchJson, pointTask) case constant.TaskTypeFunc: - ctx := context.TODO() - res, err = r.handleTask(ctx, matchJson, pointTask) + err = r.handleTask(c, matchJson, pointTask) default: return r.handleOtherTask(c, matchJson) } - fmt.Println(res) + return } -func (r *AiRouterService) handleTask(c context.Context, matchJson *entitys.Match, task *model.AiTask) (res []byte, err error) { +func (r *AiRouterService) handleTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { var configData entitys.ConfigDataTool err = json.Unmarshal([]byte(task.Config), &configData) if err != nil { return } - resInterface, err := r.toolManager.ExecuteTool(c, configData.Tool, []byte(matchJson.Parameters)) + err = r.toolManager.ExecuteTool(c, configData.Tool, []byte(matchJson.Parameters)) if err != nil { - return nil, err + return } - return json.Marshal(resInterface) + return } func (r *AiRouterService) handleOtherTask(c *websocket.Conn, matchJson *entitys.Match) (err error) { @@ -255,7 +257,7 @@ func (r *AiRouterService) handleOtherTask(c *websocket.Conn, matchJson *entitys. return } -func (r *AiRouterService) handleApiTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (resByte []byte, err error) { +func (r *AiRouterService) handleApiTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { var ( request l_request.Request auth = c.Headers("X-Authorization", "") @@ -286,7 +288,8 @@ func (r *AiRouterService) handleApiTask(c *websocket.Conn, matchJson *entitys.Ma if err != nil { return } - return res.Content, nil + c.WriteMessage(1, res.Content) + return } func (r *AiRouterService) getSessionChatHis(sessionId string) (his []model.AiChatHi, err error) { @@ -412,59 +415,6 @@ func (r *AiRouterService) buildAssistant(his []model.AiChatHi) (chatHis entitys. return } -// extractIntent 从AI响应中提取意图 -func (r *AiRouterService) extractIntent(response *entitys.ChatResponse) string { - if response == nil || response.Message == "" { - return "" - } - - // 尝试解析JSON - var intent struct { - Intent string `json:"intent"` - Confidence string `json:"confidence"` - Reasoning string `json:"reasoning"` - } - err := json.Unmarshal([]byte(response.Message), &intent) - if err != nil { - log.Printf("Failed to parse intent JSON: %v", err) - return "" - } - - return intent.Intent -} - -// handleOrderDiagnosis 处理订单诊断意图 -func (r *AiRouterService) handleOrderDiagnosis(ctx context.Context, req *entitys.ChatRequest, messages []entitys.Message) (*entitys.ChatResponse, error) { - // 调用订单详情工具 - //orderDetailTool, ok := r.toolManager.GetTool("zltxOrderDetail") - //if orderDetailTool == nil || !ok { - // return nil, fmt.Errorf("order detail tool not found") - //} - //orderDetailTool.Execute(ctx, json.RawMessage{}) - // - //// 获取相关工具定义 - //toolDefinitions := r.toolManager.GetToolDefinitions(constants.Caller(req.Caller)) - // - //// 调用AI,获取是否需要使用工具 - //response, err := r.aiClient.Chat(ctx, messages, toolDefinitions) - //if err != nil { - // return nil, fmt.Errorf("failed to chat with AI: %w", err) - //} - // - //// 如果没有工具调用,直接返回 - //if len(response.ToolCalls) == 0 { - // return response, nil - //} - // - //// 执行工具调用 - //toolResults, err := r.toolManager.ExecuteToolCalls(ctx, response.ToolCalls) - //if err != nil { - // return nil, fmt.Errorf("failed to execute tools: %w", err) - //} - - return nil, nil -} - // handleKnowledgeQA 处理知识问答意图 func (r *AiRouterService) handleKnowledgeQA(ctx context.Context, req *entitys.ChatRequest, messages []entitys.Message) (*entitys.ChatResponse, error) { diff --git a/internal/entitys/types.go b/internal/entitys/types.go index fea6177..8705225 100644 --- a/internal/entitys/types.go +++ b/internal/entitys/types.go @@ -66,7 +66,7 @@ type Tool interface { Name() string Description() string Definition() ToolDefinition - Execute(ctx context.Context, args json.RawMessage) (interface{}, error) + Execute(c *websocket.Conn, args json.RawMessage) error } type ConfigDataHttp struct { diff --git a/internal/tools/manager.go b/internal/tools/manager.go index 6b907e2..a587a61 100644 --- a/internal/tools/manager.go +++ b/internal/tools/manager.go @@ -4,10 +4,10 @@ import ( "ai_scheduler/internal/config" "ai_scheduler/internal/constants" "ai_scheduler/internal/entitys" - "context" "encoding/json" "fmt" + "github.com/gofiber/websocket/v2" ) // Manager 工具管理器 @@ -22,16 +22,16 @@ func NewManager(config *config.Config) *Manager { } // 注册天气工具 - if config.Tools.Weather.Enabled { - weatherTool := NewWeatherTool() - m.tools[weatherTool.Name()] = weatherTool - } - - // 注册计算器工具 - if config.Tools.Calculator.Enabled { - calcTool := NewCalculatorTool() - m.tools[calcTool.Name()] = calcTool - } + //if config.Tools.Weather.Enabled { + // weatherTool := NewWeatherTool() + // m.tools[weatherTool.Name()] = weatherTool + //} + // + //// 注册计算器工具 + //if config.Tools.Calculator.Enabled { + // calcTool := NewCalculatorTool() + // m.tools[calcTool.Name()] = calcTool + //} // 注册知识库工具 // if config.Knowledge.Enabled { @@ -80,43 +80,43 @@ func (m *Manager) GetToolDefinitions(caller constants.Caller) []entitys.ToolDefi } // ExecuteTool 执行工具 -func (m *Manager) ExecuteTool(ctx context.Context, name string, args json.RawMessage) (interface{}, error) { +func (m *Manager) ExecuteTool(c *websocket.Conn, name string, args json.RawMessage) error { tool, exists := m.GetTool(name) if !exists { - return nil, fmt.Errorf("tool not found: %s", name) + return fmt.Errorf("tool not found: %s", name) } - return tool.Execute(ctx, args) + return tool.Execute(c, args) } // ExecuteToolCalls 执行多个工具调用 -func (m *Manager) ExecuteToolCalls(ctx context.Context, toolCalls []entitys.ToolCall) ([]entitys.ToolCall, error) { - results := make([]entitys.ToolCall, len(toolCalls)) - - for i, toolCall := range toolCalls { - results[i] = toolCall - - // 执行工具 - result, err := m.ExecuteTool(ctx, toolCall.Function.Name, toolCall.Function.Arguments) - if err != nil { - // 将错误信息作为结果返回 - errorResult := map[string]interface{}{ - "error": err.Error(), - } - resultBytes, _ := json.Marshal(errorResult) - results[i].Result = resultBytes - } else { - // 将成功结果序列化 - resultBytes, err := json.Marshal(result) - if err != nil { - errorResult := map[string]interface{}{ - "error": fmt.Sprintf("failed to serialize result: %v", err), - } - resultBytes, _ = json.Marshal(errorResult) - } - results[i].Result = resultBytes - } - } - - return results, nil -} +//func (m *Manager) ExecuteToolCalls(c *websocket.Conn, toolCalls []entitys.ToolCall) ([]entitys.ToolCall, error) { +// results := make([]entitys.ToolCall, len(toolCalls)) +// +// for i, toolCall := range toolCalls { +// results[i] = toolCall +// +// // 执行工具 +// err := m.ExecuteTool(c, toolCall.Function.Name, toolCall.Function.Arguments) +// if err != nil { +// // 将错误信息作为结果返回 +// errorResult := map[string]interface{}{ +// "error": err.Error(), +// } +// resultBytes, _ := json.Marshal(errorResult) +// results[i].Result = resultBytes +// } else { +// // 将成功结果序列化 +// resultBytes, err := json.Marshal(result) +// if err != nil { +// errorResult := map[string]interface{}{ +// "error": fmt.Sprintf("failed to serialize result: %v", err), +// } +// resultBytes, _ = json.Marshal(errorResult) +// } +// results[i].Result = resultBytes +// } +// } +// +// return results, nil +//} diff --git a/internal/tools/zltx_order_detail.go b/internal/tools/zltx_order_detail.go index 4d6ddd8..417a409 100644 --- a/internal/tools/zltx_order_detail.go +++ b/internal/tools/zltx_order_detail.go @@ -4,10 +4,11 @@ import ( "ai_scheduler/internal/config" "ai_scheduler/internal/entitys" - "context" "encoding/json" "fmt" "net/http" + + "github.com/gofiber/websocket/v2" ) // ZltxOrderDetailTool 直连天下订单详情工具 @@ -70,37 +71,37 @@ type ZltxOrderDetailData struct { } // Execute 执行直连天下订单详情查询 -func (w *ZltxOrderDetailTool) Execute(ctx context.Context, args json.RawMessage) (interface{}, error) { +func (w *ZltxOrderDetailTool) Execute(c *websocket.Conn, args json.RawMessage) error { var req ZltxOrderDetailRequest if err := json.Unmarshal(args, &req); err != nil { - return nil, fmt.Errorf("invalid zltxOrderDetail request: %w", err) + return fmt.Errorf("invalid zltxOrderDetail request: %w", err) } if req.Number == "" { - return nil, fmt.Errorf("number is required") + return fmt.Errorf("number is required") } // 这里可以集成真实的直连天下订单详情API - return w.getZltxOrderDetail(ctx, req.Number), nil + return w.getZltxOrderDetail(c, req.Number) } // getMockZltxOrderDetail 获取模拟直连天下订单详情数据 -func (w *ZltxOrderDetailTool) getZltxOrderDetail(ctx context.Context, number string) *ZltxOrderDetailResponse { +func (w *ZltxOrderDetailTool) getZltxOrderDetail(c *websocket.Conn, number string) (err error) { url := fmt.Sprintf("%s/admin/direct/ai/%s", w.config.BaseURL, number) authorization := fmt.Sprintf("Bearer %s", w.config.APIKey) // 发送http请求 req, err := http.NewRequest("GET", url, nil) if err != nil { - return &ZltxOrderDetailResponse{} + return } req.Header.Set("Authorization", authorization) resp, err := http.DefaultClient.Do(req) if err != nil { - return &ZltxOrderDetailResponse{} + return } defer resp.Body.Close() - return &ZltxOrderDetailResponse{} + return } From 570e13e52711a71155c366729e9921b648f4fcda Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 22 Sep 2025 11:46:06 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/biz/router.go | 38 +++++++------- internal/biz/router_test.go | 54 ++++++++++++++++++++ internal/services/chat.go | 15 +++--- internal/test/{chat_test.go => task_test.go} | 6 ++- internal/tools/zltx_order_detail.go | 23 ++++----- 5 files changed, 97 insertions(+), 39 deletions(-) create mode 100644 internal/biz/router_test.go rename internal/test/{chat_test.go => task_test.go} (74%) diff --git a/internal/biz/router.go b/internal/biz/router.go index 45ad515..a127e27 100644 --- a/internal/biz/router.go +++ b/internal/biz/router.go @@ -25,8 +25,8 @@ import ( "xorm.io/builder" ) -// AiRouterService 智能路由服务 -type AiRouterService struct { +// AiRouterBiz 智能路由服务 +type AiRouterBiz struct { //aiClient entitys.AIClient toolManager *tools.Manager sessionImpl *impl.SessionImpl @@ -48,8 +48,8 @@ func NewAiRouterBiz( conf *config.Config, utilAgent *utils_ollama.UtilOllama, -) entitys.RouterService { - return &AiRouterService{ +) *AiRouterBiz { + return &AiRouterBiz{ //aiClient: aiClient, toolManager: toolManager, sessionImpl: sessionImpl, @@ -62,13 +62,13 @@ func NewAiRouterBiz( } // Route 执行智能路由 -func (r *AiRouterService) Route(ctx context.Context, req *entitys.ChatRequest) (*entitys.ChatResponse, error) { +func (r *AiRouterBiz) Route(ctx context.Context, req *entitys.ChatRequest) (*entitys.ChatResponse, error) { return nil, nil } // Route 执行智能路由 -func (r *AiRouterService) RouteWithSocket(c *websocket.Conn, req *entitys.ChatSockRequest) error { +func (r *AiRouterBiz) RouteWithSocket(c *websocket.Conn, req *entitys.ChatSockRequest) error { session := c.Headers("X-Session", "") if len(session) == 0 { @@ -201,7 +201,7 @@ func (r *AiRouterService) RouteWithSocket(c *websocket.Conn, req *entitys.ChatSo return nil } -func (r *AiRouterService) handleMatch(c *websocket.Conn, matchJson *entitys.Match, tasks []model.AiTask) (err error) { +func (r *AiRouterBiz) handleMatch(c *websocket.Conn, matchJson *entitys.Match, tasks []model.AiTask) (err error) { defer func() { if err != nil { c.WriteMessage(websocket.TextMessage, []byte(err.Error())) @@ -235,7 +235,7 @@ func (r *AiRouterService) handleMatch(c *websocket.Conn, matchJson *entitys.Matc return } -func (r *AiRouterService) handleTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { +func (r *AiRouterBiz) handleTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { var configData entitys.ConfigDataTool err = json.Unmarshal([]byte(task.Config), &configData) @@ -250,14 +250,14 @@ func (r *AiRouterService) handleTask(c *websocket.Conn, matchJson *entitys.Match return } -func (r *AiRouterService) handleOtherTask(c *websocket.Conn, matchJson *entitys.Match) (err error) { +func (r *AiRouterBiz) handleOtherTask(c *websocket.Conn, matchJson *entitys.Match) (err error) { c.WriteMessage(1, []byte(matchJson.Reasoning)) return } -func (r *AiRouterService) handleApiTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { +func (r *AiRouterBiz) handleApiTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { var ( request l_request.Request auth = c.Headers("X-Authorization", "") @@ -292,7 +292,7 @@ func (r *AiRouterService) handleApiTask(c *websocket.Conn, matchJson *entitys.Ma return } -func (r *AiRouterService) getSessionChatHis(sessionId string) (his []model.AiChatHi, err error) { +func (r *AiRouterBiz) getSessionChatHis(sessionId string) (his []model.AiChatHi, err error) { cond := builder.NewCond() cond = cond.And(builder.Eq{"session_id": sessionId}) @@ -302,7 +302,7 @@ func (r *AiRouterService) getSessionChatHis(sessionId string) (his []model.AiCha return } -func (r *AiRouterService) getSysInfo(appKey string) (sysInfo model.AiSy, err error) { +func (r *AiRouterBiz) getSysInfo(appKey string) (sysInfo model.AiSy, err error) { cond := builder.NewCond() cond = cond.And(builder.Eq{"app_key": appKey}) cond = cond.And(builder.IsNull{"delete_at"}) @@ -311,7 +311,7 @@ func (r *AiRouterService) getSysInfo(appKey string) (sysInfo model.AiSy, err err return } -func (r *AiRouterService) getTasks(sysId int32) (tasks []model.AiTask, err error) { +func (r *AiRouterBiz) getTasks(sysId int32) (tasks []model.AiTask, err error) { cond := builder.NewCond() cond = cond.And(builder.Eq{"sys_id": sysId}) @@ -322,7 +322,7 @@ func (r *AiRouterService) getTasks(sysId int32) (tasks []model.AiTask, err error return } -func (r *AiRouterService) registerTools(tasks []model.AiTask) []llms.Tool { +func (r *AiRouterBiz) registerTools(tasks []model.AiTask) []llms.Tool { taskPrompt := make([]llms.Tool, 0) for _, task := range tasks { var taskConfig entitys.TaskConfig @@ -343,7 +343,7 @@ func (r *AiRouterService) registerTools(tasks []model.AiTask) []llms.Tool { return taskPrompt } -func (r *AiRouterService) getPrompt(sysInfo model.AiSy, history []model.AiChatHi, reqInput string) []entitys.Message { +func (r *AiRouterBiz) getPrompt(sysInfo model.AiSy, history []model.AiChatHi, reqInput string) []entitys.Message { var ( prompt = make([]entitys.Message, 0) ) @@ -360,7 +360,7 @@ func (r *AiRouterService) getPrompt(sysInfo model.AiSy, history []model.AiChatHi return prompt } -func (r *AiRouterService) getPromptLLM(sysInfo model.AiSy, history []model.AiChatHi, reqInput string, tasks []model.AiTask) []llms.MessageContent { +func (r *AiRouterBiz) getPromptLLM(sysInfo model.AiSy, history []model.AiChatHi, reqInput string, tasks []model.AiTask) []llms.MessageContent { var ( prompt = make([]llms.MessageContent, 0) ) @@ -389,7 +389,7 @@ func (r *AiRouterService) getPromptLLM(sysInfo model.AiSy, history []model.AiCha } // buildSystemPrompt 构建系统提示词 -func (r *AiRouterService) buildSystemPrompt(prompt string) string { +func (r *AiRouterBiz) buildSystemPrompt(prompt string) string { if len(prompt) == 0 { prompt = "[system] 你是一个智能路由系统,核心职责是 **精准解析用户意图并路由至对应任务模块**\n[rule]\n1.返回以下格式的JSON:{ \"index\": \"工具索引index\", \"confidence\": 0.0-1.0,\"reasoning\": \"判断理由\"}\n2.严格返回字符串格式,禁用markdown格式返回\n3.只返回json字符串,不包含任何其他解释性文字\n4.当用户意图非常不清晰时使用,尝试进行追问具体希望查询内容" } @@ -397,7 +397,7 @@ func (r *AiRouterService) buildSystemPrompt(prompt string) string { return prompt } -func (r *AiRouterService) buildAssistant(his []model.AiChatHi) (chatHis entitys.ChatHis) { +func (r *AiRouterBiz) buildAssistant(his []model.AiChatHi) (chatHis entitys.ChatHis) { for _, item := range his { if len(chatHis.SessionId) == 0 { chatHis.SessionId = item.SessionID @@ -416,7 +416,7 @@ func (r *AiRouterService) buildAssistant(his []model.AiChatHi) (chatHis entitys. } // handleKnowledgeQA 处理知识问答意图 -func (r *AiRouterService) handleKnowledgeQA(ctx context.Context, req *entitys.ChatRequest, messages []entitys.Message) (*entitys.ChatResponse, error) { +func (r *AiRouterBiz) handleKnowledgeQA(ctx context.Context, req *entitys.ChatRequest, messages []entitys.Message) (*entitys.ChatResponse, error) { return nil, nil } diff --git a/internal/biz/router_test.go b/internal/biz/router_test.go new file mode 100644 index 0000000..0f43807 --- /dev/null +++ b/internal/biz/router_test.go @@ -0,0 +1,54 @@ +package biz + +import ( + "ai_scheduler/internal/config" + "ai_scheduler/internal/data/impl" + "ai_scheduler/internal/data/model" + "ai_scheduler/internal/entitys" + "ai_scheduler/internal/pkg/utils_ollama" + "ai_scheduler/internal/tools" + "ai_scheduler/utils" + "encoding/json" + "flag" + "testing" + + "github.com/gofiber/fiber/v2/log" +) + +func Test_task(t *testing.T) { + var c entitys.TaskConfig + config := `{"param": {"type": "object", "required": ["number"], "properties": {"number": {"type": "string", "description": "订单编号/流水号"}}}, "request": {"url": "http://www.baidu.com/${number}", "headers": {"Authorization": "${authorization}"}, "method": "GET"}}` + err := json.Unmarshal([]byte(config), &c) + t.Log(err) +} + +type configData struct { + Param map[string]interface{} `json:"param"` + Do map[string]interface{} `json:"do"` +} + +func Test_Order(t *testing.T) { + routerBiz := in() + err := routerBiz.handleTask(nil, &entitys.Match{Index: "order_diagnosis"}, &model.AiTask{Config: `{"tool": "zltxOrderDetail", "param": {"type": "object", "optional": [], "required": ["order_number"], "properties": {"order_number": {"type": "string", "description": "订单编号/流水号"}}}}`}) + t.Log(err) +} + +func in() *AiRouterBiz { + configPath := flag.String("config", "./config/config.yaml", "Path to configuration file") + flag.Parse() + configConfig, err := config.LoadConfig(*configPath) + if err != nil { + panic("加载配置失败") + } + allLogger := log.DefaultLogger() + manager := tools.NewManager(configConfig) + db, _ := utils.NewGormDb(configConfig) + sessionImpl := impl.NewSessionImpl(db) + sysImpl := impl.NewSysImpl(db) + taskImpl := impl.NewTaskImpl(db) + chatImpl := impl.NewChatImpl(db) + utilOllama := utils_ollama.NewUtilOllama(configConfig, allLogger) + routerBiz := NewAiRouterBiz(manager, sessionImpl, sysImpl, taskImpl, chatImpl, configConfig, utilOllama) + + return routerBiz +} diff --git a/internal/services/chat.go b/internal/services/chat.go index 43804b8..82995e1 100644 --- a/internal/services/chat.go +++ b/internal/services/chat.go @@ -1,6 +1,7 @@ package services import ( + "ai_scheduler/internal/biz" "ai_scheduler/internal/data/constant" "ai_scheduler/internal/entitys" "ai_scheduler/internal/gateway" @@ -17,16 +18,16 @@ import ( // ChatHandler 聊天处理器 type ChatService struct { - routerService entitys.RouterService - Gw *gateway.Gateway - mu sync.Mutex + routerBiz *biz.AiRouterBiz + Gw *gateway.Gateway + mu sync.Mutex } // NewChatHandler 创建聊天处理器 -func NewChatService(routerService entitys.RouterService, gw *gateway.Gateway) *ChatService { +func NewChatService(routerService *biz.AiRouterBiz, gw *gateway.Gateway) *ChatService { return &ChatService{ - routerService: routerService, - Gw: gw, + routerBiz: routerService, + Gw: gw, } } @@ -100,7 +101,7 @@ func (h *ChatService) Chat(c *websocket.Conn) { log.Println("JSON parse error:", err) continue } - err = h.routerService.RouteWithSocket(c, &req) + err = h.routerBiz.RouteWithSocket(c, &req) if err != nil { log.Println("处理失败:", err) continue diff --git a/internal/test/chat_test.go b/internal/test/task_test.go similarity index 74% rename from internal/test/chat_test.go rename to internal/test/task_test.go index 489eb4f..f46832f 100644 --- a/internal/test/chat_test.go +++ b/internal/test/task_test.go @@ -27,7 +27,7 @@ func Test_task2(t *testing.T) { config configData ) - configJson := `{"param": {"type": "object", "optional": [], "required": ["order_number"], "properties": {"order_number": {"type": "string", "description": "订单编号/流水号"}}}, "do": {"url": "http://www.baidu.com/${number}", "headers": {"Authorization": "${authorization}"}, "method": "GET"}}` + configJson := `{"tool": "zltxOrderDetail", "param": {"type": "object", "optional": [], "required": ["order_number"], "properties": {"order_number": {"type": "string", "description": "订单编号/流水号"}}}}` err := json.Unmarshal([]byte(configJson), &config) if err != nil { panic(err) @@ -35,3 +35,7 @@ func Test_task2(t *testing.T) { mapstructure.Decode(config.Do, &c) t.Log(err) } + +func in() { + +} diff --git a/internal/tools/zltx_order_detail.go b/internal/tools/zltx_order_detail.go index 417a409..8a3c1c8 100644 --- a/internal/tools/zltx_order_detail.go +++ b/internal/tools/zltx_order_detail.go @@ -6,8 +6,8 @@ import ( "encoding/json" "fmt" - "net/http" + "gitea.cdlsxd.cn/self-tools/l_request" "github.com/gofiber/websocket/v2" ) @@ -87,21 +87,20 @@ func (w *ZltxOrderDetailTool) Execute(c *websocket.Conn, args json.RawMessage) e // getMockZltxOrderDetail 获取模拟直连天下订单详情数据 func (w *ZltxOrderDetailTool) getZltxOrderDetail(c *websocket.Conn, number string) (err error) { - url := fmt.Sprintf("%s/admin/direct/ai/%s", w.config.BaseURL, number) - authorization := fmt.Sprintf("Bearer %s", w.config.APIKey) + //查询订单详情 + req := l_request.Request{ + Url: fmt.Sprintf("%s/admin/direct/ai/%s", w.config.BaseURL, number), + Headers: map[string]string{ + "Authorization": fmt.Sprintf("Bearer %s", w.config.APIKey), + }, + Method: "GET", + } + res, err := req.Send() - // 发送http请求 - req, err := http.NewRequest("GET", url, nil) if err != nil { return } - req.Header.Set("Authorization", authorization) - - resp, err := http.DefaultClient.Do(req) - if err != nil { - return - } - defer resp.Body.Close() + c.WriteMessage(websocket.TextMessage, res.Content) return } From 14125546616610eb43b41ad8db9dc8aeeabe974e Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 22 Sep 2025 11:46:42 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/tools/manager.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/tools/manager.go b/internal/tools/manager.go index a587a61..76912cc 100644 --- a/internal/tools/manager.go +++ b/internal/tools/manager.go @@ -4,7 +4,7 @@ import ( "ai_scheduler/internal/config" "ai_scheduler/internal/constants" "ai_scheduler/internal/entitys" - "context" + "encoding/json" "fmt" "github.com/gofiber/websocket/v2" From 3f37427181439aefbc59ae99c75872ac8538215f Mon Sep 17 00:00:00 2001 From: renzhiyuan <465386466@qq.com> Date: Mon, 22 Sep 2025 14:22:16 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E7=BB=93=E6=9E=84=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config/config.yaml | 6 +++++ internal/biz/router_test.go | 34 +++++++++++++++++++++++++++-- internal/config/config.go | 7 +++--- internal/tools/manager.go | 1 + internal/tools/zltx_order_detail.go | 17 ++++++++++----- 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/config/config.yaml b/config/config.yaml index a51c128..8e9c764 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -26,3 +26,9 @@ redis: db: driver: mysql source: root:SD###sdf323r343@tcp(121.199.38.107:3306)/sys_ai?charset=utf8mb4&parseTime=true&loc=Asia%2FShanghai + +tools: + zltxOrderDetail: + enabled: true + base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/ai/" + api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ" diff --git a/internal/biz/router_test.go b/internal/biz/router_test.go index 0f43807..d6c8658 100644 --- a/internal/biz/router_test.go +++ b/internal/biz/router_test.go @@ -10,6 +10,9 @@ import ( "ai_scheduler/utils" "encoding/json" "flag" + "fmt" + "os" + "path/filepath" "testing" "github.com/gofiber/fiber/v2/log" @@ -29,12 +32,16 @@ type configData struct { func Test_Order(t *testing.T) { routerBiz := in() - err := routerBiz.handleTask(nil, &entitys.Match{Index: "order_diagnosis"}, &model.AiTask{Config: `{"tool": "zltxOrderDetail", "param": {"type": "object", "optional": [], "required": ["order_number"], "properties": {"order_number": {"type": "string", "description": "订单编号/流水号"}}}}`}) + err := routerBiz.handleTask(nil, &entitys.Match{Index: "order_diagnosis", Parameters: `{"order_number":"12312312312"}`}, &model.AiTask{Config: `{"tool": "zltxOrderDetail", "param": {"type": "object", "optional": [], "required": ["order_number"], "properties": {"order_number": {"type": "string", "description": "订单编号/流水号"}}}}`}) t.Log(err) } func in() *AiRouterBiz { - configPath := flag.String("config", "./config/config.yaml", "Path to configuration file") + modDir, err := getModuleDir() + if err != nil { + panic("1") + } + configPath := flag.String("config", fmt.Sprintf("%s/config/config.yaml", modDir), "Path to configuration file") flag.Parse() configConfig, err := config.LoadConfig(*configPath) if err != nil { @@ -52,3 +59,26 @@ func in() *AiRouterBiz { return routerBiz } + +func getModuleDir() (string, error) { + dir, err := os.Getwd() + if err != nil { + return "", err + } + + for { + modPath := filepath.Join(dir, "go.mod") + if _, err := os.Stat(modPath); err == nil { + return dir, nil // 找到 go.mod + } + + // 向上查找父目录 + parent := filepath.Dir(dir) + if parent == dir { + break // 到达根目录,未找到 + } + dir = parent + } + + return "", fmt.Errorf("go.mod not found in current directory or parents") +} diff --git a/internal/config/config.go b/internal/config/config.go index bfbedbf..c3c75c9 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -73,10 +73,9 @@ type ToolsConfig struct { // ToolConfig 单个工具配置 type ToolConfig struct { - Enabled bool `mapstructure:"enabled"` - BaseURL string `mapstructure:"base_url"` - APIKey string `mapstructure:"api_key"` - BizSystem string `mapstructure:"biz_system"` + Enabled bool `mapstructure:"enabled"` + BaseURL string `mapstructure:"base_url"` + APIKey string `mapstructure:"api_key"` } // LoggingConfig 日志配置 diff --git a/internal/tools/manager.go b/internal/tools/manager.go index 76912cc..2fd86c0 100644 --- a/internal/tools/manager.go +++ b/internal/tools/manager.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" + "github.com/gofiber/websocket/v2" ) diff --git a/internal/tools/zltx_order_detail.go b/internal/tools/zltx_order_detail.go index 8a3c1c8..9cbb39e 100644 --- a/internal/tools/zltx_order_detail.go +++ b/internal/tools/zltx_order_detail.go @@ -54,7 +54,7 @@ func (w *ZltxOrderDetailTool) Definition() entitys.ToolDefinition { // ZltxOrderDetailRequest 直连天下订单详情请求参数 type ZltxOrderDetailRequest struct { - Number string `json:"number"` + OrderNumber string `json:"order_number"` } // ZltxOrderDetailResponse 直连天下订单详情响应 @@ -77,21 +77,28 @@ func (w *ZltxOrderDetailTool) Execute(c *websocket.Conn, args json.RawMessage) e return fmt.Errorf("invalid zltxOrderDetail request: %w", err) } - if req.Number == "" { + if req.OrderNumber == "" { return fmt.Errorf("number is required") } // 这里可以集成真实的直连天下订单详情API - return w.getZltxOrderDetail(c, req.Number) + return w.getZltxOrderDetail(c, req.OrderNumber) } // getMockZltxOrderDetail 获取模拟直连天下订单详情数据 func (w *ZltxOrderDetailTool) getZltxOrderDetail(c *websocket.Conn, number string) (err error) { //查询订单详情 + var auth string + if c != nil { + auth = c.Headers("X-Authorization", "") + } + if len(auth) == 0 { + auth = w.config.APIKey + } req := l_request.Request{ - Url: fmt.Sprintf("%s/admin/direct/ai/%s", w.config.BaseURL, number), + Url: fmt.Sprintf("%s%s", w.config.BaseURL, number), Headers: map[string]string{ - "Authorization": fmt.Sprintf("Bearer %s", w.config.APIKey), + "Authorization": fmt.Sprintf("Bearer %s", auth), }, Method: "GET", }