smart_brain 0.1.1 → 0.2.0

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -0
  3. data/MEMPAL_GUIDE.md +1074 -0
  4. data/README.en.md +2 -2
  5. data/README.md +356 -62
  6. data/config/brain.yml +69 -1
  7. data/conversation_demo.rb +5 -5
  8. data/db/migrate/002_turn_events_payload.sql +9 -0
  9. data/db/migrate/003_tiers_and_lifecycle.sql +28 -0
  10. data/db/migrate/004_kg_edges.sql +30 -0
  11. data/db/migrate/005_domains_and_memory_scopes.sql +163 -0
  12. data/docs/coding_todo.md +139 -0
  13. data/docs/context_package.md +220 -0
  14. data/docs/evidence_pack.md +190 -0
  15. data/docs/gap_vs_mempal.md +161 -0
  16. data/docs/mcp.md +93 -0
  17. data/docs/memory_types.md +278 -0
  18. data/docs/multi_scope_memory_refactor_plan.md +483 -0
  19. data/docs/multi_scope_migration.md +65 -0
  20. data/docs/policies.md +308 -0
  21. data/docs/retrieval_plan.md +231 -0
  22. data/docs/smartbrain_design.md +299 -0
  23. data/docs/user_guide.md +546 -0
  24. data/example.rb +2 -2
  25. data/examples/01_memory_basic.rb +57 -0
  26. data/examples/02_governance.rb +63 -0
  27. data/examples/03_postgres_persistence.rb +63 -0
  28. data/examples/04_ollama_llm.rb +69 -0
  29. data/examples/05_smart_rag_integration.rb +79 -0
  30. data/examples/06_multi_scope_memory.rb +50 -0
  31. data/examples/README.md +49 -0
  32. data/exe/smart_brain +168 -0
  33. data/lib/smart_brain/adapters/smart_rag/direct_client.rb +16 -5
  34. data/lib/smart_brain/adapters/smart_rag/http_client.rb +16 -5
  35. data/lib/smart_brain/adapters/smart_rag/null_client.rb +7 -2
  36. data/lib/smart_brain/adapters/smart_rag/scope_filter.rb +60 -0
  37. data/lib/smart_brain/configuration.rb +57 -0
  38. data/lib/smart_brain/consolidator/working_summary.rb +80 -12
  39. data/lib/smart_brain/context_composer/composer.rb +40 -3
  40. data/lib/smart_brain/contracts/retrieval_plan.rb +10 -0
  41. data/lib/smart_brain/contracts/scope_context.rb +46 -0
  42. data/lib/smart_brain/contracts/scope_ref.rb +25 -0
  43. data/lib/smart_brain/db.rb +109 -0
  44. data/lib/smart_brain/event_store/in_memory.rb +6 -2
  45. data/lib/smart_brain/event_store/postgres.rb +199 -0
  46. data/lib/smart_brain/fusion/merger.rb +31 -2
  47. data/lib/smart_brain/governance/briefing.rb +146 -0
  48. data/lib/smart_brain/governance/fact_check.rb +110 -0
  49. data/lib/smart_brain/governance/knowledge_graph.rb +60 -0
  50. data/lib/smart_brain/governance/lifecycle.rb +225 -0
  51. data/lib/smart_brain/governance/tiers.rb +60 -0
  52. data/lib/smart_brain/memory_extractor/extractor.rb +25 -7
  53. data/lib/smart_brain/memory_store/in_memory.rb +202 -17
  54. data/lib/smart_brain/memory_store/postgres.rb +500 -0
  55. data/lib/smart_brain/model_provider/base.rb +87 -0
  56. data/lib/smart_brain/model_provider/factory.rb +49 -0
  57. data/lib/smart_brain/model_provider/ollama.rb +60 -0
  58. data/lib/smart_brain/model_provider/openai.rb +60 -0
  59. data/lib/smart_brain/model_provider/stub.rb +26 -0
  60. data/lib/smart_brain/model_provider.rb +7 -0
  61. data/lib/smart_brain/observability/tracker.rb +39 -1
  62. data/lib/smart_brain/retrievers/exact_retriever.rb +6 -0
  63. data/lib/smart_brain/retrievers/memory_retriever.rb +59 -5
  64. data/lib/smart_brain/runtime.rb +288 -16
  65. data/lib/smart_brain/scopes/conflict_resolver.rb +67 -0
  66. data/lib/smart_brain/scopes/registry.rb +133 -0
  67. data/lib/smart_brain/scopes/resolver.rb +32 -0
  68. data/lib/smart_brain/server/http_app.rb +143 -0
  69. data/lib/smart_brain/server/mcp_server.rb +385 -0
  70. data/lib/smart_brain/server/service.rb +129 -0
  71. data/lib/smart_brain/support/levenshtein.rb +35 -0
  72. data/lib/smart_brain/version.rb +1 -1
  73. data/lib/smart_brain.rb +49 -4
  74. metadata +88 -36
data/README.en.md CHANGED
@@ -101,10 +101,10 @@ SmartBrain.configure(smart_rag_client: client)
101
101
  ### 3) DirectClient (used in `example.rb`)
102
102
 
