smart_rag 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.env.example +252 -0
  3. data/.rspec +2 -0
  4. data/AGENTS.md +33 -0
  5. data/API_DOCUMENTATION.md +828 -0
  6. data/CHANGELOG.md +16 -1
  7. data/ER-diagram.mmd +144 -0
  8. data/Gemfile +50 -0
  9. data/Gemfile.lock +398 -0
  10. data/Hybrid_Reranking.md +171 -0
  11. data/README.en.md +420 -28
  12. data/README.md +534 -63
  13. data/Rakefile +268 -0
  14. data/SETUP_GUIDE.md +650 -0
  15. data/SmartChunking.md +180 -0
  16. data/USAGE_EXAMPLES.md +1002 -0
  17. data/config/llm_config.yml +4 -2
  18. data/config/smart_rag.yml +45 -1
  19. data/config.ru +15 -0
  20. data/db/migrations/006_create_text_search_configs.rb +3 -2
  21. data/db/migrations/008_create_embeddings.rb +5 -4
  22. data/db/migrations/012_add_metadata_to_source_sections.rb +11 -0
  23. data/db/migrations/013_create_media_jobs.rb +25 -0
  24. data/db/migrations/014_add_media_job_operations_indexes.rb +11 -0
  25. data/db/migrations/015_add_media_leases_and_objects.rb +80 -0
  26. data/db/migrations/016_add_document_principals_and_staging_references.rb +38 -0
  27. data/db/migrations/017_add_media_job_request_fingerprint.rb +48 -0
  28. data/db/seeds/text_search_configs.sql +3 -3
  29. data/design.md +1057 -0
  30. data/docs/API_DOCUMENTATION.md +838 -0
  31. data/docs/DOCUMENTATION_INDEX.en.md +60 -0
  32. data/docs/DOCUMENTATION_INDEX.md +65 -0
  33. data/docs/FIX_SUMMARY.md +256 -0
  34. data/docs/FIX_SUMMARY_COMPLETE.md +273 -0
  35. data/docs/Hybrid_Reranking.md +171 -0
  36. data/docs/MIGRATION_GUIDE.md +151 -0
  37. data/docs/PERFORMANCE_GUIDE.md +58 -0
  38. data/docs/SETUP_GUIDE.md +659 -0
  39. data/docs/SmartChunking.md +180 -0
  40. data/docs/USAGE_EXAMPLES.md +1008 -0
  41. data/docs/design.md +1057 -0
  42. data/docs/evidence_pack.md +211 -0
  43. data/docs/requirements.md +376 -0
  44. data/docs/retrieval_plan.md +251 -0
  45. data/docs/smartrag_improvement_plan.md +201 -0
  46. data/docs/smartrag_refactor.md +216 -0
  47. data/docs/todo.md +931 -0
  48. data/examples/common.rb +1 -1
  49. data/exe/smart-rag-db +163 -0
  50. data/exe/smart-rag-media-worker +34 -0
  51. data/lib/smart_rag/config.rb +12 -0
  52. data/lib/smart_rag/core/document_processor.rb +80 -16
  53. data/lib/smart_rag/core/local_content_store.rb +51 -0
  54. data/lib/smart_rag/core/media_extractors.rb +140 -0
  55. data/lib/smart_rag/core/media_job_queue.rb +353 -0
  56. data/lib/smart_rag/core/media_metadata_extractor.rb +188 -0
  57. data/lib/smart_rag/core/media_object_registry.rb +79 -0
  58. data/lib/smart_rag/core/media_processor.rb +228 -0
  59. data/lib/smart_rag/core/media_safety_policy.rb +61 -0
  60. data/lib/smart_rag/core/s3_content_store.rb +78 -0
  61. data/lib/smart_rag/core/transcript_normalizer.rb +44 -0
  62. data/lib/smart_rag/core/video_semantic_extractor.rb +130 -0
  63. data/lib/smart_rag/http_access_policy.rb +86 -0
  64. data/lib/smart_rag/http_app.rb +188 -0
  65. data/lib/smart_rag/models/embedding.rb +1 -1
  66. data/lib/smart_rag/models/research_topic.rb +1 -1
  67. data/lib/smart_rag/models/research_topic_section.rb +5 -0
  68. data/lib/smart_rag/models/research_topic_tag.rb +5 -0
  69. data/lib/smart_rag/models/search_log.rb +1 -1
  70. data/lib/smart_rag/models/section_fts.rb +5 -0
  71. data/lib/smart_rag/models/section_tag.rb +5 -0
  72. data/lib/smart_rag/models/source_document.rb +1 -1
  73. data/lib/smart_rag/models/source_section.rb +1 -1
  74. data/lib/smart_rag/models/tag.rb +1 -1
  75. data/lib/smart_rag/models/text_search_config.rb +5 -0
  76. data/lib/smart_rag/retrieve.rb +72 -1
  77. data/lib/smart_rag/services/embedding_service.rb +1 -1
  78. data/lib/smart_rag/services/fulltext_search_service.rb +11 -13
  79. data/lib/smart_rag/services/hybrid_search_service.rb +15 -11
  80. data/lib/smart_rag/services/summarization_service.rb +1 -1
  81. data/lib/smart_rag/services/tag_service.rb +1 -1
  82. data/lib/smart_rag/version.rb +1 -1
  83. data/lib/smart_rag.rb +264 -30
  84. data/patch_language.rb +27 -0
  85. data/requirements.md +376 -0
  86. data/source_documents_export.json +11072 -0
  87. data/todo.md +931 -0
  88. data/workers/analyze_content.rb +6 -2
  89. data/workers/get_embedding.rb +1 -1
  90. metadata +151 -38
