语义搜索

📎 引用文件

本文引用的文件
- agent/src/memory/search_index.py - agent/src/session/search.py - agent/src/memory/semantic_links.py - agent/src/memory/persistent.py - agent/src/config/env_schema.py - agent/tests/memory/benchmarks/runner.py

目录

  1. 简介
  2. 项目结构
  3. 核心组件
  4. 架构总览
  5. 详细组件分析
  6. 依赖关系分析
  7. 性能与优化
  8. 故障排查指南
  9. 结论
  10. 附录:使用示例与扩展指南

简介

本文件系统性说明本项目中“语义搜索”的实现原理与技术细节。需要特别说明的是,当前代码库中的“语义搜索”并非基于向量嵌入的相似度检索,而是以全文检索(SQLite FTS5)与词项相似度(BM25)为核心的混合方案: - 会话级跨会话全文检索:通过 SQLite FTS5 对消息内容建立倒排索引,提供 O(log n) 级别的高效匹配与相关性排序。 - 记忆级全文检索:为持久化记忆条目构建 FTS5 虚拟表,支持标题、描述、关键词、正文的多字段检索,并针对中日韩字符进行单字+双字的展开以提升召回。 - 语义链接与知识图谱雏形:通过 BM25 计算条目间相似度,自动发现并维护条目间的“语义链接”,并以侧边 JSON 文件持久化;同时支持显式 wikilink 引用解析,形成轻量级的知识图谱关系。 - 检索增强:在结果返回后,可按预建语义链接扩展结果集,提升上下文完整性。

该设计兼顾了高性能、可解释性与可扩展性,适合在金融研究、交易策略与多会话协作场景中快速定位相关历史对话与记忆片段。

项目结构

围绕语义搜索的相关模块主要分布在 memory 与 session 两个子系统中: - agent/src/memory/search_index.py:持久记忆的 FTS5 索引与检索实现。 - agent/src/session/search.py:会话消息的 FTS5 索引与检索实现。 - agent/src/memory/semantic_links.py:基于 BM25 的语义链接发现与持久化。 - agent/src/memory/persistent.py:记忆条目的增删改查、重要性衰减、以及调用 FTS5 与语义链接的集成点。 - agent/src/config/env_schema.py:功能开关与环境配置(如是否启用 FTS5、语义链接等)。 - agent/tests/memory/benchmarks/runner.py:检索质量评估与 BM25 评分基准测试。

graph TB A["PersistentMemory<br/>记忆存取与扫描"] --> B["MemorySearchIndex<br/>FTS5 索引(记忆)"] A --> C["SemanticLinker<br/>BM25 语义链接"] D["SessionSearchIndex<br/>FTS5 索引(会话)"] --> E["会话检索服务"] A --> F["环境配置<br/>VT_MEMORY_* 开关"] C --> G[".relations.json<br/>关系侧车文件"]

图表来源 - agent/src/memory/persistent.py:196-438 - agent/src/memory/search_index.py:113-302 - agent/src/session/search.py:60-267 - agent/src/memory/semantic_links.py:158-319 - agent/src/config/env_schema.py:461-537

章节来源 - agent/src/memory/persistent.py:196-438 - agent/src/memory/search_index.py:113-302 - agent/src/session/search.py:60-267 - agent/src/memory/semantic_links.py:158-319 - agent/src/config/env_schema.py:461-537

核心组件

章节来源 - agent/src/memory/search_index.py:113-302 - agent/src/session/search.py:60-267 - agent/src/memory/semantic_links.py:158-319 - agent/src/memory/persistent.py:196-438

架构总览

下图展示了从用户查询到检索结果的完整流程,包括 FTS5 索引、BM25 语义链接与持久记忆的协同工作。

sequenceDiagram participant U as "用户" participant PM as "PersistentMemory" participant MSI as "MemorySearchIndex" participant SSI as "SessionSearchIndex" participant SL as "SemanticLinker" U->>PM : 发起自然语言查询 alt 启用 FTS5(记忆) PM->>MSI : search(query, max_results) MSI-->>PM : MemoryMatch[] (rank 排序) PM->>PM : 映射 entry_id -> MemoryEntry else 回退关键词检索 PM->>PM : tokenize + 加权重叠分数 PM-->>U : 结果列表 end opt 启用语义链接 PM->>SL : load_relations(entry_path) SL-->>PM : [(target_file, score)] PM->>PM : 扩展结果集(去重/限制) end U->>SSI : 跨会话检索(可选) SSI-->>U : SearchMatch[] (按会话去重)

图表来源 - agent/src/memory/persistent.py:358-438 - agent/src/memory/search_index.py:252-302 - agent/src/session/search.py:216-267 - agent/src/memory/semantic_links.py:232-319

详细组件分析

记忆 FTS5 索引(MemorySearchIndex)