103
103
  ```ruby
104
- require '/home/mlf/smart_ai/smart_rag/lib/smart_rag'
104
+ require 'smart_rag'
105
105
  require_relative 'lib/smart_brain/adapters/smart_rag/direct_client'
106
106
 
107
- rag_config = SmartRAG::Config.load('/home/mlf/smart_ai/smart_rag/config/smart_rag.yml')
107
+ rag_config = SmartRAG::Config.load(ENV.fetch('SMARTRAG_CONFIG_PATH'))
108
108
  rag = SmartRAG::SmartRAG.new(rag_config)
109
109
  client = SmartBrain::Adapters::SmartRag::DirectClient.new(rag: rag)
110
110
 
data/README.md CHANGED
@@ -1,38 +1,37 @@
1
1
  # SmartBrain
2
2
 
3
- SmartBrain 是一个面向 Agent 的记忆运行时(Memory Runtime)与上下文编排器(Context Composer)。
3
+ SmartBrain(v0.2.0)是一个面向 Agent 的**记忆运行时(Memory Runtime)与上下文编排器(Context Composer)**。
4
4
 
5
- 它的核心职责:
6
- - `commit_turn`:记录事件真相并沉淀结构化记忆
7
- - `compose_context`:在每轮请求前组装最小充分上下文
8
- - 联动 SmartRAG:对话记忆由 SmartBrain 管理,资源检索由 SmartRAG 提供
5
+ 在多轮 Agent 对话中,SmartBrain 解决的核心问题是:如何高效地记录、检索、融合记忆,并装配出"最小充分"的上下文发给 LLM。
6
+
7
+ ## 核心职责
8
+
9
+ - **`commit_turn`**:记录事件真相并沉淀结构化长期记忆(写链路)
10
+ - **`compose_context`**:在每轮请求前生成最小充分上下文(读 + 装配链路)
11
+ - **联动 SmartRAG**:对话记忆由 SmartBrain 管理(EventStore / MemoryStore),资源检索由 SmartRAG 提供(适配层)
12
+
13
+ ## 架构边界
14
+
15
+ SmartBrain 把 Agent 的可用信息分为两类,分工明确:
16
+
17
+ | 类别 | 管理者 | 内容 | 特点 |
18
+ |------|--------|------|------|
19
+ | **对话记忆** (Conversation Memory) | SmartBrain | 原始事件(turn/messages/tool_calls/refs)、结构化记忆(profile/preferences/tasks/decisions/entities/events)、滚动摘要(working_summary) | 强时序、更新频繁、有写入门控与冲突管理 |
20
+ | **资源记忆** (Resource Memory) | SmartRAG | 文档/网页/代码仓库等长期资源 | 相对静态、内容大、需要高质量检索 |
21
+
22
+ > SmartRAG 是 SmartBrain 的"资源知识库后端"。SmartBrain 不复制 SmartRAG 的索引能力,只通过契约适配层调用它。
9
23
 
10
24
  ## 当前进展
11
25
 
12
26
  当前仓库已实现并打通:
13
- - `commit_turn` / `compose_context` 主链路
14
- - Retention / Consolidation / Retrieval / Composition 策略
15
- - 检索器:exact + relational
16
- - 融合层:去重、规则重排、多样性、预算截断
17
- - SmartRAG 适配器:`NullClient` / `HttpClient` / `DirectClient`
18
- - 契约与可观测:`request_id` / `plan_id` / `context_id` 全链路追踪
19
- - RSpec 测试(单元 + 集成 + 回归)
20
-
21
- ## 项目结构
22
27
 
23
- - `lib/smart_brain.rb`:入口 API
24
- - `lib/smart_brain/runtime.rb`:主运行时编排
25
- - `lib/smart_brain/contracts/`:RetrievalPlan / EvidencePack / ContextPackage 校验
26
- - `lib/smart_brain/observability/`:日志与指标
27
- - `lib/smart_brain/event_store/`:事件存储(当前内存实现)
28
- - `lib/smart_brain/memory_store/`:记忆存储(当前内存实现)
29
- - `lib/smart_brain/retrievers/`:exact/relational 检索
30
- - `lib/smart_brain/fusion/`:多源融合
31
- - `lib/smart_brain/context_composer/`:上下文装配
32
- - `lib/smart_brain/adapters/smart_rag/`:SmartRAG 适配层
33
- - `config/brain.yml`:策略配置
34
- - `example.rb`:SmartBrain + SmartAgent + SmartPrompt + SmartRAG 联动示例
35
- - `docs/`:设计与协议文档
28
+ - `commit_turn` / `compose_context` 主链路
29
+ - Retention / Consolidation / Retrieval / Composition 四类策略
30
+ - 检索器:exact(关键词匹配) + relational(实体/引用关联)
31
+ - 融合层:去重、词重叠加分重排、多样性约束、预算截断、memory/resource 比例控制
32
+ - SmartRAG 适配器:`NullClient`(默认空)/ `HttpClient`(HTTP 远程)/ `DirectClient`(进程内直接调用)
33
+ - 契约与可观测:`request_id` → `plan_id` → `context_id` 全链路追踪
34
+ - RSpec 测试(单元 + 集成 + PostgreSQL 回归)
36
35
 
37
36
  ## 安装
38
37
 
@@ -40,14 +39,239 @@ SmartBrain 是一个面向 Agent 的记忆运行时(Memory Runtime)与上下
40
39
  bundle install
41
40
  ```
42
41
 
