qualia_core_db/inference/
application_profile.rs1use std::sync::atomic::{AtomicU8, Ordering};
16
17use crate::inference_modes::{set_inference_mode, InferenceMode};
18#[cfg(not(target_arch = "wasm32"))]
19use crate::llm_bench::{set_decode_budget_override, set_inference_timeout_override_ms};
20
21#[cfg(target_arch = "wasm32")]
22fn set_decode_budget_override(_n: u32) {}
23#[cfg(target_arch = "wasm32")]
24fn set_inference_timeout_override_ms(_ms: u64) {}
25
26#[repr(u8)]
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
28pub enum ApplicationProfile {
29 Interactive = 0,
31 LiveFast = 1,
33 BatchOvernight = 2,
35}
36
37impl ApplicationProfile {
38 pub const ALL: [ApplicationProfile; 3] = [
39 ApplicationProfile::Interactive,
40 ApplicationProfile::LiveFast,
41 ApplicationProfile::BatchOvernight,
42 ];
43
44 pub fn as_str(self) -> &'static str {
45 match self {
46 Self::Interactive => "interactive",
47 Self::LiveFast => "live-fast",
48 Self::BatchOvernight => "batch",
49 }
50 }
51
52 pub fn parse(s: &str) -> Option<Self> {
53 match s.trim().to_ascii_lowercase().as_str() {
54 "interactive" | "chat" | "ui" | "0" => Some(Self::Interactive),
55 "live-fast" | "live_fast" | "live" | "fast" | "1" => Some(Self::LiveFast),
56 "batch" | "batch-overnight" | "overnight" | "offline" | "async" | "email" | "2" => {
57 Some(Self::BatchOvernight)
58 }
59 _ => None,
60 }
61 }
62
63 pub fn description(self) -> &'static str {
64 match self {
65 Self::Interactive => {
66 "interactive chat: path-selected GPU backend, 256-tok budget, 30s wall-clock"
67 }
68 Self::LiveFast => {
69 "live-fast: FastVerify (uninterrupted decode → post graph/CML heal), still local"
70 }
71 Self::BatchOvernight => {
72 "batch/overnight: up to 2048 tokens, 8h wall-clock, HTML+CML verify — multi-system eval, email-ready"
73 }
74 }
75 }
76}
77
78static PROFILE: AtomicU8 = AtomicU8::new(ApplicationProfile::Interactive as u8);
79
80pub fn active_application_profile() -> ApplicationProfile {
81 if let Ok(s) = std::env::var("QUALIA_APP_PROFILE") {
82 if let Some(p) = ApplicationProfile::parse(&s) {
83 return p;
84 }
85 }
86 match PROFILE.load(Ordering::Relaxed) {
87 1 => ApplicationProfile::LiveFast,
88 2 => ApplicationProfile::BatchOvernight,
89 _ => ApplicationProfile::Interactive,
90 }
91}
92
93pub fn set_application_profile(profile: ApplicationProfile) {
95 PROFILE.store(profile as u8, Ordering::Relaxed);
96 apply_application_profile(profile);
97 log::info!("APP_PROFILE|{}|{}", profile.as_str(), profile.description());
98}
99
100pub fn apply_application_profile(profile: ApplicationProfile) {
101 match profile {
102 ApplicationProfile::Interactive => {
103 set_decode_budget_override(0); set_inference_timeout_override_ms(0); if std::env::var("QUALIA_INFERENCE_MODE").is_err() {
106 set_inference_mode(InferenceMode::Portable);
107 }
108 }
109 ApplicationProfile::LiveFast => {
110 set_decode_budget_override(0);
111 set_inference_timeout_override_ms(0);
112 if std::env::var("QUALIA_INFERENCE_MODE").is_err() {
113 set_inference_mode(InferenceMode::FastVerify);
114 }
115 }
116 ApplicationProfile::BatchOvernight => {
117 set_decode_budget_override(2048);
119 set_inference_timeout_override_ms(8 * 60 * 60 * 1000); std::env::set_var("QUALIA_RETURN_VERIFY_HTML", "1");
122 if std::env::var("QUALIA_INFERENCE_MODE").is_err() {
123 set_inference_mode(InferenceMode::FastVerify);
124 }
125 let n = crate::quant_graph_grounding::seed_facts_from_bundled();
127 log::info!("APP_PROFILE|batch|facts_seeded|{n}|budget=2048|timeout=8h|html=1");
128 }
129 }
130}
131
132pub fn bootstrap_application_profile() -> ApplicationProfile {
134 let p = active_application_profile();
135 apply_application_profile(p);
136 p
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn parse_profiles() {
145 assert_eq!(
146 ApplicationProfile::parse("overnight"),
147 Some(ApplicationProfile::BatchOvernight)
148 );
149 assert_eq!(
150 ApplicationProfile::parse("live-fast"),
151 Some(ApplicationProfile::LiveFast)
152 );
153 }
154}