Skip to main content

chaiss_core/
llm.rs

1use flume::Sender;
2use futures::StreamExt;
3use llm::{
4    builder::{LLMBackend, LLMBuilder},
5    chat::ChatMessage,
6};
7
8#[derive(Clone, Debug)]
9pub struct LlmPromptPayload {
10    pub prompt: String,
11    pub current_fen: String,
12    pub ascii_board: String,
13    pub algebraic_history: Vec<String>,
14    pub chat_history: Vec<(String, String)>,
15    pub predictive_matrix_hotspots: Vec<String>,
16    pub system_role: String,
17}
18
19// Orchestrate mathematically generic non-blocking HTTP REST streaming logic directly interacting with Gemini 3.1!
20pub async fn stream_llm_response(
21    payload: LlmPromptPayload,
22    tx: Sender<String>,
23) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
24    let llm_backend_str = std::env::var("LLM_BACKEND")
25        .unwrap_or_else(|_| "google".to_string())
26        .to_lowercase();
27
28    let (backend_enum, api_key_env, default_model) = match llm_backend_str.as_str() {
29        "openai" => (LLMBackend::OpenAI, "OPENAI_API_KEY", "gpt-4-turbo"),
30        "anthropic" => (
31            LLMBackend::Anthropic,
32            "ANTHROPIC_API_KEY",
33            "claude-3-opus-20240229",
34        ),
35        "ollama" => (LLMBackend::Ollama, "", "llama3"), // Added fallback for local testing maybe
36        _ => (
37            LLMBackend::Google,
38            "GOOGLE_API_KEY",
39            "gemini-3.1-pro-preview",
40        ),
41    };
42
43    let api_key = std::env::var(api_key_env).unwrap_or_else(|_| "TESTKEY".to_string());
44
45    // Validate we actually have a test key or an env var mapped, else error gracefully without crashing!
46    // Skip key check for Ollama / Local backends
47    if api_key == "TESTKEY" && backend_enum != LLMBackend::Ollama {
48        return Err(format!("No {} exported natively in your terminal! Please ensure your `.env` file is loaded correctly and you have restarted the application.", api_key_env).into());
49    }
50
51    let llm = LLMBuilder::new()
52        .backend(backend_enum)
53        .api_key(api_key.clone())
54        .model(default_model) // Frontier architecture structurally mapping rigorous mathematical constraints
55        .max_tokens(8000)
56        .temperature(0.7)
57        .build()
58        .map_err(|e| format!("Failed LLM Build: {:?}", e))?;
59
60    let fen_parts: Vec<&str> = payload.current_fen.split_whitespace().collect();
61    let is_white_turn = fen_parts.get(1).is_none_or(|&p| p == "w");
62    let active_color = if is_white_turn { "WHITE" } else { "BLACK" };
63
64    // 1. Build context mathematically formatting history and explicit ASCII layouts securely
65    let formatted_history: String = payload
66        .algebraic_history
67        .iter()
68        .enumerate()
69        .map(|(i, mov)| format!("{}. {}", i, mov))
70        .collect::<Vec<_>>()
71        .join("\n");
72    let mut futuristic_foresight = String::new();
73    if !payload.predictive_matrix_hotspots.is_empty() {
74        futuristic_foresight = format!(
75            "\n\nCRITICAL CONTEXT INJECTION:\nThe Rust Engine's 2nd-Order Predictive Matrix natively resolved that the following squares will become the MOST densely contested structural targets 1-ply into the future: {}\nIncorporate this absolute mathematical foresight organically into your conceptual strategic analysis!",
76            payload.predictive_matrix_hotspots.join(", ")
77        );
78    }
79
80    let system_prompt = format!(
81        "You are Chaiss, an advanced Chess {} mathematically bound to geometrical analysis.\n\n\
82        Current FEN String:\n{}\n\n\
83        Structural ASCII Board Matrix:\n{}\n\n\
84        Full Explicit Match Algebraic Sequence:\n{}\n\n\
85        The geometry currently dictates it is {}'s turn to move. \
86        Critically evaluate physical piece interactions natively, recognize structural blunders explicitly, and predict future hostile pressure correctly. Focus your analysis purely geometrically tracking explicit pawn structure and piece coordination sequentially over time. The user provides algebraic prompts.{}
87
88        CRITICALLY BINDING REQUIREMENT: At the mathematical conclusion of your analysis, you MUST provide exactly one hypothesized continuation line up to 4 plies deep recursively, formatted distinctly exactly on a single line like this:
89        ### PREDICTIVE MATRIX: e4, e5, Nf3, Nc6",
90        payload.system_role,
91        payload.current_fen,
92        payload.ascii_board,
93        formatted_history,
94        active_color,
95        futuristic_foresight
96    );
97
98    // 2. Synthesize Context Matrix iteratively mimicking continuous API session strings cleanly
99    let mut messages = vec![ChatMessage::user().content(&system_prompt).build()];
100
101    // Inject a dummy acknowledgment so Gemini mathematically anchors the System constraints before our formal chat!
102    messages.push(ChatMessage::assistant().content("System Context Acknowledged. I am mathematically bound to the supplied FEN bounds.").build());
103
104    for (role, content) in payload.chat_history {
105        if role == "User" {
106            messages.push(ChatMessage::user().content(&content).build());
107        } else {
108            messages.push(ChatMessage::assistant().content(&content).build());
109        }
110    }
111
112    // Inject the final active mathematical Prompt
113    messages.push(ChatMessage::user().content(&payload.prompt).build());
114
115    let mut stream = llm
116        .chat_stream(&messages)
117        .await
118        .map_err(|e| format!("Chat Stream err: {}", e))?;
119
120    while let Some(result) = stream.next().await {
121        match result {
122            Ok(token) => {
123                let _ = tx.send_async(token).await;
124            }
125            Err(e) => {
126                return Err(format!("Network Stream Disconnected Abruptly: {}", e).into());
127            }
128        }
129    }
130
131    Ok(())
132}