43
- 如遇本地权限或 shared gem 污染,建议:
42
+ 如遇本地权限或 shared gem 污染:
44
43
 
45
44
  ```bash
46
45
  bundle config set --local path 'vendor/bundle'
47
46
  bundle config set --local disable_shared_gems 'true'
48
47
  ```
49
48
 
50
- ## 快速开始(仅 SmartBrain)
49
+ ## 核心 API
50
+
51
+ SmartBrain 提供以下核心工作流 API:
52
+
53
+ ### `SmartBrain.configure(config_path: nil, smart_rag_client: nil, clock: -> { Time.now.utc })`
54
+
55
+ 初始化运行时并注入 SmartRAG 客户端(可选)。
56
+
57
+ - `config_path`:策略配置文件路径,默认 `config/brain.yml`
58
+ - `smart_rag_client`:SmartRAG 适配器实例,默认 `NullClient`(资源证据为空)
59
+ - `clock`:时间源函数,默认 `Time.now.utc`
60
+
61
+ ### `SmartBrain.commit_turn(session_id:, turn_events:, domain_id: nil, scope_context: nil)`
62
+
63
+ 写入事件、抽取记忆、冲突处理、摘要更新。返回 `CommitResult`。
64
+
65
+ **`turn_events` 支持的事件类型:**
66
+
67
+ | 字段 | 类型 | 说明 | 示例 |
68
+ |------|------|------|------|
69
+ | `messages` | Array | 消息列表,每条含 `role` 和 `content` | `[{ role: 'user', content: '...' }]` |
70
+ | `decisions` | Array | 决策/选择/承诺 | `[{ key: 'decision:pg:pool_size', decision: '...' }]` |
71
+ | `tasks` | Array | 任务,含状态流转 | `[{ key: 'task:brain:mvp', status: 'doing' }]` |
72
+ | `goals` | Array | 长期目标 | `[{ key: 'goal:learn:ruby', goal: '...' }]` |
73
+ | `entities` | Array | 重要实体 | `[{ key: 'entity:lang:ruby', name: 'Ruby', canonical: 'ruby', kind: 'language', remember: true }]` |
74
+ | `preferences` | Array | 偏好,需 `confirmed: true` 才写入长期记忆 | `[{ key: 'pref:writing:tone', value: '...', confirmed: true }]` |
75
+ | `events` | Array | 里程碑/异常等高价值事件 | — |
76
+ | `refs` | Array | 文件/URL/产物引用 | — |
77
+ | `retractions` | Array | 撤回旧记忆 | `[{ type: 'decisions', key: 'decision:old:topic' }]` |
78
+
79
+ **写入门控策略:**
80
+ - **必写**:`tasks`、`decisions`(confidence: 0.9)
81
+ - **条件写**:`goals`(需显示声明)、`preferences`(需 `confirmed: true`)、`entities`(需出现频率 ≥ 2 或含 URL/路径等结构信号)
82
+ - **不写入**:闲聊、未确认推测
83
+
84
+ **冲突处理:**
85
+ - 覆盖型(`preferences/goals/tasks`):新值写入,旧值 → `status=superseded`
86
+ - 多版本并存(`decisions/events`):保留历史
87
+ - 撤回(`retracted`):旧条目 → `status=retracted`
88
+
89
+ **返回值:**
90
+
91
+ ```ruby
92
+ {
93
+ ok: true,
94
+ commit_id: "uuid",
95
+ session_id: "...",
96
+ turn_id: "uuid",
97
+ memory_written: { count: 3, items: [...], conflicts: [...] },
98
+ summary: { triggered: true, trigger_reason: "turn_threshold", text: "..." },
99
+ explain: { retention: [...], conflicts: [...], summary: {...} }
100
+ }
101
+ ```
102
+
103
+ ### `SmartBrain.compose_context(session_id:, user_message:, agent_state: {}, domain_id: nil, scope_context: nil)`
104
+
105
+ 生成 `ContextPackage`,内部执行 5 阶段流水线:
106
+
107
+ ```
108
+ Plan → Retrieve(双路并行)→ Fuse → Compose → ContextPackage
109
+ ```
110
+
111
+ 1. **Plan**:`RetrievalPlanner` 分析意图,生成 `RetrievalPlan`(主查询 + 扩展查询),自动判断是否启用资源检索(`enable_resource_retrieval: 'auto'` 时,关键词"查资料/引用/论文/文档/compare/对比/来源"触发)
112
+ 2. **Retrieve**:双路并行 —
113
+ - 记忆侧:`ExactRetriever`(词重叠匹配,支持中英文分词)+ `RelationalRetriever`(实体/引用关联)
114
+ - 资源侧:通过 SmartRAG 适配器检索文档资源(仅当 planner 启用时)
115
+ 3. **Fuse**:`Merger` 归一化 → 去重 → 词重叠加分重排 → 多样性约束(同文档 ≤ 3 条,同来源 ≤ 2 条)→ 预算裁剪(总条数 ≤ `evidence_max_items`,snippet ≤ `max_snippet_chars`)→ memory/resource 比例控制(默认 40/60)
116
+ 4. **Compose**:`ContextComposer` 按固定槽位装配:
117
+ ```
118
+ system_blocks → developer_blocks → working_summary →
119
+ recent_turns → evidence → user_message
120
+ ```
121
+ 5. **输出**:`ContextPackage`(经过契约校验)
122
+
123
+ ### 多 Scope 记忆
124
+
125
+ 0.2.0 支持在同一 domain 内联合读取 `global/project/expert/task` 记忆,并将长期记忆写入明确授权的 scope:
126
+
127
+ ```ruby
128
+ scope_context = {
129
+ read: [
130
+ { type: 'global', id: 'default' },
131
+ { type: 'project', id: 'project-001' },
132
+ { type: 'task', id: 'task-030' }
133
+ ],
134
+ write: [
135
+ { type: 'project', id: 'project-001' },
136
+ { type: 'task', id: 'task-030' }
137
+ ],
138
+ default_write: { type: 'task', id: 'task-030' }
139
+ }
140
+
141
+ SmartBrain.commit_turn(
142
+ domain_id: 'tenant-a', session_id: 'conversation-1', scope_context: scope_context,
143
+ turn_events: { decisions: [{ key: 'decision:db', decision: 'use PostgreSQL' }] }
144
+ )
145
+ ```
146
+
147
+ `write` 必须是 `read` 的子集,`default_write` 必须包含在 `write` 中。单条结构化记忆可以用 `scope_ref` 覆盖默认写 scope,但目标仍须在 `write` 中。提供 `scope_context` 时必须同时提供 `domain_id`;两者都省略时继续使用隔离的 `legacy/session:<session_id>`,兼容 0.1.x 调用。
148
+
149
+ **返回值(ContextPackage):**
150
+
151
+ ```ruby
152
+ {
153
+ version: '0.1',
154
+ context_id: "uuid", # 本次装配唯一 ID
155
+ session_id: "...",
156
+ working_summary: "...", # 滚动摘要文本
157
+ recent_turns: [...], # 最近 N 轮对话
158
+ evidence: [ # 融合后的证据列表
159
+ {
160
+ id: "...",
161
+ source: 'memory' | 'resource',
162
+ source_uri: "...",
163
+ title: "...",
164
+ snippet: "...",
165
+ mode: 'exact' | 'relational' | 'hybrid',
166
+ score: 0.85,
167
+ ref: { memory_item_id: "..." }
168
+ }
169
+ ],
170
+ user_message: { role: 'user', content: "..." },
171
+ constraints: {
172
+ token_budget: { limit: 8000, used_estimate: 1200 },
173
+ diversity: { by_document: 3, by_source: 2 },
174
+ truncation: { snippets_max_chars: 800, recent_turns_max: 8 }
175
+ },
176
+ debug: {
177
+ trace: { request_id: "uuid", plan_id: "uuid", context_id: "uuid" },
178
+ planner: { purpose: "qa", queries: ["..."] },
179
+ why_selected: ["item-1 score=0.85 source=memory"],
180
+ ignored: [],
181
+ dropped: [{ id: "...", reason: "diversity" }]
182
+ }
183
+ }
184
+ ```
185
+
186
+ ### `SmartBrain.diagnostics`
187
+
188
+ 返回 compose/commit 观测日志与指标快照:
189
+
190
+ ```ruby
191
+ {
192
+ compose_logs: [...],
193
+ commit_logs: [...],
194
+ metrics: {
195
+ compose_p95_ms: 45.2,
196
+ memory_resource_ratio: "3/2",
197
+ token_over_budget_rate: 0.0
198
+ }
199
+ }
200
+ ```
201
+
202
+ 全链路追踪:每个请求有 `request_id` → `plan_id` → `context_id` 三连 ID,贯穿 Plan → Retrieve → Fuse → Compose 全流程。
203
+
204
+ ## 策略配置
205
+
206
+ SmartBrain 的四类策略通过 `config/brain.yml` 配置:
207
+
208
+ | 策略类别 | 生效点 | 关键参数 |
209
+ |---------|--------|---------|
210
+ | **Retention**(写入门控) | `commit_turn` | `entity_gate: { window_turns: 20, freq_threshold: 2 }`、`confidence: { user_asserted: 0.8, tool_derived: 0.9, inferred: 0.6 }`、`summarize_after_turns: 12` |
211
+ | **Retrieval**(检索) | `compose_context` | `top_k: 30`、`candidate_k: 200`、`enable_resource_retrieval: auto`、`query_expansion: { enabled: true, max_queries: 8 }` |
212
+ | **Composition**(装配) | `compose_context` | `recent_turns_max: 8`、`evidence_max_items: 12`、`max_snippet_chars: 800`、`diversity: { by_document: 3, by_source_uri: 2 }`、`memory_resource_ratio: "40/60"` |
213
+ | **Observability**(可观测) | 全局 | `trace: true` |
214
+
215
+ ## 项目结构
216
+
217
+ ```
218
+ lib/smart_brain.rb # Ruby 入口 API
219
+ lib/smart_brain/version.rb # 版本号
220
+ lib/smart_brain/configuration.rb # YAML 配置加载
221
+ lib/smart_brain/runtime.rb # 主运行时编排(commit_turn / compose_context)
222
+ lib/smart_brain/contracts/ # 契约校验
223
+ retrieval_plan.rb # RetrievalPlan 校验
224
+ evidence_pack.rb # EvidencePack 校验
225
+ context_package.rb # ContextPackage 校验
226
+ lib/smart_brain/event_store/
227
+ in_memory.rb # 事件存储(当前内存实现,含 entity_frequencies 统计)
228
+ lib/smart_brain/memory_store/
229
+ in_memory.rb # 记忆存储(当前内存实现,含 upsert 冲突管理)
230
+ lib/smart_brain/memory_extractor/
231
+ extractor.rb # 从事件中抽取结构化记忆(写入门控)
232
+ lib/smart_brain/consolidator/
233
+ working_summary.rb # 滚动摘要维护(turn_threshold / token_pressure / stage_event 触发)
234
+ lib/smart_brain/retrieval_planner/
235
+ planner.rb # 生成 RetrievalPlan(query expansion + 资源检索启停判断 + filter hints)
236
+ lib/smart_brain/retrievers/
237
+ exact_retriever.rb # 词重叠关键词匹配(支持中英文)
238
+ relational_retriever.rb # 实体/引用关联检索
239
+ memory_retriever.rb # 记忆检索门面(exact + relational 合并)
240
+ lib/smart_brain/fusion/
241
+ merger.rb # 多源融合(归一化 → 去重 → 词重叠加分重排 → 多样性 → 预算截断)
242
+ lib/smart_brain/context_composer/
243
+ composer.rb # 固定槽位上下文装配 + token 估算
244
+ lib/smart_brain/adapters/smart_rag/
245
+ null_client.rb # 默认空适配器(资源证据为空)
246
+ http_client.rb # HTTP 远程调用适配器(支持超时降级)
247
+ direct_client.rb # 进程内直接调用适配器
248
+ lib/smart_brain/observability/
249
+ tracker.rb # 日志与指标(P95 / memory_resource_ratio / token_over_budget_rate)
250
+ config/
251
+ example_llm.yml # LLM 配置示例(ollama + silicon_flow)
252
+ docs/
253
+ smartbrain_design.md # 总体设计文档
254
+ policies.md # 策略规范文档
255
+ memory_types.md # 记忆类型规范(9 种 type + key 规则)
256
+ context_package.md # ContextPackage 协议
257
+ retrieval_plan.md # RetrievalPlan 协议
258
+ evidence_pack.md # EvidencePack 协议
259
+ spec/
260
+ spec_helper.rb
261
+ commit_turn_spec.rb # commit_turn 单元测试
262
+ compose_context_spec.rb # compose_context 单元测试
263
+ fusion_merger_spec.rb # 融合层测试
264
+ integration_smart_rag_adapter_spec.rb # SmartRAG 适配器集成测试
265
+ observability_metrics_spec.rb # 可观测性测试
266
+ planner_policy_spec.rb # 检索计划策略测试
267
+ regression_context_spec.rb # 回归测试
268
+ example.rb # 简单示例
269
+ conversation_demo.rb # 完整多轮对话演示(SmartBrain + SmartRAG + SmartAgent)
270
+ ```
271
+
272
+ ## 快速开始
273
+
274
+ ### 仅 SmartBrain(不依赖外部服务)
51
275
 
