Skip to content

Feat/voyage embeddingfeat: 支持 Voyage Embedding 并增强 technical_terms 精确召回#17

Open
anmezing wants to merge 8 commits into
hsingjui:mainfrom
anmezing:feat/voyage-embedding
Open

Feat/voyage embeddingfeat: 支持 Voyage Embedding 并增强 technical_terms 精确召回#17
anmezing wants to merge 8 commits into
hsingjui:mainfrom
anmezing:feat/voyage-embedding

Conversation

@anmezing

@anmezing anmezing commented Jun 7, 2026

Copy link
Copy Markdown

本 PR 增加了 Voyage embedding provider 支持,并增强了代码检索中 technical_terms 的精确召回能力。

主要内容包括:

  • 支持 Voyage embedding 请求格式。
  • 为 Voyage 区分索引阶段和查询阶段的 input_type
  • 支持 Voyage 可选的 output_dimensionoutput_dtype
  • 新增基于 SQLite 的 exact substring index,用于 technical_terms 精确召回。
  • exact index 按 project_id 隔离,避免不同项目互相污染。
  • 增强索引一致性,避免 exact index 写入失败后被误标记为成功。
  • 在 MCP / CLI 输出中增加 exact retrieval 诊断信息。
  • 增加 fixed-string exact retrieval、project isolation、force cleanup、legacy migration、失败重试等测试。
  • 更新 Voyage 配置和 exact retrieval 相关文档。

主要改动

1. Voyage embedding provider

新增 Voyage embedding provider 兼容逻辑。

当配置:

EMBEDDINGS_PROVIDER=voyage

EMBEDDINGS_BASE_URL 指向 Voyage endpoint 时,使用 Voyage 请求格式。

Voyage 请求行为:

  • 索引阶段发送 input_type=document
  • 查询阶段发送 input_type=query
  • 默认发送 output_dtype=float
  • 仅在显式配置 EMBEDDINGS_OUTPUT_DIMENSION 时发送 output_dimension
  • 不发送 OpenAI-compatible 的 encoding_format

非 Voyage provider,例如 SiliconFlow / OpenAI-compatible:

  • 保持原有 encoding_format=float 行为。
  • 不发送 Voyage 专属字段。

同时补充说明:

  • EMBEDDINGS_DIMENSIONS 是本地向量库维度。
  • EMBEDDINGS_OUTPUT_DIMENSION 是 Voyage API 可选输出维度。
  • 两者需要与实际返回向量维度保持一致。

2. technical_terms fixed-string exact retrieval

增强 technical_terms 处理逻辑。

之前 technical_terms 主要拼接进 query。现在会额外执行 fixed-string exact retrieval,用于精确召回包含完整术语的代码片段。

支持包含特殊符号的术语,例如:

@ControllerAdvice
@ExceptionHandler
R.failed
e.getMessage
useQuery()

exact retrieval 特点:

  • 按完整 substring 匹配。
  • 不使用正则。
  • 不依赖 FTS tokenizer。
  • 不拆分 term。
  • 不把部分字符串当作命中。
  • 最终通过 raw content / display code 做 fixed-string 二次确认。

因此:

  • @ControllerAdvice 不会误命中 @RestController
  • useQuery() 不会误命中 useQueryClient
  • R.failed 不会仅因为出现 failed 而命中。

3. SQLite exact substring index

新增 SQLite-backed exact substring index,用于提升 exact retrieval 的稳定性和性能。

新增或使用的结构包括:

  • exact_chunks
  • exact_grams

特性:

  • 使用现有 SQLite / better-sqlite3,不需要额外安装数据库。
  • exact index 按 project_id 隔离。
  • 文件修改时会删除旧 exact index 并写入新内容。
  • 文件删除时会清理对应 exact index。
  • --force 重建索引时会清理当前 project 的 exact index。
  • 兼容旧 schema,旧表缺少 project_id 时会 drop 后重建。
  • 短 term fallback 会同时检查 contentdisplay_code

4. 索引一致性修复

修复 exact index 写入失败时可能造成的部分成功状态。

现在如果 exact index 写入失败:

  • 会记录错误日志。
  • 会清理本批文件的 vector_index_hash
  • 不会把本批文件标记为已成功索引。
  • 返回 errors。
  • 下一次增量索引会重新尝试。

这样可以避免:

向量写入成功
exact index 写入失败
但文件被标记为已索引
后续增量索引跳过

导致 exact retrieval 长期缺失的问题。

5. MCP / CLI exact retrieval 诊断信息

MCP / CLI 输出增加 exact retrieval 诊断信息,便于判断 technical_terms 是否真正精确命中。

可能包含:

Missing exact technical terms: ...
Exact: seeds=..., candidates=..., scanned=..., elapsed=...ms, truncated=...
Skipped exact technical terms: ...

含义:

  • Missing exact technical terms:传入的术语没有 exact 命中。
  • seeds:最终进入上下文的 exact seed 数量。
  • candidates:exact retrieval 候选数量。
  • scanned:扫描或检查过的 chunk 数量。
  • elapsed:exact retrieval 耗时。
  • truncated:结果是否因上限被截断。
  • Skipped exact technical terms:因过短或超过数量限制被跳过的术语。

6. 测试覆盖

新增或补充测试覆盖:

  • fixed-string exact matching。
  • @ControllerAdvice 不误命中 @RestController
  • useQuery() 不误命中 useQueryClient
  • R.failed 不误命中 failed
  • missing exact technical terms。
  • SQLite-backed exact index 查询。
  • project_id 隔离。
  • force cleanup。
  • legacy exact schema migration。
  • 短 term 只存在于 display_code 的场景。
  • exact seed 数量限制。
  • exact index 写入失败不更新 vector_index_hash
  • exact index 写入失败后下一次可重试。
  • 重试成功后 exact index 可正常检索。

7. 文档更新

更新文档说明:

  • Voyage embedding 配置。
  • EMBEDDINGS_OUTPUT_DIMENSION
  • EMBEDDINGS_OUTPUT_DTYPE
  • EMBEDDINGS_DIMENSIONS 与 API 返回维度的关系。
  • technical_terms exact retrieval 行为。
  • SQLite exact substring index。
  • MCP / CLI exact diagnostics。
  • IGNORE_PATTERNS 建议。

验证

已执行或建议执行:

pnpm build
npx vitest run src/search/exactTechnicalTerms.test.ts src/indexer/index.test.ts

手动 fixture 验证:

  • @ControllerAdvice 只 exact 命中包含 @ControllerAdvice 的文件。
  • useQuery() 不 exact 命中 useQueryClient
  • R.failed 不 exact 命中普通 failed
  • 不存在的术语会出现在 missingExactTechnicalTerms

真实 workspace 验证:

  • exact retrieval 可以稳定命中包含目标 technical terms 的代码。
  • missingExactTechnicalTerms 行为符合预期。
  • exactSeedCountexactCandidateCountexactHitsTruncated 等诊断信息正常输出。
  • vector / lexical fallback 仍可正常工作。

注意事项

更换 embedding provider、embedding model、输出维度或输出 dtype 后,需要重新建立向量索引:

contextweaver index --force

仅更换 rerank 配置通常不需要重新索引,因为 rerank 只影响搜索阶段排序。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant