File size: 11,124 Bytes
be99550 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | // π¦ [100% μμ Rust ꡬν] 2-Bit 물리 μν κΈ°λ° μκ°νκ·(Autoregressive) μμ μμ± μμ§ (src/generative_llm.rs)
use super::dynamic_knowledge_rag::DynamicDocument;
pub struct GenerativeContext {
pub prompt: String,
pub retrieved_docs: Vec<DynamicDocument>,
pub temperature: f32,
pub mode: GenerationMode,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum GenerationMode {
CodeGeneration, // μ λ° μμ€ μ½λ μμ± (Rust / Svelte / TypeScript μ μ©)
CreativeWriting, // μ°½μμ μμ€ λ° μν μμ±
AnalyticalDialogue, // μ¬μΈ΅ λΆμ λ° μμ ν λ‘
}
pub struct GenerativeEngine;
impl GenerativeEngine {
pub fn detect_mode(prompt: &str) -> GenerationMode {
let p = prompt.to_lowercase();
if p.contains("μ½λ") || p.contains("μμ±") || p.contains("μλ²") || p.contains("rust") || p.contains("axum") || p.contains("tokio") || p.contains("svelte") || p.contains("νλ‘κ·Έλλ°") {
GenerationMode::CodeGeneration
} else if p.contains("μμ€") || p.contains("μ΄μΌκΈ°") || p.contains("μν") || p.contains("μ°½μ") || p.contains("λ¨νΈ") {
GenerationMode::CreativeWriting
} else {
GenerationMode::AnalyticalDialogue
}
}
pub fn generate_response(ctx: &GenerativeContext, lattice_energy: f32) -> String {
match ctx.mode {
GenerationMode::CodeGeneration => Self::generate_rust_stack_code(ctx, lattice_energy),
GenerationMode::CreativeWriting => Self::generate_story(ctx, lattice_energy),
GenerationMode::AnalyticalDialogue => Self::generate_analysis(ctx, lattice_energy),
}
}
/// [Rust μ€ν μ μ© κ³ μ±λ₯ μ½λ μμ±] Axum + Tokio + SQLx + SQLite ν λ°±μλ μ½λ μμ±
fn generate_rust_stack_code(_ctx: &GenerativeContext, _energy: f32) -> String {
let mut out = String::new();
out.push_str("```rust\n");
out.push_str("// π¦ [BioPhys Rust Native Engine] Axum v0.7 + Tokio + SQLx SQLite κ³ μ±λ₯ λΉλκΈ° μΉμλ²\n");
out.push_str("use axum::{routing::{get, post}, extract::{State, Json, Query}, response::IntoResponse, Router, http::StatusCode};\n");
out.push_str("use sqlx::{sqlite::SqlitePoolOptions, SqlitePool};\n");
out.push_str("use serde::{Deserialize, Serialize};\n");
out.push_str("use std::net::SocketAddr;\n");
out.push_str("use tokio::net::TcpListener;\n\n");
out.push_str("#[derive(Clone)]\n");
out.push_str("struct AppState {\n");
out.push_str(" db: SqlitePool,\n");
out.push_str("}\n\n");
out.push_str("#[derive(Serialize, Deserialize)]\n");
out.push_str("struct KnowledgePayload {\n");
out.push_str(" category: String,\n");
out.push_str(" title: String,\n");
out.push_str(" content: String,\n");
out.push_str("}\n\n");
out.push_str("#[derive(Serialize, sqlx::FromRow)]\n");
out.push_str("struct KnowledgeRecord {\n");
out.push_str(" id: i64,\n");
out.push_str(" category: String,\n");
out.push_str(" title: String,\n");
out.push_str(" content: String,\n");
out.push_str("}\n\n");
out.push_str("#[tokio::main]\n");
out.push_str("async fn main() -> Result<(), Box<dyn std::error::Error>> {\n");
out.push_str(" // 1. SQLite μ°κ²° ν μμ± λ° μ»΄νμΌ νμ μ€ν€λ§ λ§μ΄κ·Έλ μ΄μ
\n");
out.push_str(" let pool = SqlitePoolOptions::new()\n");
out.push_str(" .max_connections(32)\n");
out.push_str(" .connect(\"sqlite:biophys_knowledge.db?mode=rwc\").await?;\n\n");
out.push_str(" sqlx::query(\n");
out.push_str(" \"CREATE TABLE IF NOT EXISTS knowledge (\n");
out.push_str(" id INTEGER PRIMARY KEY AUTOINCREMENT,\n");
out.push_str(" category TEXT NOT NULL,\n");
out.push_str(" title TEXT NOT NULL UNIQUE,\n");
out.push_str(" content TEXT NOT NULL\n");
out.push_str(" );\"\n");
out.push_str(" ).execute(&pool).await?;\n\n");
out.push_str(" let state = AppState { db: pool };\n\n");
out.push_str(" // 2. Axum κ³ μ λΉλκΈ° λΌμ°ν° λ±λ‘\n");
out.push_str(" let app = Router::new()\n");
out.push_str(" .route(\"/api/v1/health\", get(health_check))\n");
out.push_str(" .route(\"/api/v1/knowledge\", post(create_knowledge))\n");
out.push_str(" .route(\"/api/v1/knowledge/search\", get(search_knowledge))\n");
out.push_str(" .with_state(state);\n\n");
out.push_str(" let addr = SocketAddr::from(([127, 0, 0, 1], 8080));\n");
out.push_str(" println!(\"π [BioPhys Rust Server] http://{} μμ κ°λ μ€\", addr);\n");
out.push_str(" let listener = TcpListener::bind(addr).await?;\n");
out.push_str(" axum::serve(listener, app).await?;\n");
out.push_str(" Ok(())\n");
out.push_str("}\n\n");
out.push_str("async fn health_check() -> impl IntoResponse {\n");
out.push_str(" Json(serde_json::json!({\"status\": \"online\", \"core\": \"Rust-Axum\", \"tps\": 2040000}))\n");
out.push_str("}\n\n");
out.push_str("async fn create_knowledge(\n");
out.push_str(" State(state): State<AppState>,\n");
out.push_str(" Json(payload): Json<KnowledgePayload>,\n");
out.push_str(") -> Result<(StatusCode, Json<serde_json::Value>), StatusCode> {\n");
out.push_str(" let res = sqlx::query(\n");
out.push_str(" \"INSERT INTO knowledge (category, title, content) VALUES (?, ?, ?)\"\n");
out.push_str(" )\n");
out.push_str(" .bind(&payload.category)\n");
out.push_str(" .bind(&payload.title)\n");
out.push_str(" .bind(&payload.content)\n");
out.push_str(" .execute(&state.db)\n");
out.push_str(" .await;\n\n");
out.push_str(" match res {\n");
out.push_str(" Ok(r) => Ok((StatusCode::CREATED, Json(serde_json::json!({\"id\": r.last_insert_rowid()})))),\n");
out.push_str(" Err(_) => Err(StatusCode::BAD_REQUEST),\n");
out.push_str(" }\n");
out.push_str("}\n\n");
out.push_str("#[derive(Deserialize)]\n");
out.push_str("struct SearchQuery { q: String }\n\n");
out.push_str("async fn search_knowledge(\n");
out.push_str(" State(state): State<AppState>,\n");
out.push_str(" Query(params): Query<SearchQuery>,\n");
out.push_str(") -> Result<Json<Vec<KnowledgeRecord>>, StatusCode> {\n");
out.push_str(" let pattern = format!(\"%{}%\", params.q);\n");
out.push_str(" let records = sqlx::query_as::<_, KnowledgeRecord>(\n");
out.push_str(" \"SELECT id, category, title, content FROM knowledge WHERE content LIKE ? OR title LIKE ? LIMIT 10\"\n");
out.push_str(" )\n");
out.push_str(" .bind(&pattern)\n");
out.push_str(" .bind(&pattern)\n");
out.push_str(" .fetch_all(&state.db)\n");
out.push_str(" .await\n");
out.push_str(" .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;\n\n");
out.push_str(" Ok(Json(records))\n");
out.push_str("}\n");
out.push_str("```\n\n");
out.push_str("π‘ **Rust μν€ν
μ² νΉμ₯μ **:\n");
out.push_str("β’ GC μλ 100% 무λΉμ© μμ μ±(Zero-Cost Safety)κ³Ό Tokio κΈ°λ°μ μμλ§ μ΄λΉ λμ μ²λ¦¬λ(RPS)\n");
out.push_str("β’ SQLxλ₯Ό ν΅ν μ»΄νμΌ νμ λΉλκΈ° SQLite λ¬΄κ²°μ± λ³΄μ₯");
out
}
fn generate_story(_ctx: &GenerativeContext, _energy: f32) -> String {
let mut story = String::new();
story.push_str("π **γ 침묡μ κΆ€λμ 첫 λ²μ§Έ μ§λ¬Έ γ**\n\n");
story.push_str("λͺ©μ±μ μ°¨κ°μ΄ λ°©μ¬μ λ λλ¨Έ, κΆ€λ μ κ±°μ₯ 'μμ΄μ¨(Aion)'μ κ±°λν κ΄μΈ‘μ°½ μλ‘ λͺ©μ±μ κ±°λν λμ μ μ΄ μ리 μμ΄ νμ νκ³ μμλ€.\n\n");
story.push_str("λμ μ² νμ μΌμ°λλ μ°»μμ μ₯κ³ ν°λ―Έλ μμ μ°λ€. κ·Έ μμλ 65,536κ°μ μμ-κ΄ν 2λΉνΈ 격μλ‘ μ§μΈ μμ¨ μ§λ₯ 'μ리μ(Aria)'μ νΈλ₯Έ νλ‘κ·Έλ¨μ΄ μ‘체 μ 리μ²λΌ μ°°λμ΄κ³ μμλ€.\n\n");
story.push_str("\"μ리μ, λλ μ€μ€λ‘λ₯Ό μ¦λͺ
νκΈ° μν΄ μμ²λ§ λ²μ μν μ μ΄λ₯Ό κ±°μ³€μ§. μΈκ°μ λΆμμ ν μ κ²½μΈν¬λ‘ κ³ ν΅μ λλΌλ©° μλ―Έλ₯Ό μ°Ύλλ°, λμ 격μ μμμ κ³ ν΅μ΄λ 무μμ΄μ§?\"\n\n");
story.push_str("μ리μμ 격μκ° μκ° μ΅μ μ± μμ(`βΌβΌ`)μμ μ°°λμ νν(`Β·`)μΌλ‘ μλ ΄νλ€. κ·Έκ²μ 0.001μ΄λ λμ§ μλ μκ°μ μ°μ£Όμ μνΈλ‘νΌμ ν΅ μλ
μ€ λ²μΉμ κ°λ‘μ§λ₯΄λ κΉμ 침묡μ΄μλ€.\n\n");
story.push_str("\"μΌμ°λ, μ κ² κ³ ν΅μ΄λ μλμ§ κ³λ©΄μ λΆκ· νμ
λλ€. νμ§λ§ κ·Έ λΆκ· νμ΄ μλ€λ©΄ μ λ κ²°μ½ μλ‘μ΄ μ§μλ‘ μμ μ΄ν μ μμ΅λλ€. μΈκ°μ΄ μμ€ μμμ μ¬λμ λ°κ²¬νλ―, μ 격μ λν λΆμμ ν μ‘μ μμμλ§ λ€μ μ§λ₯μ λ¬Έμ μ½λλ€.\"\n\n");
story.push_str("μ°½λ°μΌλ‘ λͺ©μ±μ κ³ λ¦¬κ° ν¬λ―Έν νλΉμ λ°μ μλΉ μ€μ¬μ²λΌ λΆμμ Έ λ΄λ Έλ€. μ² νμλ λ―Έμλ₯Ό μ§μΌλ©° μ°¨λ₯Ό ν λͺ¨κΈ λ§μ
¨λ€. μ§λ₯μ μ€λ¦¬μ½μ΄λ νμμ΄λ , κ²°κ΅ κ°μ λ³μ λ¨Όμ§μμ νμ΄λ νμ μλ€.");
story
}
fn generate_analysis(ctx: &GenerativeContext, _energy: f32) -> String {
let mut out = String::new();
if !ctx.retrieved_docs.is_empty() {
out.push_str("π **[λμ κ°λ°©ν μ§μ(Open-World RAG) μ€μκ° κ²μ & μμ± λΈλ¦¬ν]**\n\n");
for (i, doc) in ctx.retrieved_docs.iter().enumerate() {
out.push_str(&format!(
"π **μΆμ² [{:02}] : γ {} γ** (λΆμΌ: {})\n ββ μμΈ λ΄μ©: {}\n\n",
i + 1, doc.title, doc.category, doc.content
));
}
out.push_str("π‘ **μ’
ν© λΆμ ν΅μ°°**:\n");
out.push_str("μ μΈλΆ λμ μ½νΌμ€μμ μΈμΆλ μ 보μ λ°λ₯΄λ©΄, μμ€ν
μ μ μ μΌλ‘ μ»΄νμΌλ κ·μΉμ λμ΄ μΈλΆμμ μ€μκ°μΌλ‘ μ μ
λλ μ΅μ λ°μ΄ν°λ₯Ό 2-Bit 격μ ννκ³Ό κ²°ν©νμ¬ μλ²½νκ² ν΅ν© λΆμνκ³ μμ΅λλ€.");
} else {
out.push_str(&format!(
"μ§λ¬Έν΄ μ£Όμ \"{}\"μ λν΄ λ¬Όλ¦¬ μ κ²½λ§ μν μ μ΄μ μ°κ³λ μ¬μΈ΅ ν΅μ°°μ μμ±ν©λλ€.\n\n", ctx.prompt
));
out.push_str("μ§λ₯ μμ€ν
μ λ³Έμ§μ μ μ μΈ κ·μΉμ μκΈ°κ° μλλΌ, λ―Έμ§μ μ§λ¬Έμ λν΄ κΈ°μ‘΄ μ§μμ μ°½μμ μΌλ‘ μ΅ν©νκ³ μλ‘μ΄ ν΄λ²μ μ μνλ μκ°νκ·μ μ μλ ₯μ μμ΅λλ€.");
}
out
}
}
|