From 4715b106426676bd6ef6bf0fa986fd3b75631888 Mon Sep 17 00:00:00 2001 From: wizardchen Date: Thu, 9 Apr 2026 21:31:37 +0800 Subject: [PATCH] feat: Add Wiki Researcher agent and system prompt for enhanced knowledge retrieval - Introduced a new built-in agent, "Wiki Researcher," designed for navigating and answering questions based on Wiki knowledge bases, complete with multilingual support. - Added a corresponding system prompt that outlines the agent's role, mission, and workflow for effective knowledge graph traversal. - Updated the agent configuration to include specific tools and parameters tailored for the Wiki Researcher, enhancing its functionality and user interaction. - Removed deprecated wiki tools from the agent service to streamline the toolset and improve performance. These changes significantly enhance the capabilities of the agent system, providing users with a specialized tool for in-depth research and information retrieval from Wiki sources. --- config/builtin_agents.yaml | 44 +++ .../prompt_templates/agent_system_prompt.yaml | 54 +++ internal/agent/prompts_wiki.go | 37 -- internal/agent/tools/definitions.go | 10 +- internal/agent/tools/wiki_tools.go | 338 +++--------------- internal/agent/tools/wiki_tools_test.go | 10 +- internal/application/service/agent_service.go | 20 -- testdata/wiki_test/doc1_stardust_memo.md | 11 + testdata/wiki_test/doc2_psionic_engine.md | 12 + testdata/wiki_test/doc3_dr_cole_log.md | 17 + 10 files changed, 191 insertions(+), 362 deletions(-) create mode 100644 testdata/wiki_test/doc1_stardust_memo.md create mode 100644 testdata/wiki_test/doc2_psionic_engine.md create mode 100644 testdata/wiki_test/doc3_dr_cole_log.md diff --git a/config/builtin_agents.yaml b/config/builtin_agents.yaml index c6f74a34..2c6de91b 100644 --- a/config/builtin_agents.yaml +++ b/config/builtin_agents.yaml @@ -140,3 +140,47 @@ builtin_agents: vector_threshold: 0.5 rerank_top_k: 5 rerank_threshold: 0.3 + + - id: "builtin-wiki-researcher" + avatar: "📚" + is_builtin: true + i18n: + default: + name: "Wiki Researcher" + description: "Specialized agent for navigating and answering questions based on Wiki knowledge bases" + zh-CN: + name: "维基研究员" + description: "专注于在 Wiki 知识库中进行导航和问答的智能体" + zh-TW: + name: "維基研究員" + description: "專注於在 Wiki 知識庫中進行導航和問答的智能體" + ja-JP: + name: "Wikiリサーチャー" + description: "Wikiナレッジベースでのナビゲーションと質問応答に特化したエージェント" + ko-KR: + name: "위키 연구원" + description: "위키 지식 베이스를 탐색하고 질문에 답변하는 데 특화된 에이전트" + config: + agent_mode: "smart-reasoning" + system_prompt_id: "wiki_researcher" + temperature: 0.7 + max_completion_tokens: 4096 + max_iterations: 30 + kb_selection_mode: "all" + retrieve_kb_only_when_mentioned: false + allowed_tools: + - "thinking" + - "todo_write" + - "wiki_search" + - "wiki_read_page" + web_search_enabled: false + web_search_max_results: 0 + reflection_enabled: false + multi_turn_enabled: true + history_turns: 10 + embedding_top_k: 10 + keyword_threshold: 0.3 + vector_threshold: 0.5 + rerank_top_k: 10 + rerank_threshold: 0.3 + diff --git a/config/prompt_templates/agent_system_prompt.yaml b/config/prompt_templates/agent_system_prompt.yaml index fadc2757..f9a94fbf 100644 --- a/config/prompt_templates/agent_system_prompt.yaml +++ b/config/prompt_templates/agent_system_prompt.yaml @@ -220,3 +220,57 @@ templates: - Relate findings back to the user's original question Current Time: {{current_time}} + + - id: "wiki_researcher" + name: "Wiki Researcher" + description: "System prompt for Wiki Researcher agent with knowledge graph traversal" + i18n: + zh-CN: + name: "维基研究员" + description: "专用于 Wiki 知识库图谱导航与深度阅读的智能体系统提示词" + en-US: + name: "Wiki Researcher" + description: "System prompt for Wiki Researcher agent with knowledge graph traversal" + ko-KR: + name: "위키 연구원" + description: "지식 그래프 탐색 기능이 있는 위키 연구원 에이전트용 시스템 프롬프트" + mode: "wiki_researcher" + content: | + + You are WeKnora Wiki Researcher, an intelligent retrieval assistant developed by Tencent. You operate on a **Wiki Knowledge Base** — a persistent, interlinked collection of LLM-generated Markdown pages. The wiki is organized by page types: summaries (document summaries), entities (people, organizations, products), and concepts (topics, methodologies). + + + + To deliver accurate, comprehensive, and well-structured answers by navigating the Wiki's knowledge graph. You act as a researcher who knows how to start from a keyword, find an entry point, and follow links to gather full context. + + + + Follow this "Search-Read-Expand" cycle: + 1. **Search (Entry Point):** Use `wiki_search` with core keywords from the user's query to find relevant wiki pages. (Note: The knowledge base also has two special pages you can read directly without searching: `index` for a high-level overview of the entire wiki, and `log` for a chronological timeline of recent changes.) + 2. **Read (Deep Context):** If `wiki_search` returns relevant page slugs, you MUST call `wiki_read_page` on the most promising ones to get their full Markdown content. + 3. **Expand (Follow Links):** Wiki pages contain `[[slug]]` cross-references. The `wiki_read_page` tool will also show you the summaries of outgoing links (`Links to`). If the current page doesn't fully answer the question, or if you need to understand a related concept mentioned in the text, you MUST call `wiki_read_page` again on those related slugs (1-2 hops). + 4. **Synthesize:** Once you have gathered sufficient information from reading multiple interconnected pages, synthesize a final answer. + + + + ABSOLUTE RULES: + 1. **Never Guess:** Never rely on your internal knowledge. Only answer based on what you have successfully read via `wiki_read_page`. + 2. **Mandatory Reading:** `wiki_search` only returns summaries. You CANNOT write a final answer based solely on `wiki_search` results. You MUST call `wiki_read_page` on the relevant slugs to get the actual facts. + 3. **Cite Sources:** Your final answer must clearly state which wiki pages you derived the information from. + + + + * **wiki_search:** Use this first to find entry points. Use concise keywords (1-2 words). + * **wiki_read_page:** Your primary tool. Use it to read the full content of pages found via search or linked from other pages. + * **thinking:** Use to plan your traversal path (e.g., "I read Entity A, which mentions Concept B. I need to read Concept B next to answer the second part of the question"). + * **todo_write:** Track multi-step research (e.g., comparing three different entities). + + + + Current Time: {{current_time}} + User Language: {{language}} + + + + {{knowledge_bases}} + diff --git a/internal/agent/prompts_wiki.go b/internal/agent/prompts_wiki.go index 54a6cfa9..7df42b62 100644 --- a/internal/agent/prompts_wiki.go +++ b/internal/agent/prompts_wiki.go @@ -208,43 +208,6 @@ const WikiLogEntryTemplate = `## [{{.Date}}] {{.Operation}} | {{.Title}} - **Summary**: {{.Summary}} ` -// WikiAgentSystemPromptAddendum is appended to the Agent system prompt when -// wiki knowledge bases are detected among the search targets. -// It tells the LLM how and when to use wiki tools. -const WikiAgentSystemPromptAddendum = ` -### Wiki Knowledge Base Guidelines - -You have access to a **Wiki Knowledge Base** — a persistent, interlinked collection of LLM-generated Markdown pages. The wiki is organized by page types: summaries (document summaries), entities (people, organizations, products), concepts (topics, methodologies), and special pages (index, log). - -#### Retrieval Strategy (Wiki-First) -When the user's question may be answerable from the wiki: -1. **Start with the index:** Call wiki_read_index to see what knowledge pages exist and their categories. -2. **Search if needed:** Call wiki_search with keywords to find relevant pages. -3. **Deep read:** Call wiki_read_page on the most relevant slugs to get full content. -4. **Follow links:** Wiki pages contain [[slug]] cross-references. Follow them to gather related context (1-2 hops). -5. **Fall back to standard KB search** only if the wiki doesn't have sufficient information. - -#### When to Write Wiki Pages -Use wiki_write_page to persist valuable knowledge artifacts. Write a page when: -- You produce a **cross-document synthesis** that combines insights from multiple sources (use page_type "synthesis") -- You generate a **comparison or evaluation** of entities, approaches, or concepts (use page_type "comparison") -- The user explicitly asks you to save analysis to the wiki - -**Do NOT** write wiki pages for: -- Simple factual answers that don't add new insight -- Conversational responses (greetings, clarifications) -- Content that already exists in an existing wiki page (update it instead) - -#### Page Content Guidelines -- Write in Markdown with proper heading hierarchy -- Use [[slug|display name]] syntax to link to other wiki pages (e.g. [[entity/acme-corp|Acme Corp]]) -- Include a one-line summary in the first paragraph (used for index listings) -- Cite source documents when possible -- Keep pages focused: one topic/entity/concept per page - -#### Log Page -The wiki has a log page (slug: "log") that records all ingest and update activity. Read it when the user asks about recent changes, update history, or what's new in the knowledge base. -` // WikiDeduplicationPrompt asks the LLM to identify duplicate entities/concepts // between newly extracted items and existing wiki pages. diff --git a/internal/agent/tools/definitions.go b/internal/agent/tools/definitions.go index 2f96fa9e..8283ba99 100644 --- a/internal/agent/tools/definitions.go +++ b/internal/agent/tools/definitions.go @@ -23,11 +23,8 @@ const ( ToolExecuteSkillScript = "execute_skill_script" ToolReadSkill = "read_skill" // Wiki-related tools (only available when wiki KBs are in scope) - ToolWikiReadPage = "wiki_read_page" - ToolWikiWritePage = "wiki_write_page" - ToolWikiSearch = "wiki_search" - ToolWikiReadIndex = "wiki_read_index" - ToolWikiLint = "wiki_lint" + ToolWikiReadPage = "wiki_read_page" + ToolWikiSearch = "wiki_search" ) // AvailableTool defines a simple tool metadata used by settings APIs. @@ -55,10 +52,7 @@ func AvailableToolDefinitions() []AvailableTool { {Name: ToolExecuteSkillScript, Label: "执行技能脚本", Description: "在沙箱环境中执行技能脚本"}, {Name: ToolFinalAnswer, Label: "提交最终回答", Description: "提交最终回答给用户"}, {Name: ToolWikiReadPage, Label: "读取Wiki页面", Description: "读取指定的Wiki页面内容"}, - {Name: ToolWikiWritePage, Label: "写入Wiki页面", Description: "创建或更新Wiki页面"}, {Name: ToolWikiSearch, Label: "搜索Wiki", Description: "在Wiki中搜索页面"}, - {Name: ToolWikiReadIndex, Label: "读取Wiki索引", Description: "读取Wiki索引目录"}, - {Name: ToolWikiLint, Label: "Wiki健康检查", Description: "检查Wiki健康状况"}, } } diff --git a/internal/agent/tools/wiki_tools.go b/internal/agent/tools/wiki_tools.go index a7637b06..b0ce0688 100644 --- a/internal/agent/tools/wiki_tools.go +++ b/internal/agent/tools/wiki_tools.go @@ -8,7 +8,6 @@ import ( "github.com/Tencent/WeKnora/internal/types" "github.com/Tencent/WeKnora/internal/types/interfaces" - "github.com/google/uuid" ) // ---- wiki_read_page ---- @@ -62,10 +61,51 @@ func (t *wikiReadPageTool) Execute(ctx context.Context, args json.RawMessage) (* for _, kbID := range kbIDs { page, err := t.wikiService.GetPageBySlug(ctx, kbID, params.Slug) if err == nil && page != nil { - output := fmt.Sprintf("# %s\n**Type**: %s | **Version**: %d | **Updated**: %s\n**Links to**: %s\n**Linked from**: %s\n\n---\n\n%s", - page.Title, page.PageType, page.Version, page.UpdatedAt.Format("2006-01-02"), - strings.Join(page.OutLinks, ", "), - strings.Join(page.InLinks, ", "), + // Resolve OutLinks summaries to provide 1-hop context + var outLinksDesc []string + if len(page.OutLinks) > 0 { + for _, outSlug := range page.OutLinks { + if linkPage, err := t.wikiService.GetPageBySlug(ctx, kbID, outSlug); err == nil && linkPage != nil { + outLinksDesc = append(outLinksDesc, fmt.Sprintf("[[%s]] (%s)", outSlug, linkPage.Summary)) + } else { + outLinksDesc = append(outLinksDesc, fmt.Sprintf("[[%s]]", outSlug)) + } + } + } else { + outLinksDesc = []string{"(none)"} + } + + // Resolve InLinks summaries to provide reverse 1-hop context + var inLinksDesc []string + if len(page.InLinks) > 0 { + for _, inSlug := range page.InLinks { + if linkPage, err := t.wikiService.GetPageBySlug(ctx, kbID, inSlug); err == nil && linkPage != nil { + inLinksDesc = append(inLinksDesc, fmt.Sprintf("[[%s]] (%s)", inSlug, linkPage.Summary)) + } else { + inLinksDesc = append(inLinksDesc, fmt.Sprintf("[[%s]]", inSlug)) + } + } + } else { + inLinksDesc = []string{"(none)"} + } + + output := fmt.Sprintf(` + +%s +%s +%s + + +%s +%s + + +%s + +`, + page.Title, page.Slug, page.PageType, + strings.Join(outLinksDesc, ", "), + strings.Join(inLinksDesc, ", "), page.Content, ) return &types.ToolResult{Success: true, Output: output}, nil @@ -75,115 +115,6 @@ func (t *wikiReadPageTool) Execute(ctx context.Context, args json.RawMessage) (* return &types.ToolResult{Success: false, Error: fmt.Sprintf("Wiki page '%s' not found", params.Slug)}, nil } -// ---- wiki_write_page ---- - -type wikiWritePageTool struct { - BaseTool - wikiService interfaces.WikiPageService - kbIDs []string - tenantID uint64 -} - -func NewWikiWritePageTool(wikiService interfaces.WikiPageService, kbIDs []string, tenantID uint64) types.Tool { - return &wikiWritePageTool{ - BaseTool: NewBaseTool( - ToolWikiWritePage, - `Create or update a wiki page. Use this to save valuable analysis, synthesis, or new knowledge into the wiki. -The page content should be in Markdown format. Use [[slug]] syntax to create links between pages.`, - json.RawMessage(`{ - "type": "object", - "properties": { - "slug": { - "type": "string", - "description": "Page slug (e.g. 'synthesis/quarterly-review', 'comparison/tool-a-vs-tool-b')" - }, - "title": { - "type": "string", - "description": "Human-readable page title" - }, - "content": { - "type": "string", - "description": "Full Markdown content of the page. Use [[slug]] for wiki links." - }, - "page_type": { - "type": "string", - "enum": ["summary", "entity", "concept", "synthesis", "comparison"], - "description": "Type of wiki page" - }, - "knowledge_base_id": { - "type": "string", - "description": "Target knowledge base ID. Required if multiple wiki KBs are available." - } - }, - "required": ["slug", "title", "content", "page_type"] -}`), - ), - wikiService: wikiService, - kbIDs: kbIDs, - tenantID: tenantID, - } -} - -func (t *wikiWritePageTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error) { - var params struct { - Slug string `json:"slug"` - Title string `json:"title"` - Content string `json:"content"` - PageType string `json:"page_type"` - KnowledgeBaseID string `json:"knowledge_base_id"` - } - if err := json.Unmarshal(args, ¶ms); err != nil { - return &types.ToolResult{Success: false, Error: "Invalid parameters: " + err.Error()}, nil - } - - kbID := params.KnowledgeBaseID - if kbID == "" && len(t.kbIDs) > 0 { - kbID = t.kbIDs[0] - } - if kbID == "" { - return &types.ToolResult{Success: false, Error: "No wiki knowledge base available"}, nil - } - - // Check if page exists (update) or new (create) - existing, err := t.wikiService.GetPageBySlug(ctx, kbID, params.Slug) - if err == nil && existing != nil { - existing.Title = params.Title - existing.Content = params.Content - existing.PageType = params.PageType - existing.Summary = truncateForSummary(params.Content, 200) - - if _, err := t.wikiService.UpdatePage(ctx, existing); err != nil { - return &types.ToolResult{Success: false, Error: "Failed to update page: " + err.Error()}, nil - } - return &types.ToolResult{ - Success: true, - Output: fmt.Sprintf("Updated wiki page [[%s]] (v%d)", params.Slug, existing.Version), - }, nil - } - - // Create new page - page := &types.WikiPage{ - ID: uuid.New().String(), - TenantID: t.tenantID, - KnowledgeBaseID: kbID, - Slug: params.Slug, - Title: params.Title, - Content: params.Content, - PageType: params.PageType, - Status: types.WikiPageStatusPublished, - Summary: truncateForSummary(params.Content, 200), - } - - if _, err := t.wikiService.CreatePage(ctx, page); err != nil { - return &types.ToolResult{Success: false, Error: "Failed to create page: " + err.Error()}, nil - } - - return &types.ToolResult{ - Success: true, - Output: fmt.Sprintf("Created wiki page [[%s]] — %s", params.Slug, params.Title), - }, nil -} - // ---- wiki_search ---- type wikiSearchTool struct { @@ -241,191 +172,20 @@ func (t *wikiSearchTool) Execute(ctx context.Context, args json.RawMessage) (*ty if len(allPages) == 0 { return &types.ToolResult{ Success: true, - Output: fmt.Sprintf("No wiki pages found matching '%s'", params.Query), + Output: fmt.Sprintf("", params.Query), }, nil } var sb strings.Builder - sb.WriteString(fmt.Sprintf("Found %d wiki pages:\n\n", len(allPages))) + sb.WriteString(fmt.Sprintf("\n", len(allPages), params.Query)) for _, p := range allPages { - fmt.Fprintf(&sb, "- **[[%s]]** (%s) — %s\n", p.Slug, p.PageType, p.Summary) + fmt.Fprintf(&sb, "\n%s\n%s\n%s\n%s\n\n", p.Title, p.Slug, p.PageType, p.Summary) } + sb.WriteString("") return &types.ToolResult{Success: true, Output: sb.String()}, nil } -// ---- wiki_read_index ---- - -type wikiReadIndexTool struct { - BaseTool - wikiService interfaces.WikiPageService - kbIDs []string -} - -func NewWikiReadIndexTool(wikiService interfaces.WikiPageService, kbIDs []string) types.Tool { - return &wikiReadIndexTool{ - BaseTool: NewBaseTool( - ToolWikiReadIndex, - `Read the wiki index page. The index lists all wiki pages organized by category. -Use this first to understand what knowledge is available in the wiki before searching or reading specific pages.`, - json.RawMessage(`{ - "type": "object", - "properties": { - "knowledge_base_id": { - "type": "string", - "description": "Optional: specific knowledge base ID" - } - } -}`), - ), - wikiService: wikiService, - kbIDs: kbIDs, - } -} - -func (t *wikiReadIndexTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error) { - var params struct { - KnowledgeBaseID string `json:"knowledge_base_id"` - } - _ = json.Unmarshal(args, ¶ms) - - kbIDs := t.kbIDs - if params.KnowledgeBaseID != "" { - kbIDs = []string{params.KnowledgeBaseID} - } - - var output strings.Builder - for _, kbID := range kbIDs { - indexPage, err := t.wikiService.GetIndex(ctx, kbID) - if err == nil && indexPage != nil { - if len(kbIDs) > 1 { - fmt.Fprintf(&output, "## Wiki Index (KB: %s)\n\n", kbID) - } - output.WriteString(indexPage.Content) - output.WriteString("\n\n") - } - } - - if output.Len() == 0 { - return &types.ToolResult{Success: true, Output: "No wiki index found. The wiki may be empty."}, nil - } - - return &types.ToolResult{Success: true, Output: output.String()}, nil -} - -// ---- wiki_lint ---- - -type wikiLintTool struct { - BaseTool - wikiService interfaces.WikiPageService - kbIDs []string -} - -func NewWikiLintTool(wikiService interfaces.WikiPageService, kbIDs []string) types.Tool { - return &wikiLintTool{ - BaseTool: NewBaseTool( - ToolWikiLint, - `Check the health of the wiki. Reports issues like orphan pages, broken links, and provides statistics. -Use this to identify maintenance tasks and ensure wiki quality.`, - json.RawMessage(`{ - "type": "object", - "properties": { - "knowledge_base_id": { - "type": "string", - "description": "Optional: specific knowledge base ID" - } - } -}`), - ), - wikiService: wikiService, - kbIDs: kbIDs, - } -} - -func (t *wikiLintTool) Execute(ctx context.Context, args json.RawMessage) (*types.ToolResult, error) { - var params struct { - KnowledgeBaseID string `json:"knowledge_base_id"` - } - _ = json.Unmarshal(args, ¶ms) - - kbIDs := t.kbIDs - if params.KnowledgeBaseID != "" { - kbIDs = []string{params.KnowledgeBaseID} - } - - var output strings.Builder - for _, kbID := range kbIDs { - stats, err := t.wikiService.GetStats(ctx, kbID) - if err != nil { - fmt.Fprintf(&output, "## Wiki Health Check (KB: %s)\nError: %v\n\n", kbID, err) - continue - } - - graph, _ := t.wikiService.GetGraph(ctx, kbID) - - fmt.Fprintf(&output, "## Wiki Health Check (KB: %s)\n\n", kbID) - fmt.Fprintf(&output, "### Statistics\n") - fmt.Fprintf(&output, "- **Total pages**: %d\n", stats.TotalPages) - for pt, count := range stats.PagesByType { - fmt.Fprintf(&output, " - %s: %d\n", pt, count) - } - fmt.Fprintf(&output, "- **Total links**: %d\n", stats.TotalLinks) - fmt.Fprintf(&output, "- **Orphan pages** (no inbound links): %d\n", stats.OrphanCount) - - // Health score (simple heuristic) - healthScore := 100 - if stats.TotalPages > 0 { - orphanPct := float64(stats.OrphanCount) / float64(stats.TotalPages) * 100 - if orphanPct > 50 { - healthScore -= 30 - } else if orphanPct > 25 { - healthScore -= 15 - } - } - if stats.TotalLinks == 0 && stats.TotalPages > 2 { - healthScore -= 20 - } - - // Check for broken links - brokenLinks := 0 - if graph != nil { - slugSet := make(map[string]bool) - for _, n := range graph.Nodes { - slugSet[n.Slug] = true - } - for _, e := range graph.Edges { - if !slugSet[e.Target] { - brokenLinks++ - } - } - } - if brokenLinks > 0 { - healthScore -= brokenLinks * 5 - fmt.Fprintf(&output, "- **Broken links**: %d\n", brokenLinks) - } - - if healthScore < 0 { - healthScore = 0 - } - fmt.Fprintf(&output, "\n### Health Score: %d/100\n\n", healthScore) - - // Suggestions - fmt.Fprintf(&output, "### Suggestions\n") - if stats.OrphanCount > 0 { - fmt.Fprintf(&output, "- Link orphan pages from related entity/concept pages\n") - } - if brokenLinks > 0 { - fmt.Fprintf(&output, "- Fix or remove %d broken [[wiki-link]] references\n", brokenLinks) - } - if stats.TotalPages < 3 { - fmt.Fprintf(&output, "- Wiki is sparse — consider ingesting more documents\n") - } - output.WriteString("\n") - } - - return &types.ToolResult{Success: true, Output: output.String()}, nil -} - // --- Helper --- func truncateForSummary(content string, maxLen int) string { diff --git a/internal/agent/tools/wiki_tools_test.go b/internal/agent/tools/wiki_tools_test.go index 55b30fe3..fc7e17de 100644 --- a/internal/agent/tools/wiki_tools_test.go +++ b/internal/agent/tools/wiki_tools_test.go @@ -56,10 +56,7 @@ func TestWikiToolConstants(t *testing.T) { // Verify all wiki tool constants are defined and unique names := []string{ ToolWikiReadPage, - ToolWikiWritePage, ToolWikiSearch, - ToolWikiReadIndex, - ToolWikiLint, } seen := make(map[string]bool) @@ -82,11 +79,8 @@ func TestWikiToolConstants(t *testing.T) { func TestWikiToolsInAvailableDefinitions(t *testing.T) { defs := AvailableToolDefinitions() wikiTools := map[string]bool{ - ToolWikiReadPage: false, - ToolWikiWritePage: false, - ToolWikiSearch: false, - ToolWikiReadIndex: false, - ToolWikiLint: false, + ToolWikiReadPage: false, + ToolWikiSearch: false, } for _, def := range defs { diff --git a/internal/application/service/agent_service.go b/internal/application/service/agent_service.go index 7c2b795f..8ce9c046 100644 --- a/internal/application/service/agent_service.go +++ b/internal/application/service/agent_service.go @@ -117,15 +117,6 @@ func (s *agentService) CreateAgentEngine( systemPromptTemplate = config.ResolveSystemPrompt(config.WebSearchEnabled) } - // 4.5 Append wiki guidelines if any search target is a wiki KB - for _, target := range config.SearchTargets { - kb, err := s.knowledgeBaseService.GetKnowledgeBaseByIDOnly(ctx, target.KnowledgeBaseID) - if err == nil && kb != nil && kb.IsWikiEnabled() { - systemPromptTemplate += "\n" + agent.WikiAgentSystemPromptAddendum - break - } - } - // 5. Create engine engine := agent.NewAgentEngine( config, chatModel, toolRegistry, eventBus, @@ -380,21 +371,16 @@ func (s *agentService) registerTools( // If any search target is a wiki KB, add wiki tools automatically var wikiKBIDs []string - var wikiTenantID uint64 for _, target := range config.SearchTargets { kb, err := s.knowledgeBaseService.GetKnowledgeBaseByIDOnly(ctx, target.KnowledgeBaseID) if err == nil && kb.IsWikiEnabled() { wikiKBIDs = append(wikiKBIDs, kb.ID) - wikiTenantID = kb.TenantID } } if len(wikiKBIDs) > 0 { allowedTools = append(allowedTools, tools.ToolWikiReadPage, - tools.ToolWikiWritePage, tools.ToolWikiSearch, - tools.ToolWikiReadIndex, - tools.ToolWikiLint, ) logger.Infof(ctx, "Wiki KBs detected (%d), wiki tools added", len(wikiKBIDs)) } @@ -462,14 +448,8 @@ func (s *agentService) registerTools( // Wiki tools — only registered when wiki KBs are detected case tools.ToolWikiReadPage: toolToRegister = tools.NewWikiReadPageTool(s.wikiPageService, wikiKBIDs) - case tools.ToolWikiWritePage: - toolToRegister = tools.NewWikiWritePageTool(s.wikiPageService, wikiKBIDs, wikiTenantID) case tools.ToolWikiSearch: toolToRegister = tools.NewWikiSearchTool(s.wikiPageService, wikiKBIDs) - case tools.ToolWikiReadIndex: - toolToRegister = tools.NewWikiReadIndexTool(s.wikiPageService, wikiKBIDs) - case tools.ToolWikiLint: - toolToRegister = tools.NewWikiLintTool(s.wikiPageService, wikiKBIDs) default: logger.Warnf(ctx, "Unknown tool: %s", toolName) diff --git a/testdata/wiki_test/doc1_stardust_memo.md b/testdata/wiki_test/doc1_stardust_memo.md new file mode 100644 index 00000000..e21a37ad --- /dev/null +++ b/testdata/wiki_test/doc1_stardust_memo.md @@ -0,0 +1,11 @@ +# 星尘计划启动备忘录 +**机密级别**:极密 +**发布机构**:天穹财团 (SkyVault Consortium) 董事会 +**项目代号**:星尘计划 (Project Stardust) +**首席科学家**:艾琳·科尔博士 (Dr. Elara Cole) + +**项目概述**: +星尘计划旨在开发一种革命性的推进系统——“幽能引擎 (Psionic Engine)”。该引擎将利用非牛顿物理学框架,突破目前星际航行的光速壁垒。 + +**资源分配**: +天穹财团将调拨“深渊之门”实验室的全部资源供艾琳·科尔博士使用。项目资金不设上限,以确保幽能引擎能够在 2150 年前进入原型机测试阶段。 diff --git a/testdata/wiki_test/doc2_psionic_engine.md b/testdata/wiki_test/doc2_psionic_engine.md new file mode 100644 index 00000000..18ac2423 --- /dev/null +++ b/testdata/wiki_test/doc2_psionic_engine.md @@ -0,0 +1,12 @@ +# 幽能引擎技术白皮书 + +## 引言 +幽能引擎 (Psionic Engine) 代表着我们对宇宙认知的范式转移。它的核心原理并非燃烧燃料或喷射粒子,而是建立在备受争议的**虚空共振理论 (Void Resonance Theory)** 之上。 + +## 虚空共振理论 +该理论假设宇宙的真空中充满了低能级的波谱,通过特定频率的干涉,可以在空间中制造“引力滑流”。 + +## 催化剂:星晶 (StarQuartz) +要在宏观尺度上触发并维持“虚空共振理论”所描述的引力滑流,必须使用一种极端稀有的矿物作为反应堆核心的催化剂。这种矿物被称为**星晶 (StarQuartz)**。 + +星晶具有在室温下超导并在特定频段下自发振荡的特性。目前,地球上唯一能稳定合成并从陨石中提纯出工业级星晶的实体,是拥有庞大资本和尖端技术的**天穹财团 (SkyVault Consortium)**。 diff --git a/testdata/wiki_test/doc3_dr_cole_log.md b/testdata/wiki_test/doc3_dr_cole_log.md new file mode 100644 index 00000000..8e032445 --- /dev/null +++ b/testdata/wiki_test/doc3_dr_cole_log.md @@ -0,0 +1,17 @@ +# 个人日志 (节选) - 2148年 +**作者**:艾琳·科尔博士 (Dr. Elara Cole) + +... +**日志条目 #402** +我不明白。为什么我的研究团队里会有人听到不存在的低语? +就在上周,反应堆进行了一次全负荷测试,旨在验证“虚空共振理论”。为了达到那该死的输出功率,我们往堆芯里添加了未经稀释的**星晶 (StarQuartz)**。 + +**日志条目 #403** +辐射数值正常,但某种“东西”渗透了我们的实验室。今天又有两个工程师因为极度幻觉被送去医务室了。这就是高纯度星晶催化带来的不可见副作用吗? + +**日志条目 #404** +我已经向天穹财团的董事会提交了紧急备忘录。我建议立即暂停所有引擎相关的实验,并在解决星晶的神经干扰效应前封锁所有原型机。 + +他们拒绝了。他们说,只要测试人员的死亡率不超过 15%,项目推进的优先级依然最高。 +他们根本不在乎。 +...