El data studio: 10-loop improvement pass — full Engram DB explorer
Full-featured terminal explorer for the Engram knowledge graph built natively in El. Features: - ANSI-colored TUI with box-drawing borders and salience bars - All API endpoints: stats, nodes by type/tier, search, edges, spreading activation, node detail with neighbor traversal - Text report export via fs_write - Offline/unreachable mode with helpful startup messages - Interactive mode command reference - ENGRAM_URL env var for connecting to non-default servers - Uses json_get_raw for nested JSON object traversal
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
// field_test.el — Proof of concept: Hebbian field model
|
||||
//
|
||||
// Tests the core mechanics:
|
||||
// 1. Nodes with 2D semantic positions and temporal coordinates
|
||||
// 2. Edges with weights that grow via co-activation (Hebb's rule)
|
||||
// 3. Spreading activation with path strength
|
||||
// 4. Temporal decay in path strength
|
||||
// 5. Epistemic confidence = node confidence * path strength
|
||||
//
|
||||
// No storage — pure in-memory demonstration using print output.
|
||||
|
||||
// ── Math helpers ──────────────────────────────────────────────────────────────
|
||||
|
||||
fn clamp_f(v: Float, lo: Float, hi: Float) -> Float {
|
||||
if v < lo {
|
||||
return lo
|
||||
}
|
||||
if v > hi {
|
||||
return hi
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// L2 distance squared — no sqrt needed for proximity comparison
|
||||
fn dist_sq(ax: Float, ay: Float, bx: Float, by: Float) -> Float {
|
||||
let dx: Float = ax - bx
|
||||
let dy: Float = ay - by
|
||||
return dx * dx + dy * dy
|
||||
}
|
||||
|
||||
// Proximity score: 1 / (1 + dist_sq) — range (0, 1], closer = higher
|
||||
fn proximity(ax: Float, ay: Float, bx: Float, by: Float) -> Float {
|
||||
let d: Float = dist_sq(ax, ay, bx, by)
|
||||
return 1.0 / (1.0 + d)
|
||||
}
|
||||
|
||||
// Linear temporal decay: 1.0 at t=0, decaying toward 0
|
||||
// decay_rate: fraction lost per time unit
|
||||
fn temporal_decay(age: Float, decay_rate: Float) -> Float {
|
||||
let d: Float = 1.0 - decay_rate * age
|
||||
return clamp_f(d, 0.0, 1.0)
|
||||
}
|
||||
|
||||
// ── Hebbian learning ──────────────────────────────────────────────────────────
|
||||
|
||||
// New edge weight after co-activation event
|
||||
// w_new = clamp(w + lr * a_i * a_j, 0, 1)
|
||||
fn hebbian_update(weight: Float, act_i: Float, act_j: Float, lr: Float) -> Float {
|
||||
let delta: Float = lr * act_i * act_j
|
||||
return clamp_f(weight + delta, 0.0, 1.0)
|
||||
}
|
||||
|
||||
// Edge decay between activations
|
||||
// w_new = w * (1 - decay_rate)
|
||||
fn edge_decay(weight: Float, decay_rate: Float) -> Float {
|
||||
return clamp_f(weight * (1.0 - decay_rate), 0.0, 1.0)
|
||||
}
|
||||
|
||||
// ── Path strength ─────────────────────────────────────────────────────────────
|
||||
|
||||
// Path strength = edge_weight * temporal_decay(node_age)
|
||||
// This is the confidence qualifier on a retrieval result
|
||||
fn path_strength(edge_weight: Float, node_age: Float, decay_rate: Float) -> Float {
|
||||
let td: Float = temporal_decay(node_age, decay_rate)
|
||||
return edge_weight * td
|
||||
}
|
||||
|
||||
// Epistemic confidence = node_confidence * path_strength
|
||||
fn epistemic_confidence(node_confidence: Float, ps: Float) -> Float {
|
||||
return node_confidence * ps
|
||||
}
|
||||
|
||||
// ── Simulation ────────────────────────────────────────────────────────────────
|
||||
|
||||
fn run_test() -> String {
|
||||
println("=== Engram Field Model — Proof of Concept ===")
|
||||
println("")
|
||||
|
||||
// ── Nodes ──
|
||||
// Each node: id, label, semantic position (x, y), temporal coordinate, confidence
|
||||
// Semantic space: 2D for demonstration
|
||||
// x=0..1: concrete←→abstract
|
||||
// y=0..1: negative←→positive valence
|
||||
|
||||
println("── Nodes ──────────────────────────────────────")
|
||||
println("A: 'patient has fever' pos=(0.2, 0.4) t=100")
|
||||
println("B: 'influenza' pos=(0.3, 0.5) t=90")
|
||||
println("C: 'drug interaction warning' pos=(0.6, 0.3) t=10 (old, unactivated)")
|
||||
println("D: 'ibuprofen' pos=(0.65, 0.3) t=10 (old, unactivated)")
|
||||
println("")
|
||||
|
||||
// Semantic positions
|
||||
let ax: Float = 0.2
|
||||
let ay: Float = 0.4
|
||||
let bx: Float = 0.3
|
||||
let by: Float = 0.5
|
||||
let cx: Float = 0.6
|
||||
let cy: Float = 0.3
|
||||
let dx_pos: Float = 0.65
|
||||
let dy_pos: Float = 0.3
|
||||
|
||||
// Initial proximity (latent gradient — implicit from positions)
|
||||
let prox_ab: Float = proximity(ax, ay, bx, by)
|
||||
let prox_ac: Float = proximity(ax, ay, cx, cy)
|
||||
let prox_cd: Float = proximity(cx, cy, dx_pos, dy_pos)
|
||||
|
||||
println("── Initial latent gradients (proximity) ───────")
|
||||
println("A↔B proximity: " + float_to_str(prox_ab) + " (semantically close — fever/flu)")
|
||||
println("A↔C proximity: " + float_to_str(prox_ac) + " (semantically distant)")
|
||||
println("C↔D proximity: " + float_to_str(prox_cd) + " (close — drug interaction/ibuprofen)")
|
||||
println("")
|
||||
|
||||
// ── Initial edge weights (all start near zero — no co-activation yet) ──
|
||||
let w_ab: Float = 0.0
|
||||
let w_ac: Float = 0.0
|
||||
let w_cd: Float = 0.0
|
||||
|
||||
println("── Initial edge weights ────────────────────────")
|
||||
println("A→B: " + float_to_str(w_ab) + " (no co-activation yet)")
|
||||
println("A→C: " + float_to_str(w_ac))
|
||||
println("C→D: " + float_to_str(w_cd))
|
||||
println("")
|
||||
|
||||
// ── Co-activation events ──
|
||||
// The doctor CGI processes a patient with fever.
|
||||
// A (fever) and B (influenza) co-activate — the diagnosis fires both.
|
||||
// Learning rate: 0.3
|
||||
|
||||
let lr: Float = 0.3
|
||||
let act_strength: Float = 1.0 // full activation
|
||||
|
||||
println("── Co-activation event 1: patient with fever → flu diagnosis ──")
|
||||
let w_ab_1: Float = hebbian_update(w_ab, act_strength, act_strength, lr)
|
||||
println("A and B fire together (strength=1.0)")
|
||||
println("A→B weight: " + float_to_str(w_ab) + " → " + float_to_str(w_ab_1))
|
||||
println("")
|
||||
|
||||
println("── Co-activation event 2: another flu case ──")
|
||||
let w_ab_2: Float = hebbian_update(w_ab_1, act_strength, act_strength, lr)
|
||||
println("A and B fire together again")
|
||||
println("A→B weight: " + float_to_str(w_ab_1) + " → " + float_to_str(w_ab_2))
|
||||
println("")
|
||||
|
||||
println("── Co-activation event 3: third flu case ──")
|
||||
let w_ab_3: Float = hebbian_update(w_ab_2, act_strength, act_strength, lr)
|
||||
println("A and B fire together again")
|
||||
println("A→B weight: " + float_to_str(w_ab_2) + " → " + float_to_str(w_ab_3))
|
||||
println("")
|
||||
|
||||
// C and D have never been activated in this context — weights stay near zero
|
||||
// (In practice, proximity means a latent gradient exists, but no learned edge yet)
|
||||
|
||||
// ── Query: activate A (fever), what spreads? ──
|
||||
println("── Query: activate A (fever) ───────────────────")
|
||||
println("Spreading activation from A...")
|
||||
println("")
|
||||
|
||||
// Decay rates
|
||||
let temporal_decay_rate: Float = 0.005 // per time unit
|
||||
let current_t: Int = 200
|
||||
|
||||
// Node ages (current_t - node_t)
|
||||
let age_b: Float = 110.0 // t=90, current=200
|
||||
let age_c: Float = 190.0 // t=10, current=200
|
||||
let age_d: Float = 190.0 // t=10, current=200
|
||||
|
||||
// Path strength to B: strong edge, recently relevant
|
||||
let ps_b: Float = path_strength(w_ab_3, age_b, temporal_decay_rate)
|
||||
let conf_b: Float = epistemic_confidence(0.9, ps_b)
|
||||
|
||||
// Path strength to C: no learned edge — only latent proximity gradient
|
||||
// Spreading activation from A can weakly reach C via proximity alone
|
||||
let latent_ac: Float = prox_ac * 0.1 // proximity contributes small initial signal
|
||||
let ps_c: Float = path_strength(latent_ac, age_c, temporal_decay_rate)
|
||||
let conf_c: Float = epistemic_confidence(0.9, ps_c)
|
||||
|
||||
// Path strength to D via C: chain of weak signals
|
||||
let ps_d: Float = path_strength(latent_ac * prox_cd * 0.1, age_d, temporal_decay_rate)
|
||||
let conf_d: Float = epistemic_confidence(0.9, ps_d)
|
||||
|
||||
println("Result: B (influenza)")
|
||||
println(" Edge weight: " + float_to_str(w_ab_3))
|
||||
println(" Node age: " + float_to_str(age_b) + " time units")
|
||||
println(" Temporal decay: " + float_to_str(temporal_decay(age_b, temporal_decay_rate)))
|
||||
println(" Path strength: " + float_to_str(ps_b))
|
||||
println(" Confidence: " + float_to_str(conf_b))
|
||||
println(" → STRONG: B surfaces with high confidence")
|
||||
println("")
|
||||
|
||||
println("Result: C (drug interaction warning)")
|
||||
println(" Edge weight: " + float_to_str(latent_ac) + " (latent only — never co-activated)")
|
||||
println(" Node age: " + float_to_str(age_c) + " time units")
|
||||
println(" Temporal decay: " + float_to_str(temporal_decay(age_c, temporal_decay_rate)))
|
||||
println(" Path strength: " + float_to_str(ps_c))
|
||||
println(" Confidence: " + float_to_str(conf_c))
|
||||
println(" → WEAK: C is distant and old — attenuated path triggers refresh signal")
|
||||
println("")
|
||||
|
||||
println("Result: D (ibuprofen) via C")
|
||||
println(" Path strength: " + float_to_str(ps_d))
|
||||
println(" Confidence: " + float_to_str(conf_d))
|
||||
println(" → VERY WEAK: chain of attenuated edges")
|
||||
println("")
|
||||
|
||||
// ── Refresh trigger ──
|
||||
println("── Attenuation trigger ─────────────────────────")
|
||||
let threshold: Float = 0.2
|
||||
println("Confidence threshold: " + float_to_str(threshold))
|
||||
if conf_c < threshold {
|
||||
println("C is below threshold (" + float_to_str(conf_c) + " < " + float_to_str(threshold) + ")")
|
||||
println("→ Trigger: 'drug interaction warning node found but path is weak.")
|
||||
println(" Last activated " + float_to_str(age_c) + " time units ago.")
|
||||
println(" Recommend fetching current information before acting.'")
|
||||
}
|
||||
println("")
|
||||
|
||||
// ── After refresh: C and D co-activate with A ──
|
||||
println("── Refresh: doctor looks up drug interactions ──")
|
||||
println("A, C, D all co-activate during research")
|
||||
let w_ac_new: Float = hebbian_update(0.0, act_strength, act_strength, lr)
|
||||
let w_cd_new: Float = hebbian_update(0.0, act_strength, act_strength, lr)
|
||||
let age_c_new: Float = 0.0 // just activated
|
||||
let age_d_new: Float = 0.0
|
||||
|
||||
let ps_c_new: Float = path_strength(w_ac_new, age_c_new, temporal_decay_rate)
|
||||
let conf_c_new: Float = epistemic_confidence(0.9, ps_c_new)
|
||||
|
||||
println("A→C weight after refresh: " + float_to_str(w_ac_new))
|
||||
println("C→D weight after refresh: " + float_to_str(w_cd_new))
|
||||
println("C confidence after refresh: " + float_to_str(conf_c_new))
|
||||
println("→ Edges strengthened. Drug interaction now reachable with high confidence.")
|
||||
println("")
|
||||
|
||||
println("=== Result ===")
|
||||
println("Perfect memory: all nodes present throughout.")
|
||||
println("Calibrated confidence: B (flu) high, C/D (drug interaction) low until refreshed.")
|
||||
println("Self-correcting: attenuation triggered fetch, fetch strengthened edges.")
|
||||
println("The field works.")
|
||||
|
||||
return "ok"
|
||||
}
|
||||
|
||||
let result: String = run_test()
|
||||
@@ -0,0 +1,103 @@
|
||||
// language_features_test.el — tests for new operators and builtins
|
||||
|
||||
// 1. Modulo operator
|
||||
let m = 17 % 5
|
||||
println(int_to_str(m))
|
||||
|
||||
// 2. Bitwise ops
|
||||
let flags_and = 10 & 12
|
||||
let flags_xor = 10 ^ 12
|
||||
let flags_shl = 1 << 3
|
||||
let flags_shr = 16 >> 2
|
||||
println(int_to_str(flags_and))
|
||||
println(int_to_str(flags_xor))
|
||||
println(int_to_str(flags_shl))
|
||||
println(int_to_str(flags_shr))
|
||||
|
||||
// 3. Math trig
|
||||
let sin0 = math_sin(0.0)
|
||||
let cos0 = math_cos(0.0)
|
||||
let pi_val = math_pi()
|
||||
println(float_to_str(sin0))
|
||||
println(float_to_str(cos0))
|
||||
println(float_to_str(pi_val))
|
||||
|
||||
// 4. String padding
|
||||
let padded = str_pad_left("42", 5, "0")
|
||||
println(padded)
|
||||
|
||||
let padded_r = str_pad_right("hi", 5, ".")
|
||||
println(padded_r)
|
||||
|
||||
// 5. str_format
|
||||
let tmpl = "Hello {name}, you are {age} years old!"
|
||||
let data = {"name": "Will", "age": "30"}
|
||||
let formatted = str_format(tmpl, data)
|
||||
println(formatted)
|
||||
|
||||
// 6. format_float
|
||||
let ff = format_float(3.14159, 2)
|
||||
println(ff)
|
||||
|
||||
// 7. Time
|
||||
let ts = time_now_utc()
|
||||
let parts = time_to_parts(ts)
|
||||
let iso_str = time_format(ts, "ISO")
|
||||
println(iso_str)
|
||||
|
||||
// 8. Time add/diff
|
||||
let ts2 = time_add(ts, 7, "day")
|
||||
let diff = time_diff(ts, ts2, "day")
|
||||
println(int_to_str(diff))
|
||||
|
||||
// 9. List range
|
||||
let rng = list_range(0, 5)
|
||||
println(list_join(rng, ","))
|
||||
|
||||
// 10. Stack push/pop
|
||||
let s0 = stack_new()
|
||||
let s1 = stack_push(s0, 10)
|
||||
let s2 = stack_push(s1, 20)
|
||||
let top = stack_peek(s2)
|
||||
let s3 = stack_pop(s2)
|
||||
println(int_to_str(top))
|
||||
|
||||
// 11. Queue enqueue/dequeue
|
||||
let q0 = queue_new()
|
||||
let q1 = queue_enqueue(q0, "first")
|
||||
let q2 = queue_enqueue(q1, "second")
|
||||
let front = queue_peek(q2)
|
||||
let q3 = queue_dequeue(q2)
|
||||
println(front)
|
||||
|
||||
// 12. Decimal round
|
||||
let rounded = decimal_round(3.14159, 2)
|
||||
println(float_to_str(rounded))
|
||||
|
||||
// 13. int_to_float / float_to_int
|
||||
let fi = int_to_float(42)
|
||||
let if_ = float_to_int(3.9)
|
||||
println(float_to_str(fi))
|
||||
println(int_to_str(if_))
|
||||
|
||||
// 14. is_nil / unwrap_or
|
||||
let n = unwrap_or(is_nil(42), false)
|
||||
println(bool_to_str(n))
|
||||
|
||||
// 15. list_push, list_pop, list_range
|
||||
let lst = list_new()
|
||||
let lst2 = list_push(lst, 100)
|
||||
let lst3 = list_push(lst2, 200)
|
||||
let last_elem = list_peek_last(lst3)
|
||||
println(int_to_str(last_elem))
|
||||
|
||||
// 16. Char ops
|
||||
let char_a = str_char_at("hello", 1)
|
||||
let code_e = str_char_code("hello", 1)
|
||||
let ch_from = str_from_char_code(65)
|
||||
println(char_a)
|
||||
println(int_to_str(code_e))
|
||||
println(ch_from)
|
||||
|
||||
// Done
|
||||
println("all tests complete")
|
||||
@@ -0,0 +1,10 @@
|
||||
// Test LLM native functions (with ANTHROPIC_API_KEY in env)
|
||||
let models: List = llm_models()
|
||||
println("Available models: " + int_to_str(list_len(models)))
|
||||
|
||||
// This test skips actual API calls since they need env vars
|
||||
// Just verify the functions exist and don't crash on missing keys
|
||||
let missing_key_result: String = llm_call("claude", "ping")
|
||||
println("llm_call returned (may be error without API key): " + str_slice(missing_key_result, 0, 50))
|
||||
|
||||
println("LLM function registration: OK")
|
||||
Reference in New Issue
Block a user