@@ -0,0 +1,251 @@
1
+ ## 1. 目的
2
+
3
+ RetrievalPlan 用于把“本轮需要检索什么、怎么检索、取多少、如何控制噪声”表达为结构化对象,避免:
4
+ - 调用方隐式依赖 SmartRAG 内部策略(不可控)
5
+ - 多模式检索无法复现与调试(不可观测)
6
+ - 上下文装配缺少预算与多样性约束(易被噪声淹没)
7
+
8
+ ---
9
+
10
+ ## 2. 顶层结构
11
+
12
+ RetrievalPlan 是一个 JSON/Ruby Hash 对象(可序列化入日志)。
13
+
14
+ ```json
15
+ {
16
+ "version": "0.1",
17
+ "request_id": "uuid",
18
+ "purpose": "qa|continue_task|debug|summarize|research|other",
19
+ "queries": [],
20
+ "global_filters": {},
21
+ "budget": {},
22
+ "ranking": {},
23
+ "output": {},
24
+ "debug": {}
25
+ }
26
+ ```
27
+
28
+ 字段说明:
29
+
30
+ * `version`:协议版本(必填)
31
+ * `request_id`:调用方生成,用于贯穿日志与可追溯(建议必填)
32
+ * `purpose`:检索目的,用于策略默认值(可选)
33
+ * `queries`:检索 query 列表(必填,至少 1 条)
34
+ * `global_filters`:对所有 queries 生效的过滤(可选)
35
+ * `budget`:数量预算与多样性约束(可选但强烈建议)
36
+ * `ranking`:融合与重排设置(可选)
37
+ * `output`:返回内容控制(可选)
38
+ * `debug`:调试信息(可选)
39
+
40
+ ---
41
+
42
+ ## 3. queries(必填)
43
+
44
+ ### 3.1 Query 对象
45
+
46
+ ```json
47
+ {
48
+ "text": "string",
49
+ "mode": "exact|semantic|hybrid|relational|associative",
50
+ "weight": 1.0,
51
+ "filters": { },
52
+ "hints": { }
53
+ }
54
+ ```
55
+
56
+ 字段说明:
57
+
58
+ * `text`:查询文本(必填)
59
+ * `mode`:
60
+
61
+ * `exact`:关键词/短语精确查找(FTS/BM25)
62
+ * `semantic`:语义召回(embedding)
63
+ * `hybrid`:exact + semantic(由执行方融合)
64
+ * `relational`:关联检索(实体/链接/任务链)
65
+ * `associative`:联想检索(通常表示“扩展 query”,执行方应按策略调用 exact/semantic 再融合)
66
+ * `weight`:该 query 的相对权重(默认 1.0)
67
+ * `filters`:只对该 query 生效的过滤(覆盖/补充 global_filters)
68
+ * `hints`:提示执行策略的附加信息(可选)
69
+
70
+ > 建议:SmartBrain 的“联想”实现为生成多个 `associative` 或多条 `semantic/exact` 扩展 queries,而不是让执行方自由发挥。
71
+
72
+ ### 3.2 queries 最小示例
73
+
74
+ ```json
75
+ {
76
+ "version": "0.1",
77
+ "request_id": "c2b2f7d6-7c3b-4d53-8f8b-6f1f3a8c2a10",
78
+ "purpose": "qa",
79
+ "queries": [
80
+ { "text": "OpenViking retrieval design", "mode": "hybrid", "weight": 1.0 }
81
+ ]
82
+ }
83
+ ```
84
+
85
+ ### 3.3 queries(扩展/联想)示例
86
+
87
+ ```json
88
+ {
89
+ "version": "0.1",
90
+ "request_id": "b7b1b1ce-2330-4f72-9f7b-92a6a1a2e12a",
91
+ "purpose": "research",
92
+ "queries": [
93
+ { "text": "RAG memory runtime design", "mode": "hybrid", "weight": 1.0 },
94
+ { "text": "MemGPT hierarchical memory", "mode": "semantic", "weight": 0.7 },
95
+ { "text": "Letta archival memory blocks", "mode": "semantic", "weight": 0.7 },
96
+ { "text": "context composer token budget diversity", "mode": "exact", "weight": 0.5 }
97
+ ]
98
+ }
99
+ ```
100
+
101
+ ---
102
+
103
+ ## 4. global_filters(可选)
104
+
105
+ 对所有 queries 生效。执行方必须支持“只过滤不改变语义”的行为。
106
+
107
+ ```json
108
+ {
109
+ "document_ids": ["..."],
110
+ "tag_ids": ["..."],
111
+ "topic_ids": ["..."],
112
+ "source_type": ["url","file","manual","memory_snapshot"],
113
+ "source_uri_prefix": ["https://...", "file://..."],
114
+ "language": ["zh","en"],
115
+ "time_range": { "from": "2026-01-01T00:00:00Z", "to": "2026-02-20T00:00:00Z" }
116
+ }
117
+ ```
118
+
119
+ 说明:
120
+
121
+ * `document_ids/tag_ids/topic_ids`:知识库内过滤
122
+ * `source_type`:资源类型过滤(建议 SmartRAG 支持)
123
+ * `source_uri_prefix`:按 URI 前缀过滤(适合域名/路径范围)
124
+ * `language`:语言过滤(可选)
125
+ * `time_range`:时间过滤(可按 documents.created_at 或 sections.created_at 实现)
126
+
127
+ ---
128
+
129
+ ## 5. budget(可选但强烈建议)
130
+
131
+ ```json
132
+ {
133
+ "top_k": 30,
134
+ "per_mode_k": { "exact": 10, "semantic": 10, "hybrid": 10, "relational": 10, "associative": 10 },
135
+ "candidate_k": 200,
136
+ "diversity": {
137
+ "by_document": 3,
138
+ "by_source": 10,
139
+ "by_section": 1
140
+ }
141
+ }
142
+ ```
143
+
144
+ 说明:
145
+
146
+ * `top_k`:最终返回条数
147
+ * `per_mode_k`:各模式配额(执行方可按存在的模式取 min)
148
+ * `candidate_k`:召回候选池规模(用于 rerank)
149
+ * `diversity`:多样性约束(避免单文档/单来源垄断)
150
+
151
+ > 实施建议:如果执行方不支持某一 diversity 维度,应忽略并在 explain 中声明。
152
+
153
+ ---
154
+
155
+ ## 6. ranking(可选)
156
+
157
+ 用于约束融合与重排。
158
+
159
+ ```json
160
+ {
161
+ "fusion": { "method": "rrf|weighted_sum|none", "rrf_k": 60, "weights": { "exact": 1.0, "semantic": 1.0 } },
162
+ "rerank": { "enabled": true, "model": "qwen3-reranker", "top_n": 50 },
163
+ "tie_breaker": "recency|source_priority|none",
164
+ "source_priority": { "url": 0.9, "file": 1.0, "manual": 0.8, "memory_snapshot": 0.7 }
165
+ }
166
+ ```
167
+
168
+ 说明:
169
+
170
+ * `fusion.method`:默认建议 `rrf`
171
+ * `rerank.enabled`:是否启用 reranker
172
+ * `tie_breaker`:分数相近时的决策
173
+ * `source_priority`:来源优先级(可选)
174
+
175
+ ---
176
+
177
+ ## 7. output(可选)
178
+
179
+ 控制返回内容形态,便于 token 控制与调试。
180
+
181
+ ```json
182
+ {
183
+ "include_snippets": true,
184
+ "snippet_policy": "l2|l1|l0|auto",
185
+ "include_signals": true,
186
+ "include_provenance": true,
187
+ "include_raw": false,
188
+ "max_snippet_chars": 800
189
+ }
190
+ ```
191
+
192
+ 说明:
193
+
194
+ * `snippet_policy`:建议未来支持 L0/L1/L2(如 OpenViking 分层)
195
+ * `max_snippet_chars`:用于截断(执行方应保证不超)
196
+
197
+ ---
198
+
199
+ ## 8. debug(可选)
200
+
201
+ ```json
202
+ {
203
+ "trace": true,
204
+ "notes": "free text",
205
+ "caller": { "app": "smart_bot", "session_id": "..." }
206
+ }
207
+ ```
208
+
209
+ ---
210
+
211
+ ## 9. 执行方最低合规要求(SmartRAG/SmartBrain)
212
+
213
+ 执行方至少要做到:
214
+
215
+ 1. 支持 `queries.text + mode` 的基本执行(exact/semantic/hybrid 至少两种)
216
+ 2. 支持 `top_k` 与基本 filters(document_ids/tag_ids/topic_ids)
217
+ 3. 返回结果时能提供最少的 explain(见下)
218
+
219
+ 建议执行方在返回 EvidencePack 时包含:
220
+
221
+ * `plan_id/request_id`
222
+ * `stats`(候选数、耗时、返回数)
223
+ * `explain`(融合方式、是否 rerank、忽略了哪些字段)
224
+
225
+ ---
226
+
227
+ ## 10. 变更策略
228
+
229
+ * v0.1:新增字段只能“可选”,不得破坏现有字段含义
230
+ * v0.x:执行方必须忽略未知字段并在 explain 中声明(可选)
231
+ * v1.0:如需破坏性变更,另起 major 版本并提供迁移说明
232
+
233
+ ---
234
+
235
+ ## 11. 当前实现状态(SmartRAG)
236
+
237
+ 已支持:
238
+
239
+ * `queries.text + mode`:`exact/semantic/hybrid`
240
+ * `global_filters.document_ids/tag_ids/topic_ids/time_range/source_type/source_uri_prefix`
241
+ * `budget.top_k/candidate_k/per_mode_k`
242
+ * `budget.diversity.by_document/by_source`
243
+ * `output.include_snippets/include_signals/include_provenance/include_raw/max_snippet_chars`
244
+
245
+ 部分支持:
246
+
247
+ * `queries.mode=relational/associative`:当前降级为 `hybrid`
248
+
249
+ 未支持(会进入 `explain.ignored_fields`):
250
+
251
+ * `budget.diversity.by_section`
@@ -0,0 +1,201 @@
1
+ # SmartRAG 改进计划(1-2 天冲刺版)
2
+
3
+ ## 1. 目标与范围
4
+
5
+ 本计划目标是在 **1-2 天内**完成 SmartRAG 与 SmartBrain 的契约化集成最小闭环,并同步补齐关键可观测与索引治理能力。
6
+
7
+ 本次改进聚焦:
8
+
9
+ - 新增统一入口:`retrieve(plan)`(`RetrievalPlan -> EvidencePack`)
10
+ - 统一输出:`EvidencePack v0.1`(含 signals/stats/explain)
11
+ - 兼容现有 `search(...)`(不破坏旧调用)
12
+ - 补齐核心可观测:`search_logs` 记录 `plan_json + stats + explain`
13
+ - 落地最小索引治理:幂等导入与重建入口
14
+
15
+ 不在本次范围:
16
+
17
+ - 对话事件管理、记忆抽取、上下文编排、Agent loop(归属 SmartBrain/SmartBot/SmartAgent)
18
+ - 大规模 schema 重构
19
+ - L0/L1/L2 全量能力落地(仅预留字段与策略)
20
+
21
+ ---
22
+
23
+ ## 2. 交付物
24
+
25
+ - `smart_rag/docs/retrieval_plan.md`(对齐实现,必要时补充“已支持/未支持”)
26
+ - `smart_rag/docs/evidence_pack.md`(对齐实现,必要时补充“最低合规字段”)
27
+ - `smart_rag/docs/smartrag_improvement_plan.md`(本文档)
28
+ - `lib/smart_rag/retrieve.rb`(或等价入口模块)
29
+ - `spec/retrieve_spec.rb`(关键路径测试)
30
+ - `CHANGELOG.md`(新增接口、兼容策略、已知限制)
31
+
32
+ ---
33
+
34
+ ## 3. 执行节奏(非按周,按里程碑)
35
+
36
+ ### M1:契约主链路打通(Day 1,上半天)
37
+
38
+ 目标:让 SmartBrain 可稳定调用 `retrieve(plan)` 并拿到结构化结果。
39
+
40
+ 任务:
41
+
42
+ 1. 新增 `retrieve(plan)` 入口,接收 `RetrievalPlan v0.1`。
43
+ 2. 支持最小 `queries` 执行:`exact/semantic/hybrid`(至少两种模式可用)。
44
+ 3. 结果统一封装为 `EvidencePack v0.1` 顶层结构:
45
+ - `version`
46
+ - `plan_id`
47
+ - `request_id`
48
+ - `generated_at`
49
+ - `evidences`
50
+ - `stats`
51
+ - `explain`
52
+ - `warnings`(可选)
53
+ 4. 保留 `search(...)`,内部逐步复用新执行路径。
54
+
55
+ 验收标准:
56
+
57
+ - 可用 `RetrievalPlan` 直接调用 `retrieve(plan)`。
58
+ - 响应结构符合 `EvidencePack` 最低要求。
59
+ - 不影响现有 `search(...)` 调用。
60
+
61
+ ---
62
+
63
+ ### M2:可解释与可观测补齐(Day 1,下半天)
64
+
65
+ 目标:结果可复现、可解释、可调试。
66
+
67
+ 任务:
68
+
69
+ 1. 为每条 evidence 增加 `signals` 最小集合:
70
+ - `vector_score/vector_rank`
71
+ - `fts_score/fts_rank`
72
+ - `rrf_score`
73
+ - `rerank_score`(模型未启用时可空或置默认)
74
+ 2. 输出 `provenance`:
75
+ - `mode`
76
+ - `query_text`
77
+ - `query_index`
78
+ - `retrieved_at`
79
+ 3. 完成 `stats` 与 `explain`:
80
+ - `candidates/returned/took_ms`
81
+ - `fusion`、`rerank`、`filters_applied`
82
+ - `ignored_fields`(未支持字段必须明示)
83
+ 4. 将 `plan_json + stats/explain` 写入 `search_logs`。
84
+
85
+ 验收标准:
86
+
87
+ - 任一结果都可追溯“来自哪个 query、以何模式命中、融合信号是什么”。
88
+ - 日志可用于离线复盘同一次检索过程。
89
+
90
+ ---
91
+
92
+ ### M3:过滤、预算、多样性与稳定性(Day 2,上半天)
93
+
94
+ 目标:把噪声控制能力落到执行层,不依赖调用方隐式技巧。
95
+
96
+ 任务:
97
+
98
+ 1. 支持 `global_filters` 最小集:
99
+ - `document_ids`
100
+ - `tag_ids`
101
+ - `topic_ids`
102
+ - `source_type`
103
+ - `time_range`(若暂不支持,显式写入 `ignored_fields`)
104
+ 2. 支持 `budget` 最小集:
105
+ - `top_k`
106
+ - `candidate_k`
107
+ - `per_mode_k`(按已启用模式截断)
108
+ 3. 支持最小多样性约束:
109
+ - `diversity.by_document`
110
+ 4. `output` 最小支持:
111
+ - `include_snippets`
112
+ - `include_signals`
113
+ - `max_snippet_chars`
114
+
115
+ 验收标准:
116
+
117
+ - 同一 query 在设置预算与多样性后,结果集中度明显降低(避免单文档垄断)。
118
+ - 不支持字段会被显式告知,不出现“静默忽略”。
119
+
120
+ ---
121
+
122
+ ### M4:索引治理与收口发布(Day 2,下半天)
123
+
124
+ 目标:避免长期运行后的索引漂移和重复污染,并完成发布闭环。
125
+
126
+ 任务:
127
+
128
+ 1. 幂等导入最小策略:
129
+ - 引入/启用 `content_hash`
130
+ - 同源同内容避免重复写入(`source_uri + content_hash`)
131
+ 2. 提供重建入口:
132
+ - `rebuild_fts(document_id=nil)`
133
+ - `rebuild_embeddings(document_id=nil)`
134
+ - `reindex(document_id=nil)`
135
+ 3. 文档与变更收口:
136
+ - 更新 `CHANGELOG.md`
137
+ - 在文档中标注已实现与待实现项(如 `tag_score/topic_score` 参与排序)
138
+
139
+ 验收标准:
140
+
141
+ - 重复导入不会持续膨胀索引。
142
+ - 可对单文档或全量执行重建。
143
+ - 变更说明清晰,可被 SmartBrain 团队直接消费。
144
+
145
+ 当前进展补充(已落地):
146
+
147
+ - 已新增 `source_documents.source_type/source_uri/content_hash` 与索引
148
+ - 已提供 `rake db:backfill_source_fields` 回填任务
149
+ - 已提供轻量单测入口(不依赖测试库连接)用于 `retrieve/reindex` 核心行为验证
150
+
151
+ ---
152
+
153
+ ## 4. 最小实现清单(MVP Done Definition)
154
+
155
+ 满足以下条件即判定本轮完成:
156
+
157
+ 1. `retrieve(plan)` 可用,`search(...)` 保持兼容。
158
+ 2. `EvidencePack` 输出包含最低必需字段与 signals。
159
+ 3. `exact/semantic/hybrid` 至少两种模式稳定可用(推荐三种都可用)。
160
+ 4. `search_logs` 可记录 `request_id + plan_json + stats + explain`。
161
+ 5. 至少一组集成测试覆盖:
162
+ - 单 query hybrid
163
+ - 多 query 融合
164
+ - filters + budget + diversity
165
+ - unknown/unsupported 字段处理(`ignored_fields`)
166
+
167
+ ---
168
+
169
+ ## 5. 风险与缓解
170
+
171
+ 风险 1:`time_range/language/source_uri_prefix` 等字段短期无法完全支持
172
+ 缓解:严格走 `ignored_fields` 与 `warnings`,不做静默降级。
173
+
174
+ 风险 2:reranker 模型不可用导致结果波动
175
+ 缓解:`rerank.enabled=false` 自动降级,`explain` 明确记录。
176
+
177
+ 风险 3:多 query 融合后结果重复或单源聚集
178
+ 缓解:先做稳定去重(按 `document_id/section_id`)+ `diversity.by_document`。
179
+
180
+ 风险 4:1-2 天冲刺导致文档与实现偏差
181
+ 缓解:以测试快照校验 `RetrievalPlan` 输入与 `EvidencePack` 输出结构。
182
+
183
+ ---
184
+
185
+ ## 6. 执行顺序(建议)
186
+
187
+ 1. 先打通 `retrieve(plan)` 与 `EvidencePack` 骨架(M1)。
188
+ 2. 再补 signals/explain/logging(M2)。
189
+ 3. 接着补 filters/budget/diversity(M3)。
190
+ 4. 最后完成索引治理与文档收口(M4)。
191
+
192
+ 这个顺序能确保即使 Day 2 出现意外,Day 1 结束时仍有可集成、可调试的主链路成果。
193
+
194
+ ---
195
+
196
+ ## 7. 后续增量(不阻塞本轮)
197
+
198
+ - `tag_score/topic_score` 从“占位字段”升级为真实排序特征
199
+ - `source_priority/tie_breaker` 精细策略
200
+ - L0/L1/L2 分层 snippet 策略(`snippet_policy` 全实现)
201
+ - 更完善的离线评测集与回归基线(NDCG/Recall/Latency)
@@ -0,0 +1,216 @@
1
+ ## 1. 目标与边界
2
+
3
+ ### 1.1 目标
4
+ SmartRAG 的职责应当被明确为:
5
+
6
+ - **资源导入与索引**:文档/URL 导入、分块、embedding、FTS(Postgres tsvector/pg_jieba)、元数据管理
7
+ - **多模式检索**:exact / semantic / hybrid(向量 + FTS + 融合)
8
+ - **统一证据输出**:输出结构化 `EvidencePack` 供 SmartBrain 做上下文装配
9
+ - **可观测**:记录检索计划、融合信号、结果解释,便于调试与评估
10
+ - **可重建**:索引可重建(embedding/FTS),内容是真相
11
+
12
+ ### 1.2 边界(SmartRAG 不做什么)
13
+ SmartRAG **不负责**:
14
+
15
+ - 对话事件(turn/tool call)存储与管理
16
+ - 记忆抽取(profile/preferences/entities/events/tasks/decisions)
17
+ - 上下文编排(token 预算、摘要、历史选择)
18
+ - Agent loop / 工具编排 / MCP
19
+
20
+ 上述能力属于 SmartBrain / SmartBot / SmartAgent。
21
+
22
+ ---
23
+
24
+ ## 2. 现状与集成痛点
25
+
26
+ > 你现有 SmartRAG 已具备:pgvector + FTS + RRF 融合、标签/主题、日志等。但为了与 SmartBrain 形成「契约式」集成,需要补齐:
27
+
28
+ 1. **检索入口表达能力不足**
29
+ 目前 `search_type: vector/fulltext/hybrid` 能选模式,但 SmartBrain 需要表达:多 query、每路预算、过滤、去重/多样性、是否 rerank、返回信号等。
30
+
31
+ 2. **输出缺乏“检索信号(signals)”**
32
+ SmartBrain 要做跨源融合(memory + resources)、上下文预算装配、结果解释,需要看到每条 evidence 的来源与分数构成(vector/fts/rrf/rerank/tag/topic)。
33
+
34
+ 3. **索引维护与幂等导入不足**
35
+ SmartBrain 会不断把“记忆快照/摘要/会议纪要/网页快照”写入资源库;缺少幂等与重建会导致噪声膨胀与索引漂移。
36
+
37
+ ---
38
+
39
+ ## 3. 改造范围(MVP -> 完整版)
40
+
41
+ ### 3.1 MVP(建议优先完成:1~2 个迭代)
42
+
43
+ #### A) 新增结构化检索入口:`retrieve(plan)`
44
+ 新增统一入口(内部可复用现有 search/hybrid 逻辑):
45
+
46
+ ```ruby
47
+ SmartRAG.retrieve(plan: RetrievalPlan) => EvidencePack
48
+ ````
49
+
50
+ **RetrievalPlan(Ruby Hash / JSON)**
51
+
52
+ ```json
53
+ {
54
+ "queries": [
55
+ {
56
+ "text": "…",
57
+ "mode": "exact|semantic|hybrid",
58
+ "weight": 1.0,
59
+ "filters": { "tag_ids": [], "topic_ids": [] }
60
+ }
61
+ ],
62
+ "global_filters": {
63
+ "tag_ids": [],
64
+ "topic_ids": [],
65
+ "document_ids": [],
66
+ "source_type": ["url", "file", "manual", "memory_snapshot"],
67
+ "time_range": { "from": "2026-01-01T00:00:00Z", "to": "2026-02-19T00:00:00Z" }
68
+ },
69
+ "budget": {
70
+ "top_k": 30,
71
+ "per_mode_k": { "exact": 10, "semantic": 10, "hybrid": 10 },
72
+ "diversity": { "by_document": 3, "by_source": 10 }
73
+ },
74
+ "rerank": { "enabled": true, "model": "qwen3-reranker", "top_n": 30 },
75
+ "return": { "include_signals": true, "include_snippets": true }
76
+ }
77
+ ```
78
+
79
+ > 说明:`queries` 用于表达 **联想/扩展 query**(由 SmartBrain 生成),SmartRAG 不需要知道“为什么扩展”,只执行计划。
80
+
81
+ #### B) 统一输出结构:`EvidencePack`
82
+
83
+ SmartRAG 的输出应当满足:可复用、可观测、可再融合。
84
+
85
+ **EvidencePack(JSON 形态)**
86
+
87
+ ```json
88
+ {
89
+ "plan_id": "uuid",
90
+ "evidences": [
91
+ {
92
+ "document_id": "…",
93
+ "section_id": "…",
94
+ "snippet": "…",
95
+ "metadata": { "title": "…", "source_uri": "…" },
96
+ "signals": {
97
+ "vector_score": 0.12,
98
+ "vector_rank": 3,
99
+ "fts_score": 0.41,
100
+ "fts_rank": 1,
101
+ "rrf_score": 0.032,
102
+ "rerank_score": 0.88,
103
+ "tag_score": 0.2,
104
+ "topic_score": 0.0
105
+ },
106
+ "provenance": { "mode": "hybrid", "query_text": "…", "retrieved_at": "…" },
107
+ "raw": { "content_ref": "section:l2" }
108
+ }
109
+ ],
110
+ "stats": { "candidates": 200, "returned": 30, "took_ms": 128 },
111
+ "explain": { "fusion": "RRF", "rerank": true }
112
+ }
113
+ ```
114
+
115
+ #### C) 结果信号可观测(signals)
116
+
117
+ MVP 至少提供:
118
+
119
+ * `vector_rank/vector_score`
120
+ * `fts_rank/fts_score`
121
+ * `rrf_score`
122
+ * `rerank_score`(可选)
123
+ * `tag_score/topic_score`(先保留字段,MVP 可为 0)
124
+
125
+ #### D) 兼容现有 API
126
+
127
+ * 现有 `search(...)` 保留为简化接口;
128
+ * 新增 `retrieve(plan)` 面向 SmartBrain;
129
+ * `search` 内部可调用 `retrieve`(或相反),逐步统一实现。
130
+
131
+ ---
132
+
133
+ ### 3.2 完整版(SmartBrain 上线后逐步演进)
134
+
135
+ #### E) 标签/主题第三路融合(不是仅过滤)
136
+
137
+ 让 tags/topics 参与排序信号:
138
+
139
+ * `tag_score/topic_score` 进入融合加权或 rerank features(如果 reranker 支持 feature 拼接则更好)
140
+
141
+ #### F) 索引维护能力
142
+
143
+ 新增维护命令/接口:
144
+
145
+ * `rebuild_fts(document_id=nil)`
146
+ * `rebuild_embeddings(document_id=nil)`
147
+ * `reindex(document_id=nil)`(组合)
148
+ * `dedupe_by_content_hash`(幂等导入)
149
+
150
+ #### G) L0/L1/L2 层(与 OpenViking 思路兼容,可选)
151
+
152
+ * L2:原始 section 内容
153
+ * L1:overview(中等摘要+导航)
154
+ * L0:abstract(极短摘要,召回友好)
155
+
156
+ SmartRAG 可先只存 L2,后续逐步补齐 L0/L1(可由 SmartBrain 或 SmartRAG 生成)。
157
+
158
+ ---
159
+
160
+ ## 4. 数据结构调整建议(最小破坏)
161
+
162
+ > 在不大改既有 schema 的前提下,建议增补:
163
+
164
+ ### 4.1 documents
165
+
166
+ * `source_type`:url/file/manual/memory_snapshot
167
+ * `source_uri`:统一 URI(用于 provenance 与去重)
168
+ * `content_hash`:幂等导入(URL 内容 hash / 文件 hash)
169
+ * `updated_at`:用于判断增量重建
170
+
171
+ ### 4.2 sections
172
+
173
+ * `layer`:L0/L1/L2(可选)
174
+ * `summary`:用于 snippet 输出(可选)
175
+ * `metadata(jsonb)`:标题、页码、语言、代码语言、chunker 参数等
176
+
177
+ ### 4.3 search_logs
178
+
179
+ * `plan_json`:保存 RetrievalPlan
180
+ * `signals_json`:保存统计与融合信号摘要(便于回归对比)
181
+
182
+ ---
183
+
184
+ ## 5. 与 SmartBrain 的契约(强约束)
185
+
186
+ * SmartBrain **只**通过 `retrieve(plan)` 调用 SmartRAG(避免隐式策略)
187
+ * SmartRAG **只**返回 `EvidencePack`(不返回最终 prompt)
188
+ * SmartBrain 负责:跨源融合(memory vs resource)、最终 rerank(可选)、上下文装配(token 预算)
189
+
190
+ ---
191
+
192
+ ## 6. 交付物清单(SmartRAG)
193
+
194
+ * `docs/retrieval_plan.md`:RetrievalPlan schema 与示例
195
+ * `docs/evidence_pack.md`:EvidencePack schema 与字段说明
196
+ * `lib/smart_rag/retrieve.rb`:新入口(或模块)
197
+ * `spec/retrieve_spec.rb`:关键路径测试
198
+ * `CHANGELOG.md`:新增接口与兼容策略说明
199
+
200
+ ---
201
+
202
+ ## 7. 里程碑与验收标准
203
+
204
+ ### MVP 验收
205
+
206
+ * 能以 RetrievalPlan 调用 `retrieve(plan)`
207
+ * 返回 EvidencePack(含 signals)
208
+ * Hybrid/Exact/Semantic 三模式可用(至少 two modes)
209
+ * search_logs 记录 plan + stats + explain
210
+
211
+ ### 完整版验收
212
+
213
+ * 幂等导入生效(相同 hash 不重复污染库)
214
+ * 索引重建命令可用
215
+ * tags/topics 对排序有显式贡献
216
+ * L0/L1/L2 支持(可选)