Compare commits

..

No commits in common. "3b91505a1262d1f811b76e3f18814a4abf84b546" and "ff81cddc468d6de23ef6af97c94d37f9c42a4803" have entirely different histories.

6 changed files with 25 additions and 75 deletions

View File

@ -30,5 +30,5 @@ db:
tools: tools:
zltxOrderDetail: zltxOrderDetail:
enabled: true enabled: true
base_url: "https://gateway.dev.cdlsxd.cn/" 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" api_key: "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ1c2VyQ2VudGVyIiwiZXhwIjoxNzU2MTgyNTM1LCJuYmYiOjE3NTYxODA3MzUsImp0aSI6IjEiLCJQaG9uZSI6IjE4MDAwMDAwMDAwIiwiVXNlck5hbWUiOiJsc3hkIiwiUmVhbE5hbWUiOiLotoXnuqfnrqHnkIblkZgiLCJBY2NvdW50VHlwZSI6MSwiR3JvdXBDb2RlcyI6IlZDTF9DQVNISUVSLFZDTF9PUEVSQVRFLFZDTF9BRE1JTixWQ0xfQUFBLFZDTF9WQ0xfT1BFUkFULFZDTF9JTlZPSUNFLENSTV9BRE1JTixMSUFOTElBTl9BRE1JTixNQVJLRVRNQUcyX0FETUlOLFBIT05FQklMTF9BRE1JTixRSUFOWkhVX1NVUFBFUl9BRE0sTUFSS0VUSU5HU0FBU19TVVBFUkFETUlOLENBUkRfQ09ERSxDQVJEX1BST0NVUkVNRU5ULE1BUktFVElOR1NZU1RFTV9TVVBFUixTVEFUSVNUSUNBTFNZU1RFTV9BRE1JTixaTFRYX0FETUlOLFpMVFhfT1BFUkFURSIsIkRpbmdVc2VySWQiOiIxNjIwMjYxMjMwMjg5MzM4MzQifQ.N1xv1PYbcO8_jR5adaczc16YzGsr4z101gwEZdulkRaREBJNYTOnFrvRxTFx3RJTooXsqTqroE1MR84v_1WPX6BS6kKonA-kC1Jgot6yrt5rFWhGNGb2Cpr9rKIFCCQYmiGd3AUgDazEeaQ0_sodv3E-EXg9VfE1SX8nMcck9Yjnc8NCy7RTWaBIaSeOdZcEl-JfCD0S6GSx3oErp_hk-U9FKGwf60wAuDGTY1R0BP4BYpcEqS-C2LSnsSGyURi54Cuk5xH8r1WuF0Dm5bwAj5d7Hvs77-N_sUF-C5ONqyZJRAEhYLgcmN9RX_WQZfizdQJxizlTczdpzYfy-v-1eQ"

View File

