This commit is contained in:
parent
fdd673810f
commit
8dd60b0877
20
config.yaml
20
config.yaml
|
@ -1,5 +1,5 @@
|
||||||
server:
|
server:
|
||||||
port: 8080
|
port: 8090
|
||||||
host: "0.0.0.0"
|
host: "0.0.0.0"
|
||||||
|
|
||||||
ollama:
|
ollama:
|
||||||
|
@ -7,12 +7,28 @@ ollama:
|
||||||
model: "qwen3:8b"
|
model: "qwen3:8b"
|
||||||
timeout: 30s
|
timeout: 30s
|
||||||
|
|
||||||
|
# 模型参数
|
||||||
|
modelParam:
|
||||||
|
temperature: 0.7
|
||||||
|
max_tokens: 2000
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
weather:
|
weather:
|
||||||
enabled: true
|
enabled: true
|
||||||
mock_data: true
|
|
||||||
calculator:
|
calculator:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
zltxOrderDetail: # 直连天下订单详情
|
||||||
|
enabled: true
|
||||||
|
base_url: https://gateway.dev.cdlsxd.cn
|
||||||
|
biz_system: "zltx"
|
||||||
|
zltxOrderLog: # 直连天下订单日志
|
||||||
|
enabled: true
|
||||||
|
base_url: https://gateway.dev.cdlsxd.cn
|
||||||
|
biz_system: "zltx"
|
||||||
|
knowledge: # 知识库
|
||||||
|
enabled: true
|
||||||
|
base_url: http://117.175.169.61:8080
|
||||||
|
api_key: sk-EfnUANKMj3DUOiEPJZ5xS8SGMsbO6be_qYAg9uZ8T3zyoFM-
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level: "info"
|
level: "info"
|
||||||
|
|
|
@ -32,12 +32,17 @@ type OllamaConfig struct {
|
||||||
type ToolsConfig struct {
|
type ToolsConfig struct {
|
||||||
Weather ToolConfig `mapstructure:"weather"`
|
Weather ToolConfig `mapstructure:"weather"`
|
||||||
Calculator ToolConfig `mapstructure:"calculator"`
|
Calculator ToolConfig `mapstructure:"calculator"`
|
||||||
|
ZltxOrderDetail ToolConfig `mapstructure:"zltxOrderDetail"`
|
||||||
|
ZltxOrderLog ToolConfig `mapstructure:"zltxOrderLog"`
|
||||||
|
Knowledge ToolConfig `mapstructure:"knowledge"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToolConfig 单个工具配置
|
// ToolConfig 单个工具配置
|
||||||
type ToolConfig struct {
|
type ToolConfig struct {
|
||||||
Enabled bool `mapstructure:"enabled"`
|
Enabled bool `mapstructure:"enabled"`
|
||||||
MockData bool `mapstructure:"mock_data"`
|
BaseURL string `mapstructure:"base_url"`
|
||||||
|
APIKey string `mapstructure:"api_key"`
|
||||||
|
BizSystem string `mapstructure:"biz_system"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoggingConfig 日志配置
|
// LoggingConfig 日志配置
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
package constants
|
||||||
|
|
||||||
|
type Caller string
|
||||||
|
|
||||||
|
const (
|
||||||
|
CallerZltx Caller = "zltx" // 直连天下
|
||||||
|
CallerHyt Caller = "hyt" // 货易通
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c Caller) String() string {
|
||||||
|
return string(c)
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package constants
|
||||||
|
|
||||||
|
type KnowledgeId string
|
||||||
|
|
||||||
|
const (
|
||||||
|
KnowledgeIdZltx KnowledgeId = "kb-00000001"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (k KnowledgeId) String() string {
|
||||||
|
return string(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
var CallerKnowledgeIdMap = map[Caller]KnowledgeId{
|
||||||
|
CallerZltx: KnowledgeIdZltx,
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetKnowledgeId(caller Caller) KnowledgeId {
|
||||||
|
if _, ok := CallerKnowledgeIdMap[caller]; !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return CallerKnowledgeIdMap[caller]
|
||||||
|
}
|
|
@ -21,14 +21,17 @@ func NewChatHandler(routerService types.RouterService) *ChatHandler {
|
||||||
|
|
||||||
// ChatRequest HTTP聊天请求
|
// ChatRequest HTTP聊天请求
|
||||||
type ChatRequest struct {
|
type ChatRequest struct {
|
||||||
Message string `json:"message" binding:"required" example:"北京今天天气怎么样?"`
|
UserInput string `json:"user_input" binding:"required" example:"考勤规则"`
|
||||||
|
Caller string `json:"caller" binding:"required" example:"zltx"`
|
||||||
|
SessionID string `json:"session_id" example:"default"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChatResponse HTTP聊天响应
|
// ChatResponse HTTP聊天响应
|
||||||
type ChatResponse struct {
|
type ChatResponse struct {
|
||||||
Message string `json:"message" example:"北京今天天气晴朗,温度15.3°C"`
|
Status string `json:"status" example:"success"` // 处理状态
|
||||||
ToolCalls []ToolCallResponse `json:"tool_calls,omitempty"`
|
Message string `json:"message" example:""` // 响应消息
|
||||||
Finished bool `json:"finished" example:"true"`
|
Data any `json:"data,omitempty"` // 响应数据
|
||||||
|
TaskCode string `json:"task_code,omitempty"` // 任务代码
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToolCallResponse 工具调用响应
|
// ToolCallResponse 工具调用响应
|
||||||
|
@ -45,46 +48,31 @@ type FunctionCallResponse struct {
|
||||||
Arguments interface{} `json:"arguments"`
|
Arguments interface{} `json:"arguments"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ErrorResponse 错误响应
|
|
||||||
type ErrorResponse struct {
|
|
||||||
Error string `json:"error" example:"Invalid request"`
|
|
||||||
Code int `json:"code" example:"400"`
|
|
||||||
Message string `json:"message" example:"请求参数错误"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chat 处理聊天请求
|
|
||||||
// @Summary 智能聊天
|
|
||||||
// @Description 发送消息给AI助手,支持工具调用
|
|
||||||
// @Tags chat
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param request body ChatRequest true "聊天请求"
|
|
||||||
// @Success 200 {object} ChatResponse "聊天响应"
|
|
||||||
// @Failure 400 {object} ErrorResponse "请求错误"
|
|
||||||
// @Failure 500 {object} ErrorResponse "服务器错误"
|
|
||||||
// @Router /api/v1/chat [post]
|
|
||||||
func (h *ChatHandler) Chat(c *gin.Context) {
|
func (h *ChatHandler) Chat(c *gin.Context) {
|
||||||
var req ChatRequest
|
var req ChatRequest
|
||||||
if err := c.ShouldBindJSON(&req); err != nil {
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||||||
c.JSON(http.StatusBadRequest, ErrorResponse{
|
c.JSON(http.StatusBadRequest, ChatResponse{
|
||||||
Error: "Invalid request",
|
Status: "error",
|
||||||
Code: http.StatusBadRequest,
|
Message: "请求参数错误",
|
||||||
Message: err.Error(),
|
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 转换为服务层请求
|
// 转换为服务层请求
|
||||||
serviceReq := &types.ChatRequest{
|
serviceReq := &types.ChatRequest{
|
||||||
Message: req.Message,
|
UserInput: req.UserInput,
|
||||||
|
Caller: req.Caller,
|
||||||
|
SessionID: req.SessionID,
|
||||||
|
ChatRequestMeta: types.ChatRequestMeta{
|
||||||
|
Authorization: c.GetHeader("Authorization"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用路由服务
|
// 调用路由服务
|
||||||
response, err := h.routerService.Route(c.Request.Context(), serviceReq)
|
response, err := h.routerService.Route(c.Request.Context(), serviceReq)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, ErrorResponse{
|
c.JSON(http.StatusInternalServerError, ChatResponse{
|
||||||
Error: "Service error",
|
Status: "error",
|
||||||
Code: http.StatusInternalServerError,
|
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
|
@ -93,38 +81,10 @@ func (h *ChatHandler) Chat(c *gin.Context) {
|
||||||
// 转换响应格式
|
// 转换响应格式
|
||||||
httpResponse := &ChatResponse{
|
httpResponse := &ChatResponse{
|
||||||
Message: response.Message,
|
Message: response.Message,
|
||||||
Finished: response.Finished,
|
Status: response.Status,
|
||||||
}
|
Data: response.Data,
|
||||||
|
TaskCode: response.TaskCode,
|
||||||
// 转换工具调用
|
|
||||||
if len(response.ToolCalls) > 0 {
|
|
||||||
httpResponse.ToolCalls = make([]ToolCallResponse, len(response.ToolCalls))
|
|
||||||
for i, toolCall := range response.ToolCalls {
|
|
||||||
httpResponse.ToolCalls[i] = ToolCallResponse{
|
|
||||||
ID: toolCall.ID,
|
|
||||||
Type: toolCall.Type,
|
|
||||||
Function: FunctionCallResponse{
|
|
||||||
Name: toolCall.Function.Name,
|
|
||||||
Arguments: toolCall.Function.Arguments,
|
|
||||||
},
|
|
||||||
Result: toolCall.Result,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, httpResponse)
|
c.JSON(http.StatusOK, httpResponse)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Health 健康检查
|
|
||||||
// @Summary 健康检查
|
|
||||||
// @Description 检查服务是否正常运行
|
|
||||||
// @Tags system
|
|
||||||
// @Produce json
|
|
||||||
// @Success 200 {object} map[string]string
|
|
||||||
// @Router /health [get]
|
|
||||||
func (h *ChatHandler) Health(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"status": "ok",
|
|
||||||
"service": "ai-scheduler",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
@ -27,9 +27,6 @@ func SetupRoutes(routerService types.RouterService) *gin.Engine {
|
||||||
// 创建处理器
|
// 创建处理器
|
||||||
chatHandler := NewChatHandler(routerService)
|
chatHandler := NewChatHandler(routerService)
|
||||||
|
|
||||||
// 健康检查
|
|
||||||
r.GET("/health", chatHandler.Health)
|
|
||||||
|
|
||||||
// API路由组
|
// API路由组
|
||||||
v1 := r.Group("/api/v1")
|
v1 := r.Group("/api/v1")
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"ai_scheduler/internal/constants"
|
||||||
"ai_scheduler/internal/tools"
|
"ai_scheduler/internal/tools"
|
||||||
"ai_scheduler/pkg/types"
|
"ai_scheduler/pkg/types"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RouterService 智能路由服务
|
// RouterService 智能路由服务
|
||||||
|
@ -27,20 +29,48 @@ func NewRouterService(aiClient types.AIClient, toolManager *tools.Manager) *Rout
|
||||||
func (r *RouterService) Route(ctx context.Context, req *types.ChatRequest) (*types.ChatResponse, error) {
|
func (r *RouterService) Route(ctx context.Context, req *types.ChatRequest) (*types.ChatResponse, error) {
|
||||||
// 构建消息
|
// 构建消息
|
||||||
messages := []types.Message{
|
messages := []types.Message{
|
||||||
|
// {
|
||||||
|
// Role: "system",
|
||||||
|
// Content: r.buildSystemPrompt(),
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
Role: "system",
|
Role: "assistant",
|
||||||
Content: r.buildSystemPrompt(),
|
Content: r.buildIntentPrompt(req.UserInput),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "user",
|
Role: "user",
|
||||||
Content: req.Message,
|
Content: req.UserInput,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取工具定义
|
// 第1次调用AI,获取用户意图
|
||||||
toolDefinitions := r.toolManager.GetToolDefinitions()
|
intentResponse, err := r.aiClient.Chat(ctx, messages, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("AI响应失败: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// 第一次调用AI,获取是否需要使用工具
|
// 从AI响应中提取意图
|
||||||
|
intent := r.extractIntent(intentResponse)
|
||||||
|
if intent == "" {
|
||||||
|
return nil, fmt.Errorf("未识别到用户意图")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch intent {
|
||||||
|
case "order_diagnosis":
|
||||||
|
// 订单诊断意图
|
||||||
|
return r.handleOrderDiagnosis(ctx, req, messages)
|
||||||
|
case "knowledge_qa":
|
||||||
|
// 知识问答意图
|
||||||
|
return r.handleKnowledgeQA(ctx, req, messages)
|
||||||
|
default:
|
||||||
|
// 未知意图
|
||||||
|
return nil, fmt.Errorf("意图识别失败,请明确您的需求呢,我可以为您")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取工具定义
|
||||||
|
toolDefinitions := r.toolManager.GetToolDefinitions(constants.Caller(req.Caller))
|
||||||
|
|
||||||
|
// 第2次调用AI,获取是否需要使用工具
|
||||||
response, err := r.aiClient.Chat(ctx, messages, toolDefinitions)
|
response, err := r.aiClient.Chat(ctx, messages, toolDefinitions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to chat with AI: %w", err)
|
return nil, fmt.Errorf("failed to chat with AI: %w", err)
|
||||||
|
@ -81,31 +111,99 @@ func (r *RouterService) Route(ctx context.Context, req *types.ChatRequest) (*typ
|
||||||
// 合并工具调用信息到最终响应
|
// 合并工具调用信息到最终响应
|
||||||
finalResponse.ToolCalls = toolResults
|
finalResponse.ToolCalls = toolResults
|
||||||
|
|
||||||
log.Printf("Router processed request: %s, used %d tools", req.Message, len(toolResults))
|
log.Printf("Router processed request: %s, used %d tools", req.UserInput, len(toolResults))
|
||||||
|
|
||||||
return finalResponse, nil
|
return finalResponse, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildSystemPrompt 构建系统提示词
|
// buildSystemPrompt 构建系统提示词
|
||||||
func (r *RouterService) buildSystemPrompt() string {
|
func (r *RouterService) buildSystemPrompt() string {
|
||||||
prompt := `你是一个智能助手,可以帮助用户解决各种问题。你有以下工具可以使用:
|
prompt := `你是一个智能路由系统,你的任务是根据用户输入判断用户的意图,并且执行对应的任务。`
|
||||||
|
|
||||||
`
|
|
||||||
|
|
||||||
// 添加工具描述
|
|
||||||
tools := r.toolManager.GetAllTools()
|
|
||||||
for _, tool := range tools {
|
|
||||||
prompt += fmt.Sprintf("- %s: %s\n", tool.Name(), tool.Description())
|
|
||||||
}
|
|
||||||
|
|
||||||
prompt += `
|
|
||||||
请根据用户的问题,判断是否需要使用工具。如果需要,请调用相应的工具获取信息,然后基于工具返回的结果给出完整的回答。
|
|
||||||
|
|
||||||
注意事项:
|
|
||||||
1. 只有在确实需要获取实时信息或进行计算时才使用工具
|
|
||||||
2. 如果用户只是普通聊天,不需要使用工具
|
|
||||||
3. 使用工具后,请基于工具返回的结果给出自然、友好的回复
|
|
||||||
4. 如果工具执行出错,请告知用户并提供替代建议`
|
|
||||||
|
|
||||||
return prompt
|
return prompt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildIntentPrompt 构建意图识别提示词
|
||||||
|
func (r *RouterService) buildIntentPrompt(userInput string) string {
|
||||||
|
prompt := `请分析以下用户输入,判断用户的意图类型。
|
||||||
|
|
||||||
|
用户输入:{user_input}
|
||||||
|
|
||||||
|
意图类型说明:
|
||||||
|
1. order_diagnosis - 订单诊断:用户想要查询、诊断或了解订单相关信息
|
||||||
|
2. knowledge_qa - 知识问答:用户想要进行一般性问答或获取知识信息
|
||||||
|
|
||||||
|
- 当用户意图不够清晰且不匹配 knowledge_qa 以外意图时,使用knowledge_qa
|
||||||
|
- 当用户意图非常不清晰时使用 unknown
|
||||||
|
|
||||||
|
请只返回以下格式的JSON:
|
||||||
|
{
|
||||||
|
"intent": "order_diagnosis" | "knowledge_qa" | "unknown",
|
||||||
|
"confidence": 0.0-1.0,
|
||||||
|
"reasoning": "判断理由"
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
prompt = strings.ReplaceAll(prompt, "{user_input}", userInput)
|
||||||
|
|
||||||
|
return prompt
|
||||||
|
}
|
||||||
|
|
||||||
|
// extractIntent 从AI响应中提取意图
|
||||||
|
func (r *RouterService) extractIntent(response *types.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 *RouterService) handleOrderDiagnosis(ctx context.Context, req *types.ChatRequest, messages []types.Message) (*types.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 *RouterService) handleKnowledgeQA(ctx context.Context, req *types.ChatRequest, messages []types.Message) (*types.ChatResponse, error) {
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package tools
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"ai_scheduler/internal/config"
|
"ai_scheduler/internal/config"
|
||||||
|
"ai_scheduler/internal/constants"
|
||||||
"ai_scheduler/pkg/types"
|
"ai_scheduler/pkg/types"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -21,7 +22,7 @@ func NewManager(config *config.ToolsConfig) *Manager {
|
||||||
|
|
||||||
// 注册天气工具
|
// 注册天气工具
|
||||||
if config.Weather.Enabled {
|
if config.Weather.Enabled {
|
||||||
weatherTool := NewWeatherTool(config.Weather.MockData)
|
weatherTool := NewWeatherTool()
|
||||||
m.tools[weatherTool.Name()] = weatherTool
|
m.tools[weatherTool.Name()] = weatherTool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +32,24 @@ func NewManager(config *config.ToolsConfig) *Manager {
|
||||||
m.tools[calcTool.Name()] = calcTool
|
m.tools[calcTool.Name()] = calcTool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 注册知识库工具
|
||||||
|
// if config.Knowledge.Enabled {
|
||||||
|
// knowledgeTool := NewKnowledgeTool()
|
||||||
|
// m.tools[knowledgeTool.Name()] = knowledgeTool
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 注册直连天下订单详情工具
|
||||||
|
if config.ZltxOrderDetail.Enabled {
|
||||||
|
zltxOrderDetailTool := NewZltxOrderDetailTool(config.ZltxOrderDetail)
|
||||||
|
m.tools[zltxOrderDetailTool.Name()] = zltxOrderDetailTool
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注册直连天下订单日志工具
|
||||||
|
// if config.ZltxOrderLog.Enabled {
|
||||||
|
// zltxOrderLogTool := NewZltxOrderLogTool(config.ZltxOrderLog)
|
||||||
|
// m.tools[zltxOrderLogTool.Name()] = zltxOrderLogTool
|
||||||
|
// }
|
||||||
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,11 +69,12 @@ func (m *Manager) GetAllTools() []types.Tool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetToolDefinitions 获取所有工具定义
|
// GetToolDefinitions 获取所有工具定义
|
||||||
func (m *Manager) GetToolDefinitions() []types.ToolDefinition {
|
func (m *Manager) GetToolDefinitions(caller constants.Caller) []types.ToolDefinition {
|
||||||
definitions := make([]types.ToolDefinition, 0, len(m.tools))
|
definitions := make([]types.ToolDefinition, 0, len(m.tools))
|
||||||
for _, tool := range m.tools {
|
for _, tool := range m.tools {
|
||||||
definitions = append(definitions, tool.Definition())
|
definitions = append(definitions, tool.Definition())
|
||||||
}
|
}
|
||||||
|
|
||||||
return definitions
|
return definitions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,10 +15,8 @@ type WeatherTool struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewWeatherTool 创建天气工具
|
// NewWeatherTool 创建天气工具
|
||||||
func NewWeatherTool(mockData bool) *WeatherTool {
|
func NewWeatherTool() *WeatherTool {
|
||||||
return &WeatherTool{
|
return &WeatherTool{}
|
||||||
mockData: mockData,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name 返回工具名称
|
// Name 返回工具名称
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
"ai_scheduler/internal/config"
|
||||||
|
"ai_scheduler/pkg/types"
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ZltxOrderDetailTool 直连天下订单详情工具
|
||||||
|
type ZltxOrderDetailTool struct {
|
||||||
|
config config.ToolConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewZltxOrderDetailTool 创建直连天下订单详情工具
|
||||||
|
func NewZltxOrderDetailTool(config config.ToolConfig) *ZltxOrderDetailTool {
|
||||||
|
return &ZltxOrderDetailTool{config: config}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Name 返回工具名称
|
||||||
|
func (w *ZltxOrderDetailTool) Name() string {
|
||||||
|
return "zltxOrderDetail"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description 返回工具描述
|
||||||
|
func (w *ZltxOrderDetailTool) Description() string {
|
||||||
|
return "获取直连天下订单详情"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Definition 返回工具定义
|
||||||
|
func (w *ZltxOrderDetailTool) Definition() types.ToolDefinition {
|
||||||
|
return types.ToolDefinition{
|
||||||
|
Type: "function",
|
||||||
|
Function: types.FunctionDef{
|
||||||
|
Name: w.Name(),
|
||||||
|
Description: w.Description(),
|
||||||
|
Parameters: map[string]interface{}{
|
||||||
|
"type": "object",
|
||||||
|
"properties": map[string]interface{}{
|
||||||
|
"number": map[string]interface{}{
|
||||||
|
"type": "string",
|
||||||
|
"description": "订单编号/流水号",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"required": []string{"number"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZltxOrderDetailRequest 直连天下订单详情请求参数
|
||||||
|
type ZltxOrderDetailRequest struct {
|
||||||
|
Number string `json:"number"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZltxOrderDetailResponse 直连天下订单详情响应
|
||||||
|
type ZltxOrderDetailResponse struct {
|
||||||
|
Code int `json:"code"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
Data ZltxOrderDetailData `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZltxOrderDetailData 直连天下订单详情数据
|
||||||
|
type ZltxOrderDetailData struct {
|
||||||
|
Direct map[string]any `json:"direct"`
|
||||||
|
Order map[string]any `json:"order"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute 执行直连天下订单详情查询
|
||||||
|
func (w *ZltxOrderDetailTool) Execute(ctx context.Context, args json.RawMessage) (interface{}, error) {
|
||||||
|
var req ZltxOrderDetailRequest
|
||||||
|
if err := json.Unmarshal(args, &req); err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid zltxOrderDetail request: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Number == "" {
|
||||||
|
return nil, fmt.Errorf("number is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 这里可以集成真实的直连天下订单详情API
|
||||||
|
return w.getZltxOrderDetail(ctx, req.Number), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// getMockZltxOrderDetail 获取模拟直连天下订单详情数据
|
||||||
|
func (w *ZltxOrderDetailTool) getZltxOrderDetail(ctx context.Context, number string) *ZltxOrderDetailResponse {
|
||||||
|
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{}
|
||||||
|
}
|
||||||
|
req.Header.Set("Authorization", authorization)
|
||||||
|
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return &ZltxOrderDetailResponse{}
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
return &ZltxOrderDetailResponse{}
|
||||||
|
}
|
|
@ -7,15 +7,23 @@ import (
|
||||||
|
|
||||||
// ChatRequest 聊天请求
|
// ChatRequest 聊天请求
|
||||||
type ChatRequest struct {
|
type ChatRequest struct {
|
||||||
Message string `json:"message" binding:"required"`
|
UserInput string `json:"user_input" binding:"required"`
|
||||||
Model string `json:"model,omitempty"`
|
Caller string `json:"caller" binding:"required"`
|
||||||
|
SessionID string `json:"session_id"`
|
||||||
|
ChatRequestMeta ChatRequestMeta `json:"meta,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChatRequestMeta 聊天请求元数据
|
||||||
|
type ChatRequestMeta struct {
|
||||||
|
Authorization string `json:"authorization"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChatResponse 聊天响应
|
// ChatResponse 聊天响应
|
||||||
type ChatResponse struct {
|
type ChatResponse struct {
|
||||||
|
Status string `json:"status"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
ToolCalls []ToolCall `json:"tool_calls,omitempty"`
|
Data any `json:"data,omitempty"`
|
||||||
Finished bool `json:"finished"`
|
TaskCode string `json:"task_code,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToolCall 工具调用
|
// ToolCall 工具调用
|
||||||
|
|
Loading…
Reference in New Issue