MyApp

<back to all web services

ChatCompletion

AI

Chat Completions API (OpenAI-Compatible)

The following routes are available for this service:
POST/v1/chat/completions
# frozen_string_literal: true
# encoding: utf-8


require 'json'
require 'servicestack'


module ResponseFormat
    TEXT = 'Text'
    JSON_OBJECT = 'JsonObject'
end

module ToolType
    FUNCTION = 'Function'
end

# @DataContract
class AiContent
    include ServiceStack::DTO

    # @DataMember(Name="type")
    # @return [String]
    attr_accessor :type

    def self.properties
        {
            type: { name: 'type' },
        }
    end

end

#
# Annotations for the message, when applicable, as when using the web search tool.
#
# @DataContract
class UrlCitation
    include ServiceStack::DTO

    # @DataMember(Name="end_index")
    # @return [Integer]
    attr_accessor :end_index

    # @DataMember(Name="start_index")
    # @return [Integer]
    attr_accessor :start_index

    # @DataMember(Name="title")
    # @return [String]
    attr_accessor :title

    # @DataMember(Name="url")
    # @return [String]
    attr_accessor :url

    def self.properties
        {
            end_index: { name: 'end_index' },
            start_index: { name: 'start_index' },
            title: { name: 'title' },
            url: { name: 'url' },
        }
    end

end

#
# Annotations for the message, when applicable, as when using the web search tool.
#
# @DataContract
class ChoiceAnnotation
    include ServiceStack::DTO

    # @DataMember(Name="type")
    # @return [String]
    attr_accessor :type

    # @DataMember(Name="url_citation")
    # @return [UrlCitation]
    attr_accessor :url_citation

    def self.properties
        {
            type: { name: 'type' },
            url_citation: { name: 'url_citation', type: UrlCitation },
        }
    end

end

#
# If the audio output modality is requested, this object contains data about the audio response from the model.
#
# @DataContract
class ChoiceAudio
    include ServiceStack::DTO

    # @DataMember(Name="data")
    # @return [String]
    attr_accessor :data

    # @DataMember(Name="expires_at")
    # @return [Integer]
    attr_accessor :expires_at

    # @DataMember(Name="id")
    # @return [String]
    attr_accessor :id

    # @DataMember(Name="transcript")
    # @return [String]
    attr_accessor :transcript

    def self.properties
        {
            data: { name: 'data' },
            expires_at: { name: 'expires_at' },
            id: { name: 'id' },
            transcript: { name: 'transcript' },
        }
    end

end

#
# The function that the model called.
#
# @DataContract
class ToolFunction
    include ServiceStack::DTO

    # @DataMember(Name="name")
    # @return [String]
    attr_accessor :name

    # @DataMember(Name="arguments")
    # @return [String]
    attr_accessor :arguments

    def self.properties
        {
            name: { name: 'name' },
            arguments: { name: 'arguments' },
        }
    end

end

#
# The tool calls generated by the model, such as function calls.
#
# @DataContract
class ToolCall
    include ServiceStack::DTO

    # @DataMember(Name="id")
    # @return [String]
    attr_accessor :id

    # @DataMember(Name="type")
    # @return [String]
    attr_accessor :type

    # @DataMember(Name="function")
    # @return [ToolFunction]
    attr_accessor :function

    def self.properties
        {
            id: { name: 'id' },
            type: { name: 'type' },
            function: { name: 'function', type: ToolFunction },
        }
    end

end

