1use crate::ids::ModelId;
4use crate::message::{Content, Message};
5use crate::MetadataMap;
6use serde::{Deserialize, Serialize};
7use serde_json::Value;
8
9#[derive(Debug, Clone, Serialize, Deserialize)]
10#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
11pub struct CompletionRequest {
12 pub messages: Vec<Message>,
13 #[serde(default, skip_serializing_if = "Vec::is_empty")]
14 pub tools: Vec<ToolSpec>,
15 #[serde(default, skip_serializing_if = "Option::is_none")]
16 pub system: Option<String>,
17 #[serde(default, skip_serializing_if = "Option::is_none")]
18 pub max_tokens: Option<u32>,
19 #[serde(default, skip_serializing_if = "Option::is_none")]
20 pub temperature: Option<f32>,
21 #[serde(default, skip_serializing_if = "Vec::is_empty")]
22 pub stop_sequences: Vec<String>,
23 #[serde(default, skip_serializing_if = "CacheHints::is_empty")]
24 pub cache_hints: CacheHints,
25 #[serde(default, skip_serializing_if = "MetadataMap::is_empty")]
27 pub extensions: MetadataMap,
28}
29
30impl CompletionRequest {
31 pub fn new(messages: Vec<Message>) -> Self {
32 Self {
33 messages,
34 tools: Vec::new(),
35 system: None,
36 max_tokens: None,
37 temperature: None,
38 stop_sequences: Vec::new(),
39 cache_hints: CacheHints::default(),
40 extensions: MetadataMap::new(),
41 }
42 }
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
46#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
47pub struct CompletionResponse {
48 pub id: String,
49 pub model: ModelId,
50 pub content: Vec<Content>,
51 pub stop_reason: StopReason,
52 pub usage: Usage,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
58#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
59#[serde(tag = "kind", content = "value", rename_all = "snake_case")]
60pub enum StopReason {
61 EndTurn,
62 MaxTokens,
63 StopSequence(String),
64 ToolUse,
65 Refusal,
66 Error(String),
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
71pub struct ToolSpec {
72 pub name: String,
73 pub description: String,
74 pub input_schema: Value,
76}
77
78#[derive(Debug, Clone, Default, Serialize, Deserialize)]
79#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
80pub struct CacheHints {
81 #[serde(default, skip_serializing_if = "Vec::is_empty")]
82 pub breakpoints: Vec<CacheBreakpoint>,
83}
84
85impl CacheHints {
86 pub fn is_empty(&self) -> bool {
87 self.breakpoints.is_empty()
88 }
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize)]
92#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
93pub struct CacheBreakpoint {
94 pub message_index: usize,
97 #[serde(default, skip_serializing_if = "Option::is_none")]
98 pub ttl: Option<CacheTtl>,
99}
100
101#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
102#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
103#[serde(rename_all = "snake_case")]
104pub enum CacheTtl {
105 Short,
106 Long,
107}
108
109#[derive(Debug, Clone, Default, Serialize, Deserialize)]
112#[cfg_attr(feature = "schemars-export", derive(schemars::JsonSchema))]
113pub struct Usage {
114 pub tokens_input: u64,
115 pub tokens_output: u64,
116 #[serde(default)]
117 pub tokens_cache_read: u64,
118 #[serde(default)]
119 pub tokens_cache_create: u64,
120}
121
122impl Usage {
123 pub fn add(&mut self, other: &Usage) {
124 self.tokens_input += other.tokens_input;
125 self.tokens_output += other.tokens_output;
126 self.tokens_cache_read += other.tokens_cache_read;
127 self.tokens_cache_create += other.tokens_cache_create;
128 }
129}