qualia_core_db/inference/
qualia_hybrid.rs1use crate::compute_universe::{
21 publish_attention_route_mask, publish_query_tensor, AttentionRouteMask,
22};
23use crate::prompt_lookup::{Draft, MAX_DRAFT};
24use crate::q_hash;
25use crate::tensor::Tensor10D;
26use crate::NQuin;
27
28pub const GRAPH_LOGIT_BIAS: f32 = 2.5;
30
31pub fn prepare_hybrid_decode(prompt: &str) {
40 if matches!(
41 crate::inference_modes::active_inference_mode(),
42 crate::inference_modes::InferenceMode::FastVerify
43 ) {
44 return;
45 }
46 let hybrid_route = crate::inference_modes::quant_graph_grounding_enabled()
47 || matches!(
48 std::env::var("QUALIA_HYBRID_ROUTE").ok().as_deref(),
49 Some("1") | Some("true")
50 );
51 if hybrid_route {
52 publish_graph_route_from_prompt(prompt);
53 publish_prompt_query_tensor(prompt);
54 }
55 if crate::inference_modes::quant_graph_grounding_enabled() {
56 let _ = publish_grounding_obligation(prompt);
57 }
58}
59
60pub fn publish_graph_route_from_prompt(prompt: &str) {
65 let mut mask = AttentionRouteMask::default();
66 for word in prompt.split(|c: char| !c.is_alphanumeric()) {
67 if word.len() < 3 {
68 continue;
69 }
70 let h = q_hash(&word.to_ascii_lowercase());
71 mask.set_index((h % 1024) as u32);
73 mask.set_index(((h.wrapping_add(1)) % 1024) as u32);
75 }
76 if crate::inference_modes::quant_graph_grounding_enabled() {
78 let g = crate::quant_graph_grounding::ground_generation(prompt, "");
79 if let Some(obj) = g.object_hash {
80 mask.set_index((obj % 1024) as u32);
81 mask.set_index(((obj >> 10) % 1024) as u32);
82 let mut buf = [NQuin {
84 subject: 0,
85 predicate: 0,
86 object: 0,
87 context: 0,
88 metadata: 0,
89 parity: 0,
90 }; 8];
91 let n = crate::quant_graph_grounding::export_fact_quins(&mut buf);
92 for q in buf.iter().take(n) {
93 mask.set_index((q.subject % 1024) as u32);
94 mask.set_index((q.object % 1024) as u32);
95 }
96 }
97 }
98 if mask.active_bits > 0 {
99 publish_attention_route_mask(mask);
100 log::debug!("qualia_hybrid|route_mask|bits={}", mask.active_bits);
101 }
102}
103
104pub fn publish_prompt_query_tensor(prompt: &str) {
106 let mut t = Tensor10D {
107 q: 0.0,
108 v: 0.0,
109 w: 0.0,
110 x: 0.0,
111 y: 0.0,
112 z: 0.0,
113 t: 0.0,
114 alpha: 0.0,
115 mu: 0.0,
116 sigma: 0.0,
117 };
118 let mut subject = 0u64;
119 let mut i = 0usize;
120 for word in prompt.split_whitespace().take(32) {
121 let h = q_hash(word);
122 subject ^= h.rotate_left((i as u32) * 3);
123 let f = ((h & 0xFFFF) as f32) / 65535.0;
124 match i % 10 {
125 0 => t.q += f,
126 1 => t.v += f,
127 2 => t.w += f,
128 3 => t.x += f,
129 4 => t.y += f,
130 5 => t.z += f,
131 6 => t.t += f,
132 7 => t.alpha += f,
133 8 => t.mu += f,
134 _ => t.sigma += f,
135 }
136 i += 1;
137 }
138 if i > 0 {
139 let n = i as f32;
140 t.q /= n;
141 t.v /= n;
142 t.w /= n;
143 t.x /= n;
144 t.y /= n;
145 t.z /= n;
146 t.t /= n;
147 t.alpha /= n;
148 t.mu /= n;
149 t.sigma /= n;
150 publish_query_tensor(t, subject);
151 }
152}
153
154pub fn propose_fact_draft(prompt: &str, encode: &dyn Fn(&str) -> Vec<u32>) -> Draft {
160 if !crate::inference_modes::quant_graph_grounding_enabled() {
161 return Draft::empty();
162 }
163 let g = crate::quant_graph_grounding::ground_generation(prompt, "");
165 let repair = if g.repaired {
167 g.text.as_str()
168 } else if g.reason.is_some() && g.object_hash.is_some() {
169 return Draft::empty();
172 } else {
173 return Draft::empty();
174 };
175 let ids = encode(repair);
176 if ids.is_empty() {
177 return Draft::empty();
178 }
179 let mut d = Draft::empty();
180 let take = ids.len().min(MAX_DRAFT);
181 d.tokens[..take].copy_from_slice(&ids[..take]);
182 d.len = take;
183 log::info!("qualia_hybrid|fact_draft|reason={:?}|len={take}", g.reason);
184 d
185}
186
187#[inline]
189pub fn graph_force_enabled() -> bool {
190 matches!(
191 std::env::var("QUALIA_GRAPH_FORCE").ok().as_deref(),
192 Some("1") | Some("true")
193 )
194}
195
196pub fn force_fact_tokens(prompt: &str, encode: &dyn Fn(&str) -> Vec<u32>) -> Option<Vec<u32>> {
198 if !crate::inference_modes::quant_graph_grounding_enabled() || !graph_force_enabled() {
199 return None;
200 }
201 let g = crate::quant_graph_grounding::ground_generation(prompt, "");
202 if !g.repaired {
203 return None;
204 }
205 let ids = encode(&g.text);
206 if ids.is_empty() {
207 None
208 } else {
209 log::info!("qualia_hybrid|fact_force|reason={:?}", g.reason);
210 Some(ids)
211 }
212}
213
214pub fn apply_graph_logit_bias(
220 prompt: &str,
221 logits: &mut [f32],
222 lookup: &dyn Fn(&str) -> Option<u32>,
223) -> usize {
224 if !crate::inference_modes::quant_graph_grounding_enabled() || logits.is_empty() {
225 return 0;
226 }
227 let g = crate::quant_graph_grounding::ground_generation(prompt, "");
228 if !g.repaired {
229 return 0;
231 }
232 let mut boosted = 0usize;
234 let candidates: [&str; 4] = [
235 g.reason.as_deref().unwrap_or(""),
236 "Paris",
237 "paris",
238 g.text.as_str(),
239 ];
240 let last_word = g
242 .text
243 .split(|c: char| !c.is_alphanumeric())
244 .filter(|w| w.len() > 2)
245 .last()
246 .unwrap_or("");
247 for s in [last_word, candidates[1], candidates[2]] {
248 if s.is_empty() {
249 continue;
250 }
251 if let Some(tid) = lookup(s) {
252 let i = tid as usize;
253 if i < logits.len() {
254 logits[i] += GRAPH_LOGIT_BIAS;
255 boosted += 1;
256 }
257 }
258 let lower = s.to_ascii_lowercase();
260 if lower != s {
261 if let Some(tid) = lookup(&lower) {
262 let i = tid as usize;
263 if i < logits.len() {
264 logits[i] += GRAPH_LOGIT_BIAS * 0.5;
265 boosted += 1;
266 }
267 }
268 }
269 }
270 if boosted > 0 {
271 log::debug!("qualia_hybrid|logit_bias|n={boosted}|reason={:?}", g.reason);
272 }
273 boosted
274}
275
276pub fn publish_grounding_obligation(prompt: &str) -> Option<NQuin> {
281 if !crate::inference_modes::quant_graph_grounding_enabled() {
282 return None;
283 }
284 let g = crate::quant_graph_grounding::ground_generation(prompt, "");
285 if g.reason.is_none() && !g.repaired {
286 return None;
287 }
288 let object = g.object_hash.unwrap_or(0);
289 if object == 0 {
290 return None;
291 }
292 let party = q_hash("q42:inference-principal");
294 let property = q_hash(crate::quant_graph_grounding::P_CAPITAL_OF);
295 let contract = q_hash(crate::quant_graph_grounding::CTX_GROUNDING);
296 #[cfg(any(
298 not(target_arch = "wasm32"),
299 feature = "wasm-ontology",
300 feature = "wasm-logic",
301 feature = "wasm-scientific",
302 feature = "wasm-full"
303 ))]
304 {
305 let quin = crate::modalities::logic::deontic::compile_norm_quin(
306 party,
307 crate::modalities::logic::deontic::OP_OBLIGATE,
308 property,
309 object,
310 contract,
311 0, false,
313 );
314 log::info!(
315 "qualia_hybrid|deontic_obligate|reason={:?}|object={object:#x}",
316 g.reason
317 );
318 Some(quin)
319 }
320 #[cfg(all(
321 target_arch = "wasm32",
322 not(any(
323 feature = "wasm-ontology",
324 feature = "wasm-logic",
325 feature = "wasm-scientific",
326 feature = "wasm-full"
327 ))
328 ))]
329 {
330 let _ = (party, property, object, contract);
331 log::info!(
332 "qualia_hybrid|deontic_obligate_skipped|portal_wasm|reason={:?}|object={object:#x}",
333 g.reason
334 );
335 None
336 }
337}
338
339pub fn propose_best_draft(prompt: &str, ctx: &[u32], encode: &dyn Fn(&str) -> Vec<u32>) -> Draft {
341 let fact = propose_fact_draft(prompt, encode);
342 if fact.len > 0 {
343 return fact;
344 }
345 crate::prompt_lookup::propose(ctx, MAX_DRAFT)
346}
347
348#[cfg(test)]
349mod tests {
350 use super::*;
351 use crate::inference_modes::{set_inference_mode, InferenceMode};
352 use crate::quant_graph_grounding::reset_fact_store_to_defaults;
353 use std::sync::Mutex;
354
355 fn mode_lock() -> std::sync::MutexGuard<'static, ()> {
357 static LOCK: Mutex<()> = Mutex::new(());
358 LOCK.lock().unwrap_or_else(|e| e.into_inner())
359 }
360
361 #[test]
362 fn fact_draft_on_capital_prompt() {
363 if std::env::var("QUALIA_INFERENCE_MODE").is_ok() {
364 return;
365 }
366 let _g = mode_lock();
367 reset_fact_store_to_defaults();
368 set_inference_mode(InferenceMode::QuantGraph);
369 let g =
371 crate::quant_graph_grounding::ground_generation("What is the capital of France?", "");
372 assert!(
373 g.repaired,
374 "expected repair on empty answer; reason={:?} text={}",
375 g.reason, g.text
376 );
377 let encode = |s: &str| {
378 s.bytes().map(|b| b as u32).collect()
380 };
381 let d = propose_fact_draft("What is the capital of France?", &encode);
382 assert!(
383 d.len > 0,
384 "draft len 0; repaired={} text={}",
385 g.repaired,
386 g.text
387 );
388 set_inference_mode(InferenceMode::Portable);
389 }
390
391 #[test]
392 fn route_mask_sets_bits() {
393 publish_graph_route_from_prompt("capital of France Paris knowledge graph");
394 let m = crate::compute_universe::attention_route_mask();
395 assert!(m.active_bits > 0);
396 }
397
398 #[test]
399 fn logit_bias_boosts_vocab_slot() {
400 if std::env::var("QUALIA_INFERENCE_MODE").is_ok() {
401 return;
402 }
403 let _g = mode_lock();
404 reset_fact_store_to_defaults();
405 set_inference_mode(InferenceMode::QuantGraph);
406 let mut logits = vec![0.0f32; 128];
407 let lookup = |s: &str| -> Option<u32> {
409 if s.eq_ignore_ascii_case("paris") {
410 Some(42)
411 } else {
412 None
413 }
414 };
415 let n = apply_graph_logit_bias("What is the capital of France?", &mut logits, &lookup);
416 assert!(n >= 1);
417 assert!(logits[42] >= GRAPH_LOGIT_BIAS);
418 set_inference_mode(InferenceMode::Portable);
419 }
420
421 #[test]
422 fn deontic_obligation_on_match() {
423 if std::env::var("QUALIA_INFERENCE_MODE").is_ok() {
424 return;
425 }
426 let _g = mode_lock();
427 reset_fact_store_to_defaults();
428 set_inference_mode(InferenceMode::QuantGraph);
429 let q = publish_grounding_obligation("What is the capital of France?");
430 assert!(q.is_some());
431 let q = q.unwrap();
432 assert_eq!(
433 (q.predicate & 0xFF) as u8,
434 crate::modalities::logic::deontic::OP_OBLIGATE
435 );
436 set_inference_mode(InferenceMode::Portable);
437 }
438}