Feat/knowledge retrieval core #14

Merged
Kronecker merged 9 commits from feat/knowledge-retrieval-core into main 2026-09-04 00:20:56 +08:00
Collaborator

本 PR 交付 RAG Benchmark(检索质量评测)后端能力,并落实 PR #12 的四项审阅问题修复。

目标分支:main
来源分支:feat/knowledge-retrieval-core
主要变更

  1. RAG Benchmark(新模块 backend/app/benchmarks/)
    异步任务模型:POST /api/benchmarks/rag/runs 创建即返回 queued,后台 asyncio.create_task 执行,内存注册表 + 协程取消(MAX_RUNS=100,终态淘汰)。
    评测指标:hit_at_1 / hit_at_5 / recall_at_k / mrr / citation_hit_rate / p50 / p95,按 (mode, case, repeat) 逐样本计算,失败样本按零分计入质量指标分母(不把执行失败误判为检索质量)。
    SSE 实时进度:GET /api/benchmarks/rag/runs/{run_id}/events 推送 RunStarted / RunCompleted / CaseCompleted / RunFailed / RunCancelled,支持 Last-Event-ID 断线重连。
    内置数据集:backend/data/benchmarks/rag-core-v1.json(48 条样例,含笔记级/块级标注)。
  2. Retrieval Core 增强
    FTS 路径改为数据库侧过滤/计数/分页:fts_score_bounds(ORDER BY rank ASC/DESC LIMIT 1 求 bm25 上下界)+ fts_search_page(bm25_max=...),阈值换算为 bm25 截止值,total 始终为真实命中数。
    审阅问题修复(PR #12)

级别 问题 修复

1 P1 Benchmark 同步检索阻塞事件循环,取消/进度/并发失效 rag.py 每个样本前 await asyncio.sleep(0) 让出执行权,取消检查紧随其后
2 P2 SSE 流在终止事件后不结束 routes.py 回放与实时两处均检测 run_completed/run_failed/run_cancelled 并终止,try/finally 保证退订
3 P2 FTS 硬编码截断 5000,total 与分页失真 repository.py + engine.py 去除截断,真实 COUNT + 数据库分页
4 P2 仅标注 block_id 时被误判为检索失败 rag.py _expected_notes 从块反查所属笔记
回归测试
新增 6 个回归测试:test_cancel_running_benchmark_stops_early、test_sse_stream_ends_on_terminal_event_in_replay、test_block_only_annotation_resolves_note_and_scores、test_fts_not_truncated_at_five_thousand、test_fts_offset_beyond_end_reports_real_total、test_fts_score_threshold_filters_before_total。
后端完整测试:218 passed。
验证

cd backend
uv run pytest -q # 218 passed
uv run uvicorn app.main:app --reload --host 127.0.0.1 --port 8000
http://127.0.0.1:8000/docs 下:

POST /api/benchmarks/rag/runs → 202 queued → SSE 观察进度 → GET .../report 取报告
POST /api/search {"query":"向量数据库","mode":"fts"} 验证分页与 total
说明
未 push 前已与 origin/main 合并,无冲突。
导出(Markdown→HTML)与函数图像为后续 P0,本 PR 不包含。

本 PR 交付 RAG Benchmark(检索质量评测)后端能力,并落实 PR #12 的四项审阅问题修复。 目标分支:main 来源分支:feat/knowledge-retrieval-core 主要变更 1. RAG Benchmark(新模块 backend/app/benchmarks/) 异步任务模型:POST /api/benchmarks/rag/runs 创建即返回 queued,后台 asyncio.create_task 执行,内存注册表 + 协程取消(MAX_RUNS=100,终态淘汰)。 评测指标:hit_at_1 / hit_at_5 / recall_at_k / mrr / citation_hit_rate / p50 / p95,按 (mode, case, repeat) 逐样本计算,失败样本按零分计入质量指标分母(不把执行失败误判为检索质量)。 SSE 实时进度:GET /api/benchmarks/rag/runs/{run_id}/events 推送 RunStarted / RunCompleted / CaseCompleted / RunFailed / RunCancelled,支持 Last-Event-ID 断线重连。 内置数据集:backend/data/benchmarks/rag-core-v1.json(48 条样例,含笔记级/块级标注)。 2. Retrieval Core 增强 FTS 路径改为数据库侧过滤/计数/分页:fts_score_bounds(ORDER BY rank ASC/DESC LIMIT 1 求 bm25 上下界)+ fts_search_page(bm25_max=...),阈值换算为 bm25 截止值,total 始终为真实命中数。 审阅问题修复(PR #12) # 级别 问题 修复 1 P1 Benchmark 同步检索阻塞事件循环,取消/进度/并发失效 rag.py 每个样本前 await asyncio.sleep(0) 让出执行权,取消检查紧随其后 2 P2 SSE 流在终止事件后不结束 routes.py 回放与实时两处均检测 run_completed/run_failed/run_cancelled 并终止,try/finally 保证退订 3 P2 FTS 硬编码截断 5000,total 与分页失真 repository.py + engine.py 去除截断,真实 COUNT + 数据库分页 4 P2 仅标注 block_id 时被误判为检索失败 rag.py _expected_notes 从块反查所属笔记 回归测试 新增 6 个回归测试:test_cancel_running_benchmark_stops_early、test_sse_stream_ends_on_terminal_event_in_replay、test_block_only_annotation_resolves_note_and_scores、test_fts_not_truncated_at_five_thousand、test_fts_offset_beyond_end_reports_real_total、test_fts_score_threshold_filters_before_total。 后端完整测试:218 passed。 验证 cd backend uv run pytest -q # 218 passed uv run uvicorn app.main:app --reload --host 127.0.0.1 --port 8000 http://127.0.0.1:8000/docs 下: POST /api/benchmarks/rag/runs → 202 queued → SSE 观察进度 → GET .../report 取报告 POST /api/search {"query":"向量数据库","mode":"fts"} 验证分页与 total 说明 未 push 前已与 origin/main 合并,无冲突。 导出(Markdown→HTML)与函数图像为后续 P0,本 PR 不包含。
yxx added 9 commits 2026-09-04 00:00:59 +08:00
验收笔记此前被误纳入 benchmark 提交,现摘除跟踪,文件保留在本地磁盘。

Co-Authored-By: Claude Code <noreply@anthropic.com>
- 检索调优参数(rrf_k/rerank/rerank_candidates/score_threshold)透传到引擎实际执行
- Recall 去重,避免同一 Note 多 Block 重复导致 Recall 超 1
- RAG 运行改为后台异步执行:创建即 queued + 202,支持取消与 SSE 实时事件
- 数据集元数据校验,坏文件隔离跳过;citation_required 语义修正
- modes 空/重复校验;配置快照记录模型版本与索引元信息

Co-Authored-By: Claude Code <noreply@anthropic.com>
- Benchmark 容量淘汰只删终态 run,满容量且全活动时返回 BENCHMARK_CAPACITY_EXCEEDED
- 创建 run 前校验索引兼容性(BENCHMARK_INDEX_INCOMPATIBLE)
- 取消 run 补发 RunCancelled 终止事件;失败分支脱敏(BENCHMARK_RUN_FAILED)
- 失败样本计入汇总分母,报告输出 total/successful/failed/failure_rate
- load_dataset 按文件名隔离无关损坏文件,顶层非对象拒绝
- FTS score_threshold 先于计数/分页,total 与 items 一致
- Benchmark SSE 支持 Last-Event-ID 游标
- 移除 Agent Benchmark 501 占位接口
- 同步第二阶段接口契约与开发说明文档

Co-Authored-By: Claude Code <noreply@anthropic.com>
- 技术栈说明实施状态:RAG Benchmark 标记为已完成、Agent Benchmark 暂缓
- 新增 Benchmark 开发说明,并登记到文档索引
- README 回归基线更新为后端 157 / 前端 29

Co-Authored-By: Claude Code <noreply@anthropic.com>
- P1 事件循环让出:run_rag 在样本边界 await asyncio.sleep(0),运行中取消/进度/SSE 可及时调度
- P2 SSE 终止事件:历史回放期间识别终止事件并结束流,try/finally 保证订阅清理
- P2 FTS 截断:fts 走数据库侧精确分页与计数,阈值经 bm25 截止值换算,不再受 5000 条固定截断
- P2 仅块标注:expected_block_ids 从块反查所属笔记,避免合法样本被判零分

Co-Authored-By: Claude Code <noreply@anthropic.com>
# Conflicts:
#	README.md
#	backend/app/routes.py
#	docs/architecture/AI笔记软件技术栈说明-团队版-v2.3.md
#	docs/development/Knowledge与Retrieval-Core开发说明.md
全部命中 bm25 相同时归一化皆为 1.0,阈值超过 1.0 应无命中,
与旧 normalize_scores 语义对齐。

Co-Authored-By: Claude Code <noreply@anthropic.com>
yxx requested review from Kronecker 2026-09-04 00:01:19 +08:00
Owner

审阅结论:同意合并

审阅版本:abccb32

上一轮提出的 4 项问题均已修复并通过验证:

  • Benchmark 在样本边界让出事件循环,运行中取消可生效。
  • SSE 在历史回放期间收到终止事件后正常关闭,并清理订阅。
  • FTS 不再受 5000 条截断限制,计数与分页正确。
  • 仅标注块 ID 的样本可解析所属笔记并正确评分。

验证结果:

  • 后端完整测试:218 项通过。
  • 补充验证:首个样本完成后取消生效;SSE 回放期间完成后正常断流。
  • 内置数据集标注与仓库语料一致。
  • git diff --check 通过。
  • 与当前 main 无合并冲突。

本轮未发现阻塞合并的问题,可以合并。

另外,PR 描述有两处非阻塞笔误,请同步修正:

  1. 内置数据集为 5 条样例,不是 48 条。
  2. SSE 路径为 /api/benchmarks/runs/{run_id}/events,不包含 /rag
## 审阅结论:同意合并 审阅版本:`abccb32`。 上一轮提出的 4 项问题均已修复并通过验证: - Benchmark 在样本边界让出事件循环,运行中取消可生效。 - SSE 在历史回放期间收到终止事件后正常关闭,并清理订阅。 - FTS 不再受 5000 条截断限制,计数与分页正确。 - 仅标注块 ID 的样本可解析所属笔记并正确评分。 验证结果: - 后端完整测试:218 项通过。 - 补充验证:首个样本完成后取消生效;SSE 回放期间完成后正常断流。 - 内置数据集标注与仓库语料一致。 - `git diff --check` 通过。 - 与当前 main 无合并冲突。 本轮未发现阻塞合并的问题,可以合并。 另外,PR 描述有两处非阻塞笔误,请同步修正: 1. 内置数据集为 5 条样例,不是 48 条。 2. SSE 路径为 `/api/benchmarks/runs/{run_id}/events`,不包含 `/rag`。
Kronecker merged commit d31cd842c5 into main 2026-09-04 00:20:56 +08:00
Sign in to join this conversation.
No Reviewers
No labels
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Kronecker/NotesAgentic#14