kbs 0.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/deploy-github-pages.yml +52 -0
- data/CHANGELOG.md +68 -2
- data/README.md +291 -362
- data/docs/advanced/custom-persistence.md +775 -0
- data/docs/advanced/debugging.md +726 -0
- data/docs/advanced/index.md +8 -0
- data/docs/advanced/performance.md +865 -0
- data/docs/advanced/testing.md +827 -0
- data/docs/api/blackboard.md +1157 -0
- data/docs/api/engine.md +1047 -0
- data/docs/api/facts.md +1212 -0
- data/docs/api/index.md +12 -0
- data/docs/api/rules.md +1104 -0
- data/docs/architecture/blackboard.md +544 -0
- data/docs/architecture/index.md +277 -0
- data/docs/architecture/network-structure.md +343 -0
- data/docs/architecture/rete-algorithm.md +737 -0
- data/docs/assets/css/custom.css +83 -0
- data/docs/assets/images/blackboard-architecture.svg +136 -0
- data/docs/assets/images/compiled-network.svg +101 -0
- data/docs/assets/images/fact-assertion-flow.svg +117 -0
- 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/kbs.jpg +0 -0
- data/docs/assets/images/pattern-matching-trace.svg +136 -0
- data/docs/assets/images/rete-network-layers.svg +96 -0
- data/docs/assets/images/rule-structure.svg +44 -0
- data/docs/assets/images/system-layers.svg +69 -0
- data/docs/assets/images/trading-signal-network.svg +139 -0
- data/docs/assets/js/mathjax.js +17 -0
- data/docs/examples/index.md +223 -0
- data/docs/guides/blackboard-memory.md +589 -0
- data/docs/guides/dsl.md +1321 -0
- data/docs/guides/facts.md +652 -0
- data/docs/guides/getting-started.md +385 -0
- data/docs/guides/index.md +23 -0
- data/docs/guides/negation.md +529 -0
- data/docs/guides/pattern-matching.md +561 -0
- data/docs/guides/persistence.md +451 -0
- data/docs/guides/variable-binding.md +491 -0
- data/docs/guides/writing-rules.md +914 -0
- data/docs/index.md +155 -0
- data/docs/installation.md +156 -0
- data/docs/quick-start.md +221 -0
- 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/README.md +2 -2
- data/examples/advanced_example.rb +2 -2
- data/examples/advanced_example_dsl.rb +224 -0
- data/examples/ai_enhanced_kbs.rb +1 -1
- data/examples/ai_enhanced_kbs_dsl.rb +538 -0
- data/examples/blackboard_demo_dsl.rb +50 -0
- data/examples/car_diagnostic.rb +1 -1
- data/examples/car_diagnostic_dsl.rb +54 -0
- data/examples/concurrent_inference_demo.rb +5 -6
- data/examples/concurrent_inference_demo_dsl.rb +362 -0
- data/examples/csv_trading_system.rb +1 -1
- data/examples/csv_trading_system_dsl.rb +525 -0
- data/examples/iot_demo_using_dsl.rb +1 -1
- data/examples/portfolio_rebalancing_system.rb +2 -2
- data/examples/portfolio_rebalancing_system_dsl.rb +613 -0
- data/examples/redis_trading_demo_dsl.rb +177 -0
- data/examples/rule_source_demo.rb +123 -0
- data/examples/run_all.rb +50 -0
- data/examples/run_all_dsl.rb +49 -0
- data/examples/stock_trading_advanced.rb +1 -1
- data/examples/stock_trading_advanced_dsl.rb +404 -0
- data/examples/temp_dsl.txt +9392 -0
- data/examples/timestamped_trading.rb +1 -1
- data/examples/timestamped_trading_dsl.rb +258 -0
- data/examples/trading_demo.rb +1 -1
- data/examples/trading_demo_dsl.rb +322 -0
- data/examples/working_demo.rb +1 -1
- data/examples/working_demo_dsl.rb +160 -0
- data/lib/kbs/blackboard/engine.rb +3 -3
- data/lib/kbs/blackboard/fact.rb +1 -1
- data/lib/kbs/condition.rb +1 -1
- data/lib/kbs/decompiler.rb +204 -0
- data/lib/kbs/dsl/knowledge_base.rb +101 -2
- data/lib/kbs/dsl/variable.rb +1 -1
- data/lib/kbs/dsl.rb +3 -1
- data/lib/kbs/{rete_engine.rb ā engine.rb} +42 -1
- data/lib/kbs/fact.rb +1 -1
- data/lib/kbs/version.rb +1 -1
- data/lib/kbs.rb +15 -13
- data/mkdocs.yml +181 -0
- metadata +74 -9
- data/examples/stock_trading_system.rb.bak +0 -563
data/examples/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.db
|
data/examples/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# KBS Examples
|
|
2
2
|
|
|
3
|
-
This directory contains comprehensive examples demonstrating the capabilities of the KBS (Knowledge-Based System) gem. Each example showcases different features and use cases of the RETE
|
|
3
|
+
This directory contains comprehensive examples demonstrating the capabilities of the KBS (Knowledge-Based System) gem. Each example showcases different features and use cases of the RETE inference engine and blackboard architecture.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
|
@@ -421,7 +421,7 @@ export OLLAMA_MODEL=gpt-oss:latest
|
|
|
421
421
|
## Summary of Capabilities
|
|
422
422
|
|
|
423
423
|
### Core KBS Features
|
|
424
|
-
- ā
RETE
|
|
424
|
+
- ā
RETE inference engine
|
|
425
425
|
- ā
Forward-chaining reasoning
|
|
426
426
|
- ā
Pattern matching
|
|
427
427
|
- ā
Negated conditions
|
|
@@ -4,7 +4,7 @@ require_relative '../lib/kbs'
|
|
|
4
4
|
|
|
5
5
|
class StockTradingExpertSystem
|
|
6
6
|
def initialize
|
|
7
|
-
@engine = KBS::
|
|
7
|
+
@engine = KBS::Engine.new
|
|
8
8
|
setup_rules
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -137,7 +137,7 @@ end
|
|
|
137
137
|
|
|
138
138
|
class NetworkDiagnosticSystem
|
|
139
139
|
def initialize
|
|
140
|
-
@engine = KBS::
|
|
140
|
+
@engine = KBS::Engine.new
|
|
141
141
|
setup_network_rules
|
|
142
142
|
end
|
|
143
143
|
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/kbs'
|
|
4
|
+
|
|
5
|
+
class StockTradingExpertSystem
|
|
6
|
+
include KBS::DSL::ConditionHelpers
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@kb = nil
|
|
10
|
+
setup_rules
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def setup_rules
|
|
14
|
+
@kb = KBS.knowledge_base do
|
|
15
|
+
rule "bull_market_buy" do
|
|
16
|
+
priority 10
|
|
17
|
+
on :market, trend: "bullish"
|
|
18
|
+
on :stock, rsi: satisfies { |rsi| rsi < 70 }
|
|
19
|
+
on :stock, pe_ratio: satisfies { |pe| pe < 25 }
|
|
20
|
+
|
|
21
|
+
perform do |facts|
|
|
22
|
+
stock = facts.find { |f| f.type == :stock }
|
|
23
|
+
puts "š BUY SIGNAL: #{stock[:symbol]} - Bull market with good fundamentals"
|
|
24
|
+
puts " RSI: #{stock[:rsi]}, P/E: #{stock[:pe_ratio]}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
rule "oversold_bounce" do
|
|
29
|
+
priority 8
|
|
30
|
+
on :stock, rsi: satisfies { |rsi| rsi < 30 }
|
|
31
|
+
on :stock, volume: satisfies { |v| v > 1000000 }
|
|
32
|
+
without.on :news, sentiment: "negative"
|
|
33
|
+
|
|
34
|
+
perform do |facts|
|
|
35
|
+
stock = facts.find { |f| f.type == :stock }
|
|
36
|
+
puts "š OVERSOLD BOUNCE: #{stock[:symbol]} - Potential reversal opportunity"
|
|
37
|
+
puts " RSI: #{stock[:rsi]}, Volume: #{stock[:volume]}"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
rule "stop_loss_trigger" do
|
|
42
|
+
priority 15
|
|
43
|
+
on :position, loss_percent: satisfies { |loss| loss > 8 }
|
|
44
|
+
on :market, trend: "bearish"
|
|
45
|
+
|
|
46
|
+
perform do |facts|
|
|
47
|
+
position = facts.find { |f| f.type == :position }
|
|
48
|
+
puts "š STOP LOSS: #{position[:symbol]} - Exit position immediately"
|
|
49
|
+
puts " Loss: #{position[:loss_percent]}%"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
rule "earnings_surprise" do
|
|
54
|
+
priority 12
|
|
55
|
+
on :earnings, surprise: satisfies { |s| s > 10 }
|
|
56
|
+
on :stock, momentum: satisfies { |m| m > 0 }
|
|
57
|
+
|
|
58
|
+
perform do |facts|
|
|
59
|
+
earnings = facts.find { |f| f.type == :earnings }
|
|
60
|
+
stock = facts.find { |f| f.type == :stock }
|
|
61
|
+
puts "š° EARNINGS BEAT: #{stock[:symbol]} - Strong earnings surprise"
|
|
62
|
+
puts " Surprise: #{earnings[:surprise]}%, Momentum: #{stock[:momentum]}"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
rule "price_volume_divergence" do
|
|
67
|
+
priority 5
|
|
68
|
+
on :stock, price_trend: "up"
|
|
69
|
+
on :stock, volume_trend: "down"
|
|
70
|
+
|
|
71
|
+
perform do |facts|
|
|
72
|
+
stock = facts.find { |f| f.type == :stock }
|
|
73
|
+
puts "ā ļø DIVERGENCE WARNING: #{stock[:symbol]} - Price/volume divergence detected"
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def analyze_market(market_conditions)
|
|
80
|
+
puts "\n" + "=" * 70
|
|
81
|
+
puts "MARKET ANALYSIS - #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
|
82
|
+
puts "=" * 70
|
|
83
|
+
|
|
84
|
+
market_conditions.each do |condition|
|
|
85
|
+
case condition[:type]
|
|
86
|
+
when :market
|
|
87
|
+
@kb.fact :market, condition[:data]
|
|
88
|
+
when :stock
|
|
89
|
+
@kb.fact :stock, condition[:data]
|
|
90
|
+
when :position
|
|
91
|
+
@kb.fact :position, condition[:data]
|
|
92
|
+
when :earnings
|
|
93
|
+
@kb.fact :earnings, condition[:data]
|
|
94
|
+
when :news
|
|
95
|
+
@kb.fact :news, condition[:data]
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
@kb.run
|
|
100
|
+
puts "=" * 70
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def clear_facts
|
|
104
|
+
@kb.reset
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
class NetworkDiagnosticSystem
|
|
109
|
+
include KBS::DSL::ConditionHelpers
|
|
110
|
+
|
|
111
|
+
def initialize
|
|
112
|
+
@kb = nil
|
|
113
|
+
setup_network_rules
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def setup_network_rules
|
|
117
|
+
@kb = KBS.knowledge_base do
|
|
118
|
+
rule "ddos_detection" do
|
|
119
|
+
on :traffic, requests_per_second: satisfies { |rps| rps > 10000 }
|
|
120
|
+
on :traffic, unique_ips: satisfies { |ips| ips < 100 }
|
|
121
|
+
without.on :firewall, status: "active"
|
|
122
|
+
|
|
123
|
+
perform do |facts|
|
|
124
|
+
traffic = facts.find { |f| f.type == :traffic }
|
|
125
|
+
puts "šØ DDoS ATTACK DETECTED!"
|
|
126
|
+
puts " Requests/sec: #{traffic[:requests_per_second]}"
|
|
127
|
+
puts " Unique IPs: #{traffic[:unique_ips]}"
|
|
128
|
+
puts " ACTION: Enabling rate limiting and firewall rules"
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
rule "bandwidth_saturation" do
|
|
133
|
+
on :network, bandwidth_usage: satisfies { |usage| usage > 90 }
|
|
134
|
+
on :service, priority: "high"
|
|
135
|
+
|
|
136
|
+
perform do |facts|
|
|
137
|
+
network = facts.find { |f| f.type == :network }
|
|
138
|
+
service = facts.find { |f| f.type == :service }
|
|
139
|
+
puts "ā ļø BANDWIDTH SATURATION: #{network[:bandwidth_usage]}% utilized"
|
|
140
|
+
puts " High priority service affected: #{service[:name]}"
|
|
141
|
+
puts " ACTION: Implementing QoS policies"
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
rule "latency_anomaly" do
|
|
146
|
+
on :latency, current_ms: satisfies { |ms| ms > 200 }
|
|
147
|
+
on :latency, baseline_ms: satisfies { |ms| ms < 50 }
|
|
148
|
+
|
|
149
|
+
perform do |facts|
|
|
150
|
+
latency = facts.find { |f| f.type == :latency }
|
|
151
|
+
puts "š§ LATENCY SPIKE DETECTED"
|
|
152
|
+
puts " Current: #{latency[:current_ms]}ms (baseline: #{latency[:baseline_ms]}ms)"
|
|
153
|
+
puts " ACTION: Rerouting traffic to alternate path"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def diagnose(conditions)
|
|
160
|
+
puts "\n" + "=" * 70
|
|
161
|
+
puts "NETWORK DIAGNOSTIC REPORT - #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
|
162
|
+
puts "=" * 70
|
|
163
|
+
|
|
164
|
+
conditions.each do |condition|
|
|
165
|
+
@kb.fact condition[:type], condition[:data]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
@kb.run
|
|
169
|
+
puts "=" * 70
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
if __FILE__ == $0
|
|
174
|
+
puts "\nš¦ STOCK TRADING EXPERT SYSTEM DEMONSTRATION"
|
|
175
|
+
puts "=" * 70
|
|
176
|
+
|
|
177
|
+
trading_system = StockTradingExpertSystem.new
|
|
178
|
+
|
|
179
|
+
scenario1 = [
|
|
180
|
+
{ type: :market, data: { trend: "bullish", volatility: "low" } },
|
|
181
|
+
{ type: :stock, data: { symbol: "AAPL", rsi: 45, pe_ratio: 22, momentum: 5 } },
|
|
182
|
+
{ type: :stock, data: { symbol: "GOOGL", rsi: 28, volume: 2000000, momentum: -2 } }
|
|
183
|
+
]
|
|
184
|
+
|
|
185
|
+
trading_system.analyze_market(scenario1)
|
|
186
|
+
trading_system.clear_facts
|
|
187
|
+
|
|
188
|
+
scenario2 = [
|
|
189
|
+
{ type: :market, data: { trend: "bearish", volatility: "high" } },
|
|
190
|
+
{ type: :position, data: { symbol: "TSLA", loss_percent: 12, shares: 100 } },
|
|
191
|
+
{ type: :earnings, data: { symbol: "MSFT", surprise: 15, quarter: "Q4" } },
|
|
192
|
+
{ type: :stock, data: { symbol: "MSFT", momentum: 8, rsi: 62 } }
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
trading_system.analyze_market(scenario2)
|
|
196
|
+
trading_system.clear_facts
|
|
197
|
+
|
|
198
|
+
scenario3 = [
|
|
199
|
+
{ type: :stock, data: { symbol: "META", price_trend: "up", volume_trend: "down" } },
|
|
200
|
+
{ type: :stock, data: { symbol: "NVDA", rsi: 25, volume: 5000000, momentum: 3 } }
|
|
201
|
+
]
|
|
202
|
+
|
|
203
|
+
trading_system.analyze_market(scenario3)
|
|
204
|
+
|
|
205
|
+
puts "\n\nš NETWORK DIAGNOSTIC SYSTEM DEMONSTRATION"
|
|
206
|
+
puts "=" * 70
|
|
207
|
+
|
|
208
|
+
network_system = NetworkDiagnosticSystem.new
|
|
209
|
+
|
|
210
|
+
network_scenario1 = [
|
|
211
|
+
{ type: :traffic, data: { requests_per_second: 15000, unique_ips: 50, protocol: "HTTP" } },
|
|
212
|
+
{ type: :network, data: { bandwidth_usage: 95, packet_loss: 2 } },
|
|
213
|
+
{ type: :service, data: { name: "API Gateway", priority: "high" } }
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
network_system.diagnose(network_scenario1)
|
|
217
|
+
|
|
218
|
+
network_scenario2 = [
|
|
219
|
+
{ type: :latency, data: { current_ms: 250, baseline_ms: 30, endpoint: "database" } },
|
|
220
|
+
{ type: :network, data: { bandwidth_usage: 60, packet_loss: 0 } }
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
network_system.diagnose(network_scenario2)
|
|
224
|
+
end
|
data/examples/ai_enhanced_kbs.rb
CHANGED