refactor(types): request.rs 类型移入 provider/openai.rs
- 删除 types/request.rs(187 行) - 所有 OpenAI wire-format 类型迁入 provider/openai.rs,可见性 pub(crate): StreamOptions / OpenaiTool / AudioParam / PredictionContent / UserLocation / Approximate / WebSearchOptions / OpenaiChatRequest - types/mod.rs 删除 pub mod request; 与对应 re-export - convert_request 同步降级为 pub(crate) 以匹配 OpenaiChatRequest 可见性 - 公共 re-export 路径 agcore::llm::types::OpenaiChatRequest 等已删除(Breaking Change,见 CHANGELOG)
This commit is contained in:
+120
-4
@@ -26,14 +26,127 @@ use crate::llm::convert::{from_openai, to_openai};
|
||||
use crate::llm::error::LlmError;
|
||||
use crate::llm::types::message::{ContentBlock, ContentBlockType, Message};
|
||||
use crate::llm::types::openai_message::{ContentField, OpenaiChatMessage};
|
||||
use crate::llm::types::request::{OpenaiChatRequest, OpenaiTool, StreamOptions};
|
||||
use crate::llm::types::request_v2::MessageRequest;
|
||||
use crate::llm::types::response::{OpenaiChatChunk, OpenaiChatResponse};
|
||||
use crate::llm::types::response_v2::{
|
||||
MessageResponse, PartialMessageResponse, PartialUsage, StopReason, StreamEvent,
|
||||
};
|
||||
use crate::llm::types::shared::FinishReason;
|
||||
use crate::llm::types::tool::OpenaiToolCall;
|
||||
use crate::llm::types::shared::{FinishReason, ResponseFormat, ServiceTier, StopSequence};
|
||||
use crate::llm::types::tool::{OpenaiToolCall, OpenaiToolDefinition, ToolChoice};
|
||||
use serde::Deserialize;
|
||||
|
||||
// =============================================================================
|
||||
// 0. OpenAI wire-format 类型(Phase 13 从 types::request 迁入)
|
||||
// =============================================================================
|
||||
|
||||
/// 流式响应选项。
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct StreamOptions {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub include_usage: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub include_obfuscation: Option<bool>,
|
||||
}
|
||||
|
||||
/// OpenAI wire-format 工具定义。
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case", tag = "type")]
|
||||
pub(crate) enum OpenaiTool {
|
||||
Function { function: OpenaiToolDefinition },
|
||||
}
|
||||
|
||||
/// 音频输出参数。
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct AudioParam {
|
||||
pub format: String,
|
||||
pub voice: String,
|
||||
}
|
||||
|
||||
/// 预测内容(OpenAI `prediction` 字段)。
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct PredictionContent {
|
||||
#[serde(rename = "type")]
|
||||
pub pred_type: String,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
/// 用户位置(web search 用)。
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct UserLocation {
|
||||
#[serde(rename = "type")]
|
||||
pub loc_type: String,
|
||||
pub approximate: Approximate,
|
||||
}
|
||||
|
||||
/// 近似位置。
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct Approximate {
|
||||
pub city: String,
|
||||
pub country: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub region: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timezone: Option<String>,
|
||||
}
|
||||
|
||||
/// Web search 选项。
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct WebSearchOptions {
|
||||
pub search_context_size: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user_location: Option<UserLocation>,
|
||||
}
|
||||
|
||||
/// OpenAI Chat Completions 请求体。
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub(crate) struct OpenaiChatRequest {
|
||||
pub model: String,
|
||||
pub messages: Vec<OpenaiChatMessage>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub frequency_penalty: Option<f32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub logit_bias: Option<Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub max_tokens: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub n: Option<u32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub presence_penalty: Option<f32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub response_format: Option<ResponseFormat>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub seed: Option<i64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub service_tier: Option<ServiceTier>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub stop: Option<StopSequence>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub stream: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub stream_options: Option<StreamOptions>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub temperature: Option<f32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub top_p: Option<f32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tools: Option<Vec<OpenaiTool>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_choice: Option<ToolChoice>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub parallel_tool_calls: Option<bool>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub user: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub extra_headers: Option<Value>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub extra_body: Option<Value>,
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// 1. GenericOpenaiProvider —— OpenAI-compatible 协议共用实现
|
||||
@@ -210,7 +323,10 @@ impl GenericOpenaiProvider {
|
||||
///
|
||||
/// 实现注意:先在函数顶部抽取出所有 needed 字段(clone 或 move),避免后续
|
||||
/// 部分移动 `request` 后无法借用其它字段。
|
||||
pub fn convert_request(&self, request: MessageRequest) -> Result<OpenaiChatRequest, LlmError> {
|
||||
pub(crate) fn convert_request(
|
||||
&self,
|
||||
request: MessageRequest,
|
||||
) -> Result<OpenaiChatRequest, LlmError> {
|
||||
// ponytail: 先抽取 / clone 所有 owned 字段,再访问 request.extra,
|
||||
// 避免部分移动导致后续 `&self` borrow 失败。
|
||||
let model = request.model.clone();
|
||||
|
||||
Reference in New Issue
Block a user