File size: 2,565 Bytes
c55968e | 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 | //! 核心类型:Provider 抽象 / 流式 chunk / 对话请求。
//!
//! 这一层刻意做到最小——你可以把任何 LLM 后端(Ollama / OpenAI 兼容接口 /
//! 自建推理服务)适配成 `Provider`,混合流与 Ultrafast 规则就能直接复用。
use std::future::Future;
use std::pin::Pin;
use futures::Stream;
use tokio_util::sync::CancellationToken;
/// 一个可取消的流式响应流。
pub type ProviderStream = Pin<Box<dyn Stream<Item = StreamChunk> + Send>>;
/// 装箱 future(避免 async-trait 依赖)。
pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send>>;
/// 流式响应分片。
#[derive(Debug, Clone)]
pub enum StreamChunk {
/// 正文增量。
Delta { text: String },
/// 思考过程增量(推理模型)。
Reasoning { text: String },
/// 接棒信号:混合流从"本机草稿"切到"云端正式"时下发,
/// 前端应清空已显示的草稿内容再继续渲染后续 delta。
Replaced { message: String },
/// 正常结束(带用量统计)。
Done {
prompt_tokens: Option<u64>,
completion_tokens: Option<u64>,
eval_ms: Option<u64>,
cached_tokens: Option<u64>,
},
/// 出错。
Error { message: String },
/// 被截断(达到 max_tokens 上限等)。
Truncated { message: String },
}
/// 思考强度档位。
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ThinkLevel {
Off,
Low,
Medium,
High,
Frenzy,
}
impl Default for ThinkLevel {
fn default() -> Self {
ThinkLevel::Medium
}
}
/// 一条对话消息。
#[derive(Debug, Clone)]
pub struct ChatMessage {
pub role: MessageRole,
pub content: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MessageRole {
System,
User,
Assistant,
}
/// 一次对话请求。`model` 是"模型锁"的落点:加速开关**不允许**改它。
#[derive(Debug, Clone, Default)]
pub struct ChatRequest {
pub model: String,
pub messages: Vec<ChatMessage>,
pub think: Option<ThinkLevel>,
pub max_tokens: Option<u32>,
/// 工具定义等由调用方自行透传;框架不解释其语义。
pub tools: Option<serde_json::Value>,
}
/// 任何能流式输出 LLM 回复的后端。
pub trait Provider: Send + Sync {
/// 发起一次流式请求。`cancel` 被触发时应尽快结束流并返回。
fn chat_stream(
&self,
request: ChatRequest,
cancel: CancellationToken,
) -> BoxFuture<Result<ProviderStream, String>>;
}
|