kbs 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- 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/examples/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*.db
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require_relative '../lib/kbs'
|
|
4
|
+
|
|
5
|
+
puts "Rule Source Introspection Demo"
|
|
6
|
+
puts "=" * 60
|
|
7
|
+
puts
|
|
8
|
+
puts "KBS can show the source of any rule — whether it was defined"
|
|
9
|
+
puts "in a file (exact source) or built dynamically at runtime"
|
|
10
|
+
puts "(reconstructed from bytecode via KBS::Decompiler)."
|
|
11
|
+
puts
|
|
12
|
+
|
|
13
|
+
# ── Part 1: File-defined rules ───────────────────────────────
|
|
14
|
+
|
|
15
|
+
puts "PART 1: File-Defined Rules"
|
|
16
|
+
puts "-" * 60
|
|
17
|
+
puts
|
|
18
|
+
|
|
19
|
+
kb = KBS.knowledge_base do
|
|
20
|
+
rule "dead_battery" do
|
|
21
|
+
on :symptom, problem: "won't start"
|
|
22
|
+
on :symptom, problem: "no lights"
|
|
23
|
+
|
|
24
|
+
perform do |facts, bindings|
|
|
25
|
+
puts "DIAGNOSIS: Dead battery"
|
|
26
|
+
puts "RECOMMENDATION: Replace or jump-start the battery"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
rule "overheating" do
|
|
31
|
+
on :symptom, problem: "high temperature"
|
|
32
|
+
on :symptom, problem: "steam from hood"
|
|
33
|
+
without :symptom, problem: "coolant leak"
|
|
34
|
+
|
|
35
|
+
perform do |facts, bindings|
|
|
36
|
+
puts "DIAGNOSIS: Engine overheating (no coolant leak)"
|
|
37
|
+
puts "RECOMMENDATION: Check radiator and cooling system"
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
kb.rules.each_key do |name|
|
|
43
|
+
puts "Source for '#{name}':"
|
|
44
|
+
puts
|
|
45
|
+
kb.print_rule_source(name)
|
|
46
|
+
puts
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# ── Part 2: Dynamically-created rules ────────────────────────
|
|
50
|
+
|
|
51
|
+
puts
|
|
52
|
+
puts "PART 2: Dynamically-Created Rules"
|
|
53
|
+
puts "-" * 60
|
|
54
|
+
puts
|
|
55
|
+
puts "These rules have no source file — KBS reconstructs them"
|
|
56
|
+
puts "from their internal state using YARV bytecode decompilation."
|
|
57
|
+
puts
|
|
58
|
+
|
|
59
|
+
# Simulate what an AI agent framework might do: build rules at
|
|
60
|
+
# runtime from configuration data, user input, or LLM output.
|
|
61
|
+
|
|
62
|
+
dynamic_kb = KBS::DSL::KnowledgeBase.new
|
|
63
|
+
|
|
64
|
+
# Rule with lambda condition helpers
|
|
65
|
+
builder = KBS::DSL::RuleBuilder.new("high_temp_alert")
|
|
66
|
+
builder.desc "Fire when temperature exceeds safe threshold"
|
|
67
|
+
builder.priority 5
|
|
68
|
+
builder.on :sensor, location: "server_room", temp: ->(v) { v > 85 }
|
|
69
|
+
builder.without :alert, type: :cooling_active
|
|
70
|
+
builder.perform { |facts| puts "ALERT: Server room temperature critical!" }
|
|
71
|
+
|
|
72
|
+
rule = builder.build
|
|
73
|
+
dynamic_kb.instance_variable_get(:@rule_builders)["high_temp_alert"] = builder
|
|
74
|
+
dynamic_kb.instance_variable_get(:@rules)["high_temp_alert"] = rule
|
|
75
|
+
dynamic_kb.engine.add_rule(rule)
|
|
76
|
+
|
|
77
|
+
# Rule with multiple proc-based conditions
|
|
78
|
+
builder2 = KBS::DSL::RuleBuilder.new("buy_signal")
|
|
79
|
+
builder2.on :stock, price: ->(v) { v < 150 }, volume: ->(v) { v > 1_000_000 }
|
|
80
|
+
builder2.without :position, status: :open
|
|
81
|
+
builder2.perform { |facts| puts "BUY signal triggered" }
|
|
82
|
+
|
|
83
|
+
rule2 = builder2.build
|
|
84
|
+
dynamic_kb.instance_variable_get(:@rule_builders)["buy_signal"] = builder2
|
|
85
|
+
dynamic_kb.instance_variable_get(:@rules)["buy_signal"] = rule2
|
|
86
|
+
dynamic_kb.engine.add_rule(rule2)
|
|
87
|
+
|
|
88
|
+
["high_temp_alert", "buy_signal"].each do |name|
|
|
89
|
+
puts "Reconstructed source for '#{name}':"
|
|
90
|
+
puts
|
|
91
|
+
dynamic_kb.print_rule_source(name)
|
|
92
|
+
puts
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# ── Part 3: Decompiler standalone ─────────────────────────────
|
|
96
|
+
|
|
97
|
+
puts
|
|
98
|
+
puts "PART 3: KBS::Decompiler Standalone"
|
|
99
|
+
puts "-" * 60
|
|
100
|
+
puts
|
|
101
|
+
puts "The decompiler works on any Proc or Lambda:"
|
|
102
|
+
puts
|
|
103
|
+
|
|
104
|
+
examples = {
|
|
105
|
+
"lambda" => ->(x) { x * 2 + 1 },
|
|
106
|
+
"proc" => proc { |a, b| a > b },
|
|
107
|
+
"complex" => ->(items) { items.select { |x| x > 0 }.map { |x| x * 2 } },
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
examples.each do |label, pr|
|
|
111
|
+
puts " #{label}:"
|
|
112
|
+
puts " decompile => #{KBS::Decompiler.new(pr).decompile}"
|
|
113
|
+
puts " decompile_block => #{KBS::Decompiler.new(pr).decompile_block}"
|
|
114
|
+
puts
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# ── Part 4: Unknown rule ──────────────────────────────────────
|
|
118
|
+
|
|
119
|
+
puts "PART 4: Unknown Rule"
|
|
120
|
+
puts "-" * 60
|
|
121
|
+
puts
|
|
122
|
+
kb.print_rule_source("nonexistent")
|
|
123
|
+
puts " rule_source returns: #{kb.rule_source('nonexistent').inspect}"
|