Skip to main content

rig_core/providers/deepseek/
extension.rs

1//! DeepSeek's typed reply extras. DeepSeek has no typed request option:
2//! thinking and its effort are generation options.
3//!
4//! ```
5//! use rig_core::completion::CompletionResponse;
6//! use rig_core::providers::deepseek::extension::DeepSeekExt;
7//!
8//! fn cache_hits(reply: &CompletionResponse) -> Option<u64> {
9//!     reply.extras_lossy::<DeepSeekExt>().prompt_cache_hit_tokens
10//! }
11//! # let _ = cache_hits;
12//! ```
13
14use serde::Serialize;
15use serde_json::Value;
16
17use crate::completion::provider_options::reply_field;
18use crate::completion::{ExtensionOptions, ProviderExtension, ReplyExtras};
19use crate::message::Api;
20
21/// DeepSeek's extension marker.
22#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
23pub struct DeepSeekExt;
24
25impl ProviderExtension for DeepSeekExt {
26    const PROVIDER: &'static str = super::PROVIDER_NAME;
27    type Options = DeepSeekOptions;
28    type Extras = DeepSeekExtras;
29}
30
31/// DeepSeek's request options: none beyond the generation options.
32#[non_exhaustive]
33#[derive(Clone, Debug, Default, PartialEq, Serialize)]
34pub struct DeepSeekOptions {}
35
36impl DeepSeekOptions {
37    /// No option set.
38    pub fn new() -> Self {
39        Self::default()
40    }
41}
42
43impl ExtensionOptions for DeepSeekOptions {
44    type Ext = DeepSeekExt;
45}
46
47/// DeepSeek's reply fields. Each is `None` when the reply lacks it.
48#[non_exhaustive]
49#[derive(Clone, Debug, Default, PartialEq)]
50pub struct DeepSeekExtras {
51    /// Prompt tokens read from the context cache.
52    pub prompt_cache_hit_tokens: Option<u64>,
53    /// Prompt tokens not in the context cache.
54    pub prompt_cache_miss_tokens: Option<u64>,
55    /// Completion tokens spent reasoning.
56    pub reasoning_tokens: Option<u64>,
57    /// The backend configuration's fingerprint.
58    pub system_fingerprint: Option<String>,
59}
60
61impl ReplyExtras for DeepSeekExtras {
62    fn from_reply(_api: &Api, raw: &Value) -> Result<Self, serde_json::Error> {
63        Ok(Self {
64            prompt_cache_hit_tokens: reply_field(raw, "/usage/prompt_cache_hit_tokens")?,
65            prompt_cache_miss_tokens: reply_field(raw, "/usage/prompt_cache_miss_tokens")?,
66            reasoning_tokens: reply_field(
67                raw,
68                "/usage/completion_tokens_details/reasoning_tokens",
69            )?,
70            system_fingerprint: reply_field(raw, "/system_fingerprint")?,
71        })
72    }
73}
74
75#[cfg(test)]
76mod tests;