feat(llm): 重构 types.rs 为完整的 OpenAI 兼容类型系统
将 `types.rs` 拆分为模块化目录,所有类型派生 `Serialize/Deserialize`, 并新增 `OpenaiChatChunk`、`Role` 扩展等 30+ 缺失类型 消除对 `cycle/usage.rs` 的反向依赖,`Usage`/`CostTracker` 移至 `types/usage.rs`
This commit is contained in:
+32
-44
@@ -7,19 +7,15 @@ pub use usage::{CostTracker, Usage};
|
||||
use crate::llm::cycle::retry::should_retry;
|
||||
use crate::llm::error::LlmError;
|
||||
use crate::llm::provider::LlmProvider;
|
||||
use crate::llm::types::{ChatRequest, ChatResponse, ContentBlock, Message, Role, ToolDefinition};
|
||||
use crate::llm::types::{
|
||||
ChatRequest, ChatResponse, OpenaiChatMessage, OpenaiTool, ToolChoice, ToolDefinition,
|
||||
};
|
||||
|
||||
/// LLM 生命周期引擎的配置。
|
||||
pub struct CycleConfig {
|
||||
/// 使用的模型名称。
|
||||
pub model: String,
|
||||
/// 最大输出 token 数。
|
||||
pub max_tokens: Option<u32>,
|
||||
/// 采样温度。
|
||||
pub temperature: Option<f32>,
|
||||
/// 最大对话轮数(预留,暂未使用)。
|
||||
pub max_turns: Option<u32>,
|
||||
/// 重试策略配置。
|
||||
pub retry: RetryConfig,
|
||||
}
|
||||
|
||||
@@ -35,22 +31,15 @@ impl Default for CycleConfig {
|
||||
}
|
||||
}
|
||||
|
||||
/// LLM 调用生命周期引擎。
|
||||
///
|
||||
/// 管理一次多轮交互的完整生命周期,包括:
|
||||
/// - 消息历史维护
|
||||
/// - Token 用量追踪
|
||||
/// - 自动重试
|
||||
pub struct LlmCycle {
|
||||
provider: Box<dyn LlmProvider>,
|
||||
config: CycleConfig,
|
||||
usage: CostTracker,
|
||||
messages: Vec<Message>,
|
||||
messages: Vec<OpenaiChatMessage>,
|
||||
system_prompt: Option<String>,
|
||||
}
|
||||
|
||||
impl LlmCycle {
|
||||
/// 创建新的生命周期引擎。
|
||||
pub fn new(provider: Box<dyn LlmProvider>, config: CycleConfig) -> Self {
|
||||
Self {
|
||||
provider,
|
||||
@@ -61,50 +50,33 @@ impl LlmCycle {
|
||||
}
|
||||
}
|
||||
|
||||
/// 设置系统提示词(Builder 模式)。
|
||||
pub fn with_system_prompt(mut self, prompt: String) -> Self {
|
||||
self.system_prompt = Some(prompt);
|
||||
self
|
||||
}
|
||||
|
||||
/// 获取 Token 用量追踪器引用。
|
||||
pub fn usage(&self) -> &CostTracker {
|
||||
&self.usage
|
||||
}
|
||||
|
||||
/// 获取当前消息历史。
|
||||
pub fn messages(&self) -> &[Message] {
|
||||
pub fn messages(&self) -> &[OpenaiChatMessage] {
|
||||
&self.messages
|
||||
}
|
||||
|
||||
/// 清空消息历史。
|
||||
pub fn clear_messages(&mut self) {
|
||||
self.messages.clear();
|
||||
}
|
||||
|
||||
/// 重置 Token 用量统计。
|
||||
pub fn reset_usage(&mut self) {
|
||||
self.usage.reset();
|
||||
}
|
||||
|
||||
/// 提交一条用户消息并获取模型响应。
|
||||
///
|
||||
/// 流程:
|
||||
/// 1. 将用户消息追加到消息历史
|
||||
/// 2. 构建 ChatRequest
|
||||
/// 3. 使用重试循环调用 provider.chat()
|
||||
/// 4. 将助手回复追加到消息历史
|
||||
/// 5. 累计 token 用量
|
||||
/// 6. 返回 ChatResponse
|
||||
pub async fn submit(
|
||||
&mut self,
|
||||
prompt: String,
|
||||
tools: Vec<ToolDefinition>,
|
||||
) -> Result<ChatResponse, LlmError> {
|
||||
self.messages.push(Message {
|
||||
role: Role::User,
|
||||
content: vec![ContentBlock::Text { text: prompt }],
|
||||
});
|
||||
self.messages.push(OpenaiChatMessage::user_text(prompt));
|
||||
|
||||
let mut attempts = 0;
|
||||
|
||||
@@ -113,10 +85,7 @@ impl LlmCycle {
|
||||
|
||||
match self.provider.chat(request).await {
|
||||
Ok(response) => {
|
||||
self.messages.push(Message {
|
||||
role: Role::Assistant,
|
||||
content: response.message.content.clone(),
|
||||
});
|
||||
self.messages.push(response.message.clone());
|
||||
|
||||
self.usage.add(&response.usage);
|
||||
|
||||
@@ -134,16 +103,35 @@ impl LlmCycle {
|
||||
}
|
||||
}
|
||||
|
||||
/// 根据当前状态构建 ChatRequest。
|
||||
fn build_request(&self, tools: &[ToolDefinition]) -> ChatRequest {
|
||||
let mut messages = self.messages.clone();
|
||||
|
||||
if let Some(sys_prompt) = &self.system_prompt
|
||||
&& !messages.iter().any(|m| matches!(m, OpenaiChatMessage::System { .. }))
|
||||
{
|
||||
messages.insert(0, OpenaiChatMessage::system_text(sys_prompt));
|
||||
}
|
||||
|
||||
let openai_tools: Option<Vec<OpenaiTool>> = if tools.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(
|
||||
tools.iter()
|
||||
.map(|t| OpenaiTool::Function {
|
||||
function: t.clone(),
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
};
|
||||
|
||||
ChatRequest {
|
||||
model: self.config.model.clone(),
|
||||
messages: self.messages.clone(),
|
||||
system_prompt: self.system_prompt.clone(),
|
||||
tools: tools.to_vec(),
|
||||
messages,
|
||||
max_tokens: self.config.max_tokens,
|
||||
temperature: self.config.temperature,
|
||||
extra_body: None,
|
||||
tools: openai_tools,
|
||||
tool_choice: Some(ToolChoice::Auto),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user