# @DataContract
class ChoiceMessage
    include ServiceStack::DTO

    # @DataMember(Name="content")
    # @return [String]
    attr_accessor :content

    # @DataMember(Name="refusal")
    # @return [String]
    attr_accessor :refusal

    # @DataMember(Name="reasoning")
    # @return [String]
    attr_accessor :reasoning

    # @DataMember(Name="reasoning_content")
    # @return [String]
    attr_accessor :reasoning_content

    # @DataMember(Name="thinking")
    # @return [String]
    attr_accessor :thinking

    # @DataMember(Name="role")
    # @return [String]
    attr_accessor :role

    # @DataMember(Name="timestamp")
    # @return [Integer]
    attr_accessor :timestamp

    # @DataMember(Name="tool_call_id")
    # @return [String]
    attr_accessor :tool_call_id

    # @DataMember(Name="images")
    # @return [List]
    attr_accessor :images

    # @DataMember(Name="audios")
    # @return [List]
    attr_accessor :audios

    # @DataMember(Name="files")
    # @return [List]
    attr_accessor :files

    # @DataMember(Name="annotations")
    # @return [List]
    attr_accessor :annotations

    # @DataMember(Name="audio")
    # @return [ChoiceAudio]
    attr_accessor :audio

    # @DataMember(Name="tool_calls")
    # @return [List]
    attr_accessor :tool_calls

    def self.properties
        {
            content: { name: 'content' },
            refusal: { name: 'refusal' },
            reasoning: { name: 'reasoning' },
            reasoning_content: { name: 'reasoning_content' },
            thinking: { name: 'thinking' },
            role: { name: 'role' },
            timestamp: { name: 'timestamp' },
            tool_call_id: { name: 'tool_call_id' },
            images: { name: 'images', type: [AiContent] },
            audios: { name: 'audios', type: [AiContent] },
            files: { name: 'files', type: [AiContent] },
            annotations: { name: 'annotations', type: [ChoiceAnnotation] },
            audio: { name: 'audio', type: ChoiceAudio },
            tool_calls: { name: 'tool_calls', type: [ToolCall] },
        }
    end

end

#
# A list of message content tokens with log probability information.
#
# @DataContract
class LogprobItem
    include ServiceStack::DTO

    # @DataMember(Name="token")
    # @return [String]
    attr_accessor :token

    # @DataMember(Name="logprob")
    # @return [Float]
    attr_accessor :logprob

    # @DataMember(Name="bytes")
    # @return [String]
    attr_accessor :bytes

    # @DataMember(Name="top_logprobs")
    # @return [List]
    attr_accessor :top_logprobs

    def self.properties
        {
            token: { name: 'token' },
            logprob: { name: 'logprob' },
            bytes: { name: 'bytes' },
            top_logprobs: { name: 'top_logprobs', type: [LogprobItem] },
        }
    end

end

#
# Log probability information for the choice.
#
# @DataContract
class Logprobs
    include ServiceStack::DTO

    # @DataMember(Name="content")
    # @return [List]
    attr_accessor :content

    def self.properties
        {
            content: { name: 'content', type: [LogprobItem] },
        }
    end

end

# @DataContract
class Choice
    include ServiceStack::DTO

    # @DataMember(Name="finish_reason")
    # @return [String]
    attr_accessor :finish_reason

    # @DataMember(Name="index")
    # @return [Integer]
    attr_accessor :index

    # @DataMember(Name="message")
    # @return [ChoiceMessage]
    attr_accessor :message

    # @DataMember(Name="logprobs")
    # @return [Logprobs]
    attr_accessor :logprobs

    def self.properties
        {
            finish_reason: { name: 'finish_reason' },
            index: { name: 'index' },
            message: { name: 'message', type: ChoiceMessage },
            logprobs: { name: 'logprobs', type: Logprobs },
        }
    end

end

#
# Usage statistics for the completion request.
#
# @DataContract
class AiCompletionUsage
    include ServiceStack::DTO

    # @DataMember(Name="accepted_prediction_tokens")
    # @return [Integer]
    attr_accessor :accepted_prediction_tokens

    # @DataMember(Name="audio_tokens")
    # @return [Integer]
    attr_accessor :audio_tokens

    # @DataMember(Name="reasoning_tokens")
    # @return [Integer]
    attr_accessor :reasoning_tokens

    # @DataMember(Name="rejected_prediction_tokens")
    # @return [Integer]
    attr_accessor :rejected_prediction_tokens

    def self.properties
        {
            accepted_prediction_tokens: { name: 'accepted_prediction_tokens' },
            audio_tokens: { name: 'audio_tokens' },
            reasoning_tokens: { name: 'reasoning_tokens' },
            rejected_prediction_tokens: { name: 'rejected_prediction_tokens' },
        }
    end