52
276
  ```ruby
53
277
  require_relative 'lib/smart_brain'
@@ -77,13 +301,73 @@ puts context.dig(:debug, :trace, :request_id)
77
301
  puts context.dig(:debug, :trace, :plan_id)
78
302
  ```
79
303
 
304
+ ### 多轮对话循环(与 SmartAgent + SmartRAG 联动)
305
+
306
+ ```ruby
307
+ require 'smart_brain'
308
+ require 'smart_agent'
309
+ require 'smart_rag'
310
+ require_relative 'lib/smart_brain/adapters/smart_rag/direct_client'
311
+
312
+ # 1. 初始化 SmartRAG
313
+ rag = SmartRAG::SmartRAG.new(database: {...}, llm: {...})
314
+ client = SmartBrain::Adapters::SmartRag::DirectClient.new(rag: rag)
315
+
316
+ # 2. 初始化 SmartBrain
317
+ SmartBrain.configure(smart_rag_client: client)
318
+
319
+ # 3. 初始化 SmartAgent
320
+ engine = SmartAgent::Engine.new('./config/example_agent.yml')
321
+ agent = engine.build_agent(:brain_assistant)
322
+
323
+ # 4. 多轮对话循环
324
+ session_id = "demo-session"
325
+ user_message = "Ruby 类名应该用什么命名风格?"
326
+
327
+ # 4a. 获取上下文(内部可能调用 SmartRAG 检索文档资源)
328
+ context = SmartBrain.compose_context(
329
+ session_id: session_id,
330
+ user_message: user_message,
331
+ agent_state: { turn: 1 }
332
+ )
333
+
334
+ # 4b. 调用 Agent(LLM)生成回复
335
+ response = agent.please(context.to_json)
336
+
337
+ # 4c. 提交本轮(沉淀记忆)
338
+ commit = SmartBrain.commit_turn(
339
+ session_id: session_id,
340
+ turn_events: {
341
+ messages: [
342
+ { role: 'user', content: user_message },
343
+ { role: 'assistant', content: response.to_s }
344
+ ],
345
+ decisions: [
346
+ { key: 'decision:ruby:class_naming', decision: '使用 CamelCase' }
347
+ ],
348
+ entities: [
349
+ { key: 'entity:lang:ruby', name: 'Ruby', canonical: 'ruby', kind: 'language', remember: true }
350
+ ]
351
+ }
352
+ )
353
+
354
+ # 5. 查看诊断信息
355
+ pp SmartBrain.diagnostics
356
+ ```
357
+
80
358
  ## SmartRAG 集成方式
