perch-ultrafast / src /ultrafast.rs
hongcoding's picture
feat: 开源混合流 + Ultrafast 推理框架(v5.2.1 提取版)
c55968e verified
Raw History Blame Contribute Delete
4.97 kB
//! 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<u32>,
/// 是否插入"简洁作答"系统提示(让模型少写铺垫)。
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<String> {
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);
}
}