""" Tool Layer - wiki_synthesize 工具 发现跨概念的综合分析机会,生成 synthesis 页面。 参考设计文档:第 2.2 节 """ import logging from typing import Dict, Any, List from ..services import QueryService, GraphService logger = logging.getLogger(__name__) class WikiSynthesizeTool: """wiki_synthesize 工具实现""" def __init__(self, query_service: QueryService, graph_service: GraphService): self.query_service = query_service self.graph_service = graph_service async def handle(self, concepts: List[str] = None, threshold: float = 0.3) -> Dict[str, Any]: """ 发现跨概念的综合分析机会 Args: concepts: 概念列表(空表示自动发现) threshold: 相关性阈值 Returns: { "synthesis": [ { "concept_a": "SQLite", "concept_b": "Concurrency", "common_references": ["page1", "page2"], "strength": 0.8, "suggestion": "Consider creating synthesis page: SQLite & Concurrency" } ], "total": 5 } """ synthesis = [] # 如果未提供概念,自动发现高相关性概念 if not concepts: # 获取高度连接的页面作为候选 highly_connected = await self.graph_service.get_highly_connected_pages(threshold=10) concepts = [item["title"] for item in highly_connected[:10]] # 分析概念间的关联 for i, concept_a in enumerate(concepts): for concept_b in concepts[i + 1:]: # 查找同时引用两个概念的页面 pages_a = await self.query_service.search(concept_a, limit=50) pages_b = await self.query_service.search(concept_b, limit=50) paths_a = {p.path for p in pages_a} paths_b = {p.path for p in pages_b} common = paths_a & paths_b if len(common) >= 2: # 至少 2 个共同引用 strength = len(common) / max(len(paths_a), len(paths_b)) if strength >= threshold: synthesis.append({ "concept_a": concept_a, "concept_b": concept_b, "common_references": sorted(list(common)), "strength": round(strength, 2), "suggestion": f"Consider creating synthesis page: {concept_a} & {concept_b}" }) # 按关联强度排序 synthesis.sort(key=lambda x: x["strength"], reverse=True) return { "synthesis": synthesis[:20], "total": len(synthesis) } def get_schema(self) -> dict: """返回 MCP Tool schema""" return { "name": "wiki_synthesize", "description": "发现跨概念的综合分析机会,生成 synthesis 页面", "inputSchema": { "type": "object", "properties": { "concepts": { "type": "array", "items": {"type": "string"}, "description": "概念列表(空表示自动发现)" }, "threshold": { "type": "number", "default": 0.3, "description": "相关性阈值" } } } }