Skip to content

feat(knowledge): v2 Phase 3+4 向量混合检索与 AI Chat/Ask 双模式#10

Open
wynxing wants to merge 3 commits into
mainfrom
feat/knowledge-v2-phase3-4
Open

feat(knowledge): v2 Phase 3+4 向量混合检索与 AI Chat/Ask 双模式#10
wynxing wants to merge 3 commits into
mainfrom
feat/knowledge-v2-phase3-4

Conversation

@wynxing

@wynxing wynxing commented Jun 20, 2026

Copy link
Copy Markdown
Owner

概述

知识库 v2 Phase 3(sqlite-vec 向量索引 + RRF 混合检索)与 Phase 4(AI Chat/Ask 双模式 + 三级上下文权限 + 引用审计)。在 PR #9(Phase 0-2)之上叠加向量层与 RAG 对话层,向 issue #7/#8 推进。

Phase 3 — sqlite-vec + RRF

  • embedding adapterpackages/ai/src/embedding.ts):OpenAI 兼容 /v1/embeddings batch,重试+超时,与 chat provider 解耦(DeepSeek 无 embedding 端点)
  • db 层loadVecExtension/toVecBuffer + vec0 延迟建表(首嵌发现维度)+ embedding_cache 内容哈希去重 + searchKnn(KNN) + getIndexStatus 三态(hybrid/indexing/fts-only)
    • 顺手修 Phase 2 bugreindexTask 缺 FTS5 INSERT,task 无法被检索 → 已补
  • service:drain 队列(单飞 mutex + cache 复用)+ searchHybrid(FTS5+vec) + rrf.ts 纯函数(k=60)
  • routes:search 切 hybrid、index-status 真实 flags、新增 GET/PUT /api/knowledge/embedding-config(内存态,apiKey 不回显)
  • 前端:api 层 + KnowledgeSection embedding baseUrl/apiKey 配置闭环

Phase 4 — Chat/Ask 双模式

  • 会话持久化ai_conversations/ai_messages 表 + createAiConversationStore(多轮 + sources_json)
  • ContextBuildermodules/ai/context.ts):权重/greedy fill/gap fill 句子边界/三明治排序
  • 引用审计modules/ai/citation.ts):injectSources(稳定 sN id) + parseAndAuditCitations(丢弃未注入 id 防幻觉) + buildSources(服务端生成,非模型自报)
  • ai servicehandleChat(全量上下文多轮) + handleAsk(RAG 一次性) + plainChat 降级
  • 路由重构/api/ai/chat 委托 service,请求体扩 mode/projectId/context/conversationId,ai:done 携带 {text, sources, retrievalMode}

降级路径

  • vec 未加载 → mode='fts-only',search 回退 FTS
  • embedding 未配 → mode='fts-only'
  • Ask 无命中 / Chat 无选中 → 退普通单轮 DeepSeek(保持现有行为不回归)

测试计划

  • pnpm typecheck 全绿(shared/ai/db/tts/desktop/server-local)
  • pnpm -r test 全绿:ai 8、db 9+4skip、server-local 41+5skip、desktop 28、tts 1
  • 单测:embedding(8)、rrf(6)、context(7)、citation(5)
  • CI:vec0 写入+KNN+embedding_cache 去重+searchHybrid(skipIf 本机跳过,CI 验证);reindexTask FTS 修复回归
  • 手动:配置 embedding provider → 语义查询命中;Chat/Ask 切换 + sources 跳转
  • 前端 4.5 Chat/Ask 对话 UI(PR 后续补充,当前仅后端 + 配置 UI)

说明

  • 本机无 better-sqlite3 原生 binding(Node 24.14),vec/sqlite 专属测试 skipIfCI 为唯一验证(Phase 2 已验证此模式)
  • sqlite-vec pre-v1,pin 版本;vec0 维度固定,模型换维度需 drop+recreate+全量重嵌
  • embedding 配置走服务端内存端点(重启丢失,YAGNI,不引持久 settings store)
  • better-sqlite3→node:sqlite 迁移仍延后(SEA 任务)

后续

Phase 3 — sqlite-vec 向量索引 + RRF 混合检索:
- packages/ai: 新增 embedding.ts(OpenAI 兼容 /v1/embeddings batch,重试+超时,与 chat provider 解耦)
- packages/db: loadVecExtension/toVecBuffer + vec0 延迟建表(维度发现)+ embedding_cache 去重 + searchKnn(KNN)
  + getIndexStatus 三态(hybrid/indexing/fts-only) + 顺手修 reindexTask 缺 FTS5 INSERT bug
- modules/knowledge: service drain 队列(单飞 mutex, cache 复用) + searchHybrid(FTS5+vec) + rrf.ts 纯函数(k=60)
- routes: search 切 hybrid、index-status 真实 flags、新增 GET/PUT /embedding-config(内存态, apiKey 不回显)
- 前端: api 层 + KnowledgeSection embedding baseUrl/apiKey 配置闭环

Phase 4 — AI Chat/Ask 双模式 + 三级上下文 + 引用审计:
- packages/db: ai_conversations/ai_messages 表 + createAiConversationStore(多轮持久化 + sources_json)
- modules/ai/context.ts: ContextBuilder 纯函数(权重/greedy fill/gap fill 句子边界/三明治排序)
- modules/ai/citation.ts: injectSources(稳定 sN id) + parseAndAuditCitations(丢弃未注入 id 防幻觉) + buildSources(服务端生成)
- modules/ai/service.ts: handleChat(全量上下文多轮) + handleAsk(RAG 一次性) + plainChat 降级
- app.ts: /api/ai/chat 重构委托 service,请求体扩 mode/projectId/context/conversationId,ai:done 携带 {text,sources,retrievalMode}

测试:embedding(8)、rrf(6)、context(7)、citation(5)、db vec(skipIf)、server-local 全绿
本机无 better-sqlite3 binding,vec/sqlite 专属测试 skipIf,CI 验证

Co-Authored-By: Claude <noreply@anthropic.com>
@fennoai

fennoai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Important

Fenno AI is not enabled for this organization

Fenno AI is currently in internal testing and is not yet open for external organizations.

If you would like to request access, sign in to Fenno AI Console, choose Give Feedback in the lower-left corner, and tell us what you need. We will follow up promptly.

wynxing and others added 2 commits June 20, 2026 19:54
CI 在真实 sqlite-vec 环境暴露两个本机 skipIf 漏掉的问题:
- KNN 测试用 updateNote 后未 reindex → 无 chunk → listPendingChunks 空。改用 reindexNote 显式触发。
- cache 测试 toEqual 失败:Float32 序列化 0.1→0.10000000149 精度损失。改 toBeCloseTo。

Co-Authored-By: Claude <noreply@anthropic.com>
原测试断言 vectorExtensionAvailable===false,但 CI 环境 vec 实际加载成功。
真实语义:mode 由 vecLoaded && providerConfigured 共同决定;无 embedding provider
配置时(providerConfigured=false)即为 fts-only,与 vec 是否加载无关。

Co-Authored-By: Claude <noreply@anthropic.com>
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