Skip to main content

rig_core/providers/
deepseek.rs

1//! DeepSeek model identifiers and typed response fields, including cache usage
2//! and reasoning content. [`from_env`] and [`new`] build a client on the [`DEEPSEEK`](crate::providers::openai::wire::DEEPSEEK) dialect.
3//!
4//! ```no_run
5//! use rig_core::providers::deepseek;
6//!
7//! # fn run() -> Result<(), Box<dyn std::error::Error>> {
8//! let deepseek_chat = deepseek::from_env()?.chat(deepseek::DEEPSEEK_V4_FLASH);
9//! # let _ = deepseek_chat;
10//! # Ok(())
11//! # }
12//! ```
13
14use serde::{Deserialize, Serialize};
15
16use crate::json_utils;
17
18pub const DEEPSEEK_V4_FLASH: &str = "deepseek-v4-flash";
19pub const DEEPSEEK_V4_PRO: &str = "deepseek-v4-pro";
20
21/// The response shape from the DeepSeek API
22#[derive(Clone, Debug, Serialize, Deserialize)]
23pub struct CompletionResponse {
24    #[serde(default)]
25    pub id: Option<String>,
26    #[serde(default)]
27    pub model: Option<String>,
28    #[serde(default)]
29    pub object: Option<String>,
30    #[serde(default)]
31    pub system_fingerprint: Option<String>,
32    /// Response choices. Decoding drops incomplete tool calls from truncated
33    /// choices while retaining the remaining content and metadata.
34    #[serde(
35        deserialize_with = "crate::providers::internal::openai_chat_completions_compatible::deserialize_choices_dropping_incomplete_tool_calls"
36    )]
37    pub choices: Vec<Choice>,
38    pub usage: Usage,
39}
40
41#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default)]
42#[serde(default)]
43pub struct Usage {
44    pub completion_tokens: u32,
45    pub prompt_tokens: u32,
46    pub prompt_cache_hit_tokens: u32,
47    pub prompt_cache_miss_tokens: u32,
48    pub total_tokens: u32,
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub completion_tokens_details: Option<CompletionTokensDetails>,
51    #[serde(skip_serializing_if = "Option::is_none")]
52    pub prompt_tokens_details: Option<PromptTokensDetails>,
53}
54
55#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default)]
56pub struct CompletionTokensDetails {
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub reasoning_tokens: Option<u32>,
59}
60
61#[derive(Clone, Copy, Debug, Serialize, Deserialize, Default)]
62pub struct PromptTokensDetails {
63    #[serde(skip_serializing_if = "Option::is_none")]
64    pub cached_tokens: Option<u32>,
65}
66
67#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
68pub struct Choice {
69    pub index: usize,
70    pub message: Message,
71    pub logprobs: Option<serde_json::Value>,
72    pub finish_reason: String,
73}
74
75/// DeepSeek's provider-native message shape, as it appears in responses.
76#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
77#[serde(tag = "role", rename_all = "lowercase")]
78pub enum Message {
79    Assistant {
80        content: String,
81        #[serde(skip_serializing_if = "Option::is_none")]
82        name: Option<String>,
83        #[serde(
84            default,
85            deserialize_with = "json_utils::null_or_default",
86            skip_serializing_if = "Vec::is_empty"
87        )]
88        tool_calls: Vec<ToolCall>,
89        /// Provider-reported reasoning text, when present.
90        #[serde(skip_serializing_if = "Option::is_none")]
91        reasoning_content: Option<String>,
92    },
93}
94
95#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
96pub struct ToolCall {
97    pub id: String,
98    pub index: usize,
99    #[serde(default)]
100    pub r#type: ToolType,
101    pub function: Function,
102}
103
104#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
105pub struct Function {
106    pub name: String,
107    #[serde(with = "json_utils::stringified_json")]
108    pub arguments: serde_json::Value,
109}
110
111#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone)]
112#[serde(rename_all = "lowercase")]
113pub enum ToolType {
114    #[default]
115    Function,
116}
117
118crate::client::macros::openai_vendor!(crate::providers::openai::wire::DEEPSEEK, "DeepSeek");