81
359
 
82
360
  ### 1) NullClient(默认)
83
361
 
84
- 不配置 `smart_rag_client` 时,资源证据为空,仅使用记忆侧证据。
362
+ 不配置 `smart_rag_client` 时,资源证据为空,仅使用记忆侧证据。适合纯对话记忆场景。
363
+
364
+ ```ruby
365
+ SmartBrain.configure # 无需额外配置
366
+ ```
85
367
 
86
- ### 2) HttpClient
368
+ ### 2) HttpClient(HTTP 远程)
369
+
370
+ 通过自定义 transport lambda 调用远端 SmartRAG 服务,支持超时降级。
87
371
 
88
372
  ```ruby
89
373
  transport = lambda do |plan, timeout_seconds:|
@@ -94,80 +378,90 @@ transport = lambda do |plan, timeout_seconds:|
94
378
  }
95
379
  end
96
380
 
97
- client = SmartBrain::Adapters::SmartRag::HttpClient.new(transport: transport, timeout_seconds: 2)
381
+ scope_mapper = lambda do |domain_id:, scopes:|
382
+ { filters: { topic_ids: scopes.map { |scope| "#{domain_id}:#{scope[:type]}:#{scope[:id]}" } } }
383
+ end
384
+ client = SmartBrain::Adapters::SmartRag::HttpClient.new(
385
+ transport: transport, timeout_seconds: 2, scope_mapper: scope_mapper
386
+ )
98
387
  SmartBrain.configure(smart_rag_client: client)
99
388
  ```
