Skip to main content

ds_api/api/
request.rs

1//! ApiRequest builder module.
2//!
3//! Provides a safe, chainable request builder that wraps the internal
4//! `crate::raw::ChatCompletionRequest`. The builder intentionally avoids
5//! exposing raw configuration enums (like `Model`) to downstream callers.
6//! Use the convenience constructors `deepseek_chat(...)` and
7//! `deepseek_reasoner(...)` to pick a model.
8
9use crate::raw::{ChatCompletionRequest, Message, ResponseFormat, ResponseFormatType, Tool};
10
11/// A safe, chainable request builder that wraps `ChatCompletionRequest`.
12///
13/// It intentionally avoids exposing raw configuration enums (like `Model`) to
14/// callers. Use the provided helpers to pick models.
15#[derive(Debug)]
16pub struct ApiRequest {
17    raw: ChatCompletionRequest,
18}
19
20impl ApiRequest {
21    /// Start a new builder with default values.
22    pub fn builder() -> Self {
23        Self {
24            raw: ChatCompletionRequest::default(),
25        }
26    }
27
28    /// Convenience constructor: deepseek-chat + messages
29    pub fn deepseek_chat(messages: Vec<Message>) -> Self {
30        let mut r = Self::builder();
31        r.raw.messages = messages;
32        r.raw.model = crate::raw::Model::DeepseekChat;
33        r
34    }
35
36    /// Convenience constructor: deepseek-reasoner + messages
37    pub fn deepseek_reasoner(messages: Vec<Message>) -> Self {
38        let mut r = Self::builder();
39        r.raw.messages = messages;
40        r.raw.model = crate::raw::Model::DeepseekReasoner;
41        r
42    }
43
44    /// Add a message to the request.
45    pub fn add_message(mut self, msg: Message) -> Self {
46        self.raw.messages.push(msg);
47        self
48    }
49
50    /// Replace messages.
51    pub fn messages(mut self, msgs: Vec<Message>) -> Self {
52        self.raw.messages = msgs;
53        self
54    }
55
56    /// Request response as JSON object.
57    pub fn json(mut self) -> Self {
58        self.raw.response_format = Some(ResponseFormat {
59            r#type: ResponseFormatType::JsonObject,
60        });
61        self
62    }
63
64    /// Request response as plain text.
65    pub fn text(mut self) -> Self {
66        self.raw.response_format = Some(ResponseFormat {
67            r#type: ResponseFormatType::Text,
68        });
69        self
70    }
71
72    /// Set temperature.
73    pub fn temperature(mut self, t: f32) -> Self {
74        self.raw.temperature = Some(t);
75        self
76    }
77
78    /// Set max tokens.
79    pub fn max_tokens(mut self, n: u32) -> Self {
80        self.raw.max_tokens = Some(n);
81        self
82    }
83
84    /// Add a raw tool definition (from `crate::raw::Tool`).
85    pub fn add_tool(mut self, tool: Tool) -> Self {
86        if let Some(ref mut v) = self.raw.tools {
87            v.push(tool);
88        } else {
89            self.raw.tools = Some(vec![tool]);
90        }
91        self
92    }
93
94    /// Set tool choice to Auto.
95    pub fn tool_choice_auto(mut self) -> Self {
96        use crate::raw::request::tool_choice::{ToolChoice, ToolChoiceType};
97        self.raw.tool_choice = Some(ToolChoice::String(ToolChoiceType::Auto));
98        self
99    }
100
101    /// Enable/disable streaming (stream: true).
102    pub fn stream(mut self, enabled: bool) -> Self {
103        self.raw.stream = Some(enabled);
104        self
105    }
106
107    /// Build and return the internal raw request (crate-internal use).
108    pub(crate) fn into_raw(self) -> ChatCompletionRequest {
109        self.raw
110    }
111}