# 知识管理系统 ## 文档维护规范 0. **先改文档,再动代码** - 新功能或重大修改需先完成文档更新、并完成审阅后,再进行代码实现;除非改动较小、不被文档涵盖 1. **文档分层,链接代码** - 重要或复杂设计可以另有详细文档;关键实现需标注代码文件路径;格式:`module/file.py:function_name` 2. **简洁快照,日志分离** - 只记录最重要的、与代码准确对应的或者明确的已完成的设计的信息,避免推测、建议、决策历史、修改日志、大量代码;决策依据或修改日志若有必要,可在`knowhub/docs/decisions.md`另行记录 --- ## 架构 KnowHub Server 是统一的知识管理服务,包含两个子系统: 1. **Knowledge 系统**:结构化知识管理(任务场景 + 经验内容) 2. **Resource 系统**:原始资源存储(代码、凭证、Cookie等)→ 详见 `knowhub/docs/resource-storage.md` ``` Agent KnowHub Server ├── knowledge_search 工具 → GET /api/knowledge/search ├── knowledge_save 工具 → POST /api/knowledge ├── knowledge_update 工具 → PUT /api/knowledge/{id} ├── goal focus 自动注入 → GET /api/knowledge/search └── resource 资源引用 → GET /api/resource/{id} ``` ### 存储架构 KnowHub 采用 Milvus Lite 单一存储架构(详见 `knowhub/docs/decisions.md#13`): ``` ┌─────────────────────────────────────────────────────┐ │ KnowHub Server │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────┐ │ │ │ Milvus Lite │ │ │ │ (单一存储) │ │ │ ├─────────────────────┤ │ │ │ knowledge 集合 │ │ │ │ - id │ │ │ │ - embedding (向量) │ │ │ │ - task/content │ │ │ │ - types/tags/scopes │ │ │ │ - owner/eval/source │ │ │ │ - resource_ids │ │ │ └─────────────────────┘ │ │ │ │ 检索流程:向量召回 → LLM 精排 → 返回 top k │ └─────────────────────────────────────────────────────┘ ``` **Milvus Lite**: - 存储完整知识数据(所有字段)+ 向量 - 提供高效的语义向量检索 - 支持标量字段过滤和查询 - 本地文件存储,部署简单 实现位置: - Milvus 封装:`knowhub/vector_store.py` - Embedding 生成:`knowhub/embeddings.py` - 检索逻辑:`knowhub/server.py:knowledge_search` --- ## 知识结构 单条知识的数据格式(基于 `agent/docs/knowledge.md` 定义): ```json { "id": "knowledge-20260305-a1b2", "message_id": "msg-xxx", "types": ["strategy", "tool"], "task": "在什么场景下要完成什么目标", "tags": { "category": "preference", "domain": "coding_style" }, "scopes": ["org:cybertogether"], "owner": "agent:research_agent", "content": "核心知识内容", "resource_ids": ["code/selenium/login", "credentials/website_a"], "source": { "name": "资源名称", "category": "exp", "urls": ["https://example.com"], "agent_id": "research_agent", "submitted_by": "user@example.com", "timestamp": "2026-03-05T12:00:00Z", "message_id": "msg-xxx" }, "eval": { "score": 4, "helpful": 5, "harmful": 0, "confidence": 0.9, "helpful_history": [], "harmful_history": [] }, "created_at": "2026-03-05T12:00:00Z", "updated_at": "2026-03-05T12:00:00Z" } ``` ### 字段说明 - **id**: 唯一标识,格式 `knowledge-{timestamp}-{random}` - **message_id**: 来源 Message ID(用于精确溯源到具体消息) - **types**: 知识类型数组(可多选) - `user_profile`: 用户偏好、习惯、背景 - `strategy`: 执行经验(从反思中获得) - `tool`: 工具使用方法、优缺点、代码示例 - `usecase`: 用户背景、方案、步骤、效果 - `definition`: 概念定义、技术原理、应用场景 - `plan`: 流程步骤、决策点、方法论 - **task**: 任务描述,什么场景、在做什么 - **tags**: 业务标签(JSON 对象),如 `{"category": "preference", "domain": "coding_style"}` - **scopes**: 可见范围数组,默认 `["user:owner"]` - **owner**: 所有者,默认取用户的git email - **content**: 核心知识内容 - **resource_ids**: 关联的资源 ID 列表(可选),引用 Resource 系统中的资源。每个资源可能包含公开内容(body)和敏感内容(secure_body) - **source**: 来源信息(嵌套对象) - **name**: 资源名称 - **category**: 来源类别(paper/exp/skill/book) - **urls**: 参考来源链接数组 - **agent_id**: 创建者 agent ID - **submitted_by**: 提交者 - **timestamp**: 创建时间戳 - **message_id**: 可选,用于溯源 - **eval**: 评估信息(嵌套对象) - **score**: 评分 1-5 - **helpful**: 好用次数 - **harmful**: 不好用次数 - **confidence**: 置信度 0-1 - **helpful_history**: 好用案例历史 - **harmful_history**: 不好用案例历史 --- ## Agent 工具 Agent 通过以下工具与 KnowHub Server 交互。工具只是 API 调用的封装,核心逻辑在 Server 实现。 实现位置:`agent/tools/builtin/knowledge.py` ### `knowledge_search` 检索知识。 ```python @tool() async def knowledge_search( query: str, top_k: int = 5, min_score: int = 3, types: Optional[List[str]] = None ) -> ToolResult ``` 调用 `GET /api/knowledge/search?q={query}&top_k={top_k}&min_score={min_score}&types={types}` ### `knowledge_save` 保存新知识。 ```python @tool() async def knowledge_save( task: str, content: str, types: List[str], tags: Optional[Dict[str, str]] = None, scopes: Optional[List[str]] = None, owner: Optional[str] = None, source_name: str = "", source_category: str = "exp", urls: List[str] = None, agent_id: str = "research_agent", submitted_by: str = "", score: int = 3, message_id: str = "" ) -> ToolResult ``` 调用 `POST /api/knowledge` **默认值**(在 agent 代码中设置): - `scopes`: `["org:cybertogether"]` - `owner`: `f"agent:{agent_id}"` ### `knowledge_update` 更新已有知识的评估反馈。 ```python @tool() async def knowledge_update( knowledge_id: str, add_helpful_case: Optional[Dict] = None, add_harmful_case: Optional[Dict] = None, update_score: Optional[int] = None, evolve_feedback: Optional[str] = None ) -> ToolResult ``` 调用 `PUT /api/knowledge/{knowledge_id}` **知识进化**:当提供 `evolve_feedback` 时,Server 使用 LLM 重写知识内容。 ### `knowledge_batch_update` 批量反馈知识有效性。 ```python @tool() async def knowledge_batch_update( feedback_list: List[Dict[str, Any]] ) -> ToolResult ``` 调用 `POST /api/knowledge/batch_update` ### `knowledge_list` 列出已保存的知识。 ```python @tool() async def knowledge_list( limit: int = 10, types: Optional[List[str]] = None, scopes: Optional[List[str]] = None ) -> ToolResult ``` 调用 `GET /api/knowledge?limit={limit}&types={types}&scopes={scopes}` ### `knowledge_slim` 知识库瘦身,合并相似知识。 ```python @tool() async def knowledge_slim( model: str = "google/gemini-2.0-flash-001" ) -> ToolResult ``` 调用 `POST /api/knowledge/slim` --- ## Resource 引用机制 Knowledge 可以通过 `resource_id` 和 `secure_resource_id` 引用 Resource 系统中的原始资源。 ### 使用场景 **场景 1:复杂代码工具** 当工具实现逻辑复杂(如 Selenium 绕过检测、复杂的 API 调用封装)时: - 将代码片段保存为 Resource(`content_type=code`) - Knowledge 记录使用场景和经验,通过 `resource_ids` 引用代码 ```json { "task": "使用 Selenium 登录某网站并绕过反爬检测", "content": "使用 undetected_chromedriver 可以绕过大部分检测。关键点:1) 设置合适的 user-agent 2) 随机延迟 3) 避免频繁请求", "types": ["tool", "strategy"], "resource_ids": ["code/selenium/undetected_login"] } ``` 对应的 Resource: ```json { "id": "code/selenium/undetected_login", "title": "Selenium 绕过检测登录代码", "body": "import undetected_chromedriver as uc\n\ndriver = uc.Chrome()...", "content_type": "code", "metadata": {"language": "python"} } ``` **场景 2:账号密码凭证** 当发现或配置了有用的工具账号时: - 将敏感信息(账号、密码)保存为 Resource(`content_type=credential`,存入 `secure_body`) - Knowledge 记录使用方法和注意事项,通过 `resource_ids` 引用凭证 ```json { "task": "登录某网站进行数据采集", "content": "使用测试账号登录,注意:1) 每天限额 100 次 2) 需要在工作时间访问 3) 登录后 session 有效期 2 小时", "types": ["tool", "usecase"], "resource_ids": ["credentials/website_a"] } ``` 对应的 Resource: ```json { "id": "credentials/website_a", "title": "某网站测试账号", "body": "使用方法:直接登录即可,每天限额 100 次", "secure_body": "账号:user@example.com\n密码:SecurePass123", "content_type": "credential", "metadata": {"acquired_at": "2026-03-06T10:00:00Z"} } ``` **场景 3:Cookie 和登录态** 当获取了有效的 Cookie 时: - 将 Cookie 保存为 Resource(`content_type=cookie`,存入 `secure_body`,设置 `expires_at`) - Knowledge 记录获取方法和使用场景,通过 `resource_ids` 引用 ```json { "task": "使用已登录的 Cookie 访问某网站 API", "content": "Cookie 获取方法:手动登录后从浏览器导出。使用时直接设置到请求头。注意检查过期时间。", "types": ["tool"], "resource_ids": ["cookies/website_a"] } ``` 对应的 Resource: ```json { "id": "cookies/website_a", "title": "某网站 Cookie", "body": "适用于:已登录状态的 API 调用", "secure_body": "session_id=abc123; auth_token=xyz789", "content_type": "cookie", "metadata": { "acquired_at": "2026-03-06T10:00:00Z", "expires_at": "2026-03-07T10:00:00Z" } } ``` **场景 4:多资源引用** 一个知识可以同时引用多个资源(如代码 + 凭证): ```json { "task": "使用 Selenium 登录某网站", "content": "使用 undetected_chromedriver 绕过检测,配合测试账号登录", "types": ["tool", "usecase"], "resource_ids": ["code/selenium/undetected_login", "credentials/website_a"] } ``` ### 提交流程 1. **识别需要提取的 Resource**:在知识反思时,识别复杂代码、凭证、Cookie 等 2. **调用 `resource_save` 工具**:提交 Resource 到 KnowHub 3. **调用 `knowledge_save` 工具**:保存 Knowledge 并关联 Resource ID 实现位置: - Resource 提交工具:`agent/tools/builtin/knowledge.py:resource_save` - Knowledge 保存工具:`agent/tools/builtin/knowledge.py:knowledge_save` - 知识反思 prompt:`agent/core/prompts/knowledge.py:KNOWLEDGE_EXTRACTION_PROMPT` --- ## 知识注入机制 知识注入在 goal focus 时自动触发。 实现位置:`agent/trace/goal_tool.py:focus_goal` ### 注入流程 ```python # 1. LLM 调用 goal 工具 goal(action="focus", goal_id="goal-123") # 2. goal 工具内部自动执行 current_goal = goal_tree.find("goal-123") knowledge_results = await knowledge_search( query=current_goal.description, top_k=3, min_score=3 ) # 3. 保存到 goal 对象 current_goal.knowledge = knowledge_results.metadata["items"] # 4. 持久化到 trace store await trace_store.update_goal_tree(trace_id, goal_tree) # 5. 返回给 LLM return ToolResult( title="✅ Goal 已聚焦", output=f"当前 Goal: {current_goal.description}\n\n📚 相关知识 ({len(knowledge_results)} 条):\n..." ) ``` ### 知识展示 注入的知识会显示在 GoalTree 的「📚 相关知识」部分。 --- ## 调研决策 调研决策与知识注入分离,通过 system prompt 引导。 ### 决策流程 ``` 1. goal focus → 自动注入知识 ↓ 2. LLM 看到 GoalTree 中的「📚 相关知识」 ↓ 3. LLM 自主判断: ├─ 知识充足 → 直接制定计划 └─ 知识不足 → 调用 agent 工具启动调研子任务 ``` ### System Prompt 引导 ```markdown ## 知识管理 当你使用 `goal(action="focus")` 聚焦到某个 goal 时,系统会自动检索相关知识并显示在 GoalTree 的「📚 相关知识」部分。 根据知识充足性判断: **知识充足**: - 如果相关知识足以完成任务,直接制定计划 - 使用 `goal` 工具创建执行计划的子 goal **知识不足**: - 如果相关知识不足,需要进行调研 - 调用 `agent` 工具启动调研子任务 - 调研完成后,使用 `knowledge_save` 保存结果 调研完成后,再次 focus 该 goal,新保存的知识会被自动注入。 ``` ### 调研 Skill 调研指南存储在 `agent/memory/skills/research.md`。 --- ## KnowHub Server API ### `GET /api/knowledge/search` 检索知识。使用向量召回 + LLM 精排策略。 **参数**: - `q`: 查询文本 - `top_k`: 返回数量(默认 5) - `min_score`: 最低评分过滤(默认 3) - `types`: 按类型过滤(可选,逗号分隔) - `owner`: 按所有者过滤(可选) **检索流程**: 1. **向量召回**(快速、便宜) - 生成查询向量(使用 OpenAI text-embedding-3-small 或本地模型) - Milvus Lite 检索语义相似的知识,召回 `top_k * 3` 个候选 - 支持标量过滤(types、owner、scopes、min_score) 2. **LLM 精排**(准确、贵) - 使用 LLM(gemini-2.5-flash-lite)对候选重新排序 - 根据查询意图和知识内容,选出最相关的 `top_k` 条 - 输出按相关性从高到低排序 3. **Fallback**(保证可用性) - 如果 LLM 精排失败或超时,直接返回向量召回的 `top_k` 结果 - 保证检索始终可用 实现位置: - `knowhub/server.py:knowledge_search` - 主检索逻辑 - `knowhub/server.py:llm_rerank` - LLM 精排 **响应**: ```json { "results": [ { "id": "knowledge-xxx", "task": "...", "content": "...", "types": ["strategy", "tool"], "tags": {"category": "preference"}, "eval": { "score": 4, "helpful": 2, "harmful": 0, "confidence": 0.9 } } ], "count": 3, "reranked": true } ``` ### `POST /api/knowledge` 保存新知识。 **请求体**: ```json { "task": "在什么场景下要完成什么目标", "content": "核心知识内容", "types": ["tool", "strategy"], "tags": {"category": "preference", "domain": "coding_style"}, "scopes": ["org:cybertogether"], "owner": "agent:research_agent", "source": { "name": "资源名称", "category": "exp", "urls": ["https://example.com"], "agent_id": "research_agent", "submitted_by": "user@example.com", "message_id": "msg-xxx" }, "score": 4 } ``` 实现位置:`knowhub/server.py:save_knowledge` ### `PUT /api/knowledge/{id}` 更新知识。 **请求体**: ```json { "add_helpful_case": { "task": "任务描述", "outcome": "成功", "timestamp": "2026-03-05T12:00:00Z" }, "add_harmful_case": { "task": "任务描述", "outcome": "失败", "reason": "原因", "timestamp": "2026-03-05T12:00:00Z" }, "update_score": 4, "evolve_feedback": "改进建议(触发知识进化)" } ``` **知识进化**:当提供 `evolve_feedback` 时,Server 使用 LLM 重写知识内容。 实现位置:`knowhub/server.py:update_knowledge` ### `POST /api/knowledge/batch_update` 批量反馈知识有效性。 **请求体**: ```json { "feedback_list": [ { "knowledge_id": "knowledge-xxx", "is_helpful": true, "case": { "task": "任务描述", "outcome": "成功", "timestamp": "2026-03-05T12:00:00Z" } } ] } ``` 实现位置:`knowhub/server.py:batch_update_knowledge` ### `GET /api/knowledge` 列出知识。 **参数**: - `limit`: 返回数量(默认 10) - `types`: 按类型过滤(可选,逗号分隔) - `scopes`: 按可见范围过滤(可选,逗号分隔) 实现位置:`knowhub/server.py:list_knowledge` ### `POST /api/knowledge/slim` 知识库瘦身,合并相似知识。 **请求体**: ```json { "model": "google/gemini-2.0-flash-001" } ``` 实现位置:`knowhub/server.py:slim_knowledge` --- ## 实现位置 | 组件 | 实现位置 | |------|---------| | KnowHub Server | `knowhub/server.py` | | Agent 工具 | `agent/tools/builtin/knowledge.py` | | goal 工具(知识注入) | `agent/trace/goal_tool.py:focus_goal` | | 调研 skill | `agent/memory/skills/research.md` | --- ## 设计原则 1. **统一服务**:KnowHub Server 是唯一的知识存储和管理服务 2. **Server 端逻辑**:检索、进化等核心逻辑在 Server 实现,Agent 工具只是 API 封装 3. **自动注入**:知识注入在 goal focus 时自动触发 4. **分离关注点**:知识注入(自动)与调研决策(显式)分离 5. **工具自治**:知识注入逻辑在 goal 工具中,不在 runner 中 6. **精确溯源**:使用 message_id 而非 trace_id,可精确定位到具体消息 7. **质量保证**:两阶段检索(语义路由 + 质量精排)确保准确性