100
389
 
101
- ### 3) DirectClient(当前示例使用)
390
+ ### 3) DirectClient(进程内直接调用)
391
+
392
+ 直接依赖 `smart_rag` gem,进程内调用。需要配置 PostgreSQL 连接和 LLM。
102
393
 
103
394
  ```ruby
104
- require '/home/mlf/smart_ai/smart_rag/lib/smart_rag'
395
+ require 'smart_rag'
105
396
  require_relative 'lib/smart_brain/adapters/smart_rag/direct_client'
106
397
 
107
- rag_config = SmartRAG::Config.load('/home/mlf/smart_ai/smart_rag/config/smart_rag.yml')
398
+ rag_config = SmartRAG::Config.load(ENV.fetch('SMARTRAG_CONFIG_PATH'))
108
399
  rag = SmartRAG::SmartRAG.new(rag_config)
109
- client = SmartBrain::Adapters::SmartRag::DirectClient.new(rag: rag)
400
+ scope_mapper = lambda do |domain_id:, scopes:|
401
+ { filters: { topic_ids: scopes.map { |scope| "#{domain_id}:#{scope[:type]}:#{scope[:id]}" } } }
402
+ end
403
+ client = SmartBrain::Adapters::SmartRag::DirectClient.new(rag: rag, scope_mapper: scope_mapper)
110
404
 
111
405
  SmartBrain.configure(smart_rag_client: client)
112
406
  ```
113
407
 
114
- ## example.rb 说明(已更新)
408
+ Mapper 返回的 `filters` 会作为 `scope_filters` 发送给 SmartRAG。业务 scope 存在时,后端必须返回 `scope_filter_applied: true`;mapper 缺失、映射失败或后端未确认时,adapter 默认 fail closed,丢弃资源证据并在 `warnings` 和 `explain.ignored_fields` 中说明原因。
115
409
 
116
- `example.rb` 演示完整链路:
117
- 1. SmartBrain `compose_context`
118
- 2. SmartAgent 通过 `call_worker` 调用 SmartPrompt worker
119
- 3. SmartBrain `commit_turn`
120
- 4. 打印 `evidence(memory/resource)` 验证 SmartRAG 是否参与
410
+ ## 运行示例
121
411
 
122
- 示例依赖的本地文件:
123
- - `config/example_agent.yml`
124
- - `config/example_llm.yml`
125
- - `agents/brain_assistant.rb`
126
- - `workers/brain_assistant.rb`
127
- - `templates/brain_assistant.erb`
412
+ ### example.rb
128
413
 
129
- 运行:
414
+ SmartBrain + SmartAgent + SmartPrompt + SmartRAG 联动示例(2 轮对话)。
130
415
 
131
416
  ```bash
132
417
  bundle exec ruby example.rb
133
418
  ```
134
419
 
135
- ## 核心 API
136
-
137
- ### `SmartBrain.configure(config_path: nil, smart_rag_client: nil, clock: -> { Time.now.utc })`
138
- 初始化运行时并注入 SmartRAG 客户端(可选)。
420
+ 依赖的本地文件:
421
+ - `config/example_agent.yml`
422
+ - `config/example_llm.yml`
423
+ - `agents/brain_assistant.rb`
424
+ - `workers/brain_assistant.rb`
425
+ - `templates/brain_assistant.erb`
139
426
 
140
- ### `SmartBrain.commit_turn(session_id:, turn_events:)`
141
- 写入事件、抽取记忆、冲突处理、摘要更新。
427
+ ### conversation_demo.rb
142
428
 
