Feat/knowledge retrieval core #14

Merged
Kronecker merged 0 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 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