end

#
# Breakdown of tokens used in the prompt.
#
# @DataContract
class AiPromptUsage
    include ServiceStack::DTO

    # @DataMember(Name="accepted_prediction_tokens")
    # @return [Integer]
    attr_accessor :accepted_prediction_tokens

    # @DataMember(Name="audio_tokens")
    # @return [Integer]
    attr_accessor :audio_tokens

    # @DataMember(Name="cached_tokens")
    # @return [Integer]
    attr_accessor :cached_tokens

    def self.properties
        {
            accepted_prediction_tokens: { name: 'accepted_prediction_tokens' },
            audio_tokens: { name: 'audio_tokens' },
            cached_tokens: { name: 'cached_tokens' },
        }
    end

end

#
# Usage statistics for the completion request.
#
# @DataContract
class AiUsage
    include ServiceStack::DTO

    # @DataMember(Name="completion_tokens")
    # @return [Integer]
    attr_accessor :completion_tokens

    # @DataMember(Name="prompt_tokens")
    # @return [Integer]
    attr_accessor :prompt_tokens

    # @DataMember(Name="total_tokens")
    # @return [Integer]
    attr_accessor :total_tokens

    # @DataMember(Name="completion_tokens_details")
    # @return [AiCompletionUsage]
    attr_accessor :completion_tokens_details

    # @DataMember(Name="prompt_tokens_details")
    # @return [AiPromptUsage]
    attr_accessor :prompt_tokens_details

    # @DataMember(Name="duration")
    # @return [Integer]
    attr_accessor :duration

    def self.properties
        {
            completion_tokens: { name: 'completion_tokens' },
            prompt_tokens: { name: 'prompt_tokens' },
            total_tokens: { name: 'total_tokens' },
            completion_tokens_details: { name: 'completion_tokens_details', type: AiCompletionUsage },
            prompt_tokens_details: { name: 'prompt_tokens_details', type: AiPromptUsage },
            duration: { name: 'duration' },
        }
    end

end

# @DataContract
class ChatResponse
    include ServiceStack::DTO

    # @DataMember(Name="id")
    # @return [String]
    attr_accessor :id

    # @DataMember(Name="choices")
    # @return [List]
    attr_accessor :choices

    # @DataMember(Name="created")
    # @return [Integer]
    attr_accessor :created

    # @DataMember(Name="model")
    # @return [String]
    attr_accessor :model

    # @DataMember(Name="system_fingerprint")
    # @return [String]
    attr_accessor :system_fingerprint

    # @DataMember(Name="object")
    # @return [String]
    attr_accessor :object

    # @DataMember(Name="service_tier")
    # @return [String]
    attr_accessor :service_tier

    # @DataMember(Name="usage")
    # @return [AiUsage]
    attr_accessor :usage

    # @DataMember(Name="provider")
    # @return [String]
    attr_accessor :provider

    # @DataMember(Name="cost")
    # @return [Float]
    attr_accessor :cost

    # @DataMember(Name="tool_history")
    # @return [List]
    attr_accessor :tool_history

    # @DataMember(Name="metadata")
    # @return [Dictionary]
    attr_accessor :metadata

    # @DataMember(Name="responseStatus")
    # @return [ServiceStack::ResponseStatus]
    attr_accessor :response_status

    def self.properties
        {
            id: { name: 'id' },
            choices: { name: 'choices', type: [Choice] },
            created: { name: 'created' },
            model: { name: 'model' },
            system_fingerprint: { name: 'system_fingerprint' },
            object: { name: 'object' },
            service_tier: { name: 'service_tier' },
            usage: { name: 'usage', type: AiUsage },
            provider: { name: 'provider' },
            cost: { name: 'cost' },
            tool_history: { name: 'tool_history', type: [ChoiceMessage] },
            metadata: { name: 'metadata' },
            response_status: { name: 'responseStatus', type: ServiceStack::ResponseStatus },
        }
    end

end