143
- ### `SmartBrain.compose_context(session_id:, user_message:, agent_state: {})`
144
- 生成 `ContextPackage`,内部包含检索计划与证据融合结果。
429
+ 完整多轮对话演示(5 轮),包含 SmartRAG 文档存储、检索、SmartAgent LLM 调用和 SmartBrain 记忆沉淀全流程。
145
430
 
146
- ### `SmartBrain.diagnostics`
147
- 返回 compose/commit 观测日志与指标快照。
431
+ ```bash
432
+ bundle exec ruby conversation_demo.rb
433
+ ```
148
434
 
149
435
  ## 测试
150
436
 
151
437
  ```bash
152
- rspec
438
+ bundle exec rspec
153
439
  ```
154
440
 
441
+ 测试覆盖 commit/compose、存储、治理、KG、协议适配、多 scope 隔离以及 PostgreSQL 迁移和持久化。
442
+
155
443
  ## 常见问题
156
444
 
157
445
  ### 1) `cannot load such file -- sequel/extensions/pgvector`
446
+
158
447
  当前示例已在 `example.rb` 做兼容处理(`Sequel.extension 'pgvector'` + 去除 `database.extensions` 连接参数)。
159
448
 
160
449
  ### 2) `Config file not found: config/llm_config.yml`
450
+
161
451
  `example.rb` 已将 SmartRAG 里 EmbeddingService 的 `config_path` 注入为 `./config/example_llm.yml`。
162
452
 
163
453
  ### 3) `ruby-lsp: not found`
454
+
164
455
  ```bash
165
456
  gem install --user-install ruby-lsp debug
166
457
  ```
458
+
167
459
  并将用户 gem bin 加入 `PATH`。
168
460
 
169
461
  ## 路线图
170
462
 
171
- - 将 EventStore/MemoryStore 从内存实现切换到 Postgres 实现
172
- - 接入真实 reranker / embedding 模型
463
+ - 将 EventStore/MemoryStore 从内存实现切换到 Postgres 持久化实现
464
+ - 接入真实 reranker / embedding 模型(当前为规则分 + 词重叠加分)
173
465
  - 完善 SmartRAG ingest 与跨会话评估工具
466
+ - 扩展 `SemanticRetriever`(依赖 pgvector/embedding)
467
+ - 支持 `memory_chunks` 表(FTS 索引 + 可选 embedding 字段)
data/config/brain.yml CHANGED
@@ -1,4 +1,69 @@
1
+ # SmartBrain 运行时配置(映射 docs/policies.md §6 默认策略)
2
+ #
3
+ # 存储:默认 memory(零依赖,开发/测试/纯库用法);
4
+ # 切到 postgres 即启用 EventStore/MemoryStore 持久化与 memory_chunks FTS。
5
+ # backend 也可用环境变量 SMARTBRAIN_BACKEND 覆盖。
6
+ # 数据库连接可用 SMARTBRAIN_DB_{HOST,PORT,NAME,USER,PASSWORD} 覆盖。
7
+
8
+ storage:
9
+ backend: memory
10
+ database:
11
+ adapter: postgres
12
+ host: 127.0.0.1
13
+ port: 5432
14
+ database: smart_brain_development
15
+ user: smart_brain
16
+ password: smart_brain
17
+ # 用于 search_memory 的 FTS 文本搜索配置(内置 'simple',零扩展依赖)。
18
+ # 中文通过分词后的 chunk 文本在 simple 下命中;如装了 pg_jieba 可改为 'jieba'。
19
+ fts_config: simple
20
+
21
+ # 本地模型调用(兑现 smartbrain_design.md §9)。
22
+ # 默认 stub:确定性、零网络(summary 走模板、rerank 走词法)。
23
+ # 切 ollama / openai 后,working_summary 走真摘要、merger 走 LLM rerank。
24
+ model_provider:
25
+ provider: stub # stub | ollama | openai (env: SMARTBRAIN_LLM_PROVIDER)
26
+ model: qwen3
27
+ base_url: http://localhost:11434
28
+ api_key: "" # openai-compatible 提供商需要
29
+ rerank_model: qwen3 # rerank 走 complete(LLM-as-judge),用同一模型
30
+ temperature: 0.2
31
+ timeout_seconds: 120 # 思维链模型较慢,摘要调用给足超时
32
+ summary_max_tokens: 900
33
+ think: false # 关闭思维链(支持的 ollama 版本会更快更干净)
34
+ rerank_enabled: false # compose 时是否做 LLM rerank(每轮都跑,默认关;改 true 启用)
35
+
36
+ # 思维分层(mempal mind model):dao_tian 天道 / dao_ren 人道 / shu 术 / qi 器 / evidence 证据
37
+ tiers:
38
+ dao_tian_limit: 1 # 自动装配时 dao_tian(不可变原则)默认最多注入条数
39
+
40
+ # 知识生命周期(Stage-1):evidence → distill(candidate) → gate → promote → demote/retire
41
+ lifecycle:
42
+ min_supporting_refs: 2 # distill/promote 门槛:至少 N 条 evidence 支撑(reviewer=human 可豁免)
43
+
44
+ # 知识图谱(KG):三元组 + 时态有效性,与 memory_items/lifecycle 正交
45
+ kg:
46
+ default_confidence: 0.6
47
+ expand_retrieval: true # relational 检索匹配 entity 时是否顺带拉其 KG 边
48
+
49
+ # 事实核查(离线、零 LLM)
50
+ fact_check:
51
+ similar_name_distance: 2 # Levenshtein ≤ 此值视为同名冲突
52
+ negation_cues: ["not", "stopped", "no longer", "replaced", "never", "不", "不再", "停用", "弃用", "替换"]
53
+
54
+ # Brief / wake-up(确定性、citation-first、不写 DB)
55
+ briefing:
56
+ key_facts_max: 8
57
+ uncertainty_threshold: 0.6
58
+ recent_turns: 6
59
+
1
60
  policies:
