diff --git a/config/config.yaml b/config/config.yaml index 8e9c764..f8057ef 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -30,5 +30,5 @@ db: tools: zltxOrderDetail: enabled: true - base_url: "https://gateway.dev.cdlsxd.cn/zltx_api/admin/direct/ai/" + base_url: "https://gateway.dev.cdlsxd.cn/" 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.go b/internal/biz/router.go index a127e27..dac3809 100644 --- a/internal/biz/router.go +++ b/internal/biz/router.go @@ -202,7 +202,9 @@ func (r *AiRouterBiz) RouteWithSocket(c *websocket.Conn, req *entitys.ChatSockRe } func (r *AiRouterBiz) handleMatch(c *websocket.Conn, matchJson *entitys.Match, tasks []model.AiTask) (err error) { + var resChan = make(chan []byte, 10) defer func() { + close(resChan) if err != nil { c.WriteMessage(websocket.TextMessage, []byte(err.Error())) } @@ -219,30 +221,35 @@ func (r *AiRouterBiz) handleMatch(c *websocket.Conn, matchJson *entitys.Match, t break } } - if pointTask == nil || pointTask.Index == "other" { - return r.handleOtherTask(c, matchJson) - } + if pointTask == nil || pointTask.Index == "other" { + return r.handleOtherTask(resChan, c, matchJson) + } switch pointTask.Type { case constant.TaskTypeApi: - err = r.handleApiTask(c, matchJson, pointTask) + err = r.handleApiTask(resChan, c, matchJson, pointTask) case constant.TaskTypeFunc: - err = r.handleTask(c, matchJson, pointTask) + err = r.handleTask(resChan, c, matchJson, pointTask) default: - return r.handleOtherTask(c, matchJson) + return r.handleOtherTask(resChan, c, matchJson) + } + select { + case v := <-resChan: // 尝试接收 + fmt.Println("接收到值:", v) + default: + fmt.Println("无数据可接收") } - return } -func (r *AiRouterBiz) handleTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { +func (r *AiRouterBiz) handleTask(channel chan []byte, 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 } - err = r.toolManager.ExecuteTool(c, configData.Tool, []byte(matchJson.Parameters)) + err = r.toolManager.ExecuteTool(channel, c, configData.Tool, []byte(matchJson.Parameters)) if err != nil { return } @@ -250,14 +257,12 @@ func (r *AiRouterBiz) handleTask(c *websocket.Conn, matchJson *entitys.Match, ta return } -func (r *AiRouterBiz) handleOtherTask(c *websocket.Conn, matchJson *entitys.Match) (err error) { - - c.WriteMessage(1, []byte(matchJson.Reasoning)) - +func (r *AiRouterBiz) handleOtherTask(channel chan []byte, c *websocket.Conn, matchJson *entitys.Match) (err error) { + channel <- []byte(matchJson.Reasoning) return } -func (r *AiRouterBiz) handleApiTask(c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { +func (r *AiRouterBiz) handleApiTask(channels chan []byte, c *websocket.Conn, matchJson *entitys.Match, task *model.AiTask) (err error) { var ( request l_request.Request auth = c.Headers("X-Authorization", "") diff --git a/internal/biz/router_test.go b/internal/biz/router_test.go index d6c8658..2cef402 100644 --- a/internal/biz/router_test.go +++ b/internal/biz/router_test.go @@ -32,7 +32,15 @@ type configData struct { func Test_Order(t *testing.T) { routerBiz := in() - 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": "订单编号/流水号"}}}}`}) + ch := make(chan []byte, 5) + defer close(ch) + err := routerBiz.handleTask(ch, nil, &entitys.Match{Index: "order_diagnosis", Parameters: `{"order_number":"822895927188791297"}`}, &model.AiTask{Config: `{"tool": "zltxOrderDetail", "param": {"type": "object", "optional": [], "required": ["order_number"], "properties": {"order_number": {"type": "string", "description": "订单编号/流水号"}}}}`}) + select { + case v := <-ch: // 尝试接收 + fmt.Println("接收到值:", v) + default: + fmt.Println("无数据可接收") + } t.Log(err) } diff --git a/internal/entitys/types.go b/internal/entitys/types.go index 8705225..3e61305 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(c *websocket.Conn, args json.RawMessage) error + Execute(channel chan []byte, c *websocket.Conn, args json.RawMessage) error } type ConfigDataHttp struct { diff --git a/internal/tools/manager.go b/internal/tools/manager.go index 2fd86c0..4cb88d1 100644 --- a/internal/tools/manager.go +++ b/internal/tools/manager.go @@ -4,6 +4,7 @@ import ( "ai_scheduler/internal/config" "ai_scheduler/internal/constants" "ai_scheduler/internal/entitys" + "ai_scheduler/internal/pkg/utils_ollama" "encoding/json" "fmt" @@ -14,12 +15,14 @@ import ( // Manager 工具管理器 type Manager struct { tools map[string]entitys.Tool + llm *utils_ollama.UtilOllama } // NewManager 创建工具管理器 -func NewManager(config *config.Config) *Manager { +func NewManager(config *config.Config, llm *utils_ollama.UtilOllama) *Manager { m := &Manager{ tools: make(map[string]entitys.Tool), + llm: llm, } // 注册天气工具 @@ -81,13 +84,13 @@ func (m *Manager) GetToolDefinitions(caller constants.Caller) []entitys.ToolDefi } // ExecuteTool 执行工具 -func (m *Manager) ExecuteTool(c *websocket.Conn, name string, args json.RawMessage) error { +func (m *Manager) ExecuteTool(channel chan []byte, c *websocket.Conn, name string, args json.RawMessage) error { tool, exists := m.GetTool(name) if !exists { return fmt.Errorf("tool not found: %s", name) } - return tool.Execute(c, args) + return tool.Execute(channel, c, args) } // ExecuteToolCalls 执行多个工具调用 diff --git a/internal/tools/zltx_order_detail.go b/internal/tools/zltx_order_detail.go index 9cbb39e..44a83e9 100644 --- a/internal/tools/zltx_order_detail.go +++ b/internal/tools/zltx_order_detail.go @@ -3,7 +3,6 @@ package tools import ( "ai_scheduler/internal/config" "ai_scheduler/internal/entitys" - "encoding/json" "fmt" @@ -64,6 +63,12 @@ type ZltxOrderDetailResponse struct { Data ZltxOrderDetailData `json:"data"` } +type ZltxOrderLogResponse struct { + Code int `json:"code"` + Error string `json:"error"` + Data any `json:"data"` +} + // ZltxOrderDetailData 直连天下订单详情数据 type ZltxOrderDetailData struct { Direct map[string]any `json:"direct"` @@ -71,7 +76,7 @@ type ZltxOrderDetailData struct { } // Execute 执行直连天下订单详情查询 -func (w *ZltxOrderDetailTool) Execute(c *websocket.Conn, args json.RawMessage) error { +func (w *ZltxOrderDetailTool) Execute(channel chan []byte, c *websocket.Conn, args json.RawMessage) error { var req ZltxOrderDetailRequest if err := json.Unmarshal(args, &req); err != nil { return fmt.Errorf("invalid zltxOrderDetail request: %w", err) @@ -82,11 +87,11 @@ func (w *ZltxOrderDetailTool) Execute(c *websocket.Conn, args json.RawMessage) e } // 这里可以集成真实的直连天下订单详情API - return w.getZltxOrderDetail(c, req.OrderNumber) + return w.getZltxOrderDetail(channel, c, req.OrderNumber) } // getMockZltxOrderDetail 获取模拟直连天下订单详情数据 -func (w *ZltxOrderDetailTool) getZltxOrderDetail(c *websocket.Conn, number string) (err error) { +func (w *ZltxOrderDetailTool) getZltxOrderDetail(ch chan []byte, c *websocket.Conn, number string) (err error) { //查询订单详情 var auth string if c != nil { @@ -96,7 +101,7 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(c *websocket.Conn, number strin auth = w.config.APIKey } req := l_request.Request{ - Url: fmt.Sprintf("%s%s", w.config.BaseURL, number), + Url: fmt.Sprintf("%szltx_api/admin/direct/ai/%s", w.config.BaseURL, number), Headers: map[string]string{ "Authorization": fmt.Sprintf("Bearer %s", auth), }, @@ -107,7 +112,36 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(c *websocket.Conn, number strin if err != nil { return } - c.WriteMessage(websocket.TextMessage, res.Content) + var resData ZltxOrderDetailResponse + if err = json.Unmarshal(res.Content, &resData); err != nil { + return + } + if resData.Code != 200 { + return fmt.Errorf("订单查询失败:%s", resData.Error) + } + ch <- res.Content + if resData.Data.Direct != nil && resData.Data.Direct["needAi"].(bool) { + ch <- []byte("orderErrorChecking") + req = l_request.Request{ + Url: fmt.Sprintf("%szltx_api/admin/direct/log/%s/%s", w.config.BaseURL, resData.Data.Direct["orderOrderNumber"].(string), resData.Data.Direct["serialNumber"].(string)), + Headers: map[string]string{ + "Authorization": fmt.Sprintf("Bearer %s", auth), + }, + Method: "GET", + } + res, err = req.Send() + if err != nil { + return + } + var orderLog ZltxOrderLogResponse + if err = json.Unmarshal(res.Content, &orderLog); err != nil { + return + } + if orderLog.Code != 200 { + return fmt.Errorf("订单日志查询失败:%s", orderLog.Error) + } + + } return }