//! Ultrafast 推理框架:不换模型、不切 provider,只靠"减少浪费"把延迟压下来。 //! //! # 三条加速法则 //! //! 1. **关思考**(think-off):推理模型的 thinking 链会显著拉高首 token 延迟。 //! 加速模式在**下发时**把思考档强制为 off——只影响本次请求,不改用户持久化档位。 //! 2. **连接池复用**:HTTP 客户端做成进程级单例,省掉每条请求的 TCP + TLS 握手。 //! 3. **回复预算**:未指定时用一个较小的 `max_tokens`(如 2048),避免模型啰嗦。 //! //! # 红线 //! //! - **锁模型**:加速开关绝不允许更换模型(速度不能靠"偷偷换成更快的模型")。 //! - **只改下发值**:关掉开关立刻回到用户原来的思考档位。 //! - **不改协议**:只复用连接,不改请求协议(避免触发风控)。 use crate::types::{ChatRequest, ThinkLevel}; /// Ultrafast 配置。 #[derive(Debug, Clone)] pub struct UltrafastConfig { /// 是否强制关思考(下发值,不改用户存档)。 pub force_think_off: bool, /// 未显式指定时的回复上限(`None` = 不限制)。 pub default_max_tokens: Option, /// 是否插入"简洁作答"系统提示(让模型少写铺垫)。 pub concise_prompt: bool, /// 简洁提示的文案(可自定义/本地化)。 pub concise_prompt_text: String, } impl Default for UltrafastConfig { fn default() -> Self { Self { force_think_off: true, default_max_tokens: Some(2048), concise_prompt: true, concise_prompt_text: "请简洁作答,直接给结论,减少铺垫。".to_string(), } } } /// 应用 Ultrafast 规则到一次请求上(**原地修改,不碰 model**)。 /// /// 返回值是实际生效的规则说明(便于前端展示/审计): /// 例如 `["think-off", "budget=2048", "concise"]`。 pub fn apply_ultrafast(request: &mut ChatRequest, config: &UltrafastConfig) -> Vec { let mut applied = Vec::new(); // 法则 1:关思考(只改本次下发值) if config.force_think_off { request.think = Some(ThinkLevel::Off); applied.push("think-off".to_string()); } // 法则 3:回复预算(只在调用方没显式指定时兜底) if let (None, Some(budget)) = (request.max_tokens, config.default_max_tokens) { request.max_tokens = Some(budget); applied.push(format!("budget={budget}")); } // 简洁提示(插到消息最前面,仅当没有 system 消息时) if config.concise_prompt && !config.concise_prompt_text.trim().is_empty() && !request .messages .iter() .any(|m| m.role == crate::types::MessageRole::System) { request.messages.insert( 0, crate::types::ChatMessage { role: crate::types::MessageRole::System, content: config.concise_prompt_text.clone(), }, ); applied.push("concise".to_string()); } // 红线:模型锁——这里**故意什么都不做**。 // `request.model` 永远保持调用方设置的值,加速开关无权改它。 applied } #[cfg(test)] mod tests { use super::*; use crate::types::{ChatMessage, MessageRole}; fn req() -> ChatRequest { ChatRequest { model: "cloud-big".to_string(), messages: vec![ChatMessage { role: MessageRole::User, content: "hi".to_string(), }], think: Some(ThinkLevel::High), max_tokens: None, tools: None, } } #[test] fn forces_think_off_without_touching_model() { let mut request = req(); apply_ultrafast(&mut request, &UltrafastConfig::default()); assert_eq!(request.think, Some(ThinkLevel::Off)); // 红线:模型锁 assert_eq!(request.model, "cloud-big"); } #[test] fn respects_explicit_max_tokens() { let mut request = req(); request.max_tokens = Some(8192); apply_ultrafast(&mut request, &UltrafastConfig::default()); assert_eq!(request.max_tokens, Some(8192), "用户显式设定的上限不能被覆盖"); } #[test] fn inserts_concise_prompt_once() { let mut request = req(); apply_ultrafast(&mut request, &UltrafastConfig::default()); let systems = request .messages .iter() .filter(|m| m.role == MessageRole::System) .count(); assert_eq!(systems, 1); // 再跑一次不会重复插入 apply_ultrafast(&mut request, &UltrafastConfig::default()); let systems = request .messages .iter() .filter(|m| m.role == MessageRole::System) .count(); assert_eq!(systems, 1); } }