61
+ scopes:
62
+ allowed_types: [global, project, expert, task, session]
63
+ conflict_priority: [task, project, expert, global, session]
64
+ max_items_per_scope: 10
65
+ require_explicit_elevated_write: true
66
+
2
67
  retention:
3
68
  summarize_after_turns: 12
4
69
  entity_gate:
@@ -8,6 +73,7 @@ policies:
8
73
  user_asserted: 0.8
9
74
  tool_derived: 0.9
10
75
  inferred: 0.6
76
+
11
77
  retrieval:
12
78
  enable_resource_retrieval: auto
13
79
  top_k: 30
@@ -15,6 +81,7 @@ policies:
15
81
  query_expansion:
16
82
  enabled: true
17
83
  max_queries: 8
84
+
18
85
  composition:
19
86
  token_limit: 8192
20
87
  system_blocks_max_tokens: 800
@@ -25,7 +92,8 @@ policies:
25
92
  diversity:
26
93
  by_document: 3
27
94
  by_source_uri: 2
28
- memory_resource_ratio: '40/60'
95
+ memory_resource_ratio: "40/60"
96
+
29
97
  observability:
30
98
  trace: true
31
99
  store_plans: true
data/conversation_demo.rb CHANGED
@@ -14,7 +14,7 @@ require 'logger'
14
14
  require 'json'
15
15
 
16
16
  # 环境变量配置 - 使用轨迹流动 Kimi-K2.5 模型
17
- ENV['SMARTRAG_DB_HOST'] ||= 'localhost'
17
+ ENV['SMARTRAG_DB_HOST'] ||= '192.168.1.48'
18
18
  ENV['SMARTRAG_DB_PORT'] ||= '5432'
19
19
  ENV['SMARTRAG_DB_NAME'] ||= 'smart_rag_development'
20
20
  ENV['SMARTRAG_DB_USER'] ||= 'rag_user'
@@ -23,7 +23,7 @@ ENV['EMBEDDING_MODEL'] = 'qwen3-embedding'
23
23
 
24
24
  # 硅基流动 API 配置
25
25
  SILICON_FLOW_API_KEY = ENV['SILICON_FLOW_API_KEY']
26
- SILICON_FLOW_ENDPOINT = ENV['SILICON_FLOW_ENDPOINT']
26
+ SILICON_FLOW_ENDPOINT = "https://api.siliconflow.cn/v1/"
27
27
  SILICON_FLOW_MODEL = 'Pro/moonshotai/Kimi-K2.5'
28
28
 
29
29
  # 加载依赖
@@ -41,7 +41,7 @@ rescue LoadError
41
41
  end
42
42
 
43
43
  begin
44
- require '/home/mlf/smart_ai/smart_rag/lib/smart_rag'
44
+ require 'smart_rag'
45
45
  rescue LoadError => e
46
46
  warn "SmartRAG load failed: #{e.message}"
47
47
  exit 1
@@ -63,7 +63,7 @@ null_logger = Logger.new(File.open(File::NULL, 'w'))
63
63
  rag_config = {
64
64
  database: {
65
65
  adapter: 'postgresql',
66
- host: ENV['SMARTRAG_DB_HOST'] || 'localhost',
66
+ host: ENV['SMARTRAG_DB_HOST'] || '192.168.1.48',
67
67
  port: (ENV['SMARTRAG_DB_PORT'] || '5432').to_i,
68
68
  database: ENV['SMARTRAG_DB_NAME'] || 'smart_rag_development',
69
69
  user: ENV['SMARTRAG_DB_USER'] || 'rag_user',
@@ -78,7 +78,7 @@ rag_config = {
78
78
  },
79
79
  # Embedding 配置 - 禁用(轨迹流动暂不支持 embedding)
80
80
  embedding: {
81
- config_path: '/home/mlf/smart_ai/smart_rag/config/llm_config.yml'
81
+ config_path: File.expand_path('./config/llm_config.yml', __dir__)
82
82
  },
83
83
  # 禁用所有 SmartRAG 内部日志输出
84
84
  logger: null_logger
@@ -0,0 +1,9 @@
1
+ -- SmartBrain v0.1.1: persist the full per-turn events payload (JSONB).
2
+ --
3
+ -- Why: the runtime computes entity-gate frequencies from the *candidate*
4
+ -- entities a caller passes in each turn_events (before any gating decision).
5
+ -- The normalized tables (messages / refs / entity_mentions) don't capture
6
+ -- that raw input, so we store the normalized turn_events blob here to let
7
+ -- EventStore::Postgres faithfully reproduce EventStore::InMemory semantics.
8
+
9
+ ALTER TABLE turns ADD COLUMN IF NOT EXISTS events_json JSONB NOT NULL DEFAULT '{}'::jsonb;