From c84870b968378be68c2ee3d181b25b3324862b3f Mon Sep 17 00:00:00 2001 From: mlogclub Date: Sat, 18 Apr 2026 13:36:44 +0800 Subject: [PATCH] feat: add fallback mode for AI agents and update knowledge base handling - Introduced AIAgentFallbackMode with options for NoAnswer and SuggestRetry. - Updated AI agent edit component to include fallback mode selection. - Modified API types and payloads to accommodate fallback mode. - Removed deprecated KnowledgeFallbackMode and related logic from knowledge base. - Adjusted knowledge retrieval and response handling to utilize new fallback logic. - Updated tests to reflect changes in fallback mode handling for AI agents. --- cmd/enums/generator.go | 2 +- cmd/testdata/aiagent/init.go | 1 + cmd/testdata/kb/kb.go | 3 - .../ai-agents/_components/edit.tsx | 36 +- .../_components/knowledge-base-edit.tsx | 43 -- dashboard/lib/api/admin.ts | 7 +- dashboard/lib/generated/enums.ts | 20 +- docs | 2 +- internal/ai/rag/answer.go | 16 +- internal/ai/rag/answer_test.go | 11 +- .../ai/runtime/executor/knowledge_guard.go | 10 +- .../runtime/executor/knowledge_guard_test.go | 10 +- .../impl/retrievers/knowledge_retriever.go | 21 +- internal/builders/knowledge_builder.go | 2 - .../dashboard/ai_agent_controller.go | 2 + internal/models/models.go | 2 +- internal/pkg/dto/request/ai_request.go | 1 + internal/pkg/dto/request/knowledge_request.go | 2 - internal/pkg/dto/response/ai_response.go | 2 + .../pkg/dto/response/knowledge_response.go | 2 - internal/pkg/enums/im.go | 21 + internal/pkg/enums/knowledge.go | 18 - internal/services/ai_agent_service.go | 8 + internal/services/knowledge_base_service.go | 5 - web/lib/generated/enums.ts | 389 ++++++++++++++++++ 25 files changed, 497 insertions(+), 139 deletions(-) create mode 100644 web/lib/generated/enums.ts diff --git a/cmd/enums/generator.go b/cmd/enums/generator.go index 7cf1cb7..2eb51e6 100644 --- a/cmd/enums/generator.go +++ b/cmd/enums/generator.go @@ -17,7 +17,7 @@ import ( const ( enumsPkgName = "enums" enumsDir = "internal/pkg/enums" - outputPath = "web/lib/generated/enums.ts" + outputPath = "dashboard/lib/generated/enums.ts" ) type enumValueType string diff --git a/cmd/testdata/aiagent/init.go b/cmd/testdata/aiagent/init.go index 9f0ee77..4eda9d2 100644 --- a/cmd/testdata/aiagent/init.go +++ b/cmd/testdata/aiagent/init.go @@ -87,6 +87,7 @@ func buildSeedItems(aiConfigID int64, knowledgeIDs []int64, defaultTeamIDs strin ReplyTimeoutSeconds: 180, TeamIDs: defaultTeamIDs, HandoffMode: enums.AIAgentHandoffModeWaitPool, + FallbackMode: enums.AIAgentFallbackModeSuggestRetry, FallbackMessage: "我暂时没有找到足够准确的信息。你可以补充具体的问题,我再继续帮你查。", KnowledgeIDs: utils.JoinInt64s(knowledgeIDs), SkillIDs: defaultSkillIDs, diff --git a/cmd/testdata/kb/kb.go b/cmd/testdata/kb/kb.go index a11428e..26c16c8 100644 --- a/cmd/testdata/kb/kb.go +++ b/cmd/testdata/kb/kb.go @@ -118,7 +118,6 @@ func ensureKnowledgeBase(db *gorm.DB) (*models.KnowledgeBase, error) { ChunkMaxTokens: 400, ChunkOverlapTokens: 40, AnswerMode: int(enums.KnowledgeAnswerModeStrict), - FallbackMode: int(enums.KnowledgeFallbackModeNoAnswer), AuditFields: models.AuditFields{ CreatedAt: now, CreateUserID: constants.SystemAuditUserID, @@ -168,7 +167,6 @@ func ensureFAQKnowledgeBase(db *gorm.DB) (*models.KnowledgeBase, error) { ChunkMaxTokens: 0, ChunkOverlapTokens: 0, AnswerMode: int(enums.KnowledgeAnswerModeStrict), - FallbackMode: int(enums.KnowledgeFallbackModeNoAnswer), Remark: "测试数据初始化自动生成", AuditFields: models.AuditFields{ CreatedAt: now, @@ -197,7 +195,6 @@ func ensureFAQKnowledgeBase(db *gorm.DB) (*models.KnowledgeBase, error) { "chunk_max_tokens": 0, "chunk_overlap_tokens": 0, "answer_mode": int(enums.KnowledgeAnswerModeStrict), - "fallback_mode": int(enums.KnowledgeFallbackModeNoAnswer), "remark": "测试数据初始化自动生成", "update_user_id": constants.SystemAuditUserID, "update_user_name": constants.SystemAuditUserName, diff --git a/dashboard/app/(dashboard)/ai-agents/_components/edit.tsx b/dashboard/app/(dashboard)/ai-agents/_components/edit.tsx index f31ab4c..6f44729 100644 --- a/dashboard/app/(dashboard)/ai-agents/_components/edit.tsx +++ b/dashboard/app/(dashboard)/ai-agents/_components/edit.tsx @@ -50,6 +50,8 @@ import { } from "@/lib/api/admin"; import { getEnumOptions } from "@/lib/enums"; import { + AIAgentFallbackMode, + AIAgentFallbackModeLabels, AIAgentHandoffMode, AIAgentHandoffModeLabels, AIModelType, @@ -93,6 +95,7 @@ const schema = z.object({ .number() .min(0, "回复超时秒数必须是大于等于 0 的整数"), handoffMode: z.string().trim().min(1, "请选择转人工模式"), + fallbackMode: z.string().trim().min(1, "请选择兜底策略"), fallbackMessage: z.string().trim(), }); @@ -118,6 +121,13 @@ const handoffModeOptions = getEnumOptions(AIAgentHandoffModeLabels).map( }), ); +const fallbackModeOptions = getEnumOptions(AIAgentFallbackModeLabels).map( + (option) => ({ + value: String(option.value), + label: option.label, + }), +); + function buildForm(item: AIAgent | null): EditForm { if (!item) { return { @@ -129,6 +139,7 @@ function buildForm(item: AIAgent | null): EditForm { welcomeMessage: "", replyTimeoutSeconds: 180, handoffMode: String(AIAgentHandoffMode.WaitPool), + fallbackMode: String(AIAgentFallbackMode.NoAnswer), fallbackMessage: "", }; } @@ -141,6 +152,7 @@ function buildForm(item: AIAgent | null): EditForm { welcomeMessage: item.welcomeMessage || "", replyTimeoutSeconds: item.replyTimeoutSeconds ?? 180, handoffMode: String(item.handoffMode), + fallbackMode: String(item.fallbackMode), fallbackMessage: item.fallbackMessage || "", }; } @@ -163,6 +175,7 @@ function buildPayload( replyTimeoutSeconds: Number(form.replyTimeoutSeconds), teamIds, handoffMode: Number(form.handoffMode), + fallbackMode: Number(form.fallbackMode), fallbackMessage: form.fallbackMessage.trim(), knowledgeIds, skillIds, @@ -737,13 +750,34 @@ function EditDialogBody({ + + 知识库兜底策略 + + ( + + )} + /> + + + + 兜底文案
- 仅在兜底模式为“直接声明无答案”或“引导补充信息”时使用。转人工已统一改为 AI Graph Tool,不再通过兜底模式直接触发。 + 知识库未命中或命中证据不足时,会按这里的策略和文案进行兜底回复。转人工请通过 Graph Tool 配合转人工模式实现。