#
# A list of messages comprising the conversation so far.
#
# @DataContract
class AiMessage
    include ServiceStack::DTO

    # @DataMember(Name="content")
    # @return [List]
    attr_accessor :content

    # @DataMember(Name="role")
    # @return [String]
    attr_accessor :role

    # @DataMember(Name="name")
    # @return [String]
    attr_accessor :name

    # @DataMember(Name="tool_calls")
    # @return [List]
    attr_accessor :tool_calls

    # @DataMember(Name="tool_call_id")
    # @return [String]
    attr_accessor :tool_call_id

    # @DataMember(Name="reasoning")
    # @return [String]
    attr_accessor :reasoning

    # @DataMember(Name="reasoning_content")
    # @return [String]
    attr_accessor :reasoning_content

    # @DataMember(Name="timestamp")
    # @return [Integer]
    attr_accessor :timestamp

    # @DataMember(Name="images")
    # @return [List]
    attr_accessor :images

    def self.properties
        {
            content: { name: 'content', type: [AiContent] },
            role: { name: 'role' },
            name: { name: 'name' },
            tool_calls: { name: 'tool_calls', type: [ToolCall] },
            tool_call_id: { name: 'tool_call_id' },
            reasoning: { name: 'reasoning' },
            reasoning_content: { name: 'reasoning_content' },
            timestamp: { name: 'timestamp' },
            images: { name: 'images', type: [AiContent] },
        }
    end

end

#
# Parameters for audio output. Required when audio output is requested with modalities: [audio]
#
# @DataContract
class AiChatAudio
    include ServiceStack::DTO

    # @DataMember(Name="format")
    # @return [String]
    attr_accessor :format

    # @DataMember(Name="voice")
    # @return [String]
    attr_accessor :voice

    def self.properties
        {
            format: { name: 'format' },
            voice: { name: 'voice' },
        }
    end

end

# @DataContract
class AiResponseFormat
    include ServiceStack::DTO

    # @DataMember(Name="type")
    # @return [ResponseFormat]
    attr_accessor :type

    def self.properties
        {
            type: { name: 'type' },
        }
    end

end

# @DataContract
class AiToolFunction
    include ServiceStack::DTO

    # @DataMember(Name="name")
    # @return [String]
    attr_accessor :name

    # @DataMember(Name="description")
    # @return [String]
    attr_accessor :description

    # @DataMember(Name="parameters")
    # @return [Dictionary]
    attr_accessor :parameters

    def self.properties
        {
            name: { name: 'name' },
            description: { name: 'description' },
            parameters: { name: 'parameters' },
        }
    end

end

# @DataContract
class Tool
    include ServiceStack::DTO

    # @DataMember(Name="type")
    # @return [ToolType]
    attr_accessor :type

    # @DataMember(Name="function")
    # @return [AiToolFunction]
    attr_accessor :function

    def self.properties
        {
            type: { name: 'type' },
            function: { name: 'function', type: AiToolFunction },
        }
    end

end