@ -202,9 +202,7 @@ 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) { func (r *AiRouterBiz) handleMatch(c *websocket.Conn, matchJson *entitys.Match, tasks []model.AiTask) (err error) {
var resChan = make(chan []byte, 10)
defer func() { defer func() {
close(resChan)
if err != nil { if err != nil {
c.WriteMessage(websocket.TextMessage, []byte(err.Error())) c.WriteMessage(websocket.TextMessage, []byte(err.Error()))
} }
@ -221,35 +219,30 @@ func (r *AiRouterBiz) handleMatch(c *websocket.Conn, matchJson *entitys.Match, t
break break
} }
} }
if pointTask == nil || pointTask.Index == "other" { if pointTask == nil || pointTask.Index == "other" {
return r.handleOtherTask(resChan, c, matchJson) return r.handleOtherTask(c, matchJson)
} }
switch pointTask.Type { switch pointTask.Type {
case constant.TaskTypeApi: case constant.TaskTypeApi:
err = r.handleApiTask(resChan, c, matchJson, pointTask) err = r.handleApiTask(c, matchJson, pointTask)
case constant.TaskTypeFunc: case constant.TaskTypeFunc:
err = r.handleTask(resChan, c, matchJson, pointTask) err = r.handleTask(c, matchJson, pointTask)
default: default:
return r.handleOtherTask(resChan, c, matchJson) return r.handleOtherTask(c, matchJson)
}
select {
case v := <-resChan: // 尝试接收
fmt.Println("接收到值:", v)
default:
fmt.Println("无数据可接收")
} }
return return
} }
func (r *AiRouterBiz) handleTask(channel chan []byte, 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 var configData entitys.ConfigDataTool
err = json.Unmarshal([]byte(task.Config), &configData) err = json.Unmarshal([]byte(task.Config), &configData)
if err != nil { if err != nil {
return return
} }
err = r.toolManager.ExecuteTool(channel, c, configData.Tool, []byte(matchJson.Parameters)) err = r.toolManager.ExecuteTool(c, configData.Tool, []byte(matchJson.Parameters))
if err != nil { if err != nil {
return return
} }
@ -257,12 +250,14 @@ func (r *AiRouterBiz) handleTask(channel chan []byte, c *websocket.Conn, matchJs
return return
} }
func (r *AiRouterBiz) handleOtherTask(channel chan []byte, c *websocket.Conn, matchJson *entitys.Match) (err error) { func (r *AiRouterBiz) handleOtherTask(c *websocket.Conn, matchJson *entitys.Match) (err error) {
channel <- []byte(matchJson.Reasoning)
c.WriteMessage(1, []byte(matchJson.Reasoning))
return return
} }
func (r *AiRouterBiz) handleApiTask(channels chan []byte, 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 ( var (
request l_request.Request request l_request.Request
auth = c.Headers("X-Authorization", "") auth = c.Headers("X-Authorization", "")

View File

@ -32,15 +32,7 @@ type configData struct {
func Test_Order(t *testing.T) { func Test_Order(t *testing.T) {
routerBiz := in() routerBiz := in()
ch := make(chan []byte, 5) 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": "订单编号/流水号"}}}}`})
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) t.Log(err)
} }

View File

@ -66,7 +66,7 @@ type Tool interface {
Name() string Name() string
Description() string Description() string
Definition() ToolDefinition Definition() ToolDefinition
Execute(channel chan []byte, c *websocket.Conn, args json.RawMessage) error Execute(c *websocket.Conn, args json.RawMessage) error
} }
type ConfigDataHttp struct { type ConfigDataHttp struct {

View File

@ -4,7 +4,6 @@ import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
"ai_scheduler/internal/data/constants" "ai_scheduler/internal/data/constants"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg/utils_ollama"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -15,14 +14,12 @@ import (
// Manager 工具管理器 // Manager 工具管理器
type Manager struct { type Manager struct {
tools map[string]entitys.Tool tools map[string]entitys.Tool
llm *utils_ollama.UtilOllama
} }
// NewManager 创建工具管理器 // NewManager 创建工具管理器
func NewManager(config *config.Config, llm *utils_ollama.UtilOllama) *Manager { func NewManager(config *config.Config) *Manager {
m := &Manager{ m := &Manager{
tools: make(map[string]entitys.Tool), tools: make(map[string]entitys.Tool),
llm: llm,
} }
// 注册天气工具 // 注册天气工具
@ -84,13 +81,13 @@ func (m *Manager) GetToolDefinitions(caller constants.Caller) []entitys.ToolDefi
} }
// ExecuteTool 执行工具 // ExecuteTool 执行工具
func (m *Manager) ExecuteTool(channel chan []byte, c *websocket.Conn, name string, args json.RawMessage) error { func (m *Manager) ExecuteTool(c *websocket.Conn, name string, args json.RawMessage) error {
tool, exists := m.GetTool(name) tool, exists := m.GetTool(name)
if !exists { if !exists {
return fmt.Errorf("tool not found: %s", name) return fmt.Errorf("tool not found: %s", name)
} }
return tool.Execute(channel, c, args) return tool.Execute(c, args)
} }
// ExecuteToolCalls 执行多个工具调用 // ExecuteToolCalls 执行多个工具调用

View File

@ -3,6 +3,7 @@ package tools
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -63,12 +64,6 @@ type ZltxOrderDetailResponse struct {
Data ZltxOrderDetailData `json:"data"` Data ZltxOrderDetailData `json:"data"`
} }
type ZltxOrderLogResponse struct {
Code int `json:"code"`
Error string `json:"error"`
Data any `json:"data"`
}
// ZltxOrderDetailData 直连天下订单详情数据 // ZltxOrderDetailData 直连天下订单详情数据
type ZltxOrderDetailData struct { type ZltxOrderDetailData struct {
Direct map[string]any `json:"direct"` Direct map[string]any `json:"direct"`
@ -76,7 +71,7 @@ type ZltxOrderDetailData struct {
} }
// Execute 执行直连天下订单详情查询 // Execute 执行直连天下订单详情查询
func (w *ZltxOrderDetailTool) Execute(channel chan []byte, c *websocket.Conn, args json.RawMessage) error { func (w *ZltxOrderDetailTool) Execute(c *websocket.Conn, args json.RawMessage) error {
var req ZltxOrderDetailRequest var req ZltxOrderDetailRequest
if err := json.Unmarshal(args, &req); err != nil { if err := json.Unmarshal(args, &req); err != nil {
return fmt.Errorf("invalid zltxOrderDetail request: %w", err) return fmt.Errorf("invalid zltxOrderDetail request: %w", err)
@ -87,11 +82,11 @@ func (w *ZltxOrderDetailTool) Execute(channel chan []byte, c *websocket.Conn, ar
} }
// 这里可以集成真实的直连天下订单详情API // 这里可以集成真实的直连天下订单详情API
return w.getZltxOrderDetail(channel, c, req.OrderNumber) return w.getZltxOrderDetail(c, req.OrderNumber)
} }
// getMockZltxOrderDetail 获取模拟直连天下订单详情数据 // getMockZltxOrderDetail 获取模拟直连天下订单详情数据
func (w *ZltxOrderDetailTool) getZltxOrderDetail(ch chan []byte, c *websocket.Conn, number string) (err error) { func (w *ZltxOrderDetailTool) getZltxOrderDetail(c *websocket.Conn, number string) (err error) {
//查询订单详情 //查询订单详情
var auth string var auth string
if c != nil { if c != nil {
@ -101,7 +96,7 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(ch chan []byte, c *websocket.Co
auth = w.config.APIKey auth = w.config.APIKey
} }
req := l_request.Request{ req := l_request.Request{
Url: fmt.Sprintf("%szltx_api/admin/direct/ai/%s", w.config.BaseURL, number), Url: fmt.Sprintf("%s%s", w.config.BaseURL, number),
Headers: map[string]string{ Headers: map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", auth), "Authorization": fmt.Sprintf("Bearer %s", auth),
}, },
@ -112,36 +107,7 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(ch chan []byte, c *websocket.Co
if err != nil { if err != nil {
return return
} }
var resData ZltxOrderDetailResponse c.WriteMessage(websocket.TextMessage, res.Content)
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 return
} }