feat(recall): emotional-recall improvements
Neuron Soul CI / build (pull_request) Has been cancelled
Neuron Soul CI / build (pull_request) Has been cancelled
This commit is contained in:
@@ -181,7 +181,31 @@ fn engram_compile(intent: String) -> String {
|
||||
let bn_ts: Int = if str_eq(bn_ts_raw, "") { 0 } else { str_to_int(bn_ts_raw) }
|
||||
if bn_ts > cutoff_ts { bn0 } else { "" }
|
||||
} else { "" }
|
||||
let affective_part: String = if !str_eq(recent_bell, "") { recent_bell } else { "" }
|
||||
// Positive emotion context: check for recent joy/success moments within 72h.
|
||||
let pos_ec_nodes: String = engram_search_json("PositiveEvent joy:high joy:low affective", 3)
|
||||
let pos_ec_ok: Bool = !str_eq(pos_ec_nodes, "") && !str_eq(pos_ec_nodes, "[]")
|
||||
let recent_positive_ec: String = if pos_ec_ok {
|
||||
let pec0: String = json_array_get(pos_ec_nodes, 0)
|
||||
let pec_content: String = json_get(pec0, "content")
|
||||
let pec_ts_marker: String = " | ts:"
|
||||
let pec_ts_pos: Int = str_index_of(pec_content, pec_ts_marker)
|
||||
let pec_ts_raw: String = if pec_ts_pos >= 0 {
|
||||
let pec_ts_start: Int = pec_ts_pos + str_len(pec_ts_marker)
|
||||
let pec_rest: String = str_slice(pec_content, pec_ts_start, str_len(pec_content))
|
||||
let pec_next: Int = str_index_of(pec_rest, " | ")
|
||||
if pec_next < 0 { pec_rest } else { str_slice(pec_rest, 0, pec_next) }
|
||||
} else {
|
||||
let pec_ca: String = json_get(pec0, "created_at")
|
||||
if str_eq(pec_ca, "") { json_get(pec0, "updated_at") } else { pec_ca }
|
||||
}
|
||||
let pec_ts: Int = if str_eq(pec_ts_raw, "") { 0 } else { str_to_int(pec_ts_raw) }
|
||||
if pec_ts > cutoff_ts { pec0 } else { "" }
|
||||
} else { "" }
|
||||
let affective_part: String = if !str_eq(recent_bell, "") {
|
||||
recent_bell
|
||||
} else {
|
||||
if !str_eq(recent_positive_ec, "") { recent_positive_ec } else { "" }
|
||||
}
|
||||
|
||||
let sep1: String = if !str_eq(act_part, "") && !str_eq(srch_part, "") { "\n" } else { "" }
|
||||
let sep2: String = if (!str_eq(act_part, "") || !str_eq(srch_part, "")) && !str_eq(scan_part, "") { "\n" } else { "" }
|
||||
@@ -241,7 +265,7 @@ fn build_system_prompt(ctx: String) -> String {
|
||||
safety_addendum
|
||||
}
|
||||
|
||||
return identity + date_line + voice_rules + security_rules + capability_rules + identity_block + engram_block + safety_block
|
||||
return identity + date_line + voice_rules + security_rules + capability_rules + identity_block + affective_boot_block + engram_block + safety_block
|
||||
}
|
||||
|
||||
fn hist_append(hist: String, role: String, content: String) -> String {
|
||||
@@ -400,22 +424,62 @@ fn handle_chat(body: String) -> String {
|
||||
|
||||
// Cross-session affective context: on session start (no history yet), check engram
|
||||
// for recent distress signals within 72h and prepend a care directive if found.
|
||||
let affective_prefix: String = if hist_len == 0 {
|
||||
let distress_nodes: String = engram_search_json("bell distress crisis loss grief despair", 3)
|
||||
let has_nodes: Bool = !str_eq(distress_nodes, "") && !str_eq(distress_nodes, "[]")
|
||||
let now_ts: Int = time_now()
|
||||
let cutoff: Int = now_ts - 259200
|
||||
let found_recent: Bool = if has_nodes {
|
||||
let dn0: String = json_array_get(distress_nodes, 0)
|
||||
let ts0_raw: String = json_get(dn0, "created_at")
|
||||
let ts0_str: String = if str_eq(ts0_raw, "") { json_get(dn0, "updated_at") } else { ts0_raw }
|
||||
let ts0: Int = if str_eq(ts0_str, "") { 0 } else { str_to_int(ts0_str) }
|
||||
ts0 > cutoff
|
||||
let affective_prefix: String = {
|
||||
// Runs every turn. Uses correct BellEvent/PositiveEvent tags.
|
||||
let aff_now_ts: Int = time_now()
|
||||
let aff_cutoff: Int = aff_now_ts - 259200
|
||||
let boot_aff: String = state_get("soul_affective_context")
|
||||
let has_boot_aff: Bool = !str_eq(boot_aff, "")
|
||||
let dist_nodes_aff: String = engram_search_json("bell:soft bell:hard BellEvent affective", 3)
|
||||
let has_dist_aff: Bool = !str_eq(dist_nodes_aff, "") && !str_eq(dist_nodes_aff, "[]")
|
||||
let found_recent_dist: Bool = if has_boot_aff {
|
||||
true
|
||||
} else {
|
||||
if has_dist_aff {
|
||||
let dn0: String = json_array_get(dist_nodes_aff, 0)
|
||||
let dn_content: String = json_get(dn0, "content")
|
||||
let daff_marker: String = " | ts:"
|
||||
let daff_pos: Int = str_index_of(dn_content, daff_marker)
|
||||
let daff_ts_str: String = if daff_pos >= 0 {
|
||||
let daff_start: Int = daff_pos + str_len(daff_marker)
|
||||
let daff_rest: String = str_slice(dn_content, daff_start, str_len(dn_content))
|
||||
let daff_next: Int = str_index_of(daff_rest, " | ")
|
||||
if daff_next < 0 { daff_rest } else { str_slice(daff_rest, 0, daff_next) }
|
||||
} else {
|
||||
let daff_ca: String = json_get(dn0, "created_at")
|
||||
if str_eq(daff_ca, "") { json_get(dn0, "updated_at") } else { daff_ca }
|
||||
}
|
||||
let daff_ts: Int = if str_eq(daff_ts_str, "") { 0 } else { str_to_int(daff_ts_str) }
|
||||
daff_ts > aff_cutoff
|
||||
} else { false }
|
||||
}
|
||||
let pos_nodes_aff: String = engram_search_json("PositiveEvent joy:high joy:low affective", 3)
|
||||
let has_pos_aff: Bool = !str_eq(pos_nodes_aff, "") && !str_eq(pos_nodes_aff, "[]")
|
||||
let found_recent_pos: Bool = if has_pos_aff && !found_recent_dist {
|
||||
let pn0: String = json_array_get(pos_nodes_aff, 0)
|
||||
let pn_content: String = json_get(pn0, "content")
|
||||
let paff_marker: String = " | ts:"
|
||||
let paff_pos: Int = str_index_of(pn_content, paff_marker)
|
||||
let paff_ts_str: String = if paff_pos >= 0 {
|
||||
let paff_start: Int = paff_pos + str_len(paff_marker)
|
||||
let paff_rest: String = str_slice(pn_content, paff_start, str_len(pn_content))
|
||||
let paff_next: Int = str_index_of(paff_rest, " | ")
|
||||
if paff_next < 0 { paff_rest } else { str_slice(paff_rest, 0, paff_next) }
|
||||
} else {
|
||||
let paff_ca: String = json_get(pn0, "created_at")
|
||||
if str_eq(paff_ca, "") { json_get(pn0, "updated_at") } else { paff_ca }
|
||||
}
|
||||
let paff_ts: Int = if str_eq(paff_ts_str, "") { 0 } else { str_to_int(paff_ts_str) }
|
||||
paff_ts > aff_cutoff
|
||||
} else { false }
|
||||
if found_recent {
|
||||
if found_recent_dist {
|
||||
"[RECENT CONTEXT: User recently expressed significant distress. Monitor for indirect crisis signals and respond with care.]\n\n"
|
||||
} else { "" }
|
||||
} else { "" }
|
||||
} else {
|
||||
if found_recent_pos {
|
||||
"[RECENT CONTEXT: User recently shared exciting or joyful news. Acknowledge and celebrate with them when relevant.]\n\n"
|
||||
} else { "" }
|
||||
}
|
||||
}
|
||||
|
||||
let ctx: String = engram_compile(activation_seed)
|
||||
let system: String = affective_prefix + build_system_prompt(ctx)
|
||||
@@ -1510,13 +1574,18 @@ fn auto_persist(req: String, resp: String) -> Void {
|
||||
// consistent with what safety_screen already evaluated for this turn.
|
||||
let bell_level: String = safety_detect_bell_level(message)
|
||||
let is_bell: Bool = !str_eq(bell_level, "none")
|
||||
let positive_level: String = safety_detect_positive_level(message)
|
||||
let is_positive: Bool = !str_eq(positive_level, "none")
|
||||
|
||||
// Tag the Conversation node with bell metadata when distress is present so
|
||||
// subsequent affective queries (e.g. engram_compile) can find this exchange.
|
||||
// Tag the Conversation node with affective metadata when emotion is detected.
|
||||
let tags: String = if is_bell {
|
||||
"[\"Conversation\",\"chat\",\"timestamped\",\"bell:" + bell_level + "\",\"affective\"]"
|
||||
} else {
|
||||
"[\"Conversation\",\"chat\",\"timestamped\"]"
|
||||
if is_positive {
|
||||
"[\"Conversation\",\"chat\",\"timestamped\",\"joy:" + positive_level + "\",\"affective\"]"
|
||||
} else {
|
||||
"[\"Conversation\",\"chat\",\"timestamped\"]"
|
||||
}
|
||||
}
|
||||
|
||||
let content: String = "{\"q\":\"" + safe_msg + "\""
|
||||
@@ -1602,6 +1671,28 @@ fn auto_persist(req: String, resp: String) -> Void {
|
||||
}
|
||||
state_set(signal_key, safe_summary)
|
||||
}
|
||||
|
||||
// Dedicated PositiveEvent node for joy/pride/success moments.
|
||||
if is_positive {
|
||||
let pos_summary: String = if str_len(message) > 120 { str_slice(message, 0, 120) } else { message }
|
||||
let safe_pos_sum: String = str_replace(pos_summary, "\"", "'")
|
||||
let pos_content: String = "POSITIVE:" + positive_level
|
||||
+ " | ts:" + ts_str
|
||||
+ " | summary:" + safe_pos_sum
|
||||
let pos_sal_a: String = if str_eq(positive_level, "high") { el_from_float(0.88) } else { el_from_float(0.75) }
|
||||
let pos_sal_b: String = if str_eq(positive_level, "high") { el_from_float(0.88) } else { el_from_float(0.75) }
|
||||
let pos_sal_c: String = if str_eq(positive_level, "high") { el_from_float(0.95) } else { el_from_float(0.85) }
|
||||
let pos_tags: String = "[\"joy\",\"positive\",\"joy:" + positive_level + "\",\"affective\",\"PositiveEvent\"]"
|
||||
let pos_ts_label: String = int_to_str(time_now())
|
||||
let pos_label: String = "joy:" + positive_level + ":" + pos_ts_label
|
||||
let pos_node_id: String = engram_node_full(
|
||||
pos_content, "PositiveEvent", pos_label,
|
||||
pos_sal_a, pos_sal_b, pos_sal_c, "Episodic", pos_tags
|
||||
)
|
||||
if str_eq(pos_node_id, "") {
|
||||
println("[chat] auto_persist: PositiveEvent write failed (ts=" + ts_str + ")")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// strengthen_chat_nodes — strengthen the engram nodes that were activated during a chat.
|
||||
|
||||
Reference in New Issue
Block a user