fix: 优化负利润分析和缓存处理逻辑

This commit is contained in:
renzhiyuan 2026-01-19 15:32:45 +08:00
parent fab60c6fc8
commit c4e2d30fc5
21 changed files with 160 additions and 69 deletions

View File

@ -4,10 +4,10 @@ server:
host: "0.0.0.0" host: "0.0.0.0"
ollama: ollama:
base_url: "http://127.0.0.1:11434" base_url: "http://192.168.6.115:11434"
model: "qwen3-coder:480b-cloud" model: "qwen3:8b"
generate_model: "qwen3-coder:480b-cloud" generate_model: "qwen3:8b"
mapping_model: "deepseek-v3.2:cloud" mapping_model: "qwen3:8b"
vl_model: "gemini-3-pro-preview" vl_model: "gemini-3-pro-preview"
timeout: "120s" timeout: "120s"
level: "info" level: "info"
@ -26,11 +26,11 @@ coze:
lsxd: lsxd:
# 统一登录 # 统一登录
login_url: "https://api.user.1688sup.com/v1/login/phone" login_url: "http://api.test.user.1688sup.com/v1/login/phone"
phone: "ORlviZN7N06W2+WKLe76xg==" phone: "OFJ8UpqOlI7+w3Qklf36ZA=="
password: "V5Uh8C4bamEM6UQZh4TCeQ==" password: "tEbFegH/DRRh6LutFb7o3g=="
code: "456789" code: "123456"
check_token_url: "https://api.user.1688sup.com/v1/user/welcome" check_token_url: "http://api.test.user.1688sup.com/v1/user/welcome"
sys: sys:
@ -43,7 +43,7 @@ redis:
host: 47.97.27.195:6379 host: 47.97.27.195:6379
type: node type: node
pass: lansexiongdi@666 pass: lansexiongdi@666
key: ai_scheduler-test key: ai_scheduler_test
pollSize: 5 #连接池大小不配置或配置为0表示不启用连接池 pollSize: 5 #连接池大小不配置或配置为0表示不启用连接池
minIdleConns: 2 #最小空闲连接数 minIdleConns: 2 #最小空闲连接数
maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭 maxIdleTime: 30 #每个连接最大空闲时间,如果超过了这个时间会被关闭

View File

