use crate::completion::FinishReason;
use super::{
Auth, AuthAlternative, BodyRewrite, Dialect, DimensionsField, EmbeddingQuirks, ImageBody,
OutputCap, Quirks, RerankQuirks, ResponsesQuirks, Route, Routing, SpeechBody,
SystemInstructionsPlacement, TranscriptionBody,
};
pub(super) const AZURE_API_VERSION_ENV: &str = "AZURE_API_VERSION";
pub const AZURE_DEFAULT_API_VERSION: &str = "2024-10-21";
pub(super) const AZURE_AUDIO_API_VERSION_ENV: &str = "AZURE_AUDIO_API_VERSION";
pub(super) const AZURE_DEFAULT_AUDIO_API_VERSION: &str = "2025-04-01-preview";
pub const OPENAI: Dialect = Dialect {
base_url_env: Some("OPENAI_BASE_URL"),
request_id_header: Some("x-request-id"),
quirks: Quirks {
completion_route: Route::Responses,
output_cap: OutputCap::OpenAiReasoningFamilies,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::openai::PROVIDER_NAME,
"https://api.openai.com/v1",
"OPENAI_API_KEY",
)
};
pub const AZURE: Dialect = Dialect {
base_url_env: Some("AZURE_ENDPOINT"),
alternate_auth: Some(AuthAlternative {
api_key_env: "AZURE_TOKEN",
auth: Auth::Bearer,
}),
quirks: Quirks {
auth: Auth::ApiKeyHeader,
routing: Routing::AzureDeployment,
verify_path: "",
transcription_path: "/audio/translations",
embedding: EmbeddingQuirks {
sends_model_field: false,
..EmbeddingQuirks::openai()
},
..Quirks::openai()
},
..Dialect::gateway(crate::providers::azure::PROVIDER_NAME, "", "AZURE_API_KEY")
};
pub const DEEPSEEK: Dialect = Dialect {
quirks: Quirks {
supports_response_format: false,
verify_path: "/user/balance",
rewrite: BodyRewrite::DeepSeek,
reasoning_field: Some("reasoning_content"),
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::deepseek::PROVIDER_NAME,
"https://api.deepseek.com",
"DEEPSEEK_API_KEY",
)
};
pub const GROQ: Dialect = Dialect {
request_id_header: Some("x-request-id"),
..Dialect::gateway(
crate::providers::groq::PROVIDER_NAME,
"https://api.groq.com/openai/v1",
"GROQ_API_KEY",
)
};
pub const HYPERBOLIC: Dialect = Dialect {
quirks: Quirks {
supports_tools: false,
supports_response_format: false,
completion_path: "/v1/chat/completions",
embeddings_path: "/v1/embeddings",
models_path: "/v1/models",
verify_path: "/models",
image_generation_path: "/v1/image/generation",
audio_generation_path: "/v1/audio/generation",
image_body: ImageBody::Hyperbolic,
speech_body: SpeechBody::Hyperbolic,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::hyperbolic::PROVIDER_NAME,
"https://api.hyperbolic.xyz",
"HYPERBOLIC_API_KEY",
)
};
pub const MIRA: Dialect = Dialect {
quirks: Quirks {
supports_tools: false,
supports_response_format: false,
stream_include_usage: false,
completion_path: "/v1/chat/completions",
models_path: "/v1/models",
verify_path: "/user-credits",
accepts_bare_string_reply: true,
rewrite: BodyRewrite::Mira,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::mira::PROVIDER_NAME,
"https://api.mira.network",
"MIRA_API_KEY",
)
};
pub const PERPLEXITY: Dialect = Dialect {
quirks: Quirks {
supports_tools: false,
supports_response_format: false,
stream_include_usage: false,
verify_path: "",
rewrite: BodyRewrite::Perplexity,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::perplexity::PROVIDER_NAME,
"https://api.perplexity.ai",
"PERPLEXITY_API_KEY",
)
};
pub const TOGETHER: Dialect = Dialect {
quirks: Quirks {
supports_response_format: false,
completion_path: "/v1/chat/completions",
embeddings_path: "/v1/embeddings",
models_path: "/v1/models",
verify_path: "/models",
embedding: EmbeddingQuirks {
requires_usage: false,
supports_encoding_format: false,
supports_user: false,
..EmbeddingQuirks::openai()
},
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::together::PROVIDER_NAME,
"https://api.together.xyz",
"TOGETHER_API_KEY",
)
};
pub const HUGGINGFACE: Dialect = Dialect {
quirks: Quirks {
supports_response_format: false,
completion_path: "/v1/chat/completions",
verify_path: "/api/whoami-v2",
model_is_modality_path: true,
image_body: ImageBody::HuggingFace,
rewrite: BodyRewrite::HuggingFaceRouter,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::huggingface::PROVIDER_NAME,
"https://router.huggingface.co",
"HUGGINGFACE_API_KEY",
)
};
pub const LLAMACPP: Dialect = Dialect {
base_url_env: Some("LLAMACPP_API_BASE_URL"),
quirks: Quirks {
auth: Auth::OptionalBearer,
supports_image_tool_results: true,
verify_path: "/props",
root_relative_routes: &[
"/props",
"/health",
"/slots",
"/metrics",
"/tokenize",
"/detokenize",
"/apply-template",
"/infill",
"/lora-adapters",
],
rewrite: BodyRewrite::LlamaCpp,
rerank: RerankQuirks {
path: "/rerank",
max_documents: 1024,
sends_model_field: true,
},
embedding: EmbeddingQuirks {
dimensions: DimensionsField::Ignored,
..EmbeddingQuirks::openai()
},
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::llamacpp::PROVIDER_NAME,
"http://localhost:8080/v1",
"LLAMACPP_API_KEY",
)
};
pub const MISTRAL: Dialect = Dialect {
request_id_header: Some("mistral-correlation-id"),
quirks: Quirks {
stream_include_usage: false,
later_system: crate::completion::LaterSystem::Leading,
completion_path: "/v1/chat/completions",
embeddings_path: "/v1/embeddings",
models_path: "/v1/models",
verify_path: "/v1/models",
transcription_path: "/v1/audio/transcriptions",
rewrite: BodyRewrite::Mistral,
embedding: EmbeddingQuirks {
max_documents: 256,
supports_user: false,
dimensions: DimensionsField::OutputDimension,
widths: super::modality::MISTRAL_EMBEDDING_WIDTHS,
..EmbeddingQuirks::openai()
},
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::mistral::PROVIDER_NAME,
"https://api.mistral.ai",
"MISTRAL_API_KEY",
)
};
pub const OPENROUTER: Dialect = Dialect {
quirks: Quirks {
stream_include_usage: false,
verify_path: "/key",
native_finish_reason: true,
response_format_with_tools: true,
accepts_file_ids: false,
rewrite: BodyRewrite::OpenRouter,
transcription_body: TranscriptionBody::InputAudioJson,
embedding: EmbeddingQuirks {
requires_usage: false,
..EmbeddingQuirks::openai()
},
responses: ResponsesQuirks {
system_instructions: SystemInstructionsPlacement::InputSystemMessages,
..ResponsesQuirks::openai()
},
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::openrouter::PROVIDER_NAME,
"https://openrouter.ai/api/v1",
"OPENROUTER_API_KEY",
)
};
pub const VENICE: Dialect = Dialect {
base_url_env: Some("VENICE_BASE_URL"),
quirks: Quirks {
image_generation_path: "/image/generate",
image_body: ImageBody::Venice,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::venice::PROVIDER_NAME,
"https://api.venice.ai/api/v1",
"VENICE_API_KEY",
)
};
pub const DOUBLEWORD: Dialect = Dialect {
base_url_env: Some("DOUBLEWORD_BASE_URL"),
quirks: Quirks {
embedding: EmbeddingQuirks {
requires_usage: false,
supports_encoding_format: false,
supports_user: false,
widths: super::modality::DOUBLEWORD_EMBEDDING_WIDTHS,
refuse_zero_width: Some("to be greater than zero"),
..EmbeddingQuirks::openai()
},
reliable_reasoning_count: false,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::doubleword::PROVIDER_NAME,
"https://api.doubleword.ai/v1",
"DOUBLEWORD_API_KEY",
)
};
pub const ZAI: Dialect = Dialect {
base_url_env: Some("ZAI_API_BASE"),
quirks: Quirks {
finishes: &[
("model_context_window_exceeded", FinishReason::Length),
("sensitive", FinishReason::ContentFilter),
],
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::zai::PROVIDER_NAME,
"https://api.z.ai/api/paas/v4",
"ZAI_API_KEY",
)
};
pub const ZAI_CODING: Dialect = Dialect {
base_url: "https://api.z.ai/api/coding/paas/v4",
..ZAI
};
pub const MINIMAX: Dialect = Dialect {
base_url_env: Some("MINIMAX_API_BASE"),
..Dialect::gateway(
crate::providers::minimax::PROVIDER_NAME,
"https://api.minimax.io/v1",
"MINIMAX_API_KEY",
)
};
pub const MINIMAX_CHINA: Dialect = Dialect {
base_url: "https://api.minimaxi.com/v1",
..MINIMAX
};
pub const MOONSHOT: Dialect = Dialect {
base_url_env: Some("MOONSHOT_API_BASE"),
quirks: Quirks {
supports_response_format: false,
rewrite: BodyRewrite::Moonshot,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::moonshot::PROVIDER_NAME,
"https://api.moonshot.ai/v1",
"MOONSHOT_API_KEY",
)
};
pub const MOONSHOT_CHINA: Dialect = Dialect {
base_url: "https://api.moonshot.cn/v1",
..MOONSHOT
};
pub const XIAOMIMIMO: Dialect = Dialect {
base_url_env: Some("XIAOMI_MIMO_API_BASE"),
quirks: Quirks {
reasoning_field: Some("reasoning_content"),
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::xiaomimimo::PROVIDER_NAME,
"https://api.xiaomimimo.com/v1",
"XIAOMI_MIMO_API_KEY",
)
};
pub const COHERE: Dialect = Dialect::gateway(
crate::providers::cohere::PROVIDER_NAME,
"https://api.cohere.ai/compatibility/v1",
"COHERE_API_KEY",
);
pub const OLLAMA: Dialect = Dialect {
quirks: Quirks {
auth: Auth::OptionalBearer,
rewrite: BodyRewrite::Ollama,
..Quirks::openai()
},
..Dialect::gateway(
crate::providers::ollama::PROVIDER_NAME,
"http://localhost:11434/v1",
"OLLAMA_API_KEY",
)
};
pub fn by_name(name: &str) -> Option<&'static Dialect> {
all().find(|dialect| dialect.name == name)
}
pub fn all() -> impl Iterator<Item = &'static Dialect> {
crate::providers::registry::OPENAI_DIALECTS.iter().copied()
}