kbs 0.1.0 → 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.
- checksums.yaml +4 -4
- data/README.md +85 -57
- data/docs/advanced/performance.md +109 -76
- data/docs/advanced/testing.md +399 -263
- data/docs/api/blackboard.md +1 -1
- data/docs/api/engine.md +77 -8
- data/docs/api/facts.md +3 -3
- data/docs/api/rules.md +110 -40
- data/docs/architecture/blackboard.md +108 -117
- data/docs/assets/images/fact-rule-relationship.svg +65 -0
- data/docs/assets/images/fact-structure.svg +42 -0
- data/docs/assets/images/inference-cycle.svg +47 -0
- data/docs/assets/images/kb-components.svg +43 -0
- data/docs/assets/images/rule-structure.svg +44 -0
- data/docs/assets/images/trading-signal-network.svg +1 -1
- data/docs/examples/index.md +219 -5
- data/docs/guides/blackboard-memory.md +89 -58
- data/docs/guides/dsl.md +24 -24
- data/docs/guides/getting-started.md +109 -107
- data/docs/guides/writing-rules.md +470 -311
- data/docs/index.md +16 -18
- data/docs/quick-start.md +92 -99
- data/docs/what-is-a-fact.md +694 -0
- data/docs/what-is-a-knowledge-base.md +350 -0
- data/docs/what-is-a-rule.md +833 -0
- data/examples/.gitignore +1 -0
- data/examples/advanced_example_dsl.rb +1 -1
- data/examples/ai_enhanced_kbs_dsl.rb +1 -1
- data/examples/car_diagnostic_dsl.rb +1 -1
- data/examples/concurrent_inference_demo.rb +0 -1
- data/examples/concurrent_inference_demo_dsl.rb +0 -1
- data/examples/csv_trading_system_dsl.rb +1 -1
- data/examples/iot_demo_using_dsl.rb +1 -1
- data/examples/portfolio_rebalancing_system_dsl.rb +1 -1
- data/examples/rule_source_demo.rb +123 -0
- data/examples/stock_trading_advanced_dsl.rb +1 -1
- data/examples/temp_dsl.txt +6214 -5269
- data/examples/timestamped_trading_dsl.rb +1 -1
- data/examples/trading_demo_dsl.rb +1 -1
- data/examples/working_demo_dsl.rb +1 -1
- data/lib/kbs/decompiler.rb +204 -0
- data/lib/kbs/dsl/knowledge_base.rb +100 -1
- data/lib/kbs/dsl.rb +3 -1
- data/lib/kbs/engine.rb +41 -0
- data/lib/kbs/version.rb +1 -1
- data/lib/kbs.rb +14 -12
- data/mkdocs.yml +30 -30
- metadata +15 -10
- data/docs/DOCUMENTATION_STATUS.md +0 -158
- data/docs/examples/expert-systems.md +0 -1031
- data/docs/examples/multi-agent.md +0 -1335
- data/docs/examples/stock-trading.md +0 -488
- data/examples/knowledge_base.db +0 -0
- data/examples/temp.txt +0 -7693
data/docs/examples/index.md
CHANGED
|
@@ -1,9 +1,223 @@
|
|
|
1
1
|
# Examples
|
|
2
2
|
|
|
3
|
-
Real-world applications
|
|
3
|
+
Real-world applications demonstrating KBS capabilities. Each example is available in both low-level API and DSL versions.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- **[Expert Systems](expert-systems.md)** - Diagnostic and decision support
|
|
7
|
-
- **[Multi-Agent Systems](multi-agent.md)** - Collaborative problem-solving
|
|
5
|
+
## Getting Started
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
### Working Demo
|
|
8
|
+
**Files:** [`working_demo.rb`](https://github.com/madbomber/kbs/blob/main/examples/working_demo.rb) | [`working_demo_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/working_demo_dsl.rb)
|
|
9
|
+
|
|
10
|
+
Simple trading system demonstrating the basics of KBS with momentum signals, volume alerts, and price movement detection. Perfect starting point for learning KBS fundamentals.
|
|
11
|
+
|
|
12
|
+
**Features:**
|
|
13
|
+
|
|
14
|
+
- Basic rule definition and pattern matching
|
|
15
|
+
- Stock momentum detection
|
|
16
|
+
- High volume alerts
|
|
17
|
+
- Price change notifications
|
|
18
|
+
|
|
19
|
+
### Advanced Example
|
|
20
|
+
**Files:** [`advanced_example.rb`](https://github.com/madbomber/kbs/blob/main/examples/advanced_example.rb) | [`advanced_example_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/advanced_example_dsl.rb)
|
|
21
|
+
|
|
22
|
+
More complex patterns including multi-condition rules, variable bindings, and negation patterns. Shows advanced RETE features and rule chaining.
|
|
23
|
+
|
|
24
|
+
**Features:**
|
|
25
|
+
|
|
26
|
+
- Multi-condition pattern matching
|
|
27
|
+
- Variable binding and join tests
|
|
28
|
+
- Negation (NOT conditions)
|
|
29
|
+
- Rule priorities
|
|
30
|
+
|
|
31
|
+
## Stock Trading Systems
|
|
32
|
+
|
|
33
|
+
### Basic Trading Demo
|
|
34
|
+
**Files:** [`trading_demo.rb`](https://github.com/madbomber/kbs/blob/main/examples/trading_demo.rb) | [`trading_demo_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/trading_demo_dsl.rb)
|
|
35
|
+
|
|
36
|
+
Foundational trading signals including momentum detection and volume analysis.
|
|
37
|
+
|
|
38
|
+
**Features:**
|
|
39
|
+
|
|
40
|
+
- Buy/sell signal generation
|
|
41
|
+
- Volume-based alerts
|
|
42
|
+
- Price momentum tracking
|
|
43
|
+
|
|
44
|
+
### Advanced Stock Trading
|
|
45
|
+
**Files:** [`stock_trading_advanced.rb`](https://github.com/madbomber/kbs/blob/main/examples/stock_trading_advanced.rb) | [`stock_trading_advanced_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/stock_trading_advanced_dsl.rb)
|
|
46
|
+
|
|
47
|
+
Sophisticated trading system with technical indicators, portfolio management, and risk controls.
|
|
48
|
+
|
|
49
|
+
**Features:**
|
|
50
|
+
|
|
51
|
+
- Golden cross detection (MA crossover)
|
|
52
|
+
- Momentum breakout signals
|
|
53
|
+
- RSI indicators
|
|
54
|
+
- Volume ratio analysis
|
|
55
|
+
- Risk management rules
|
|
56
|
+
|
|
57
|
+
### CSV Trading System
|
|
58
|
+
**Files:** [`csv_trading_system.rb`](https://github.com/madbomber/kbs/blob/main/examples/csv_trading_system.rb) | [`csv_trading_system_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/csv_trading_system_dsl.rb)
|
|
59
|
+
|
|
60
|
+
Complete trading system that processes historical stock data from CSV files, calculates technical indicators, and generates trading signals.
|
|
61
|
+
|
|
62
|
+
**Features:**
|
|
63
|
+
|
|
64
|
+
- CSV data ingestion
|
|
65
|
+
- Moving average calculations
|
|
66
|
+
- Technical indicator generation
|
|
67
|
+
- Backtesting support
|
|
68
|
+
- Portfolio tracking
|
|
69
|
+
|
|
70
|
+
### Portfolio Rebalancing System
|
|
71
|
+
**Files:** [`portfolio_rebalancing_system.rb`](https://github.com/madbomber/kbs/blob/main/examples/portfolio_rebalancing_system.rb) | [`portfolio_rebalancing_system_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/portfolio_rebalancing_system_dsl.rb)
|
|
72
|
+
|
|
73
|
+
Sector-based portfolio management with automatic rebalancing, drift detection, and underperformer replacement.
|
|
74
|
+
|
|
75
|
+
**Features:**
|
|
76
|
+
|
|
77
|
+
- Target allocation management
|
|
78
|
+
- Sector drift detection
|
|
79
|
+
- Automatic rebalancing rules
|
|
80
|
+
- Underperformer identification
|
|
81
|
+
- Position replacement logic
|
|
82
|
+
|
|
83
|
+
### Timestamped Trading
|
|
84
|
+
**Files:** [`timestamped_trading.rb`](https://github.com/madbomber/kbs/blob/main/examples/timestamped_trading.rb) | [`timestamped_trading_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/timestamped_trading_dsl.rb)
|
|
85
|
+
|
|
86
|
+
Time-aware trading system demonstrating temporal reasoning and time-based rule activation.
|
|
87
|
+
|
|
88
|
+
**Features:**
|
|
89
|
+
|
|
90
|
+
- Time-based rule conditions
|
|
91
|
+
- Stale data detection
|
|
92
|
+
- Market hours awareness
|
|
93
|
+
- Temporal pattern matching
|
|
94
|
+
|
|
95
|
+
### Redis High-Frequency Trading
|
|
96
|
+
**Files:** [`redis_trading_demo.rb`](https://github.com/madbomber/kbs/blob/main/examples/redis_trading_demo.rb) | [`redis_trading_demo_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/redis_trading_demo_dsl.rb)
|
|
97
|
+
|
|
98
|
+
High-performance trading system using Redis for fast in-memory fact storage, ideal for low-latency trading applications.
|
|
99
|
+
|
|
100
|
+
**Features:**
|
|
101
|
+
|
|
102
|
+
- Redis-backed persistence
|
|
103
|
+
- High-frequency market data processing
|
|
104
|
+
- Fast fact lookup and updates
|
|
105
|
+
- Distributed knowledge base support
|
|
106
|
+
|
|
107
|
+
## Expert Systems
|
|
108
|
+
|
|
109
|
+
### Car Diagnostic System
|
|
110
|
+
**Files:** [`car_diagnostic.rb`](https://github.com/madbomber/kbs/blob/main/examples/car_diagnostic.rb) | [`car_diagnostic_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/car_diagnostic_dsl.rb)
|
|
111
|
+
|
|
112
|
+
Expert system for diagnosing car problems based on symptoms. Demonstrates classic expert system pattern with IF-THEN diagnostic rules.
|
|
113
|
+
|
|
114
|
+
**Features:**
|
|
115
|
+
|
|
116
|
+
- Symptom-based diagnosis
|
|
117
|
+
- Multiple diagnostic rules
|
|
118
|
+
- Recommendation generation
|
|
119
|
+
- Negation for ruling out conditions
|
|
120
|
+
|
|
121
|
+
### IoT Monitoring System
|
|
122
|
+
**File:** [`iot_demo_using_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/iot_demo_using_dsl.rb)
|
|
123
|
+
|
|
124
|
+
IoT sensor monitoring system with temperature alerts, inventory management, and customer VIP upgrades. Shows real-world DSL usage patterns.
|
|
125
|
+
|
|
126
|
+
**Features:**
|
|
127
|
+
|
|
128
|
+
- Sensor monitoring
|
|
129
|
+
- Temperature threshold alerts
|
|
130
|
+
- Inventory tracking
|
|
131
|
+
- Multi-domain rules (IoT, inventory, CRM)
|
|
132
|
+
|
|
133
|
+
## AI-Enhanced Systems
|
|
134
|
+
|
|
135
|
+
### AI-Enhanced Knowledge Base
|
|
136
|
+
**Files:** [`ai_enhanced_kbs.rb`](https://github.com/madbomber/kbs/blob/main/examples/ai_enhanced_kbs.rb) | [`ai_enhanced_kbs_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/ai_enhanced_kbs_dsl.rb)
|
|
137
|
+
|
|
138
|
+
Integration with Large Language Models (LLMs) for AI-powered sentiment analysis, market insights, and intelligent trading decisions.
|
|
139
|
+
|
|
140
|
+
**Features:**
|
|
141
|
+
|
|
142
|
+
- LLM integration via `ruby_llm` gem
|
|
143
|
+
- News sentiment analysis
|
|
144
|
+
- AI-powered market insights
|
|
145
|
+
- MCP agent support
|
|
146
|
+
- Hybrid AI + rule-based reasoning
|
|
147
|
+
|
|
148
|
+
**Requirements:**
|
|
149
|
+
|
|
150
|
+
- Ollama running locally (or compatible LLM provider)
|
|
151
|
+
- `ruby_llm` and `ruby_llm-mcp` gems
|
|
152
|
+
|
|
153
|
+
## Advanced Features
|
|
154
|
+
|
|
155
|
+
### Blackboard Memory System
|
|
156
|
+
**Files:** [`blackboard_demo.rb`](https://github.com/madbomber/kbs/blob/main/examples/blackboard_demo.rb) | [`blackboard_demo_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/blackboard_demo_dsl.rb)
|
|
157
|
+
|
|
158
|
+
Demonstrates persistent blackboard architecture with SQLite storage, message queues, audit logs, and fact history tracking.
|
|
159
|
+
|
|
160
|
+
**Features:**
|
|
161
|
+
+
|
|
162
|
+
- SQLite-backed persistence
|
|
163
|
+
- UUID-based fact tracking
|
|
164
|
+
- Message queue (priority-based)
|
|
165
|
+
- Complete audit trail
|
|
166
|
+
- Fact update history
|
|
167
|
+
- Database statistics
|
|
168
|
+
|
|
169
|
+
### Concurrent Inference Patterns
|
|
170
|
+
**Files:** [`concurrent_inference_demo.rb`](https://github.com/madbomber/kbs/blob/main/examples/concurrent_inference_demo.rb) | [`concurrent_inference_demo_dsl.rb`](https://github.com/madbomber/kbs/blob/main/examples/concurrent_inference_demo_dsl.rb)
|
|
171
|
+
|
|
172
|
+
Advanced patterns for multi-threaded knowledge bases including reactive engines, background inference, and event-driven architectures.
|
|
173
|
+
|
|
174
|
+
**Features:**
|
|
175
|
+
|
|
176
|
+
- Auto-inference mode (reactive)
|
|
177
|
+
- Background thread inference
|
|
178
|
+
- Event-driven processing
|
|
179
|
+
- Thread-safe fact addition
|
|
180
|
+
- Continuous reasoning loops
|
|
181
|
+
|
|
182
|
+
## Running Examples
|
|
183
|
+
|
|
184
|
+
### Run Individual Examples
|
|
185
|
+
|
|
186
|
+
Each example is executable from the command line:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Run a specific example
|
|
190
|
+
ruby examples/working_demo.rb
|
|
191
|
+
|
|
192
|
+
# Run DSL version
|
|
193
|
+
ruby examples/working_demo_dsl.rb
|
|
194
|
+
|
|
195
|
+
# Run AI-enhanced example (requires Ollama)
|
|
196
|
+
OLLAMA_MODEL=gpt-oss:latest ruby examples/ai_enhanced_kbs.rb
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Run All Examples
|
|
200
|
+
|
|
201
|
+
Run all examples at once:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Run all low-level API examples
|
|
205
|
+
ruby examples/run_all.rb
|
|
206
|
+
|
|
207
|
+
# Run all DSL examples
|
|
208
|
+
ruby examples/run_all_dsl.rb
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Example Organization
|
|
212
|
+
|
|
213
|
+
- **Low-level API examples** (`*.rb`) - Direct use of `KBS::Engine`, `KBS::Rule`, `KBS::Condition`
|
|
214
|
+
- **DSL examples** (`*_dsl.rb`) - Using `KBS.knowledge_base` and declarative syntax
|
|
215
|
+
- Both versions demonstrate the same functionality with different APIs
|
|
216
|
+
|
|
217
|
+
## Further Reading
|
|
218
|
+
|
|
219
|
+
- **[Quick Start Guide](../quick-start.md)** - Step-by-step tutorial
|
|
220
|
+
- **[DSL Reference](../guides/dsl.md)** - Complete DSL syntax guide
|
|
221
|
+
- **[Writing Rules](../guides/writing-rules.md)** - Best practices for rule design
|
|
222
|
+
- **[Blackboard Memory](../guides/blackboard-memory.md)** - Persistence guide
|
|
223
|
+
- **[API Reference](../api/index.md)** - Complete API documentation
|
|
@@ -24,27 +24,34 @@ require 'kbs'
|
|
|
24
24
|
# With SQLite (default)
|
|
25
25
|
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
28
|
+
# Facts persist across restarts
|
|
29
|
+
fact :sensor, id: "bedroom", temp: 28
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
kb.close
|
|
30
33
|
|
|
31
34
|
# Next run
|
|
32
35
|
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
33
|
-
|
|
36
|
+
kb = KBS.knowledge_base(engine: engine)
|
|
37
|
+
puts kb.engine.facts.size # => 1
|
|
34
38
|
```
|
|
35
39
|
|
|
36
40
|
### Blackboard vs Regular Engine
|
|
37
41
|
|
|
38
42
|
```ruby
|
|
39
43
|
# Regular engine (transient)
|
|
40
|
-
|
|
41
|
-
|
|
44
|
+
kb_regular = KBS.knowledge_base do
|
|
45
|
+
fact :foo, bar: 1
|
|
46
|
+
end
|
|
42
47
|
# Lost on exit
|
|
43
48
|
|
|
44
49
|
# Blackboard engine (persistent)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
50
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
51
|
+
kb_blackboard = KBS.knowledge_base(engine: engine) do
|
|
52
|
+
fact :foo, bar: 1
|
|
53
|
+
end
|
|
54
|
+
kb_blackboard.close
|
|
48
55
|
# Persisted to database
|
|
49
56
|
```
|
|
50
57
|
|
|
@@ -53,14 +60,16 @@ blackboard.close
|
|
|
53
60
|
### Fact Lifecycle
|
|
54
61
|
|
|
55
62
|
```ruby
|
|
63
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
64
|
+
|
|
56
65
|
# Create fact
|
|
57
|
-
fact = engine.add_fact(:sensor,
|
|
66
|
+
fact = engine.add_fact(:sensor, id: "bedroom", temp: 28)
|
|
58
67
|
|
|
59
68
|
# Fact has UUID
|
|
60
69
|
puts fact.id # => "550e8400-e29b-41d4-a716-446655440000"
|
|
61
70
|
|
|
62
71
|
# Update fact
|
|
63
|
-
engine.update_fact(fact.id,
|
|
72
|
+
engine.update_fact(fact.id, temp: 30)
|
|
64
73
|
|
|
65
74
|
# Query fact history
|
|
66
75
|
history = engine.fact_history(fact.id)
|
|
@@ -77,7 +86,8 @@ engine.delete_fact(fact.id)
|
|
|
77
86
|
Blackboard facts support the same interface as regular facts:
|
|
78
87
|
|
|
79
88
|
```ruby
|
|
80
|
-
|
|
89
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
90
|
+
fact = engine.add_fact(:stock, symbol: "AAPL", price: 150)
|
|
81
91
|
|
|
82
92
|
# Access
|
|
83
93
|
fact.type # => :stock
|
|
@@ -97,6 +107,8 @@ The blackboard includes a priority-based message queue for agent communication:
|
|
|
97
107
|
### Sending Messages
|
|
98
108
|
|
|
99
109
|
```ruby
|
|
110
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
111
|
+
|
|
100
112
|
# Add message to queue
|
|
101
113
|
engine.send_message(:alerts, "High temperature detected", priority: 10)
|
|
102
114
|
engine.send_message(:alerts, "Critical failure", priority: 100) # Higher priority
|
|
@@ -139,11 +151,13 @@ Blackboard automatically logs all changes:
|
|
|
139
151
|
### Fact Audit Log
|
|
140
152
|
|
|
141
153
|
```ruby
|
|
154
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
155
|
+
|
|
142
156
|
# Add fact
|
|
143
|
-
fact = engine.add_fact(:order,
|
|
157
|
+
fact = engine.add_fact(:order, id: 1, status: "pending")
|
|
144
158
|
|
|
145
159
|
# Update fact
|
|
146
|
-
engine.update_fact(fact.id,
|
|
160
|
+
engine.update_fact(fact.id, status: "processing")
|
|
147
161
|
|
|
148
162
|
# Delete fact
|
|
149
163
|
engine.delete_fact(fact.id)
|
|
@@ -173,9 +187,15 @@ engine = KBS::Blackboard::Engine.new(
|
|
|
173
187
|
audit_rules: true
|
|
174
188
|
)
|
|
175
189
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
190
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
191
|
+
rule "my_rule" do
|
|
192
|
+
on :trigger, {}
|
|
193
|
+
perform { }
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
fact :trigger, {}
|
|
197
|
+
run
|
|
198
|
+
end
|
|
179
199
|
|
|
180
200
|
# Query rule firings
|
|
181
201
|
firings = engine.rule_firings(rule_name: "my_rule")
|
|
@@ -202,12 +222,12 @@ class Agent
|
|
|
202
222
|
@engine.facts.select { |f| relevant?(f) }
|
|
203
223
|
end
|
|
204
224
|
|
|
205
|
-
def decide
|
|
225
|
+
def decide(observations)
|
|
206
226
|
# Apply agent's expertise
|
|
207
227
|
# Return action or nil
|
|
208
228
|
end
|
|
209
229
|
|
|
210
|
-
def act
|
|
230
|
+
def act(action)
|
|
211
231
|
# Write facts to blackboard
|
|
212
232
|
# Send messages to other agents
|
|
213
233
|
end
|
|
@@ -277,7 +297,7 @@ class ExecutionAgent < Agent
|
|
|
277
297
|
execute_order(order)
|
|
278
298
|
|
|
279
299
|
# Update fact
|
|
280
|
-
@engine.update_fact(order.id,
|
|
300
|
+
@engine.update_fact(order.id, executed: true)
|
|
281
301
|
|
|
282
302
|
# Notify
|
|
283
303
|
@engine.send_message(:notifications, "Order executed", priority: 10)
|
|
@@ -306,19 +326,21 @@ end
|
|
|
306
326
|
Blackboard supports ACID transactions (SQLite backend):
|
|
307
327
|
|
|
308
328
|
```ruby
|
|
329
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
330
|
+
|
|
309
331
|
# Transaction succeeds
|
|
310
332
|
engine.transaction do
|
|
311
|
-
engine.add_fact(:account,
|
|
312
|
-
engine.add_fact(:account,
|
|
333
|
+
engine.add_fact(:account, id: 1, balance: 1000)
|
|
334
|
+
engine.add_fact(:account, id: 2, balance: 500)
|
|
313
335
|
end
|
|
314
336
|
# Both facts committed
|
|
315
337
|
|
|
316
338
|
# Transaction fails
|
|
317
339
|
begin
|
|
318
340
|
engine.transaction do
|
|
319
|
-
engine.add_fact(:account,
|
|
341
|
+
engine.add_fact(:account, id: 3, balance: 100)
|
|
320
342
|
raise "Error!"
|
|
321
|
-
engine.add_fact(:account,
|
|
343
|
+
engine.add_fact(:account, id: 4, balance: 200) # Never reached
|
|
322
344
|
end
|
|
323
345
|
rescue => e
|
|
324
346
|
puts "Transaction rolled back"
|
|
@@ -344,10 +366,11 @@ class FactObserver
|
|
|
344
366
|
end
|
|
345
367
|
end
|
|
346
368
|
|
|
369
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
347
370
|
observer = FactObserver.new
|
|
348
371
|
engine.memory.add_observer(observer)
|
|
349
372
|
|
|
350
|
-
engine.add_fact(:sensor,
|
|
373
|
+
engine.add_fact(:sensor, temp: 28)
|
|
351
374
|
# Output: Fact added: sensor - {:temp=>28}
|
|
352
375
|
```
|
|
353
376
|
|
|
@@ -402,11 +425,11 @@ engine = KBS::Blackboard::Engine.new(store: store)
|
|
|
402
425
|
```ruby
|
|
403
426
|
# Good: Store fact UUID
|
|
404
427
|
order_id = engine.add_fact(:order, { ... }).id
|
|
405
|
-
engine.add_fact(:payment,
|
|
428
|
+
engine.add_fact(:payment, order_id: order_id)
|
|
406
429
|
|
|
407
430
|
# Bad: Use attribute as reference
|
|
408
|
-
engine.add_fact(:order,
|
|
409
|
-
engine.add_fact(:payment,
|
|
431
|
+
engine.add_fact(:order, id: 1)
|
|
432
|
+
engine.add_fact(:payment, order_id: 1) # Fragile
|
|
410
433
|
```
|
|
411
434
|
|
|
412
435
|
### 2. Namespace Facts by Agent
|
|
@@ -438,17 +461,19 @@ end
|
|
|
438
461
|
|
|
439
462
|
```ruby
|
|
440
463
|
# Remove stale data
|
|
441
|
-
KBS::
|
|
442
|
-
r.conditions = [
|
|
443
|
-
KBS::Condition.new(:market_data, {
|
|
444
|
-
timestamp: :time?
|
|
445
|
-
}, predicate: lambda { |f|
|
|
446
|
-
(Time.now - f[:timestamp]) > 3600 # 1 hour old
|
|
447
|
-
})
|
|
448
|
-
]
|
|
464
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
449
465
|
|
|
450
|
-
|
|
451
|
-
|
|
466
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
467
|
+
rule "cleanup_old_facts", priority: 1 do
|
|
468
|
+
on :market_data,
|
|
469
|
+
timestamp: :time?,
|
|
470
|
+
predicate: lambda { |f|
|
|
471
|
+
(Time.now - f[:timestamp]) > 3600 # 1 hour old
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
perform do |facts, bindings|
|
|
475
|
+
engine.remove_fact(facts[0])
|
|
476
|
+
end
|
|
452
477
|
end
|
|
453
478
|
end
|
|
454
479
|
```
|
|
@@ -456,15 +481,17 @@ end
|
|
|
456
481
|
### 5. Use Transactions for Multi-Fact Updates
|
|
457
482
|
|
|
458
483
|
```ruby
|
|
484
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
485
|
+
|
|
459
486
|
# Good: Atomic updates
|
|
460
487
|
engine.transaction do
|
|
461
|
-
engine.update_fact(account1_id,
|
|
462
|
-
engine.update_fact(account2_id,
|
|
488
|
+
engine.update_fact(account1_id, balance: new_balance1)
|
|
489
|
+
engine.update_fact(account2_id, balance: new_balance2)
|
|
463
490
|
end
|
|
464
491
|
|
|
465
492
|
# Bad: Separate updates (not atomic)
|
|
466
|
-
engine.update_fact(account1_id,
|
|
467
|
-
engine.update_fact(account2_id,
|
|
493
|
+
engine.update_fact(account1_id, balance: new_balance1)
|
|
494
|
+
engine.update_fact(account2_id, balance: new_balance2)
|
|
468
495
|
```
|
|
469
496
|
|
|
470
497
|
## Common Patterns
|
|
@@ -472,16 +499,18 @@ engine.update_fact(account2_id, { balance: new_balance2 })
|
|
|
472
499
|
### Leader Election
|
|
473
500
|
|
|
474
501
|
```ruby
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
502
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
503
|
+
|
|
504
|
+
kb = KBS.knowledge_base(engine: engine) do
|
|
505
|
+
# Agent attempts to become leader
|
|
506
|
+
rule "become_leader" do
|
|
507
|
+
on :agent, name: :name?
|
|
508
|
+
without :leader, {}
|
|
509
|
+
|
|
510
|
+
perform do |facts, bindings|
|
|
511
|
+
fact :leader, name: bindings[:name?]
|
|
512
|
+
puts "#{bindings[:name?]} is now leader"
|
|
513
|
+
end
|
|
485
514
|
end
|
|
486
515
|
end
|
|
487
516
|
```
|
|
@@ -490,7 +519,7 @@ end
|
|
|
490
519
|
|
|
491
520
|
```ruby
|
|
492
521
|
# Acquire lock
|
|
493
|
-
def acquire_lock(resource_id)
|
|
522
|
+
def acquire_lock(engine, resource_id, agent_id)
|
|
494
523
|
engine.transaction do
|
|
495
524
|
lock = engine.facts.find { |f|
|
|
496
525
|
f.type == :lock && f[:resource_id] == resource_id
|
|
@@ -499,7 +528,7 @@ def acquire_lock(resource_id)
|
|
|
499
528
|
if lock.nil?
|
|
500
529
|
engine.add_fact(:lock, {
|
|
501
530
|
resource_id: resource_id,
|
|
502
|
-
owner:
|
|
531
|
+
owner: agent_id,
|
|
503
532
|
acquired_at: Time.now
|
|
504
533
|
})
|
|
505
534
|
true
|
|
@@ -510,11 +539,11 @@ def acquire_lock(resource_id)
|
|
|
510
539
|
end
|
|
511
540
|
|
|
512
541
|
# Release lock
|
|
513
|
-
def release_lock(resource_id)
|
|
542
|
+
def release_lock(engine, resource_id, agent_id)
|
|
514
543
|
lock = engine.facts.find { |f|
|
|
515
544
|
f.type == :lock &&
|
|
516
545
|
f[:resource_id] == resource_id &&
|
|
517
|
-
f[:owner] ==
|
|
546
|
+
f[:owner] == agent_id
|
|
518
547
|
}
|
|
519
548
|
|
|
520
549
|
engine.remove_fact(lock) if lock
|
|
@@ -524,6 +553,8 @@ end
|
|
|
524
553
|
### Event Sourcing
|
|
525
554
|
|
|
526
555
|
```ruby
|
|
556
|
+
engine = KBS::Blackboard::Engine.new(db_path: 'kb.db')
|
|
557
|
+
|
|
527
558
|
# Store events as facts
|
|
528
559
|
engine.add_fact(:event, {
|
|
529
560
|
type: "order_created",
|
|
@@ -533,7 +564,7 @@ engine.add_fact(:event, {
|
|
|
533
564
|
})
|
|
534
565
|
|
|
535
566
|
# Reconstruct state from events
|
|
536
|
-
def rebuild_order(order_id)
|
|
567
|
+
def rebuild_order(engine, order_id)
|
|
537
568
|
events = engine.facts
|
|
538
569
|
.select { |f| f.type == :event && f[:aggregate_id] == order_id }
|
|
539
570
|
.sort_by { |f| f[:timestamp] }
|
|
@@ -550,7 +581,7 @@ end
|
|
|
550
581
|
|
|
551
582
|
- **[Persistence](persistence.md)** - Storage backend options
|
|
552
583
|
- **[Architecture](../architecture/blackboard.md)** - Blackboard implementation details
|
|
553
|
-
- **[
|
|
584
|
+
- **[Blackboard Examples](../examples/index.md#advanced-features)** - Complete multi-agent and blackboard systems
|
|
554
585
|
- **[API Reference](../api/blackboard.md)** - Complete blackboard API
|
|
555
586
|
|
|
556
587
|
---
|