#
# Chat Completions API (OpenAI-Compatible)
#
# @DataContract
class ChatCompletion
    include ServiceStack::DTO

    # @DataMember(Name="messages")
    # @return [List]
    attr_accessor :messages

    # @DataMember(Name="model")
    # @return [String]
    attr_accessor :model

    # @DataMember(Name="audio")
    # @return [AiChatAudio]
    attr_accessor :audio

    # @DataMember(Name="logit_bias")
    # @return [Dictionary]
    attr_accessor :logit_bias

    # @DataMember(Name="metadata")
    # @return [Dictionary]
    attr_accessor :metadata

    # @DataMember(Name="reasoning_effort")
    # @return [String]
    attr_accessor :reasoning_effort

    # @DataMember(Name="response_format")
    # @return [AiResponseFormat]
    attr_accessor :response_format

    # @DataMember(Name="service_tier")
    # @return [String]
    attr_accessor :service_tier

    # @DataMember(Name="safety_identifier")
    # @return [String]
    attr_accessor :safety_identifier

    # @DataMember(Name="stop")
    # @return [List]
    attr_accessor :stop

    # @DataMember(Name="modalities")
    # @return [List]
    attr_accessor :modalities

    # @DataMember(Name="prompt_cache_key")
    # @return [String]
    attr_accessor :prompt_cache_key

    # @DataMember(Name="tools")
    # @return [List]
    attr_accessor :tools

    # @DataMember(Name="verbosity")
    # @return [String]
    attr_accessor :verbosity

    # @DataMember(Name="temperature")
    # @return [Float]
    attr_accessor :temperature

    # @DataMember(Name="max_completion_tokens")
    # @return [Integer]
    attr_accessor :max_completion_tokens

    # @DataMember(Name="top_logprobs")
    # @return [Integer]
    attr_accessor :top_logprobs

    # @DataMember(Name="top_p")
    # @return [Float]
    attr_accessor :top_p

    # @DataMember(Name="frequency_penalty")
    # @return [Float]
    attr_accessor :frequency_penalty

    # @DataMember(Name="presence_penalty")
    # @return [Float]
    attr_accessor :presence_penalty

    # @DataMember(Name="seed")
    # @return [Integer]
    attr_accessor :seed

    # @DataMember(Name="n")
    # @return [Integer]
    attr_accessor :n

    # @DataMember(Name="store")
    # @return [TrueClass]
    attr_accessor :store

    # @DataMember(Name="logprobs")
    # @return [TrueClass]
    attr_accessor :logprobs

    # @DataMember(Name="parallel_tool_calls")
    # @return [TrueClass]
    attr_accessor :parallel_tool_calls

    # @DataMember(Name="enable_thinking")
    # @return [TrueClass]
    attr_accessor :enable_thinking

    # @DataMember(Name="stream")
    # @return [TrueClass]
    attr_accessor :stream

    def self.properties
        {
            messages: { name: 'messages', type: [AiMessage] },
            model: { name: 'model' },
            audio: { name: 'audio', type: AiChatAudio },
            logit_bias: { name: 'logit_bias' },
            metadata: { name: 'metadata' },
            reasoning_effort: { name: 'reasoning_effort' },
            response_format: { name: 'response_format', type: AiResponseFormat },
            service_tier: { name: 'service_tier' },
            safety_identifier: { name: 'safety_identifier' },
            stop: { name: 'stop' },
            modalities: { name: 'modalities' },
            prompt_cache_key: { name: 'prompt_cache_key' },
            tools: { name: 'tools', type: [Tool] },
            verbosity: { name: 'verbosity' },
            temperature: { name: 'temperature' },
            max_completion_tokens: { name: 'max_completion_tokens' },
            top_logprobs: { name: 'top_logprobs' },
            top_p: { name: 'top_p' },
            frequency_penalty: { name: 'frequency_penalty' },
            presence_penalty: { name: 'presence_penalty' },
            seed: { name: 'seed' },
            n: { name: 'n' },
            store: { name: 'store' },
            logprobs: { name: 'logprobs' },
            parallel_tool_calls: { name: 'parallel_tool_calls' },
            enable_thinking: { name: 'enable_thinking' },
            stream: { name: 'stream' },
        }
    end

    def response_type() = ChatResponse
    def get_type_name() = 'ChatCompletion'
end

Ruby ChatCompletion DTOs

To override the Content-type in your clients, use the HTTP Accept Header, append the .jsv suffix or ?format=jsv

HTTP + JSV

The following are sample HTTP requests and responses. The placeholders shown need to be replaced with actual values.

POST /v1/chat/completions HTTP/1.1 
Host: blazor-vue.web-templates.io 
Accept: text/jsv
Content-Type: text/jsv
Content-Length: length

