///|
/// Service tier types for chat completion requests
pub enum ChatCompletionServiceTier {
Auto
Default
Flex
Scale
Priority
}
///|
impl ToJson for ChatCompletionServiceTier with to_json(
self : ChatCompletionServiceTier,
) -> Json {
match self {
Auto => Json::string("auto")
Default => Json::string("default")
Flex => Json::string("flex")
Scale => Json::string("scale")
Priority => Json::string("priority")
}
}
///|
impl @json.FromJson for ChatCompletionServiceTier with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionServiceTier {
guard json is String(tier) else {
raise @json.JsonDecodeError((json_path, "Expected a string"))
}
match tier {
"auto" => ChatCompletionServiceTier::Auto
"default" => ChatCompletionServiceTier::Default
"flex" => ChatCompletionServiceTier::Flex
"scale" => ChatCompletionServiceTier::Scale
"priority" => ChatCompletionServiceTier::Priority
_ =>
raise @json.JsonDecodeError((json_path, "Unknown service tier: \{tier}"))
}
}
///|
/// Alias for chunk service tier
typealias ChatCompletionServiceTier as ChatCompletionChunkServiceTier
///|
/// Logprobs information for chat completion choices
pub struct ChatCompletionChoiceLogprobs {
content : Array[ChatCompletionTokenLogprob]?
refusal : Array[ChatCompletionTokenLogprob]?
}
///|
impl @json.FromJson for ChatCompletionChoiceLogprobs with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChoiceLogprobs {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
let content = match json.get("content") {
Some(Null) => None
Some(content) => {
let content : Array[ChatCompletionTokenLogprob] = @json.from_json(
content,
path=json_path.add_key("content"),
)
Some(content)
}
None => None
}
let refusal = match json.get("refusal") {
Some(Null) => None
Some(refusal) => {
let refusal : Array[ChatCompletionTokenLogprob] = @json.from_json(
refusal,
path=json_path.add_key("refusal"),
)
Some(refusal)
}
None => None
}
ChatCompletionChoiceLogprobs::{ content, refusal }
}
///|
/// Token logprob information
pub struct ChatCompletionTokenLogprob {
token : String
logprob : Double
bytes : Array[Int]?
top_logprobs : Array[ChatCompletionTopLogprob]
}
///|
impl @json.FromJson for ChatCompletionTokenLogprob with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionTokenLogprob {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("token") is Some(String(token)) else {
raise @json.JsonDecodeError((json_path, "Missing 'token' field"))
}
guard json.get("logprob") is Some(Number(logprob, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'logprob' field"))
}
let bytes = match json.get("bytes") {
Some(Null) => None
Some(bytes) => {
let bytes : Array[Int] = @json.from_json(
bytes,
path=json_path.add_key("bytes"),
)
Some(bytes)
}
None => None
}
guard json.get("top_logprobs") is Some(top_logprobs) else {
raise @json.JsonDecodeError((json_path, "Missing 'top_logprobs' field"))
}
let top_logprobs : Array[ChatCompletionTopLogprob] = @json.from_json(
top_logprobs,
path=json_path.add_key("top_logprobs"),
)
ChatCompletionTokenLogprob::{ token, logprob, bytes, top_logprobs }
}
///|
/// Top logprob information
pub struct ChatCompletionTopLogprob {
token : String
logprob : Double
bytes : Array[Int]?
}
///|
impl @json.FromJson for ChatCompletionTopLogprob with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionTopLogprob {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("token") is Some(String(token)) else {
raise @json.JsonDecodeError((json_path, "Missing 'token' field"))
}
guard json.get("logprob") is Some(Number(logprob, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'logprob' field"))
}
let bytes = match json.get("bytes") {
Some(Null) => None
Some(bytes) => {
let bytes : Array[Int] = @json.from_json(
bytes,
path=json_path.add_key("bytes"),
)
Some(bytes)
}
None => None
}
ChatCompletionTopLogprob::{ token, logprob, bytes }
}
///|
/// Audio information for chat completions
pub struct ChatCompletionAudio {
id : String?
}
///|
impl @json.FromJson for ChatCompletionAudio with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionAudio {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
let id = match json.get("id") {
Some(Null) => None
Some(String(id)) => Some(id)
Some(_) =>
raise @json.JsonDecodeError((json_path, "Expected 'id' to be a string"))
None => None
}
ChatCompletionAudio::{ id, }
}
///|
impl ToJson for ChatCompletionAudio with to_json(self : ChatCompletionAudio) -> Json {
let json : Map[String, Json] = {}
if self.id is Some(id) {
json["id"] = Json::string(id)
}
Json::object(json)
}
///|
/// Message annotation for web search results
pub struct ChatCompletionMessageAnnotation {
type_ : String
text : String
file_citation : ChatCompletionMessageAnnotationFileCitation?
file_path : ChatCompletionMessageAnnotationFilePath?
start_index : Int
end_index : Int
}
///|
impl @json.FromJson for ChatCompletionMessageAnnotation with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionMessageAnnotation {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("type") is Some(String(type_)) else {
raise @json.JsonDecodeError((json_path, "Missing 'type' field"))
}
guard json.get("text") is Some(String(text)) else {
raise @json.JsonDecodeError((json_path, "Missing 'text' field"))
}
let file_citation = match json.get("file_citation") {
Some(Null) => None
Some(file_citation) => {
let file_citation : ChatCompletionMessageAnnotationFileCitation = @json.from_json(
file_citation,
path=json_path.add_key("file_citation"),
)
Some(file_citation)
}
None => None
}
let file_path = match json.get("file_path") {
Some(Null) => None
Some(file_path) => {
let file_path : ChatCompletionMessageAnnotationFilePath = @json.from_json(
file_path,
path=json_path.add_key("file_path"),
)
Some(file_path)
}
None => None
}
guard json.get("start_index") is Some(Number(start_index, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'start_index' field"))
}
guard json.get("end_index") is Some(Number(end_index, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'end_index' field"))
}
ChatCompletionMessageAnnotation::{
type_,
text,
file_citation,
file_path,
start_index: start_index.to_int(),
end_index: end_index.to_int(),
}
}
///|
/// File citation annotation
pub struct ChatCompletionMessageAnnotationFileCitation {
file_id : String
quote : String
}
///|
impl @json.FromJson for ChatCompletionMessageAnnotationFileCitation with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionMessageAnnotationFileCitation {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("file_id") is Some(String(file_id)) else {
raise @json.JsonDecodeError((json_path, "Missing 'file_id' field"))
}
guard json.get("quote") is Some(String(quote)) else {
raise @json.JsonDecodeError((json_path, "Missing 'quote' field"))
}
ChatCompletionMessageAnnotationFileCitation::{ file_id, quote }
}
///|
/// File path annotation
pub struct ChatCompletionMessageAnnotationFilePath {
file_id : String
}
///|
impl @json.FromJson for ChatCompletionMessageAnnotationFilePath with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionMessageAnnotationFilePath {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("file_id") is Some(String(file_id)) else {
raise @json.JsonDecodeError((json_path, "Missing 'file_id' field"))
}
ChatCompletionMessageAnnotationFilePath::{ file_id, }
}
///|
/// Metadata type alias for key-value pairs
type Metadata = Map[String, String]
///|
/// Reasoning effort levels for reasoning models
pub enum ReasoningEffort {
Minimal
Low
Medium
High
}
///|
impl ToJson for ReasoningEffort with to_json(self : ReasoningEffort) -> Json {
match self {
Minimal => Json::string("minimal")
Low => Json::string("low")
Medium => Json::string("medium")
High => Json::string("high")
}
}
///|
impl @json.FromJson for ReasoningEffort with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ReasoningEffort {
guard json is String(effort) else {
raise @json.JsonDecodeError((json_path, "Expected a string"))
}
match effort {
"minimal" => ReasoningEffort::Minimal
"low" => ReasoningEffort::Low
"medium" => ReasoningEffort::Medium
"high" => ReasoningEffort::High
_ =>
raise @json.JsonDecodeError(
(json_path, "Unknown reasoning effort: \{effort}"),
)
}
}
///|
/// Verbosity levels for model responses
pub enum Verbosity {
Low
Medium
High
}
///|
impl ToJson for Verbosity with to_json(self : Verbosity) -> Json {
match self {
Low => Json::string("low")
Medium => Json::string("medium")
High => Json::string("high")
}
}
///|
impl @json.FromJson for Verbosity with from_json(
json : Json,
json_path : @json.JsonPath,
) -> Verbosity {
guard json is String(verbosity) else {
raise @json.JsonDecodeError((json_path, "Expected a string"))
}
match verbosity {
"low" => Verbosity::Low
"medium" => Verbosity::Medium
"high" => Verbosity::High
_ =>
raise @json.JsonDecodeError(
(json_path, "Unknown verbosity: \{verbosity}"),
)
}
}
///|
pub struct Function {
arguments : String
name : String
}
///|
impl ToJson for Function with to_json(self : Function) -> Json {
{ "name": self.name, "arguments": self.arguments }
}
///|
impl @json.FromJson for Function with from_json(
json : Json,
json_path : @json.JsonPath,
) -> Function {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("arguments") is Some(String(arguments)) else {
raise @json.JsonDecodeError((json_path, "Missing 'arguments' field"))
}
guard json.get("name") is Some(String(name)) else {
raise @json.JsonDecodeError((json_path, "Missing 'name' field"))
}
Function::{ arguments, name }
}
///|
pub struct ChatCompletionMessageToolCall {
id : String
function : Function
}
///|
impl ToJson for ChatCompletionMessageToolCall with to_json(
self : ChatCompletionMessageToolCall,
) -> Json {
{ "id": self.id, "function": self.function, "type": "function" }
}
///|
impl @json.FromJson for ChatCompletionMessageToolCall with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionMessageToolCall {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("id") is Some(String(id)) else {
raise @json.JsonDecodeError((json_path, "Missing 'id' field"))
}
guard json.get("function") is Some(function) else {
raise @json.JsonDecodeError((json_path, "Missing 'function' field"))
}
let function : Function = @json.from_json(
function,
path=json_path.add_key("function"),
)
ChatCompletionMessageToolCall::{ id, function }
}
///|
pub struct ChatCompletionMessage {
content : String?
refusal : String?
tool_calls : Array[ChatCompletionMessageToolCall]
annotations : Array[ChatCompletionMessageAnnotation]
audio : ChatCompletionAudio?
function_call : ChatCompletionMessageFunctionCall?
}
///|
/// Deprecated function call format (replaced by tool_calls)
pub struct ChatCompletionMessageFunctionCall {
arguments : String
name : String
}
///|
impl @json.FromJson for ChatCompletionMessageFunctionCall with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionMessageFunctionCall {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("arguments") is Some(String(arguments)) else {
raise @json.JsonDecodeError((json_path, "Missing 'arguments' field"))
}
guard json.get("name") is Some(String(name)) else {
raise @json.JsonDecodeError((json_path, "Missing 'name' field"))
}
ChatCompletionMessageFunctionCall::{ arguments, name }
}
///|
impl ToJson for ChatCompletionMessageFunctionCall with to_json(
self : ChatCompletionMessageFunctionCall,
) -> Json {
{ "arguments": self.arguments, "name": self.name }
}
///|
pub fn ChatCompletionMessage::to_param(
self : ChatCompletionMessage,
) -> ChatCompletionMessageParam {
Assistant({
content: self.content,
name: None,
tool_calls: self.tool_calls,
function_call: self.function_call,
})
}
///|
impl @json.FromJson for ChatCompletionMessage with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionMessage {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
let content = match json.get("content") {
Some(Null) => None
Some(content) => {
let content : String = @json.from_json(
content,
path=json_path.add_key("content"),
)
Some(content)
}
None => None
}
let refusal = match json.get("refusal") {
Some(Null) => None
Some(refusal) => {
let refusal : String = @json.from_json(
refusal,
path=json_path.add_key("refusal"),
)
Some(refusal)
}
None => None
}
let tool_calls = match json.get("tool_calls") {
Some(tool_calls) => {
let tool_calls : Array[ChatCompletionMessageToolCall] = @json.from_json(
tool_calls,
path=json_path.add_key("tool_calls"),
)
tool_calls
}
None => []
}
let annotations = match json.get("annotations") {
Some(annotations) => {
let annotations : Array[ChatCompletionMessageAnnotation] = @json.from_json(
annotations,
path=json_path.add_key("annotations"),
)
annotations
}
None => []
}
let audio = match json.get("audio") {
Some(Null) => None
Some(audio) => {
let audio : ChatCompletionAudio = @json.from_json(
audio,
path=json_path.add_key("audio"),
)
Some(audio)
}
None => None
}
let function_call = match json.get("function_call") {
Some(Null) => None
Some(function_call) => {
let function_call : ChatCompletionMessageFunctionCall = @json.from_json(
function_call,
path=json_path.add_key("function_call"),
)
Some(function_call)
}
None => None
}
ChatCompletionMessage::{
content,
refusal,
tool_calls,
annotations,
audio,
function_call,
}
}
///|
pub enum ChatCompletionChoiceFinishReason {
Stop
Length
ToolCalls
ContentFilter
FunctionCall
}
///|
impl @json.FromJson for ChatCompletionChoiceFinishReason with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChoiceFinishReason {
guard json is String(reason) else {
raise @json.JsonDecodeError((json_path, "Expected a string"))
}
match reason {
"stop" => ChatCompletionChoiceFinishReason::Stop
"length" => ChatCompletionChoiceFinishReason::Length
"tool_calls" => ChatCompletionChoiceFinishReason::ToolCalls
"content_filter" => ChatCompletionChoiceFinishReason::ContentFilter
"function_call" => ChatCompletionChoiceFinishReason::FunctionCall
_ =>
raise @json.JsonDecodeError(
(json_path, "Unknown finish reason: \{reason}"),
)
}
}
///|
pub struct ChatCompletionChoice {
finish_reason : ChatCompletionChoiceFinishReason
index : Int
message : ChatCompletionMessage
logprobs : ChatCompletionChoiceLogprobs?
}
///|
impl @json.FromJson for ChatCompletionChoice with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChoice {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("finish_reason") is Some(finish_reason) else {
raise @json.JsonDecodeError((json_path, "Missing 'finish_reason' field"))
}
let finish_reason : ChatCompletionChoiceFinishReason = @json.from_json(
finish_reason,
path=json_path.add_key("finish_reason"),
)
guard json.get("index") is Some(Number(index, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'index' field"))
}
guard json.get("message") is Some(message) else {
raise @json.JsonDecodeError((json_path, "Missing 'message' field"))
}
let message : ChatCompletionMessage = @json.from_json(
message,
path=json_path.add_key("message"),
)
let logprobs = match json.get("logprobs") {
Some(Null) => None
Some(logprobs) => {
let logprobs : ChatCompletionChoiceLogprobs = @json.from_json(
logprobs,
path=json_path.add_key("logprobs"),
)
Some(logprobs)
}
None => None
}
ChatCompletionChoice::{
finish_reason,
index: index.to_int(),
message,
logprobs,
}
}
///|
/// Content part types for multimodal messages
pub enum ChatCompletionContentPart {
Text(ChatCompletionContentPartText)
ImageURL(ChatCompletionContentPartImage)
InputAudio(ChatCompletionContentPartInputAudio)
File(ChatCompletionContentPartFile)
}
///|
impl ToJson for ChatCompletionContentPart with to_json(
self : ChatCompletionContentPart,
) -> Json {
match self {
Text(text) => {
let json : Map[String, Json] = {
"type": "text",
"text": Json::string(text.text),
}
Json::object(json)
}
ImageURL(image) => {
let json : Map[String, Json] = {
"type": "image_url",
"image_url": image.image_url.to_json(),
}
Json::object(json)
}
InputAudio(audio) => {
let json : Map[String, Json] = {
"type": "input_audio",
"input_audio": audio.input_audio.to_json(),
}
Json::object(json)
}
File(file) => {
let json : Map[String, Json] = {
"type": "file",
"file": file.file.to_json(),
}
Json::object(json)
}
}
}
///|
impl @json.FromJson for ChatCompletionContentPart with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPart {
guard json is Object(obj) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard obj.get("type") is Some(String(type_)) else {
raise @json.JsonDecodeError((json_path, "Missing 'type' field"))
}
match type_ {
"text" => {
let text : ChatCompletionContentPartText = @json.from_json(
json,
path=json_path,
)
ChatCompletionContentPart::Text(text)
}
"image_url" => {
let image : ChatCompletionContentPartImage = @json.from_json(
json,
path=json_path,
)
ChatCompletionContentPart::ImageURL(image)
}
"input_audio" => {
let audio : ChatCompletionContentPartInputAudio = @json.from_json(
json,
path=json_path,
)
ChatCompletionContentPart::InputAudio(audio)
}
"file" => {
let file : ChatCompletionContentPartFile = @json.from_json(
json,
path=json_path,
)
ChatCompletionContentPart::File(file)
}
_ =>
raise @json.JsonDecodeError(
(json_path, "Unknown content part type: \{type_}"),
)
}
}
///|
/// Text content part
pub struct ChatCompletionContentPartText {
text : String
}
///|
impl @json.FromJson for ChatCompletionContentPartText with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPartText {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("text") is Some(String(text)) else {
raise @json.JsonDecodeError((json_path, "Missing 'text' field"))
}
ChatCompletionContentPartText::{ text, }
}
///|
/// Image URL content part
pub struct ChatCompletionContentPartImage {
image_url : ChatCompletionContentPartImageImageURL
}
///|
impl @json.FromJson for ChatCompletionContentPartImage with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPartImage {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("image_url") is Some(image_url) else {
raise @json.JsonDecodeError((json_path, "Missing 'image_url' field"))
}
let image_url : ChatCompletionContentPartImageImageURL = @json.from_json(
image_url,
path=json_path.add_key("image_url"),
)
ChatCompletionContentPartImage::{ image_url, }
}
///|
/// Image URL information
pub struct ChatCompletionContentPartImageImageURL {
url : String
detail : String?
}
///|
impl ToJson for ChatCompletionContentPartImageImageURL with to_json(
self : ChatCompletionContentPartImageImageURL,
) -> Json {
let json : Map[String, Json] = { "url": Json::string(self.url) }
if self.detail is Some(detail) {
json["detail"] = Json::string(detail)
}
Json::object(json)
}
///|
impl @json.FromJson for ChatCompletionContentPartImageImageURL with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPartImageImageURL {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("url") is Some(String(url)) else {
raise @json.JsonDecodeError((json_path, "Missing 'url' field"))
}
let detail = match json.get("detail") {
Some(Null) => None
Some(String(detail)) => Some(detail)
Some(_) =>
raise @json.JsonDecodeError(
(json_path, "Expected 'detail' to be a string"),
)
None => None
}
ChatCompletionContentPartImageImageURL::{ url, detail }
}
///|
/// Input audio content part
pub struct ChatCompletionContentPartInputAudio {
input_audio : ChatCompletionContentPartInputAudioInputAudio
}
///|
impl @json.FromJson for ChatCompletionContentPartInputAudio with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPartInputAudio {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("input_audio") is Some(input_audio) else {
raise @json.JsonDecodeError((json_path, "Missing 'input_audio' field"))
}
let input_audio : ChatCompletionContentPartInputAudioInputAudio = @json.from_json(
input_audio,
path=json_path.add_key("input_audio"),
)
ChatCompletionContentPartInputAudio::{ input_audio, }
}
///|
/// Input audio information
pub struct ChatCompletionContentPartInputAudioInputAudio {
data : String
format : String
}
///|
impl ToJson for ChatCompletionContentPartInputAudioInputAudio with to_json(
self : ChatCompletionContentPartInputAudioInputAudio,
) -> Json {
{ "data": self.data, "format": self.format }
}
///|
impl @json.FromJson for ChatCompletionContentPartInputAudioInputAudio with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPartInputAudioInputAudio {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("data") is Some(String(data)) else {
raise @json.JsonDecodeError((json_path, "Missing 'data' field"))
}
guard json.get("format") is Some(String(format)) else {
raise @json.JsonDecodeError((json_path, "Missing 'format' field"))
}
ChatCompletionContentPartInputAudioInputAudio::{ data, format }
}
///|
/// File content part
pub struct ChatCompletionContentPartFile {
file : ChatCompletionContentPartFileFile
}
///|
impl @json.FromJson for ChatCompletionContentPartFile with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPartFile {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("file") is Some(file) else {
raise @json.JsonDecodeError((json_path, "Missing 'file' field"))
}
let file : ChatCompletionContentPartFileFile = @json.from_json(
file,
path=json_path.add_key("file"),
)
ChatCompletionContentPartFile::{ file, }
}
///|
/// File information
pub struct ChatCompletionContentPartFileFile {
file_id : String
}
///|
impl ToJson for ChatCompletionContentPartFileFile with to_json(
self : ChatCompletionContentPartFileFile,
) -> Json {
{ "file_id": self.file_id }
}
///|
impl @json.FromJson for ChatCompletionContentPartFileFile with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionContentPartFileFile {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("file_id") is Some(String(file_id)) else {
raise @json.JsonDecodeError((json_path, "Missing 'file_id' field"))
}
ChatCompletionContentPartFileFile::{ file_id, }
}
///|
pub struct CompletionUsage {
completion_tokens : Int
prompt_tokens : Int
total_tokens : Int
}
///|
impl @json.FromJson for CompletionUsage with from_json(
json : Json,
json_path : @json.JsonPath,
) -> CompletionUsage {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("completion_tokens") is Some(Number(completion_tokens, ..)) else {
raise @json.JsonDecodeError(
(json_path, "Missing 'completion_tokens' field"),
)
}
guard json.get("prompt_tokens") is Some(Number(prompt_tokens, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'prompt_tokens' field"))
}
guard json.get("total_tokens") is Some(Number(total_tokens, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'total_tokens' field"))
}
CompletionUsage::{
completion_tokens: completion_tokens.to_int(),
prompt_tokens: prompt_tokens.to_int(),
total_tokens: total_tokens.to_int(),
}
}
///|
pub struct ChatCompletion {
id : String
choices : Array[ChatCompletionChoice]
created : Int
model : String
usage : CompletionUsage?
system_fingerprint : String?
service_tier : ChatCompletionServiceTier?
}
///|
impl @json.FromJson for ChatCompletion with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletion {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("id") is Some(String(id)) else {
raise @json.JsonDecodeError((json_path, "Missing 'id' field"))
}
guard json.get("choices") is Some(choices) else {
raise @json.JsonDecodeError((json_path, "Missing 'choices' field"))
}
let choices : Array[ChatCompletionChoice] = @json.from_json(
choices,
path=json_path.add_key("choices"),
)
guard json.get("created") is Some(Number(created, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'created' field"))
}
guard json.get("model") is Some(String(model)) else {
raise @json.JsonDecodeError((json_path, "Missing 'model' field"))
}
let usage = match json.get("usage") {
Some(Null) => None
Some(usage) => {
let usage : CompletionUsage = @json.from_json(
usage,
path=json_path.add_key("usage"),
)
Some(usage)
}
None => None
}
let system_fingerprint = match json.get("system_fingerprint") {
Some(Null) => None
Some(String(fingerprint)) => Some(fingerprint)
Some(_) =>
raise @json.JsonDecodeError(
(json_path, "Expected 'system_fingerprint' to be a string"),
)
None => None
}
let service_tier = match json.get("service_tier") {
Some(Null) => None
Some(service_tier) => {
let service_tier : ChatCompletionServiceTier = @json.from_json(
service_tier,
path=json_path.add_key("service_tier"),
)
Some(service_tier)
}
None => None
}
ChatCompletion::{
id,
choices,
created: created.to_int(),
model,
usage,
system_fingerprint,
service_tier,
}
}
///|
pub struct ChatCompletionSystemMessageParam {
content : String
name : String?
}
///|
pub struct ChatCompletionUserMessageParam {
content : String
name : String?
}
///|
typealias ChatCompletionMessageToolCall as ChatCompletionMessageToolCallParam
///|
pub struct ChatCompletionAssistantMessageParam {
content : String?
name : String?
tool_calls : Array[ChatCompletionMessageToolCallParam]
function_call : ChatCompletionMessageFunctionCall?
}
///|
pub struct ChatCompletionToolMessageParam {
content : String
tool_call_id : String
}
///|
pub enum ChatCompletionMessageParam {
System(ChatCompletionSystemMessageParam)
User(ChatCompletionUserMessageParam)
Assistant(ChatCompletionAssistantMessageParam)
Tool(ChatCompletionToolMessageParam)
}
///|
impl ToJson for ChatCompletionMessageParam with to_json(
self : ChatCompletionMessageParam,
) {
match self {
System(param) => {
let json : Map[String, Json] = {
"role": "system",
"content": Json::string(param.content),
}
if param.name is Some(name) {
json["name"] = Json::string(name)
}
Json::object(json)
}
User(param) => {
let json : Map[String, Json] = {
"role": "user",
"content": Json::string(param.content),
}
if param.name is Some(name) {
json["name"] = Json::string(name)
}
Json::object(json)
}
Assistant(param) => {
let json : Map[String, Json] = {
"role": "assistant",
"tool_calls": param.tool_calls.to_json(),
}
if param.content is Some(content) {
json["content"] = Json::string(content)
}
if param.name is Some(name) {
json["name"] = Json::string(name)
}
if param.function_call is Some(function_call) {
json["function_call"] = function_call.to_json()
}
Json::object(json)
}
Tool(param) =>
{
"role": "tool",
"content": param.content,
"tool_call_id": param.tool_call_id,
}
}
}
///|
pub fn system_message(
content~ : String,
name? : String,
) -> ChatCompletionMessageParam {
ChatCompletionMessageParam::System({ content, name })
}
///|
pub fn user_message(
content~ : String,
name? : String,
) -> ChatCompletionMessageParam {
ChatCompletionMessageParam::User({ content, name })
}
///|
pub fn tool_message(
content~ : String,
tool_call_id~ : String,
) -> ChatCompletionMessageParam {
ChatCompletionMessageParam::Tool({ content, tool_call_id })
}
///|
/// Audio parameters for chat completion
pub struct ChatCompletionAudioParam {
voice : String
format : String
}
///|
impl ToJson for ChatCompletionAudioParam with to_json(
self : ChatCompletionAudioParam,
) -> Json {
{ "voice": self.voice, "format": self.format }
}
///|
/// Streaming options for chat completion
pub struct ChatCompletionStreamOptions {
include_usage : Bool?
}
///|
impl ToJson for ChatCompletionStreamOptions with to_json(
self : ChatCompletionStreamOptions,
) -> Json {
let json : Map[String, Json] = {}
if self.include_usage is Some(include_usage) {
json["include_usage"] = Json::boolean(include_usage)
}
Json::object(json)
}
///|
/// Response format types
pub enum ChatCompletionResponseFormat {
JsonObject
JsonSchema(ChatCompletionResponseFormatJsonSchema)
Text
}
///|
impl ToJson for ChatCompletionResponseFormat with to_json(
self : ChatCompletionResponseFormat,
) -> Json {
match self {
JsonObject => { "type": "json_object" }
JsonSchema(schema) => {
let json : Map[String, Json] = {
"type": "json_schema",
"json_schema": schema.to_json(),
}
Json::object(json)
}
Text => { "type": "text" }
}
}
///|
/// JSON schema for response format
pub struct ChatCompletionResponseFormatJsonSchema {
name : String
description : String?
schema : Map[String, Json]
strict : Bool?
}
///|
impl ToJson for ChatCompletionResponseFormatJsonSchema with to_json(
self : ChatCompletionResponseFormatJsonSchema,
) -> Json {
let json : Map[String, Json] = {
"name": Json::string(self.name),
"schema": Json::object(self.schema),
}
if self.description is Some(description) {
json["description"] = Json::string(description)
}
if self.strict is Some(strict) {
json["strict"] = Json::boolean(strict)
}
Json::object(json)
}
///|
/// Prediction content for static predicted output
pub struct ChatCompletionPredictionContent {
type_ : String
content : String
}
///|
impl ToJson for ChatCompletionPredictionContent with to_json(
self : ChatCompletionPredictionContent,
) -> Json {
{ "type": self.type_, "content": self.content }
}
///|
/// Stop sequences parameter
pub enum ChatCompletionStopParam {
String(String)
Array(Array[String])
}
///|
impl ToJson for ChatCompletionStopParam with to_json(
self : ChatCompletionStopParam,
) -> Json {
match self {
String(s) => Json::string(s)
Array(arr) => arr.to_json()
}
}
///|
/// Web search options
pub struct ChatCompletionWebSearchOptions {
max_results : Int?
}
///|
impl ToJson for ChatCompletionWebSearchOptions with to_json(
self : ChatCompletionWebSearchOptions,
) -> Json {
let json : Map[String, Json] = {}
if self.max_results is Some(max_results) {
json["max_results"] = max_results.to_json()
}
Json::object(json)
}
///|
pub async fn ChatCompletionsService::create(
self : ChatCompletionsService,
messages~ : Array[ChatCompletionMessageParam],
model~ : String,
tools? : Array[ChatCompletionToolParam],
frequency_penalty? : Double,
logprobs? : Bool,
max_completion_tokens? : Int,
max_tokens? : Int,
n? : Int,
presence_penalty? : Double,
seed? : Int,
store? : Bool,
temperature? : Double,
top_logprobs? : Int,
top_p? : Double,
parallel_tool_calls? : Bool,
prompt_cache_key? : String,
safety_identifier? : String,
user? : String,
audio? : ChatCompletionAudioParam,
logit_bias? : Map[String, Int],
metadata? : Metadata,
modalities? : Array[String],
reasoning_effort? : ReasoningEffort,
service_tier? : ChatCompletionServiceTier,
stop? : ChatCompletionStopParam,
stream_options? : ChatCompletionStreamOptions,
verbosity? : Verbosity,
prediction? : ChatCompletionPredictionContent,
response_format? : ChatCompletionResponseFormat,
web_search_options? : ChatCompletionWebSearchOptions,
) -> ChatCompletion {
let body : Map[String, Json] = {
"model": model.to_json(),
"messages": messages.to_json(),
}
if tools is Some(tools) {
body["tools"] = tools.to_json()
}
if frequency_penalty is Some(frequency_penalty) {
body["frequency_penalty"] = frequency_penalty.to_json()
}
if logprobs is Some(logprobs) {
body["logprobs"] = logprobs.to_json()
}
if max_completion_tokens is Some(max_completion_tokens) {
body["max_completion_tokens"] = max_completion_tokens.to_json()
}
if max_tokens is Some(max_tokens) {
body["max_tokens"] = max_tokens.to_json()
}
if n is Some(n) {
body["n"] = n.to_json()
}
if presence_penalty is Some(presence_penalty) {
body["presence_penalty"] = presence_penalty.to_json()
}
if seed is Some(seed) {
body["seed"] = seed.to_json()
}
if store is Some(store) {
body["store"] = store.to_json()
}
if temperature is Some(temperature) {
body["temperature"] = temperature.to_json()
}
if top_logprobs is Some(top_logprobs) {
body["top_logprobs"] = top_logprobs.to_json()
}
if top_p is Some(top_p) {
body["top_p"] = top_p.to_json()
}
if parallel_tool_calls is Some(parallel_tool_calls) {
body["parallel_tool_calls"] = parallel_tool_calls.to_json()
}
if prompt_cache_key is Some(prompt_cache_key) {
body["prompt_cache_key"] = prompt_cache_key.to_json()
}
if safety_identifier is Some(safety_identifier) {
body["safety_identifier"] = safety_identifier.to_json()
}
if user is Some(user) {
body["user"] = user.to_json()
}
if audio is Some(audio) {
body["audio"] = audio.to_json()
}
if logit_bias is Some(logit_bias) {
body["logit_bias"] = logit_bias.to_json()
}
if metadata is Some(metadata) {
body["metadata"] = metadata.to_json()
}
if modalities is Some(modalities) {
body["modalities"] = modalities.to_json()
}
if reasoning_effort is Some(reasoning_effort) {
body["reasoning_effort"] = reasoning_effort.to_json()
}
if service_tier is Some(service_tier) {
body["service_tier"] = service_tier.to_json()
}
if stop is Some(stop) {
body["stop"] = stop.to_json()
}
if stream_options is Some(stream_options) {
body["stream_options"] = stream_options.to_json()
}
if verbosity is Some(verbosity) {
body["verbosity"] = verbosity.to_json()
}
if prediction is Some(prediction) {
body["prediction"] = prediction.to_json()
}
if response_format is Some(response_format) {
body["response_format"] = response_format.to_json()
}
if web_search_options is Some(web_search_options) {
body["web_search_options"] = web_search_options.to_json()
}
let body = body.to_json().stringify()
let response : Response = self.options.http_client.fetch(
url="\{self.options.base_url}/chat/completions",
method_=HttpMethod::Post,
headers=self.options.headers,
body~,
)
guard response.status_code is (200..=299) else {
fail(
"HTTP request failed with status code \{response.status_code}: \{response.reason_phrase}",
)
}
let body = @buffer.new()
loop response.body.read() {
None => break
Some(data) => {
body.write_string(data)
continue response.body.read()
}
}
body.to_string() |> @json.parse() |> @json.from_json()
}
///|
pub async fn ChatCompletionsService::stream(
self : ChatCompletionsService,
messages~ : Array[ChatCompletionMessageParam],
model~ : String,
tools? : Array[ChatCompletionToolParam] = [],
) -> Reader[ChatCompletionChunk] {
let body : Json = {
"model": model,
"messages": messages,
"tools": tools,
"stream": true,
}
let body = body.stringify()
let buffer = StringBuilder::new()
let response = self.options.http_client.fetch(
url="\{self.options.base_url}/chat/completions",
method_=HttpMethod::Post,
headers=self.options.headers,
body~,
)
guard response.status_code is (200..=299) else {
fail(
"HTTP request failed with status code \{response.status_code}: \{response.reason_phrase}",
)
}
let mut offset = 0
Reader::new(() => body~: loop buffer.to_string()[offset:] {
[.. "\n\n", .. rest] as view => {
let text = buffer.to_string()[offset:view.start_offset()]
offset = rest.start_offset()
match text {
[':', ..] => continue rest
"data: [DONE]" => None
[.. "data: ", .. data] => {
let data = @json.parse([..data])
let data : ChatCompletionChunk = @json.from_json(data)
Some(data)
}
[..] as data => fail("Invalid data format: \{data}")
}
}
[_, .. rest] => continue rest
[] => {
match response.body.read() {
None => break None
Some(data) => buffer.write_string(data)
}
continue body~ buffer.to_string()[offset:]
}
})
}
///|
priv struct FunctionDefinition {
name : String
description : String
parameters : Map[String, Json]
strict : Bool?
}
///|
impl ToJson for FunctionDefinition with to_json(self : FunctionDefinition) -> Json {
let json : Map[String, Json] = {
"name": Json::string(self.name),
"description": Json::string(self.description),
"parameters": Json::object(self.parameters),
}
if self.strict is Some(bool) {
json["strict"] = Json::boolean(bool)
}
Json::object(json)
}
///|
pub fn tool(
name~ : String,
description~ : String,
parameters~ : Map[String, Json],
strict? : Bool,
) -> ChatCompletionToolParam {
Function(FunctionDefinition::{ name, description, parameters, strict })
}
///|
enum ChatCompletionToolParam {
Function(FunctionDefinition)
}
///|
impl ToJson for ChatCompletionToolParam with to_json(
self : ChatCompletionToolParam,
) -> Json {
match self {
Function(function_definition) =>
{ "type": "function", "function": function_definition.to_json() }
}
}
///|
pub struct ChatCompletionChunkChoiceDeltaToolCallFunction {
arguments : String?
name : String?
}
///|
impl @json.FromJson for ChatCompletionChunkChoiceDeltaToolCallFunction with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChunkChoiceDeltaToolCallFunction {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
let arguments = match json.get("arguments") {
None | Some(Null) => None
Some(String(arguments)) => Some(arguments)
Some(_) =>
raise @json.JsonDecodeError(
(json_path, "Expected 'arguments' to be a string"),
)
}
let name = match json.get("name") {
None | Some(Null) => None
Some(String(name)) => Some(name)
Some(_) =>
raise @json.JsonDecodeError((json_path, "Expected 'name' to be a string"))
}
ChatCompletionChunkChoiceDeltaToolCallFunction::{ arguments, name }
}
///|
pub struct ChatCompletionChunkChoiceDeltaToolCall {
index : Int
id : String?
function : ChatCompletionChunkChoiceDeltaToolCallFunction
}
///|
impl @json.FromJson for ChatCompletionChunkChoiceDeltaToolCall with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChunkChoiceDeltaToolCall {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("index") is Some(Number(index, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'index' field"))
}
let id = match json.get("id") {
None | Some(Null) => None
Some(String(id)) => Some(id)
Some(_) =>
raise @json.JsonDecodeError((json_path, "Expected 'id' to be a string"))
}
guard json.get("function") is Some(function) else {
raise @json.JsonDecodeError((json_path, "Missing 'function' field"))
}
let function : ChatCompletionChunkChoiceDeltaToolCallFunction = @json.from_json(
function,
path=json_path.add_key("function"),
)
ChatCompletionChunkChoiceDeltaToolCall::{
index: index.to_int(),
id,
function,
}
}
///|
pub enum ChatCompletionRole {
Developer
System
User
Assistant
Tool
}
///|
impl @json.FromJson for ChatCompletionRole with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionRole {
guard json is String(role) else {
raise @json.JsonDecodeError((json_path, "Expected a string"))
}
match role {
"developer" => ChatCompletionRole::Developer
"system" => ChatCompletionRole::System
"user" => ChatCompletionRole::User
"assistant" => ChatCompletionRole::Assistant
"tool" => ChatCompletionRole::Tool
role => raise @json.JsonDecodeError((json_path, "Unknown role: \{role}"))
}
}
///|
pub struct ChatCompletionChunkChoiceDelta {
content : String?
role : ChatCompletionRole?
tool_calls : Array[ChatCompletionChunkChoiceDeltaToolCall]?
}
///|
impl @json.FromJson for ChatCompletionChunkChoiceDelta with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChunkChoiceDelta {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
let content = match json.get("content") {
Some(Null) => None
Some(content) => {
let content : String = @json.from_json(
content,
path=json_path.add_key("content"),
)
Some(content)
}
None => None
}
let role = match json.get("role") {
Some(role) => {
let role : ChatCompletionRole = @json.from_json(
role,
path=json_path.add_key("role"),
)
Some(role)
}
None => None
}
let tool_calls = match json.get("tool_calls") {
Some(tool_calls) => {
let tool_calls : Array[ChatCompletionChunkChoiceDeltaToolCall] = @json.from_json(
tool_calls,
path=json_path.add_key("tool_calls"),
)
Some(tool_calls)
}
None => None
}
ChatCompletionChunkChoiceDelta::{ content, role, tool_calls }
}
///|
pub struct ChatCompletionChunkChoice {
index : Int
delta : ChatCompletionChunkChoiceDelta
finish_reason : ChatCompletionChoiceFinishReason?
}
///|
impl @json.FromJson for ChatCompletionChunkChoice with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChunkChoice {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("index") is Some(Number(index, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'index' field"))
}
guard json.get("delta") is Some(delta) else {
raise @json.JsonDecodeError((json_path, "Missing 'delta' field"))
}
let delta : ChatCompletionChunkChoiceDelta = @json.from_json(
delta,
path=json_path.add_key("delta"),
)
let finish_reason = match json.get("finish_reason") {
Some(Null) => None
Some(finish_reason) => {
let finish_reason : ChatCompletionChoiceFinishReason = @json.from_json(
finish_reason,
path=json_path.add_key("finish_reason"),
)
Some(finish_reason)
}
None => None
}
ChatCompletionChunkChoice::{ index: index.to_int(), delta, finish_reason }
}
///|
pub struct ChatCompletionChunk {
id : String
choices : Array[ChatCompletionChunkChoice]
created : Int
model : String
usage : CompletionUsage?
system_fingerprint : String?
service_tier : ChatCompletionChunkServiceTier?
}
///|
impl @json.FromJson for ChatCompletionChunk with from_json(
json : Json,
json_path : @json.JsonPath,
) -> ChatCompletionChunk {
guard json is Object(json) else {
raise @json.JsonDecodeError((json_path, "Expected an object"))
}
guard json.get("id") is Some(String(id)) else {
raise @json.JsonDecodeError((json_path, "Missing 'id' field"))
}
guard json.get("choices") is Some(choices) else {
raise @json.JsonDecodeError((json_path, "Missing 'choices' field"))
}
let choices : Array[ChatCompletionChunkChoice] = @json.from_json(
choices,
path=json_path.add_key("choices"),
)
guard json.get("created") is Some(Number(created, ..)) else {
raise @json.JsonDecodeError((json_path, "Missing 'created' field"))
}
guard json.get("model") is Some(String(model)) else {
raise @json.JsonDecodeError((json_path, "Missing 'model' field"))
}
let usage = match json.get("usage") {
Some(Null) => None
Some(usage) => {
let usage : CompletionUsage = @json.from_json(
usage,
path=json_path.add_key("usage"),
)
Some(usage)
}
None => None
}
let system_fingerprint = match json.get("system_fingerprint") {
Some(Null) => None
Some(String(fingerprint)) => Some(fingerprint)
Some(_) =>
raise @json.JsonDecodeError(
(json_path, "Expected 'system_fingerprint' to be a string"),
)
None => None
}
let service_tier = match json.get("service_tier") {
Some(Null) => None
Some(service_tier) => {
let service_tier : ChatCompletionChunkServiceTier = @json.from_json(
service_tier,
path=json_path.add_key("service_tier"),
)
Some(service_tier)
}
None => None
}
ChatCompletionChunk::{
id,
choices,
created: created.to_int(),
model,
usage,
system_fingerprint,
service_tier,
}
}
///|
pub fn text_content_part(text : String) -> ChatCompletionContentPart {
ChatCompletionContentPart::Text(ChatCompletionContentPartText::{ text, })
}
///|
pub fn image_content_part(
url : String,
detail? : String,
) -> ChatCompletionContentPart {
ChatCompletionContentPart::ImageURL(ChatCompletionContentPartImage::{
image_url: ChatCompletionContentPartImageImageURL::{ url, detail },
})
}
///|
pub fn audio_content_part(
data : String,
format : String,
) -> ChatCompletionContentPart {
ChatCompletionContentPart::InputAudio(ChatCompletionContentPartInputAudio::{
input_audio: ChatCompletionContentPartInputAudioInputAudio::{ data, format },
})
}
///|
pub fn file_content_part(file_id : String) -> ChatCompletionContentPart {
ChatCompletionContentPart::File(ChatCompletionContentPartFile::{
file: ChatCompletionContentPartFileFile::{ file_id, },
})
}
///|
pub fn assistant_message(
content? : String,
tool_calls? : Array[ChatCompletionMessageToolCall] = [],
name? : String,
) -> ChatCompletionMessageParam {
ChatCompletionMessageParam::Assistant(ChatCompletionAssistantMessageParam::{
content,
name,
tool_calls,
function_call: None,
})
}