@ -9,6 +9,7 @@ import (
"ai_scheduler/internal/data/impl" "ai_scheduler/internal/data/impl"
"ai_scheduler/internal/data/model" "ai_scheduler/internal/data/model"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg"
"ai_scheduler/internal/tools" "ai_scheduler/internal/tools"
"ai_scheduler/internal/tools/bbxt" "ai_scheduler/internal/tools/bbxt"
"ai_scheduler/tmpl/dataTemp" "ai_scheduler/tmpl/dataTemp"
@ -223,11 +224,16 @@ func (d *DingTalkBotBiz) recognize(ctx context.Context, requireData *entitys.Req
rec.Tasks = append(rec.Tasks, entitys.RegistrationTask{ rec.Tasks = append(rec.Tasks, entitys.RegistrationTask{
Name: task.Index, Name: task.Index,
Desc: task.Desc, Desc: task.TempPrompt,
TaskConfigDetail: taskConfig, // 直接使用解析后的配置,避免重复构建 TaskConfigDetail: taskConfig, // 直接使用解析后的配置,避免重复构建
}) })
} }
} }
rec.Ext = pkg.JsonByteIgonErr(&entitys.TaskExt{
UserName: requireData.Req.SenderNick,
})
err = d.handle.Recognize(ctx, rec, &do.WithDingTalkBot{}) err = d.handle.Recognize(ctx, rec, &do.WithDingTalkBot{})
return return
} }
@ -393,7 +399,7 @@ func (d *DingTalkBotBiz) defaultPrompt() string {
- 注意区分 parameters 中的 必须参数required 可选参数optional按下述参数提取规则处理 - 注意区分 parameters 中的 必须参数required 可选参数optional按下述参数提取规则处理
- **完全无法匹配**立即设置 is_match: false并在 chat 中已第一人称的角度提醒用户需要适用何种工具"请问您是要查询订单还是商品呢" - **完全无法匹配**立即设置 is_match: false并在 chat 中已第一人称的角度提醒用户需要适用何种工具"请问您是要查询订单还是商品呢"
1. **参数提取** 3. **参数提取**
- 根据 parameters 字段列出的参数名从用户输入中提取对应值 - 根据 parameters 字段列出的参数名从用户输入中提取对应值
- **仅提取**明确提及的参数忽略未列出的内容 - **仅提取**明确提及的参数忽略未列出的内容

View File

@ -133,7 +133,9 @@ func (r *Handle) HandleMatch(ctx context.Context, client *gateway.Client, rec *e
case constants.TaskTypeFunc: case constants.TaskTypeFunc:
return r.handleTask(ctx, rec, pointTask) return r.handleTask(ctx, rec, pointTask)
case constants.TaskTypeBot: case constants.TaskTypeBot:
return r.handleBot(ctx, rec, pointTask) return r.HandleBot(ctx, rec, &entitys.Task{
Index: pointTask.Index,
})
case constants.TaskTypeEinoWorkflow: case constants.TaskTypeEinoWorkflow:
return r.handleEinoWorkflow(ctx, rec, pointTask) return r.handleEinoWorkflow(ctx, rec, pointTask)
case constants.TaskTypeCozeWorkflow: case constants.TaskTypeCozeWorkflow:
@ -247,23 +249,34 @@ func (r *Handle) handleKnowle(ctx context.Context, rec *entitys.Recognize, task
} }
// bot 临时实现,后续转到 eino 工作流 // bot 临时实现,后续转到 eino 工作流
func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *model.AiTask) (err error) { func (r *Handle) HandleBot(ctx context.Context, rec *entitys.Recognize, task *entitys.Task) (err error) {
if task.Index == "bug_optimization_submit" { if task.Index == "bug_optimization_submit" {
entitys.ResLoading(rec.Ch, task.Index, "需求记录中...") var unionId string
entitys.ResLoading(rec.Ch, task.Index, "需求记录中...\n")
// Ext 中获取 sessionId
sessionID := rec.GetSession()
// 获取dingtalk accessToken // 获取dingtalk accessToken
accessToken, _ := r.dingtalkOldClient.GetAccessToken() accessToken, _ := r.dingtalkOldClient.GetAccessToken()
// Ext 中获取 sessionId
taskExt := rec.GetTaskExt()
if taskExt == nil {
return errorcode.ParamErr("taskExt参数错误")
}
if len(taskExt.Session) > 0 {
// 获取创建者 dingtalk unionId // 获取创建者 dingtalk unionId
unionId := r.getUserDingtalkUnionId(ctx, accessToken, sessionID) unionId = r.getUserDingtalkUnionId(ctx, accessToken, taskExt.Session)
} else if len(taskExt.UserName) > 0 {
unionId = r.getUserDingtalkUnionIdWithUserName(ctx, accessToken, taskExt.UserName)
} else {
return errorcode.ParamErr("taskExt参数错误,重要参数缺失")
}
// 附件url // 附件url
var attachmentUrl string var attachmentUrl string
for _, file := range rec.UserContent.File { for _, file := range rec.UserContent.File {
attachmentUrl = file.FileUrl attachmentUrl = file.FileUrl
break break
} }
recordId, err := r.dingtalkNotableClient.InsertRecord(accessToken, &dingtalk.InsertRecordReq{
req := &dingtalk.InsertRecordReq{
BaseId: r.conf.Dingtalk.TableDemand.BaseId, BaseId: r.conf.Dingtalk.TableDemand.BaseId,
SheetIdOrName: r.conf.Dingtalk.TableDemand.SheetIdOrName, SheetIdOrName: r.conf.Dingtalk.TableDemand.SheetIdOrName,
// OperatorId: tool_callback.BotBugOptimizationSubmitAdminUnionId, // OperatorId: tool_callback.BotBugOptimizationSubmitAdminUnionId,
@ -271,7 +284,9 @@ func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *mo
CreatorUnionId: unionId, CreatorUnionId: unionId,
Content: rec.UserContent.Text, Content: rec.UserContent.Text,
AttachmentUrl: attachmentUrl, AttachmentUrl: attachmentUrl,
}) }
recordId, err := r.dingtalkNotableClient.InsertRecord(accessToken, req)
if err != nil { if err != nil {
errCode := r.dingtalkNotableClient.GetHTTPStatus(err) errCode := r.dingtalkNotableClient.GetHTTPStatus(err)
// 权限不足 // 权限不足
@ -284,12 +299,16 @@ func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *mo
if recordId == "" { if recordId == "" {
return errors.NewBusinessErr(422, "创建记录失败,请联系管理员") return errors.NewBusinessErr(422, "创建记录失败,请联系管理员")
} }
var detailPage string
entitys.ResLog(rec.Ch, task.Index, "需求记录完成") entitys.ResLog(rec.Ch, task.Index, "需求记录完成")
switch task.OutPutFormat {
case entitys.OutPutFormatMarkdown:
// 构建跳转链接 // 构建跳转链接
detailPage := util.BuildJumpLink(r.conf.Dingtalk.TableDemand.Url, "去查看") detailPage = "[去查看](" + r.conf.Dingtalk.TableDemand.Url + ")"
default:
// 构建跳转链接
detailPage = util.BuildJumpLink(r.conf.Dingtalk.TableDemand.Url, "去查看")
}
entitys.ResText(rec.Ch, task.Index, fmt.Sprintf("需求已记录,正在分配相关人员处理,请您耐心等待处理结果。点击查看工单进度:%s", detailPage)) entitys.ResText(rec.Ch, task.Index, fmt.Sprintf("需求已记录,正在分配相关人员处理,请您耐心等待处理结果。点击查看工单进度:%s", detailPage))
return nil return nil
@ -300,16 +319,21 @@ func (r *Handle) handleBot(ctx context.Context, rec *entitys.Recognize, task *mo
// getUserDingtalkUnionId 获取用户的 dingtalk unionId // getUserDingtalkUnionId 获取用户的 dingtalk unionId
func (r *Handle) getUserDingtalkUnionId(ctx context.Context, accessToken, sessionID string) (unionId string) { func (r *Handle) getUserDingtalkUnionId(ctx context.Context, accessToken, sessionID string) (unionId string) {
if len(sessionID) == 0 {
// 查询用户名 // 查询用户名
return ""
}
session, has, err := r.sessionImpl.FindOne(r.sessionImpl.WithSessionId(sessionID)) session, has, err := r.sessionImpl.FindOne(r.sessionImpl.WithSessionId(sessionID))
if err != nil || !has { if err != nil || !has {
log.Warnf("session not found: %s", sessionID) log.Warnf("session not found: %s", sessionID)
return return
} }
creatorName := session.UserName return r.getUserDingtalkUnionIdWithUserName(ctx, accessToken, session.UserName)
}
func (r *Handle) getUserDingtalkUnionIdWithUserName(ctx context.Context, accessToken, userName string) (unionId string) {
// 获取创建者uid 用户名 -> dingtalk uid // 获取创建者uid 用户名 -> dingtalk uid
creatorId, err := r.dingtalkContactClient.SearchUserOne(accessToken, creatorName) creatorId, err := r.dingtalkContactClient.SearchUserOne(accessToken, userName)
if err != nil { if err != nil {
log.Warnf("search dingtalk user one failed: %v", err) log.Warnf("search dingtalk user one failed: %v", err)
return return

View File

@ -166,6 +166,7 @@ func (f *WithDingTalkBot) getUserContent(ctx context.Context, rec *entitys.Recog
} }
if len(rec.ChatHis.Messages) > 0 { if len(rec.ChatHis.Messages) > 0 {
content.WriteString("\n")
content.WriteString("### 引用历史聊天记录:\n") content.WriteString("### 引用历史聊天记录:\n")
content.WriteString(pkg.JsonStringIgonErr(rec.ChatHis)) content.WriteString(pkg.JsonStringIgonErr(rec.ChatHis))
} }

View File

@ -42,6 +42,7 @@ type GroupConfigBiz struct {
conf *config.Config conf *config.Config
rdb *utils.Rdb rdb *utils.Rdb
macro *do.Macro macro *do.Macro
handle *do.Handle
} }
// NewDingTalkBotBiz // NewDingTalkBotBiz
@ -54,6 +55,8 @@ func NewGroupConfigBiz(
reportDailyCacheImpl *impl.ReportDailyCacheImpl, reportDailyCacheImpl *impl.ReportDailyCacheImpl,
rdb *utils.Rdb, rdb *utils.Rdb,
macro *do.Macro, macro *do.Macro,
toolManager *tools.Manager,
handle *do.Handle,
) *GroupConfigBiz { ) *GroupConfigBiz {
return &GroupConfigBiz{ return &GroupConfigBiz{
botTools: tools.BootTools, botTools: tools.BootTools,
@ -64,6 +67,8 @@ func NewGroupConfigBiz(
reportDailyCacheImpl: reportDailyCacheImpl, reportDailyCacheImpl: reportDailyCacheImpl,
rdb: rdb, rdb: rdb,
macro: macro, macro: macro,
toolManager: toolManager,
handle: handle,
} }
} }
@ -254,6 +259,11 @@ func (g *GroupConfigBiz) handleMatch(ctx context.Context, rec *entitys.Recognize
switch constants.TaskType(pointTask.Type) { switch constants.TaskType(pointTask.Type) {
case constants.TaskTypeFunc: case constants.TaskTypeFunc:
return g.handleTask(ctx, rec, pointTask) return g.handleTask(ctx, rec, pointTask)
case constants.TaskTypeBot:
return g.handle.HandleBot(ctx, rec, &entitys.Task{
Index: pointTask.Index,
OutPutFormat: entitys.OutPutFormatMarkdown,
})
case constants.TaskTypeReport: case constants.TaskTypeReport:
return g.handleReport(ctx, rec, pointTask, groupConfig) return g.handleReport(ctx, rec, pointTask, groupConfig)
case constants.TaskTypeCozeWorkflow: case constants.TaskTypeCozeWorkflow:
@ -303,7 +313,6 @@ func (q *GroupConfigBiz) handleTask(ctx context.Context, rec *entitys.Recognize,
if err != nil { if err != nil {
return return
} }
err = q.toolManager.ExecuteTool(ctx, configData.Tool, rec) err = q.toolManager.ExecuteTool(ctx, configData.Tool, rec)
if err != nil { if err != nil {
return return

View File

@ -21,3 +21,13 @@ type DingTalkBot struct {
ClientId string `json:"client_id"` ClientId string `json:"client_id"`
ClientSecret string `json:"client_secret"` ClientSecret string `json:"client_secret"`
} }
type Task struct {
Index string `json:"bot_index"`
OutPutFormat OutPutFormat `json:"out_put_format"`
}
type OutPutFormat string
const OutPutFormatMarkdown OutPutFormat = "markdown"
const OutPutFormatHtml OutPutFormat = "html"

View File

@ -23,6 +23,7 @@ type TaskExt struct {
SessionInfo model.AiSession SessionInfo model.AiSession
Sys model.AiSy Sys model.AiSy
KnowledgeConf KnowledgeBaseRequest KnowledgeConf KnowledgeBaseRequest
UserName string
} }
type RegistrationTask struct { type RegistrationTask struct {

View File

@ -64,7 +64,9 @@ type FunctionCall struct {
type ToolDefinition struct { type ToolDefinition struct {
Type string `json:"type"` Type string `json:"type"`
Function FunctionDef `json:"function"` Function FunctionDef `json:"function"`
AuthFunc AuthFunc `json:"function"`
} }
type AuthFunc func(rec *Recognize) (token []byte, err error)
// FunctionDef 函数定义 // FunctionDef 函数定义
type FunctionDef struct { type FunctionDef struct {
@ -77,7 +79,7 @@ type FunctionDef struct {
type Tool interface { type Tool interface {
Name() string Name() string
Description() string Description() string
Definition() ToolDefinition Definition(ctx context.Context) ToolDefinition
Execute(ctx context.Context, requireData *Recognize) error Execute(ctx context.Context, requireData *Recognize) error
} }

View File

@ -6,6 +6,7 @@ import (
"ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/pkg/utils_ollama"
"ai_scheduler/internal/tools/public" "ai_scheduler/internal/tools/public"
zltxtool "ai_scheduler/internal/tools/zltx" zltxtool "ai_scheduler/internal/tools/zltx"
"ai_scheduler/utils"
"context" "context"
"fmt" "fmt"
@ -15,10 +16,11 @@ import (
type Manager struct { type Manager struct {
tools map[string]entitys.Tool tools map[string]entitys.Tool
llm *utils_ollama.Client llm *utils_ollama.Client
rdb *utils.Rdb
} }
// NewManager 创建工具管理器 // NewManager 创建工具管理器
func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager { func NewManager(config *config.Config, llm *utils_ollama.Client, rdb *utils.Rdb) *Manager {
m := &Manager{ m := &Manager{
tools: make(map[string]entitys.Tool), tools: make(map[string]entitys.Tool),
llm: llm, llm: llm,
@ -26,7 +28,7 @@ func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager {
// 注册直连天下订单详情工具 // 注册直连天下订单详情工具
if config.Tools.ZltxOrderDetail.Enabled { if config.Tools.ZltxOrderDetail.Enabled {
zltxOrderDetailTool := zltxtool.NewZltxOrderDetailTool(config.Tools.ZltxOrderDetail, m.llm) zltxOrderDetailTool := zltxtool.NewZltxOrderDetailTool(config, rdb, m.llm)
m.tools[zltxOrderDetailTool.Name()] = zltxOrderDetailTool m.tools[zltxOrderDetailTool.Name()] = zltxOrderDetailTool
} }
@ -43,7 +45,7 @@ func NewManager(config *config.Config, llm *utils_ollama.Client) *Manager {
} }
//注册直连天下订单统计工具 //注册直连天下订单统计工具
if config.Tools.ZltxOrderStatistics.Enabled { if config.Tools.ZltxOrderStatistics.Enabled {
zltxOrderStatisticsTool := zltxtool.NewZltxOrderStatisticsTool(config.Tools.ZltxOrderStatistics) zltxOrderStatisticsTool := zltxtool.NewZltxOrderStatisticsTool(config, rdb)
m.tools[zltxOrderStatisticsTool.Name()] = zltxOrderStatisticsTool m.tools[zltxOrderStatisticsTool.Name()] = zltxOrderStatisticsTool
} }
@ -104,5 +106,10 @@ func (m *Manager) ExecuteTool(ctx context.Context, name string, rec *entitys.Rec
return fmt.Errorf("tool not found: %s", name) return fmt.Errorf("tool not found: %s", name)
} }
return m.ExecuteToolWithToolObj(ctx, tool, rec)
}
// ExecuteTool 执行工具
func (m *Manager) ExecuteToolWithToolObj(ctx context.Context, tool entitys.Tool, rec *entitys.Recognize) error {
return tool.Execute(ctx, rec) return tool.Execute(ctx, rec)
} }

View File

@ -50,7 +50,7 @@ func (c *CozeCompany) Description() string {
} }
// Definition 返回工具定义 // Definition 返回工具定义
func (c *CozeCompany) Definition() entitys.ToolDefinition { func (c *CozeCompany) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{

View File

@ -47,7 +47,7 @@ func (c *CozeExpress) Description() string {
} }
// Definition 返回工具定义 // Definition 返回工具定义
func (c *CozeExpress) Definition() entitys.ToolDefinition { func (c *CozeExpress) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{

View File

@ -38,7 +38,7 @@ func (k *KnowledgeBaseTool) Description() string {
} }
// Definition 返回工具定义 // Definition 返回工具定义
func (k *KnowledgeBaseTool) Definition() entitys.ToolDefinition { func (k *KnowledgeBaseTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{

View File

@ -38,7 +38,7 @@ type NormalChat struct {
} }
// Definition 返回工具定义 // Definition 返回工具定义
func (w *NormalChatTool) Definition() entitys.ToolDefinition { func (w *NormalChatTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{} return entitys.ToolDefinition{}
} }

View File

@ -35,7 +35,7 @@ func (w *WeatherTool) Description() string {
} }
// Definition 返回工具定义 // Definition 返回工具定义
func (w *WeatherTool) Definition() entitys.ToolDefinition { func (w *WeatherTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{

View File

@ -33,7 +33,7 @@ func (t *OrderAfterSaleResellerTool) Description() string {
} }
// 未使用-仅实现接口 // 未使用-仅实现接口
func (t *OrderAfterSaleResellerTool) Definition() entitys.ToolDefinition { func (t *OrderAfterSaleResellerTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{} return entitys.ToolDefinition{}
} }

View File

@ -31,7 +31,7 @@ func (t *OrderAfterSaleResellerBatchTool) Description() string {
} }
// 未使用-仅实现接口 // 未使用-仅实现接口
func (t *OrderAfterSaleResellerBatchTool) Definition() entitys.ToolDefinition { func (t *OrderAfterSaleResellerBatchTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{} return entitys.ToolDefinition{}
} }

View File

@ -33,7 +33,7 @@ func (t *OrderAfterSaleSupplierTool) Description() string {
} }
// 未使用-仅实现接口 // 未使用-仅实现接口
func (t *OrderAfterSaleSupplierTool) Definition() entitys.ToolDefinition { func (t *OrderAfterSaleSupplierTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{} return entitys.ToolDefinition{}
} }

View File

@ -4,26 +4,28 @@ import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg" "ai_scheduler/internal/pkg"
"ai_scheduler/internal/pkg/lsxd"
"ai_scheduler/internal/pkg/rec_extra" "ai_scheduler/internal/pkg/rec_extra"
"ai_scheduler/internal/pkg/utils_ollama" "ai_scheduler/internal/pkg/utils_ollama"
"ai_scheduler/utils"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"gitea.cdlsxd.cn/self-tools/l_request" "gitea.cdlsxd.cn/self-tools/l_request"
"github.com/gofiber/fiber/v2/log"
"github.com/ollama/ollama/api" "github.com/ollama/ollama/api"
) )
// ZltxOrderDetailTool 直连天下订单详情工具 // ZltxOrderDetailTool 直连天下订单详情工具
type ZltxOrderDetailTool struct { type ZltxOrderDetailTool struct {
config config.ToolConfig config *config.Config
llm *utils_ollama.Client llm *utils_ollama.Client
rdb *utils.Rdb
} }
// NewZltxOrderDetailTool 创建直连天下订单详情工具 // NewZltxOrderDetailTool 创建直连天下订单详情工具
func NewZltxOrderDetailTool(config config.ToolConfig, llm *utils_ollama.Client) *ZltxOrderDetailTool { func NewZltxOrderDetailTool(config *config.Config, rdb *utils.Rdb, llm *utils_ollama.Client) *ZltxOrderDetailTool {
return &ZltxOrderDetailTool{config: config, llm: llm} return &ZltxOrderDetailTool{config: config, rdb: rdb, llm: llm}
} }
// Name 返回工具名称 // Name 返回工具名称
@ -37,7 +39,7 @@ func (w *ZltxOrderDetailTool) Description() string {
} }
// Definition 返回工具定义 // Definition 返回工具定义
func (w *ZltxOrderDetailTool) Definition() entitys.ToolDefinition { func (w *ZltxOrderDetailTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{
@ -54,6 +56,19 @@ func (w *ZltxOrderDetailTool) Definition() entitys.ToolDefinition {
"required": []string{"number"}, "required": []string{"number"},
}, },
}, },
AuthFunc: func(rec *entitys.Recognize) ([]byte, error) {
ext, err := rec_extra.GetTaskRecExt(rec)
if err != nil {
return nil, err
}
if len(ext.Auth) > 0 {
return []byte(ext.Auth), nil
} else {
login := lsxd.NewLogin(w.config, w.rdb)
token := login.GetToken(ctx)
return []byte(token), nil
}
},
} }
} }
@ -93,7 +108,7 @@ func (w *ZltxOrderDetailTool) Execute(ctx context.Context, rec *entitys.Recogniz
} }
// 这里可以集成真实的直连天下订单详情API // 这里可以集成真实的直连天下订单详情API
return w.getZltxOrderDetail(rec, req.OrderNumber) return w.getZltxOrderDetail(ctx, rec, req.OrderNumber)
} }
func (r *ZltxOrderDetailRequest) UnmarshalJSON(data []byte) error { func (r *ZltxOrderDetailRequest) UnmarshalJSON(data []byte) error {
@ -113,8 +128,8 @@ func (r *ZltxOrderDetailRequest) UnmarshalJSON(data []byte) error {
} }
// getMockZltxOrderDetail 获取模拟直连天下订单详情数据 // getMockZltxOrderDetail 获取模拟直连天下订单详情数据
func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number interface{}) (err error) { func (w *ZltxOrderDetailTool) getZltxOrderDetail(ctx context.Context, rec *entitys.Recognize, number interface{}) (err error) {
log.Infof("订单编号:%v,类型:%v")
var orderNum string var orderNum string
switch number.(type) { switch number.(type) {
case int, int32, int64: case int, int32, int64:
@ -127,15 +142,15 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number
orderNum = fmt.Sprintf("%v", number) orderNum = fmt.Sprintf("%v", number)
} }
ext, err := rec_extra.GetTaskRecExt(rec) token, err := w.Definition(ctx).AuthFunc(rec)
if err != nil { if err != nil {
return return err
} }
//查询订单详情 //查询订单详情
req := l_request.Request{ req := l_request.Request{
Url: fmt.Sprintf(w.config.BaseURL, orderNum), Url: fmt.Sprintf(w.config.Tools.ZltxOrderDetail.BaseURL, orderNum),
Headers: map[string]string{ Headers: map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", ext.Auth), "Authorization": fmt.Sprintf("Bearer %s", token),
}, },
Method: "GET", Method: "GET",
} }
@ -160,11 +175,10 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number
if resData.Data.Direct != nil { if resData.Data.Direct != nil {
entitys.ResLoading(rec.Ch, w.Name(), "正在分析订单日志") entitys.ResLoading(rec.Ch, w.Name(), "正在分析订单日志")
req = l_request.Request{ req = l_request.Request{
Url: fmt.Sprintf(w.config.AddURL, resData.Data.Direct["orderOrderNumber"].(string), resData.Data.Direct["serialNumber"].(string)), Url: fmt.Sprintf(w.config.Tools.ZltxOrderDetail.AddURL, resData.Data.Direct["orderOrderNumber"].(string), resData.Data.Direct["serialNumber"].(string)),
Headers: map[string]string{ Headers: map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", ext.Auth), "Authorization": fmt.Sprintf("Bearer %s", token),
}, },
Method: "GET", Method: "GET",
} }
@ -184,7 +198,7 @@ func (w *ZltxOrderDetailTool) getZltxOrderDetail(rec *entitys.Recognize, number
return fmt.Errorf("订单日志解析失败:%s", err) return fmt.Errorf("订单日志解析失败:%s", err)
} }
err = w.llm.ChatStream(context.TODO(), rec.Ch, []api.Message{ err = w.llm.ChatStream(ctx, rec.Ch, []api.Message{
{ {
Role: "system", Role: "system",
Content: "你是一个订单日志助手。用户可能会提供订单日志,你需要按以下规则处理:\n" + Content: "你是一个订单日志助手。用户可能会提供订单日志,你需要按以下规则处理:\n" +

View File

@ -23,7 +23,7 @@ func (t *ZltxOrderLogTool) Description() string {
return "查询订单日志" return "查询订单日志"
} }
func (t *ZltxOrderLogTool) Definition() entitys.ToolDefinition { func (t *ZltxOrderLogTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{

View File

@ -25,7 +25,7 @@ func (z ZltxProductTool) Description() string {
return "获取直连天下商品信息" return "获取直连天下商品信息"
} }
func (z ZltxProductTool) Definition() entitys.ToolDefinition { func (z ZltxProductTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{

View File

@ -3,7 +3,9 @@ package zltx
import ( import (
"ai_scheduler/internal/config" "ai_scheduler/internal/config"
"ai_scheduler/internal/entitys" "ai_scheduler/internal/entitys"
"ai_scheduler/internal/pkg/lsxd"
"ai_scheduler/internal/pkg/rec_extra" "ai_scheduler/internal/pkg/rec_extra"
"ai_scheduler/utils"
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
@ -13,7 +15,8 @@ import (
) )
type ZltxOrderStatisticsTool struct { type ZltxOrderStatisticsTool struct {
config config.ToolConfig config *config.Config
rdb *utils.Rdb
} }
func (z ZltxOrderStatisticsTool) Name() string { func (z ZltxOrderStatisticsTool) Name() string {
@ -24,7 +27,7 @@ func (z ZltxOrderStatisticsTool) Description() string {
return "通过账号获取订单统计信息" return "通过账号获取订单统计信息"
} }
func (z ZltxOrderStatisticsTool) Definition() entitys.ToolDefinition { func (z ZltxOrderStatisticsTool) Definition(ctx context.Context) entitys.ToolDefinition {
return entitys.ToolDefinition{ return entitys.ToolDefinition{
Type: "function", Type: "function",
Function: entitys.FunctionDef{ Function: entitys.FunctionDef{
@ -41,6 +44,19 @@ func (z ZltxOrderStatisticsTool) Definition() entitys.ToolDefinition {
"required": []string{"number"}, "required": []string{"number"},
}, },
}, },
AuthFunc: func(rec *entitys.Recognize) ([]byte, error) {
ext, err := rec_extra.GetTaskRecExt(rec)
if err != nil {
return nil, err
}
if len(ext.Auth) > 0 {
return []byte(ext.Auth), nil
} else {
login := lsxd.NewLogin(z.config, z.rdb)
token := login.GetToken(ctx)
return []byte(token), nil
}
},
} }
} }
@ -56,7 +72,7 @@ func (z ZltxOrderStatisticsTool) Execute(ctx context.Context, rec *entitys.Recog
if req.Number == nil { if req.Number == nil {
return fmt.Errorf("number is required") return fmt.Errorf("number is required")
} }
return z.getZltxOrderStatistics(req.Number, rec) return z.getZltxOrderStatistics(ctx, req.Number, rec)
} }
type ZltxOrderStatisticsResponse struct { type ZltxOrderStatisticsResponse struct {
@ -76,17 +92,17 @@ type ZltxOrderStatisticsData struct {
Total int `json:"total"` Total int `json:"total"`
} }
func (z ZltxOrderStatisticsTool) getZltxOrderStatistics(number interface{}, rec *entitys.Recognize) error { func (z ZltxOrderStatisticsTool) getZltxOrderStatistics(ctx context.Context, number interface{}, rec *entitys.Recognize) error {
ext, err := rec_extra.GetTaskRecExt(rec) token, err := z.Definition(ctx).AuthFunc(rec)
if err != nil { if err != nil {
return err return err
} }
//查询订单详情 //查询订单详情
url := fmt.Sprintf("%s%s", z.config.BaseURL, fmt.Sprintf("%v", number)) url := fmt.Sprintf("%s%s", z.config.Tools.ZltxOrderStatistics.BaseURL, fmt.Sprintf("%v", number))
req := l_request.Request{ req := l_request.Request{
Url: url, Url: url,
Headers: map[string]string{ Headers: map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", ext.Auth), "Authorization": fmt.Sprintf("Bearer %s", string(token)),
}, },
Method: "GET", Method: "GET",
} }
@ -116,8 +132,9 @@ func (z ZltxOrderStatisticsTool) getZltxOrderStatistics(number interface{}, rec
return nil return nil
} }
func NewZltxOrderStatisticsTool(config config.ToolConfig) *ZltxOrderStatisticsTool { func NewZltxOrderStatisticsTool(config *config.Config, rdb *utils.Rdb) *ZltxOrderStatisticsTool {
return &ZltxOrderStatisticsTool{ return &ZltxOrderStatisticsTool{
config: config, config: config,
rdb: rdb,
} }
} }