{
	messages: 
	[
		{
			content: 
			[
				{
					
				}
			],
			role: String,
			name: String,
			tool_calls: 
			[
				{
					id: String,
					type: String,
					function: 
					{
						name: String,
						arguments: String
					}
				}
			],
			tool_call_id: String,
			reasoning: String,
			reasoning_content: String,
			timestamp: 0,
			images: 
			[
				{
					
				}
			]
		}
	],
	model: String,
	audio: 
	{
		format: String,
		voice: String
	},
	logit_bias: 
	{
		0: 0
	},
	metadata: 
	{
		String: String
	},
	reasoning_effort: String,
	response_format: 
	{
		type: text
	},
	service_tier: String,
	safety_identifier: String,
	stop: 
	[
		String
	],
	modalities: 
	[
		String
	],
	prompt_cache_key: String,
	tools: 
	[
		{
			type: function,
			function: 
			{
				name: String,
				description: String,
				parameters: 
				{
					String: {}
				}
			}
		}
	],
	verbosity: String,
	temperature: 0,
	max_completion_tokens: 0,
	top_logprobs: 0,
	top_p: 0,
	frequency_penalty: 0,
	presence_penalty: 0,
	seed: 0,
	n: 0,
	store: False,
	logprobs: False,
	parallel_tool_calls: False,
	enable_thinking: False,
	stream: False
}
HTTP/1.1 200 OK
Content-Type: text/jsv
Content-Length: length

{
	id: String,
	choices: 
	[
		{
			finish_reason: String,
			index: 0,
			message: 
			{
				content: String,
				refusal: String,
				reasoning: String,
				reasoning_content: String,
				thinking: String,
				role: String,
				timestamp: 0,
				tool_call_id: String,
				images: 
				[
					{
						
					}
				],
				audios: 
				[
					{
						
					}
				],
				files: 
				[
					{
						
					}
				],
				annotations: 
				[
					{
						type: String,
						url_citation: 
						{
							end_index: 0,
							start_index: 0,
							title: String,
							url: String
						}
					}
				],
				audio: 
				{
					data: String,
					expires_at: 0,
					id: String,
					transcript: String
				},
				tool_calls: 
				[
					{
						id: String,
						type: String,
						function: 
						{
							name: String,
							arguments: String
						}
					}
				]
			},
			logprobs: 
			{
				content: 
				[
					{
						token: String,
						logprob: 0,
						bytes: AA==,
						top_logprobs: 
						[
							{
								token: String,
								logprob: 0,
								bytes: AA==,
								top_logprobs: 
								[
									{
										token: String,
										logprob: 0,
										bytes: AA==
									}
								]
							}
						]
					}
				]
			}
		}
	],
	created: 0,
	model: String,
	system_fingerprint: String,
	object: String,
	service_tier: String,
	usage: 
	{
		completion_tokens: 0,
		prompt_tokens: 0,
		total_tokens: 0,
		completion_tokens_details: 
		{
			accepted_prediction_tokens: 0,
			audio_tokens: 0,
			reasoning_tokens: 0,
			rejected_prediction_tokens: 0
		},
		prompt_tokens_details: 
		{
			accepted_prediction_tokens: 0,
			audio_tokens: 0,
			cached_tokens: 0
		},
		duration: 0
	},
	provider: String,
	cost: 0,
	tool_history: 
	[
		{
			content: String,
			refusal: String,
			reasoning: String,
			reasoning_content: String,
			thinking: String,
			role: String,
			timestamp: 0,
			tool_call_id: String,
			images: 
			[
				{
					
				}
			],
			audios: 
			[
				{
					
				}
			],
			files: 
			[
				{
					
				}
			],
			annotations: 
			[
				{
					type: String,
					url_citation: 
					{
						end_index: 0,
						start_index: 0,
						title: String,
						url: String
					}
				}
			],
			audio: 
			{
				data: String,
				expires_at: 0,
				id: String,
				transcript: String
			},
			tool_calls: 
			[
				{
					id: String,
					type: String,
					function: 
					{
						name: String,
						arguments: String
					}
				}
			]
		}
	],
	metadata: 
	{
		String: String
	},
	responseStatus: 
	{
		errorCode: String,
		message: String,
		stackTrace: String,
		errors: 
		[
			{
				errorCode: String,
				fieldName: String,
				message: String,
				meta: 
				{
					String: String
				}
			}
		],
		meta: 
		{
			String: String
		}
	}
}