use serde::{Deserialize, Serialize};
use crate::error::Error;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeepSeekConfig {
pub base_url: String,
pub api_key: String,
pub model: String,
pub max_tokens: u32,
pub temperature: f32,
}
pub struct DeepSeekClient {
client: reqwest::Client,
config: DeepSeekConfig,
}
impl DeepSeekClient {
pub fn new(config: DeepSeekConfig) -> Self {
let client = reqwest::Client::new();
Self { client, config }
}
pub async fn chat(&self, messages: Vec<ChatMessage>) -> Result<ChatResponse, Error> {
let request = ChatRequest {
model: self.config.model.clone(),
messages,
max_tokens: Some(self.config.max_tokens),
temperature: Some(self.config.temperature),
stream: Some(false),
tools: None,
};
let response = self.client
.post(&format!("{}/chat/completions", self.config.base_url))
.header("Authorization", format!("Bearer {}", self.config.api_key))
.header("Content-Type", "application/json")
.json(&request)
.send()
.await
.map_err(|e| Error::Other(e.to_string()))?;
if !response.status().is_success() {
let error_text = response.text().await.unwrap_or_default();
return Err(Error::Other(format!("API请求失败: {}", error_text)));
}
let chat_response: ChatResponse = response
.json()
.await
.map_err(|e| Error::Other(e.to_string()))?;
Ok(chat_response)
}
pub async fn chat_with_tools(&self, messages: Vec<ChatMessage>, tools: Vec<serde_json::Value>) -> Result<ChatResponse, Error> {
let request = ChatRequest {
model: self.config.model.clone(),
messages,
max_tokens: Some(self.config.max_tokens),
temperature: Some(self.config.temperature),
stream: Some(false),
tools: Some(tools),
};
let response = self.client
.post(&format!("{}/chat/completions", self.config.base_url))
.header("Authorization", format!("Bearer {}", self.config.api_key))
.header("Content-Type", "application/json")
.json(&request)
.send()
.await
.map_err(|e| Error::Other(e.to_string()))?;
if !response.status().is_success() {
let error_text = response.text().await.unwrap_or_default();
return Err(Error::Other(format!("API请求失败: {}", error_text)));
}
let chat_response: ChatResponse = response
.json()
.await
.map_err(|e| Error::Other(e.to_string()))?;
Ok(chat_response)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatMessage {
pub role: String,
pub content: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_calls: Option<Vec<ToolCallMessage>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tool_call_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCallMessage {
pub id: Option<String>,
#[serde(rename = "type")]
pub call_type: String,
pub function: FunctionCall,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FunctionCall {
pub name: String,
pub arguments: String,
}
#[derive(Debug, Serialize)]
struct ChatRequest {
model: String,
messages: Vec<ChatMessage>,
max_tokens: Option<u32>,
temperature: Option<f32>,
stream: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
tools: Option<Vec<serde_json::Value>>,
}
#[derive(Debug, Deserialize)]
pub struct ChatResponse {
pub choices: Vec<Choice>,
pub usage: Option<Usage>,
}
#[derive(Debug, Deserialize)]
pub struct Choice {
pub message: ChatMessage,
pub finish_reason: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct Usage {
pub prompt_tokens: u32,
pub completion_tokens: u32,
pub total_tokens: u32,
}