From c1d42be1fc9f2312baecb89ab58238e1a6a615a9 Mon Sep 17 00:00:00 2001 From: mlogclub Date: Fri, 10 Apr 2026 16:08:17 +0800 Subject: [PATCH] feat: remove fallback mode and max AI reply rounds from AIAgent model and related components --- internal/ai/runtime/registry/registry.go | 8 +- internal/ai/runtime/service.go | 19 +---- .../console/ai_agent_controller.go | 3 - internal/models/models.go | 2 - internal/pkg/dto/request/ai_request.go | 2 - internal/pkg/dto/response/ai_response.go | 3 - internal/pkg/enums/im.go | 24 ------ internal/services/ai_agent_service.go | 8 -- .../(console)/ai-agents/_components/edit.tsx | 74 ------------------- web/lib/api/admin.ts | 5 -- web/lib/generated/enums.ts | 35 +-------- 11 files changed, 11 insertions(+), 172 deletions(-) diff --git a/internal/ai/runtime/registry/registry.go b/internal/ai/runtime/registry/registry.go index fbd3273..714e9de 100644 --- a/internal/ai/runtime/registry/registry.go +++ b/internal/ai/runtime/registry/registry.go @@ -3,6 +3,8 @@ package registry import ( "strings" + "cs-agent/internal/pkg/toolx" + einotool "github.com/cloudwego/eino/components/tool" ) @@ -28,7 +30,7 @@ func (r *Registry) Resolve(ctx Context) (*ToolSet, error) { } toolCode := strings.TrimSpace(toolDef.Code()) if len(allowedToolCodes) > 0 { - if _, ok := allowedToolCodes[toolCode]; !ok { + if _, ok := allowedToolCodes[toolCode]; !ok && !isAlwaysAllowedToolCode(toolCode) { continue } } @@ -63,3 +65,7 @@ func makeAllowedToolCodeSet(input []string) map[string]struct{} { } return ret } + +func isAlwaysAllowedToolCode(toolCode string) bool { + return strings.TrimSpace(toolCode) == toolx.GraphHandoffConversationToolCode +} diff --git a/internal/ai/runtime/service.go b/internal/ai/runtime/service.go index fbb5eda..b6a0a09 100644 --- a/internal/ai/runtime/service.go +++ b/internal/ai/runtime/service.go @@ -95,7 +95,7 @@ func (s *service) prepareToolsForRun(req *Request) error { AIAgent: req.AIAgent, AIConfig: req.AIConfig, UserMessage: req.UserMessage, - AllowedToolCodes: ensureCoreGraphToolCodes(resolveAllowedToolCodes(req.AIAgent, req.SelectedSkill)), + AllowedToolCodes: resolveAllowedToolCodes(req.AIAgent, req.SelectedSkill), }) if err != nil { return err @@ -113,7 +113,7 @@ func (s *service) prepareToolsForResume(req *ResumeRequest) error { Conversation: req.Conversation, AIAgent: req.AIAgent, AIConfig: req.AIConfig, - AllowedToolCodes: ensureCoreGraphToolCodes(parseAgentAllowedToolCodes(req.AIAgent)), + AllowedToolCodes: parseAgentAllowedToolCodes(req.AIAgent), }) if err != nil { return err @@ -281,18 +281,3 @@ func resolveAllowedToolCodes(aiAgent *models.AIAgent, skill *models.SkillDefinit return ret } } - -func ensureCoreGraphToolCodes(toolCodes []string) []string { - if len(toolCodes) == 0 { - return nil - } - ret := make([]string, 0, len(toolCodes)+1) - ret = append(ret, toolCodes...) - for _, item := range ret { - if strings.TrimSpace(item) == toolx.GraphHandoffConversationToolCode { - return ret - } - } - ret = append(ret, toolx.GraphHandoffConversationToolCode) - return ret -} diff --git a/internal/controllers/console/ai_agent_controller.go b/internal/controllers/console/ai_agent_controller.go index 5ab8229..8248413 100644 --- a/internal/controllers/console/ai_agent_controller.go +++ b/internal/controllers/console/ai_agent_controller.go @@ -124,9 +124,6 @@ func buildAIAgentResponse(item *models.AIAgent) response.AIAgentResponse { ReplyTimeoutSeconds: item.ReplyTimeoutSeconds, HandoffMode: item.HandoffMode, HandoffModeName: enums.GetAIAgentHandoffModeLabel(item.HandoffMode), - MaxAIReplyRounds: item.MaxAIReplyRounds, - FallbackMode: item.FallbackMode, - FallbackModeName: enums.GetAIAgentFallbackModeLabel(item.FallbackMode), FallbackMessage: item.FallbackMessage, KnowledgeIDs: utils.SplitInt64s(item.KnowledgeIDs), SkillIDs: utils.SplitInt64s(item.SkillIDs), diff --git a/internal/models/models.go b/internal/models/models.go index 78211ef..972c924 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -510,8 +510,6 @@ type AIAgent struct { ReplyTimeoutSeconds int `gorm:"type:int;not null;default:180"` // ReplyTimeoutSeconds 为异步自动回复超时秒数。 TeamIDs string `gorm:"type:varchar(500);not null;default:''"` // TeamIDs 为转人工时可路由的客服组ID列表,多个之间使用逗号分隔。 HandoffMode enums.AIAgentHandoffMode `gorm:"type:int;not null;default:1"` // HandoffMode 为转人工模式,如进入待接入池、进入默认客服组待接入池。 - MaxAIReplyRounds int `gorm:"type:int;not null;default:2"` // MaxAIReplyRounds 为单个会话允许的 AI 最大成功回复次数,超过后强制转人工。 - FallbackMode enums.AIAgentFallbackMode `gorm:"type:int;not null;default:2"` // FallbackMode 为无答案或低置信度时的兜底模式。 FallbackMessage string `gorm:"type:text"` // FallbackMessage 为兜底回复文案。 KnowledgeIDs string `gorm:"type:varchar(500);not null;default:''"` // KnowledgeIDs 为绑定的知识库ID列表,按顺序表示优先级。 SkillIDs string `gorm:"type:varchar(500);not null;default:''"` // SkillIDs 为绑定的技能ID列表,按顺序表示允许路由的范围。 diff --git a/internal/pkg/dto/request/ai_request.go b/internal/pkg/dto/request/ai_request.go index 8538179..b8dc1cc 100644 --- a/internal/pkg/dto/request/ai_request.go +++ b/internal/pkg/dto/request/ai_request.go @@ -52,8 +52,6 @@ type CreateAIAgentRequest struct { ReplyTimeoutSeconds int `json:"replyTimeoutSeconds"` TeamIDs []int64 `json:"teamIds"` HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"` - MaxAIReplyRounds int `json:"maxAiReplyRounds"` - FallbackMode enums.AIAgentFallbackMode `json:"fallbackMode"` FallbackMessage string `json:"fallbackMessage"` KnowledgeIDs []int64 `json:"knowledgeIds"` SkillIDs []int64 `json:"skillIds"` diff --git a/internal/pkg/dto/response/ai_response.go b/internal/pkg/dto/response/ai_response.go index 4d82516..29ccec4 100644 --- a/internal/pkg/dto/response/ai_response.go +++ b/internal/pkg/dto/response/ai_response.go @@ -83,9 +83,6 @@ type AIAgentResponse struct { Teams []AIAgentTeamResponse `json:"teams"` HandoffMode enums.AIAgentHandoffMode `json:"handoffMode"` HandoffModeName string `json:"handoffModeName"` - MaxAIReplyRounds int `json:"maxAiReplyRounds"` - FallbackMode enums.AIAgentFallbackMode `json:"fallbackMode"` - FallbackModeName string `json:"fallbackModeName"` FallbackMessage string `json:"fallbackMessage"` KnowledgeIDs []int64 `json:"knowledgeIds"` KnowledgeBaseNames []string `json:"knowledgeBaseNames"` diff --git a/internal/pkg/enums/im.go b/internal/pkg/enums/im.go index 809a032..3df47ac 100644 --- a/internal/pkg/enums/im.go +++ b/internal/pkg/enums/im.go @@ -212,30 +212,6 @@ func GetAIAgentHandoffModeLabel(mode AIAgentHandoffMode) string { return aiAgentHandoffModeLabelMap[mode] } -type AIAgentFallbackMode int - -const ( - AIAgentFallbackModeNoAnswer AIAgentFallbackMode = 1 - AIAgentFallbackModeGuideRephrase AIAgentFallbackMode = 2 - AIAgentFallbackModeHandoff AIAgentFallbackMode = 3 -) - -var AIAgentFallbackModeValues = []AIAgentFallbackMode{ - AIAgentFallbackModeNoAnswer, - AIAgentFallbackModeGuideRephrase, - AIAgentFallbackModeHandoff, -} - -var aiAgentFallbackModeLabelMap = map[AIAgentFallbackMode]string{ - AIAgentFallbackModeNoAnswer: "直接声明无答案", - AIAgentFallbackModeGuideRephrase: "引导补充信息或换个问法", - AIAgentFallbackModeHandoff: "直接转人工", -} - -func GetAIAgentFallbackModeLabel(mode AIAgentFallbackMode) string { - return aiAgentFallbackModeLabelMap[mode] -} - const ( IMRealtimeEventConnected = "connected" IMRealtimeEventPong = "pong" diff --git a/internal/services/ai_agent_service.go b/internal/services/ai_agent_service.go index cacee9c..68f6091 100644 --- a/internal/services/ai_agent_service.go +++ b/internal/services/ai_agent_service.go @@ -101,8 +101,6 @@ func (s *aIAgentService) UpdateAIAgent(req request.UpdateAIAgentRequest, operato "reply_timeout_seconds": item.ReplyTimeoutSeconds, "team_ids": item.TeamIDs, "handoff_mode": item.HandoffMode, - "max_ai_reply_rounds": item.MaxAIReplyRounds, - "fallback_mode": item.FallbackMode, "fallback_message": item.FallbackMessage, "knowledge_ids": item.KnowledgeIDs, "skill_ids": item.SkillIDs, @@ -162,10 +160,6 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe if enums.AIAgentHandoffMode(req.HandoffMode) == enums.AIAgentHandoffModeDefaultTeamPool && len(teamIDs) == 0 { return nil, errorsx.InvalidParam("默认客服组待接入池模式必须至少选择一个客服组") } - - if !slices.Contains(enums.AIAgentFallbackModeValues, enums.AIAgentFallbackMode(req.FallbackMode)) { - return nil, errorsx.InvalidParam("兜底模式不合法") - } if req.ReplyTimeoutSeconds < 0 { return nil, errorsx.InvalidParam("回复超时秒数不能小于 0") } @@ -203,8 +197,6 @@ func (s *aIAgentService) buildAIAgentModel(id int64, req request.CreateAIAgentRe ReplyTimeoutSeconds: req.ReplyTimeoutSeconds, TeamIDs: utils.JoinInt64s(teamIDs), HandoffMode: req.HandoffMode, - MaxAIReplyRounds: req.MaxAIReplyRounds, - FallbackMode: req.FallbackMode, FallbackMessage: strings.TrimSpace(req.FallbackMessage), KnowledgeIDs: utils.JoinInt64s(knowledgeIDs), SkillIDs: utils.JoinInt64s(skillIDs), diff --git a/web/app/(console)/ai-agents/_components/edit.tsx b/web/app/(console)/ai-agents/_components/edit.tsx index aa1d69b..338aa13 100644 --- a/web/app/(console)/ai-agents/_components/edit.tsx +++ b/web/app/(console)/ai-agents/_components/edit.tsx @@ -47,8 +47,6 @@ import { fetchSkillDefinitionsAll, } from "@/lib/api/admin"; import { - AIAgentFallbackMode, - AIAgentFallbackModeLabels, AIAgentHandoffMode, AIAgentHandoffModeLabels, AIModelType, @@ -89,10 +87,6 @@ const schema = z.object({ .number() .min(0, "回复超时秒数必须是大于等于 0 的整数"), handoffMode: z.string().trim().min(1, "请选择转人工模式"), - maxAiReplyRounds: z - .number() - .min(0, "AI 最大回复次数必须是大于等于 0 的整数"), - fallbackMode: z.string().trim().min(1, "请选择兜底模式"), fallbackMessage: z.string().trim(), remark: z.string().trim(), }); @@ -119,13 +113,6 @@ const handoffModeOptions = getEnumOptions(AIAgentHandoffModeLabels).map( }), ); -const fallbackModeOptions = getEnumOptions(AIAgentFallbackModeLabels).map( - (option) => ({ - value: String(option.value), - label: option.label, - }), -).filter((option) => option.value !== String(AIAgentFallbackMode.Handoff)); - function buildForm(item: AIAgent | null): EditForm { if (!item) { return { @@ -137,8 +124,6 @@ function buildForm(item: AIAgent | null): EditForm { welcomeMessage: "", replyTimeoutSeconds: 180, handoffMode: String(AIAgentHandoffMode.WaitPool), - maxAiReplyRounds: 2, - fallbackMode: String(AIAgentFallbackMode.GuideRephrase), fallbackMessage: "我暂时没有找到足够准确的信息。你可以补充订单号、产品名或更具体的问题,我再继续帮你查。", remark: "", @@ -153,8 +138,6 @@ function buildForm(item: AIAgent | null): EditForm { welcomeMessage: item.welcomeMessage || "", replyTimeoutSeconds: item.replyTimeoutSeconds ?? 180, handoffMode: String(item.handoffMode), - maxAiReplyRounds: item.maxAiReplyRounds ?? 2, - fallbackMode: String(item.fallbackMode), fallbackMessage: item.fallbackMessage || "", remark: item.remark || "", }; @@ -177,8 +160,6 @@ function buildPayload( replyTimeoutSeconds: Number(form.replyTimeoutSeconds), teamIds, handoffMode: Number(form.handoffMode), - maxAiReplyRounds: Number(form.maxAiReplyRounds), - fallbackMode: Number(form.fallbackMode), fallbackMessage: form.fallbackMessage.trim(), knowledgeIds, skillIds, @@ -1031,61 +1012,6 @@ function EditDialogBody({ - - - AI 最大回复次数 - - - - - } - /> - - - 该字段不再触发系统自动转人工,当前仅保留为兼容配置。转人工统一通过 AI 的 handoff_to_human Graph Tool 执行。 - - - - - - - - - - - 兜底模式 - - ( - - )} - /> - - -
diff --git a/web/lib/api/admin.ts b/web/lib/api/admin.ts index 06c2dfe..b0a9f2b 100644 --- a/web/lib/api/admin.ts +++ b/web/lib/api/admin.ts @@ -207,9 +207,6 @@ export type AIAgent = { teams: { id: number; name: string }[] handoffMode: number handoffModeName: string - maxAiReplyRounds: number - fallbackMode: number - fallbackModeName: string fallbackMessage: string knowledgeIds: number[] knowledgeBaseNames: string[] @@ -241,8 +238,6 @@ export type CreateAIAgentPayload = { replyTimeoutSeconds: number teamIds: number[] handoffMode: number - maxAiReplyRounds: number - fallbackMode: number fallbackMessage: string knowledgeIds: number[] skillIds: number[] diff --git a/web/lib/generated/enums.ts b/web/lib/generated/enums.ts index 9a9eba2..d16c394 100644 --- a/web/lib/generated/enums.ts +++ b/web/lib/generated/enums.ts @@ -1,16 +1,5 @@ // Code generated by cmd/enums/generator.go. DO NOT EDIT. -export enum AIAgentFallbackMode { - NoAnswer = 1, - GuideRephrase = 2, - Handoff = 3, -} -export const AIAgentFallbackModeLabels: Record = { - [AIAgentFallbackMode.NoAnswer]: "直接声明无答案", - [AIAgentFallbackMode.GuideRephrase]: "引导补充信息或换个问法", - [AIAgentFallbackMode.Handoff]: "直接转人工", -} - export enum AIAgentHandoffMode { WaitPool = 1, DefaultTeamPool = 2, @@ -75,9 +64,11 @@ export const ContactTypeLabels: Record = { export enum ExternalSource { WebChat = "web_chat", + WxWorkKF = "wxwork_kf", } export const ExternalSourceLabels: Record = { [ExternalSource.WebChat]: "网页客服", + [ExternalSource.WxWorkKF]: "企业微信客服", } export enum Gender { @@ -340,15 +331,6 @@ export const ServiceStatusLabels: Record = { [ServiceStatus.Busy]: "忙碌", } -export enum SkillExecutionMode { - PromptOnly = "prompt_only", - MCPTool = "mcp_tool", -} -export const SkillExecutionModeLabels: Record = { - [SkillExecutionMode.PromptOnly]: "Prompt直出", - [SkillExecutionMode.MCPTool]: "MCP工具", -} - export enum Status { Ok = 0, Disabled = 1, @@ -369,19 +351,6 @@ export const ThirdProviderLabels: Record = { [ThirdProvider.Dingtalk]: "钉钉", } -export enum TicketPriority { - Low = 1, - Normal = 2, - High = 3, - Urgent = 4, -} -export const TicketPriorityLabels: Record = { - [TicketPriority.Low]: "低", - [TicketPriority.Normal]: "普通", - [TicketPriority.High]: "高", - [TicketPriority.Urgent]: "紧急", -} - export enum TicketSeverity { Minor = 1, Major = 2,