flowchart TD Start(["查询入口"]) --> Sanitize["安全化查询<br/>提取令牌并引号包裹"] Sanitize --> Query{"是否有有效令牌?"} Query -- 否 --> ReturnEmpty["返回空结果"] Query -- 是 --> Exec["执行 MATCH 查询<br/>JOIN 获取标题/摘要/rank"] Exec --> Clean["清理 CJK 显示文本"] Clean --> Sort["按 rank 排序并限制数量"] Sort --> End(["返回结果"])

图表来源 - agent/src/memory/search_index.py:252-302 - agent/src/memory/search_index.py:409-445 - agent/src/memory/search_index.py:357-407

章节来源 - agent/src/memory/search_index.py:113-302 - agent/src/memory/search_index.py:304-355 - agent/src/memory/search_index.py:357-445

会话 FTS5 索引(SessionSearchIndex)

sequenceDiagram participant Client as "客户端" participant SSI as "SessionSearchIndex" participant DB as "SQLite(WAL)" Client->>SSI : search(query, max_sessions) SSI->>DB : MATCH 查询(messages_fts JOIN messages JOIN sessions) DB-->>SSI : 命中行(rank, snippet, session_id...) SSI->>SSI : 按 session_id 去重 SSI-->>Client : SearchMatch[]

图表来源 - agent/src/session/search.py:216-267 - agent/src/session/search.py:137-192 - agent/src/session/search.py:269-329

章节来源 - agent/src/session/search.py:60-267 - agent/src/session/search.py:269-329

语义链接(SemanticLinker)

classDiagram class SemanticLinker { +memory_dir Path +discover_links(entry_title, entry_tokens, all_entries_data, top_k) List[(str,float)] +save_relations(entry_path, links) void +load_relations(entry_path) List[(str,float)] +resolve_wikilinks(body) List[str] +get_relation_path(entry_path) Path +remove_relations(entry_path) void } class BM25 { +compute_idf(corpus) Dict[str,float] +compute_bm25_score(query_tokens, doc_tokens, idf_scores, avg_dl) float } SemanticLinker --> BM25 : "使用"

图表来源 - agent/src/memory/semantic_links.py:63-150 - agent/src/memory/semantic_links.py:158-319

章节来源 - agent/src/memory/semantic_links.py:63-150 - agent/src/memory/semantic_links.py:158-319

持久记忆(PersistentMemory)

flowchart TD Q["输入查询"] --> CheckFTS{"是否启用 FTS5?"} CheckFTS -- 是 --> TryFTS["调用 MemorySearchIndex.search"] TryFTS --> FTSResult{"是否有结果?"} FTSResult -- 是 --> MapEntries["映射 entry_id -> MemoryEntry"] FTSResult -- 否 --> AutoRebuild["首次空结果时自动重建索引"] AutoRebuild --> TryFTS CheckFTS -- 否 --> KeywordScan["关键词重叠评分(元数据权重×2)"] KeywordScan --> ScoreSort["按分数与修改时间排序"] MapEntries --> LinksOpt{"是否启用语义链接?"} ScoreSort --> LinksOpt LinksOpt -- 是 --> Expand["加载 .relations.json 并扩展结果"] LinksOpt -- 否 --> Return["返回结果"] Expand --> Return

图表来源 - agent/src/memory/persistent.py:358-438 - agent/src/memory/persistent.py:80-91

章节来源 - agent/src/memory/persistent.py:80-91 - agent/src/memory/persistent.py:358-438

依赖关系分析

graph LR CFG["EnvConfig.memory<br/>VT_MEMORY_* 开关"] --> PM["PersistentMemory"] PM --> MSI["MemorySearchIndex"] PM --> SL["SemanticLinker"] SSI["SessionSearchIndex"] --> API["会话检索接口"]

图表来源 - agent/src/config/env_schema.py:461-537 - agent/src/memory/persistent.py:358-438

章节来源 - agent/src/config/env_schema.py:461-537 - agent/src/memory/persistent.py:358-438

性能与优化

[本节为通用性能讨论,不直接分析具体文件]

故障排查指南

章节来源 - agent/src/memory/search_index.py:147-196 - agent/src/memory/search_index.py:252-302 - agent/src/memory/semantic_links.py:232-319

结论

本项目的语义搜索以 FTS5 全文检索为核心,辅以 BM25 语义链接与重要性衰减,实现了高效、可解释、可扩展的检索能力。通过配置开关,用户可在不同场景下灵活启用/禁用各功能,平衡性能与召回。未来如需引入向量嵌入检索,可在现有架构基础上增加向量索引层,并与 FTS5/BM25 结果融合排序。

[本节为总结性内容,不直接分析具体文件]

附录:使用示例与扩展指南

使用示例

索引更新与缓存策略

章节来源 - agent/src/memory/search_index.py:207-355 - agent/src/session/search.py:137-192 - agent/src/session/search.py:269-329

自定义搜索算法扩展指南

章节来源 - agent/src/memory/semantic_links.py:104-150 - agent/src/memory/search_index.py:147-196 - agent/src/memory/persistent.py:358-438