Personnalisé Models
Ajoutez des fournisseurs et des modèles personnalisés (Ollama, vLLM, LM Studio, proxys) via ~/.pi/agent/models.json.
Table des matières
- Minimal Example
- Full Example
- Supported APIs
- Provider Configuration
- Model Configuration
- Overriding Built-in Providers
- Per-model Overrides
- Anthropic Messages Compatibility
- OpenAI Compatibility
Exemple minimal
Pour les modèles locaux (Ollama, LM Studio, vLLM), seul id est requis par modèle:
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [
{ "id": "llama3.1:8b" },
{ "id": "qwen2.5-coder:7b" }
]
}
}
}La valeur apiKey est un espace réservé car Ollama l'ignore. pi traite toujours les modèles comme nécessitant une authentification avant d'apparaître dans /model, donc les serveurs locaux sans clé doivent conserver une valeur factice, enregistrer une clé pour ce fournisseur avec /login ou transmettre --api-key lors de la sélection du modèle.
Certains serveurs compatibles OpenAI ne comprennent pas le rôle developer utilisé pour les modèles capables de raisonner. Pour ces fournisseurs, définissez compat.supportsDeveloperRole sur false afin que pi envoie l'invite système sous forme de message system à la place. Si le serveur ne prend pas non plus en charge reasoning_effort, définissez également compat.supportsReasoningEffort sur false.
Vous pouvez définir compat au niveau du fournisseur pour l'appliquer à tous les modèles, ou au niveau du modèle pour remplacer un modèle spécifique. Cela s'applique généralement aux serveurs Ollama, vLLM, SGLang et similaires compatibles OpenAI.
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"compat": {
"supportsDeveloperRole": false,
"supportsReasoningEffort": false
},
"models": [
{
"id": "gpt-oss:20b",
"reasoning": true
}
]
}
}
}Exemple complet
Remplacez les valeurs par défaut lorsque vous avez besoin de valeurs spécifiques:
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [
{
"id": "llama3.1:8b",
"name": "Llama 3.1 8B (Local)",
"reasoning": false,
"input": ["text"],
"contextWindow": 128000,
"maxTokens": 32000,
"cost": { "input": 0, "output": 0, "cacheRead": 0, "cacheWrite": 0 }
}
]
}
}
}Le fichier se recharge à chaque fois que vous ouvrez /model. Modifier pendant la session; aucun redémarrage n'est nécessaire.
Exemple de Google AI Studio
Utilisez google-generative-ai avec un baseUrl pour ajouter des modèles de Google AI Studio, y compris des entrées Gemma 4 personnalisées:
{
"providers": {
"my-google": {
"baseUrl": "https://generativelanguage.googleapis.com/v1beta",
"api": "google-generative-ai",
"apiKey": "$GEMINI_API_KEY",
"models": [
{
"id": "gemma-4-31b-it",
"name": "Gemma 4 31B",
"input": ["text", "image"],
"contextWindow": 262144,
"reasoning": true
}
]
}
}
}Le baseUrl est requis lors de l'ajout de modèles personnalisés au type google-generative-ai API.
API pris en charge
| API | Description |
|---|---|
openai-completions |
Achèvements de chat OpenAI (les plus compatibles) |
openai-responses |
Réponses OpenAI API |
anthropic-messages |
Messages anthropiques API |
google-generative-ai |
IA générative de Google |
Définissez api au niveau du fournisseur (par défaut pour tous les modèles) ou au niveau du modèle (remplacement par modèle).
Configuration du fournisseur
| Champ | Description |
|---|---|
baseUrl |
API URL du point de terminaison |
api |
Tapez API (voir ci-dessus) |
apiKey |
Configuration API key facultative (voir résolution de valeur ci-dessous). Omettez-le lorsque l'authentification est fournie par /login/auth.json ou CLI --api-key. |
oauth |
Type de fournisseur dynamique OAuth. Prend actuellement en charge "radius"; nécessite la passerelle baseUrl. |
headers |
En-têtes personnalisés (voir la résolution des valeurs ci-dessous) |
authHeader |
Définissez true pour ajouter Authorization: Bearer <apiKey> automatiquement |
models |
Tableau de configurations de modèles |
modelOverrides |
Remplacements par modèle pour les modèles intégrés ou enregistrés avec une extension sur ce fournisseur |
Pour les fournisseurs avec models, les configurations de fournisseur non intégrées ont besoin de baseUrl et d'une valeur api au niveau du fournisseur ou du modèle. apiKey n'est pas requis pour charger le fichier: les modèles deviennent disponibles lorsque l'authentification est configurée via /login/auth.json, CLI --api-key ou le fournisseur apiKey. Si aucune authentification n'est configurée, les modèles se chargent mais restent indisponibles en /model et --list-models.
Résolution de valeur
Les champs apiKey et headers prennent en charge l'exécution de commandes, l'interpolation d'environnement et les littéraux:
- Commande Shell:
"!command"au début exécute la valeur entière en tant que commande et utilise stdout"apiKey": "!security find-generic-password -ws 'anthropic'" "apiKey": "!op read 'op://vault/item/credential'" - Interpolation d'environnement:
"$ENV_VAR"ou"${ENV_VAR}"utilise la valeur de la variable nommée. L'interpolation fonctionne à l'intérieur de littéraux plus grands."apiKey": "$MY_API_KEY" "apiKey": "${KEY_PREFIX}_${KEY_SUFFIX}"$FOO_BARest la variableFOO_BAR; utilisez${FOO}_BARlorsqueBARest un texte littéral. Les variables d'environnement manquantes rendent la valeur non résolue. - Échappe:
"quot;émet un"quot;littéral;"$!"émet un"!"littéral sans déclencher l'exécution de la commande."apiKey": "$literal-dollar-prefix" "apiKey": "$!literal-bang-prefix" - Valeur littérale: Utilisé directement. Les chaînes majuscules simples telles que
MY_API_KEYsont des littéraux; utilisez$MY_API_KEYpour les variables d'environnement."apiKey": "sk-..."
Pour models.json, les commandes shell sont résolues au moment de la demande. pi n'applique pas intentionnellement le TTL intégré, la réutilisation obsolète ou la logique de récupération pour les commandes arbitraires. Différentes commandes nécessitent différentes stratégies de mise en cache et de défaillance, et pi ne peut pas déduire la bonne.
Si votre commande est lente, coûteuse, limitée en débit ou si elle doit continuer à utiliser une valeur précédente en cas d'échecs transitoires, enveloppez-la dans votre propre script ou commande qui implémente la mise en cache ou le comportement TTL souhaité.
Les contrôles de disponibilité /model utilisent la présence d'authentification configurée et n'exécutent pas de commandes shell.
En-têtes personnalisés
{
"providers": {
"custom-proxy": {
"baseUrl": "https://proxy.example.com/v1",
"apiKey": "$MY_API_KEY",
"api": "anthropic-messages",
"headers": {
"x-portkey-api-key": "$PORTKEY_API_KEY",
"x-secret": "!op read 'op://vault/item/secret'"
},
"models": [...]
}
}
}Configuration du modèle
| Champ | Requis | Défaut | Description |
|---|---|---|---|
id |
Oui | — | Identifiant du modèle (passé au API) |
name |
Non | id |
Étiquette de modèle lisible par l'homme. Utilisé pour la correspondance (modèles --model) et affiché comme texte de détail du modèle secondaire. |
api |
Non | api du fournisseur |
Remplacer le API du fournisseur pour ce modèle |
reasoning |
Non | false |
Prend en charge la réflexion étendue |
thinkingLevelMap |
Non | omis | Mappe les niveaux de réflexion Pi aux valeurs du fournisseur et marque les niveaux non pris en charge (voir ci-dessous) |
input |
Non | ["text"] |
Types d'entrée: ["text"] ou ["text", "image"] |
contextWindow |
Non | 128000 |
Taille de la fenêtre contextuelle en jetons |
maxTokens |
Non | 16384 |
Jetons de sortie maximale |
samplingParams |
Non | omis | Paramètres d'échantillonnage fusionnés textuellement dans chaque corps de requête (voir ci-dessous) |
cost |
Non | tous les zéros | Tarifs par million de jetons avec niveaux de tarification d'entrée facultatifs à l'échelle de la demande |
compat |
Non | fournisseur compat |
Remplacements de compatibilité du fournisseur. Fusionné avec le niveau du fournisseur compat lorsque les deux sont définis. |
Un niveau de coût fournit un ensemble complet de tarifs alternatifs et s'applique à la demande complète lorsque l'utilisation totale des entrées (input + cacheRead + cacheWrite) dépasse inputTokensAbove. Lorsque plusieurs niveaux correspondent, le seuil le plus élevé l’emporte.
{
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 6.25,
"tiers": [
{
"inputTokensAbove": 272000,
"input": 10,
"output": 45,
"cacheRead": 1,
"cacheWrite": 12.5
}
]
}
}Comportement actuel:
/model,--list-modelset le pied de page interactif affichent les entrées par modèleid.- Le
nameconfiguré est utilisé pour la correspondance du modèle et le texte détaillé du modèle secondaire. Il ne remplace pas l’identifiant du modèle de pied de page/barre d’état.
Paramètres d'échantillonnage
samplingParams est un objet de forme libre fusionné textuellement dans chaque corps de requête pour le modèle, une fois que les champs pi se sont définis, de sorte que ses clés gagnent. Utilisez-le pour envoyer des paramètres d'échantillonnage que pi ne modélise pas, y compris ceux spécifiques au serveur comme le min_p de llama.cpp ou le top_k de vLLM:
{
"id": "deepseek-v4-flash",
"samplingParams": {
"temperature": 1.0,
"top_p": 0.95,
"top_k": 0,
"min_p": 0.0
}
}Seuls les API compatibles OpenAI l'appliquent (openai-completions, openai-responses, azure-openai-responses); les autres API l'ignorent. Les clés remplacent les champs de requête nommés de pi (par exemple, une touche temperature bat ici la température au niveau de la requête), préférez-la donc comme source unique de vérité d'échantillonnage pour un modèle. Dans modelOverrides, samplingParams fusionne par clé avec la valeur du modèle de base.
Carte des niveaux de réflexion
Utilisez thinkingLevelMap sur un modèle pour décrire les contrôles de réflexion spécifiques au modèle. Les clés sont les niveaux de pensée Pi: off, minimal, low, medium, high, xhigh, max. Les cartes peuvent contenir des trous; par exemple, un modèle peut exposer high et max sans exposer xhigh.
Les valeurs sont à trois états:
| Valeur | Signification |
|---|---|
| omis | Les niveaux standard jusqu'à high utilisent le mappage par défaut du fournisseur; Les niveaux étendus xhigh et max ne sont pas pris en charge |
| chaîne | Le niveau est pris en charge et cette valeur est envoyée au fournisseur |
null |
Le niveau n'est pas pris en charge et est masqué/ignoré/bloqué |
Exemple pour un modèle qui prend uniquement en charge les raisonnements off, high et max:
{
"id": "deepseek-v4-pro",
"reasoning": true,
"thinkingLevelMap": {
"minimal": null,
"low": null,
"medium": null,
"high": "high",
"xhigh": null,
"max": "max"
}
}Exemple de modèle où la pensée ne peut pas être désactivée:
{
"id": "always-thinking-model",
"reasoning": true,
"thinkingLevelMap": {
"off": null
}
}Migration: les anciennes configurations qui utilisaient compat.reasoningEffortMap devraient déplacer ce mappage au niveau du modèle thinkingLevelMap. Utilisez null pour les niveaux qui ne doivent pas apparaître dans l'interface utilisateur.
Remplacement du Providers intégré
Acheminez un fournisseur intégré via un proxy sans redéfinir les modèles:
{
"providers": {
"anthropic": {
"baseUrl": "https://my-proxy.example.com/v1"
}
}
}Tous les modèles Anthropic intégrés restent disponibles. L'authentification OAuth ou API key existante continue de fonctionner.
Pour fusionner des modèles personnalisés dans un fournisseur intégré, incluez le tableau models:
{
"providers": {
"anthropic": {
"baseUrl": "https://my-proxy.example.com/v1",
"apiKey": "$ANTHROPIC_API_KEY",
"api": "anthropic-messages",
"models": [...]
}
}
}Fusionner la sémantique:
- Les modèles intégrés sont conservés.
- Les modèles personnalisés sont remplacés par
idau sein du fournisseur. - Si un modèle personnalisé
idcorrespond à un modèle intégréid, le modèle personnalisé remplace ce modèle intégré. - Si un modèle personnalisé
idest nouveau, il est ajouté aux côtés des modèles intégrés.
Remplacements par modèle
Utilisez modelOverrides pour personnaliser les modèles intégrés et les modèles correspondants enregistrés avec l'extension sans remplacer la liste complète des modèles du fournisseur.
{
"providers": {
"openrouter": {
"modelOverrides": {
"anthropic/claude-sonnet-4": {
"name": "Claude Sonnet 4 (Bedrock Route)",
"compat": {
"openRouterRouting": {
"only": ["amazon-bedrock"]
}
}
}
}
}
}
}modelOverrides prend en charge ces champs par modèle: name, reasoning, thinkingLevelMap, input, cost (partiel), contextWindow, maxTokens, samplingParams (fusionné par clé), headers, compat.
Direct OpenAI GPT-5.6 Sol, Terra et Luna par défaut sur une fenêtre contextuelle 272000 afin que les demandes restent dans le niveau tarifaire à contexte court d'OpenAI. Pour activer la fenêtre contextuelle de 1,05 million d'OpenAI, augmentez-la pour chaque modèle que vous utilisez:
{
"providers": {
"openai": {
"modelOverrides": {
"gpt-5.6-sol": {
"contextWindow": 1050000
}
}
}
}
}Le remplacement préserve les métadonnées de tarification intégrées. Les requêtes comportant plus de 272 000 jetons d'entrée au total utilisent les taux de contexte long de GPT-5.6 pour l'intégralité de la requête. Appliquez le même remplacement à gpt-5.6-terra ou gpt-5.6-luna si nécessaire.
Notes de comportement:
modelOverridessont appliqués aux modèles de fournisseur intégrés et aux modèles de fournisseur enregistrés par extension correspondants.- Les ID de modèle inconnus sont ignorés.
- Vous pouvez combiner
baseUrl/headersau niveau du fournisseur avecmodelOverrides. - Le remplacement de
namemodifie uniquement la correspondance du modèle et le texte des détails secondaires; les listes de pied de page et de modèles principaux continuent d'afficher le modèleid. - Si
modelsest également défini pour un fournisseur, les modèles personnalisés sont fusionnés après les remplacements intégrés. Un modèle personnalisé avec le mêmeidremplace l'entrée de modèle intégrée remplacée.
Compatibilité des messages anthropiques
Pour les fournisseurs ou les proxys utilisant api: "anthropic-messages", utilisez compat pour contrôler la compatibilité des requêtes spécifiques à Anthropic.
Par défaut, pi envoie par outil eager_input_streaming: true. Si un proxy ou un backend compatible Anthropic rejette ce champ, définissez supportsEagerToolInputStreaming sur false. Pi omettra tools[].eager_input_streaming et enverra à la place l'ancien en-tête bêta fine-grained-tool-streaming-2025-05-14 pour les requêtes activées par les outils.
Certains modèles anthropiques nécessitent une pensée adaptative (thinking.type: "adaptive" plus output_config.effort) au lieu de la charge utile de réflexion traditionnelle basée sur le budget. Les modèles intégrés le règlent automatiquement. Pour les fournisseurs personnalisés ou les alias qui redirigent vers ces modèles, définissez forceAdaptiveThinking sur true.
Certains fournisseurs compatibles Anthropic émettent des blocs de réflexion avec des signatures vides et les attendent toujours lors de la relecture. Définissez allowEmptySignature sur true uniquement pour ces fournisseurs; Le véritable Anthropique rejette les signatures vides de sens.
Les modèles anthropiques intégrés activent supportsStrictTools dans leurs métadonnées de modèle. Les modèles personnalisés compatibles Anthropic doivent le définir sur true lorsque leur point de terminaison accepte les définitions strictes de l'outil de schéma JSON.
{
"providers": {
"anthropic-proxy": {
"baseUrl": "https://proxy.example.com",
"api": "anthropic-messages",
"apiKey": "$ANTHROPIC_PROXY_KEY",
"compat": {
"supportsEagerToolInputStreaming": false,
"supportsLongCacheRetention": true,
"forceAdaptiveThinking": true,
"allowEmptySignature": true
},
"models": [
{
"id": "claude-opus-4-7",
"reasoning": true,
"input": ["text", "image"]
}
]
}
}
}| Champ | Description |
|---|---|
supportsEagerToolInputStreaming |
Si le fournisseur accepte par outil eager_input_streaming. Par défaut: true. Définissez sur false pour omettre ce champ et utiliser l'en-tête bêta de streaming d'outils à granularité fine hérité sur les requêtes activées par les outils. |
supportsLongCacheRetention |
Indique si le fournisseur accepte la rétention de cache longue Anthropic (cache_control.ttl: "1h") lorsque la rétention de cache est long. Par défaut: true. |
sendSessionAffinityHeaders |
S'il faut envoyer x-session-affinity à partir de l'identifiant de session lorsque la mise en cache est activée. Par défaut: détecté automatiquement pour les fournisseurs connus. |
supportsCacheControlOnTools |
Indique si le fournisseur accepte les marqueurs cache_control de style anthropique sur les définitions d'outils. Par défaut: true. |
forceAdaptiveThinking |
S'il faut envoyer une pensée adaptative (thinking.type: "adaptive" plus output_config.effort) pour ce modèle. Les modèles adaptatifs intégrés règlent cela automatiquement. Par défaut: false. |
allowEmptySignature |
S'il faut rejouer les signatures de pensée vides sous la forme signature: "" au lieu de convertir la pensée en texte. Par défaut: false. |
supportsStrictTools |
Indique si le fournisseur accepte les définitions strictes des outils de schéma JSON. Par défaut: false; Les modèles anthropiques intégrés le permettent dans les métadonnées générées. |
Compatibilité OpenAI
Pour les fournisseurs offrant une compatibilité partielle avec OpenAI, utilisez le champ compat.
- Au niveau du fournisseur
compatapplique les valeurs par défaut à tous les modèles sous ce fournisseur. - Au niveau du modèle
compatremplace les valeurs au niveau du fournisseur pour ce modèle.
{
"providers": {
"local-llm": {
"baseUrl": "http://localhost:8080/v1",
"api": "openai-completions",
"compat": {
"supportsUsageInStreaming": false,
"maxTokensField": "max_tokens"
},
"models": [...]
}
}
}| Champ | Description |
|---|---|
supportsStore |
Le fournisseur prend en charge le champ store |
supportsDeveloperRole |
Utilisez le rôle developer vs system |
supportsReasoningEffort |
Prise en charge du paramètre reasoning_effort |
supportsUsageInStreaming |
Prend en charge stream_options: { include_usage: true } (par défaut: true) |
supportsFinishReason |
Si les réponses diffusées incluent finish_reason. Lorsque false, pi déduit stop ou toolUse lorsque le flux se termine. Par défaut: true. |
maxTokensField |
Utilisez max_completion_tokens ou max_tokens |
requiresToolResultName |
Incluez name dans les messages de résultat de l'outil |
requiresAssistantAfterToolResult |
Insérer un message d'assistant avant un message utilisateur après les résultats de l'outil |
requiresThinkingAsText |
Convertir les blocs de réflexion en texte brut |
requiresReasoningContentOnAssistantMessages |
Incluez un reasoning_content vide sur tous les messages de l'assistant rejoués lorsque le raisonnement est activé |
thinkingFormat |
Utilisez les paramètres de réflexion reasoning_effort, openrouter, deepseek, together, baseten, zai, qwen, chat-template ou qwen-chat-template |
chatTemplateKwargs |
Valeurs chat_template_kwargs pour thinkingFormat: "chat-template"; utilisez { "$var": "thinking.enabled" } ou { "$var": "thinking.effort" } pour les valeurs de pensée contrôlées par pi |
chatTemplateArgs |
Valeurs chat_template_args pour thinkingFormat: "baseten"; utilisez { "$var": "thinking.enabled" } ou { "$var": "thinking.effort" } pour les valeurs de pensée contrôlées par pi |
cacheControlFormat |
Utilisez des marqueurs cache_control de style anthropique sur l'invite système, la dernière définition d'outil et le contenu textuel du dernier utilisateur, assistant ou résultat de l'outil. Actuellement, seul anthropic est pris en charge. |
sendSessionAffinityHeaders |
Pour openai-completions, envoyez les en-têtes d'affinité de session à partir de l'identifiant de session lorsque la mise en cache est activée. Par défaut: false. |
sessionAffinityFormat |
Pour openai-completions et openai-responses, le format d'en-tête d'affinité de session: openai envoie session_id/x-client-request-id (les complétions également x-session-affinity), openai-nosession omet l'en-tête session_id contenant le trait de soulignement, openrouter envoie x-session-id. N'affecte pas le paramètre de corps prompt_cache_key. Par défaut: détection automatique. |
supportsStrictMode |
Si le fournisseur accepte les définitions strictes des outils de fonction de schéma JSON. Les valeurs par défaut dépendent du API; Les modèles OpenAI intégrés contiennent des métadonnées de capacités explicites. |
supportsOpenAIGrammarTools |
Si les API compatibles OpenAI émettent des outils de grammaire Lark/regex personnalisés. Lorsque false, les outils contraints par la grammaire reviennent aux outils de fonction normaux. Par défaut: false; le catalogue de modèles intégré le permet pour les modèles GPT-5+ sur OpenAI, OpenAI Codex, Azure OpenAI, GitHub Copilot, opencode et Cloudflare AI Gateway. |
deferredToolsMode |
Utilisez la sérialisation différée des outils spécifique au fournisseur. Actuellement, seul "kimi" est pris en charge pour le format de complétion de discussion compatible OpenAI de Kimi. |
supportsLongCacheRetention |
Indique si le fournisseur accepte une longue conservation du cache lorsque la rétention du cache est long: prompt_cache_retention: "24h" pour la mise en cache des invites OpenAI, ou cache_control.ttl: "1h" lorsque cacheControlFormat est anthropic. Par défaut: true. |
openRouterRouting |
Préférences de routage du fournisseur OpenRouter. Cet objet est envoyé tel quel dans le champ provider du OpenRouter API request. |
vercelGatewayRouting |
Configuration de routage Vercel AI Gateway pour la sélection du fournisseur (only, order) |
openrouter utilise reasoning: { effort }. together utilise reasoning: { enabled } et également reasoning_effort lorsque supportsReasoningEffort est activé. qwen utilise le niveau supérieur enable_thinking. Utilisez qwen-chat-template pour les serveurs locaux compatibles Qwen qui nécessitent chat_template_kwargs.enable_thinking et preserve_thinking. Utilisez chat-template pour les modèles de discussion vLLM/Hugging Face qui nécessitent un chat_template_kwargs configurable, tel que chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } } pour les modèles DeepSeek V3.x. Utilisez thinkingFormat: "baseten" avec chatTemplateArgs pour les fournisseurs qui exposent des contrôles à bascule via chat_template_args et prennent éventuellement en charge reasoning_effort de niveau supérieur.
cacheControlFormat: "anthropic" est destiné aux fournisseurs compatibles OpenAI qui exposent la mise en cache des invites de style Anthropic via des marqueurs cache_control sur le contenu du texte et les définitions d'outils.
Exemple:
{
"providers": {
"openrouter": {
"baseUrl": "https://openrouter.ai/api/v1",
"apiKey": "$OPENROUTER_API_KEY",
"api": "openai-completions",
"models": [
{
"id": "openrouter/anthropic/claude-3.5-sonnet",
"name": "OpenRouter Claude 3.5 Sonnet",
"compat": {
"openRouterRouting": {
"allow_fallbacks": true,
"require_parameters": false,
"data_collection": "deny",
"zdr": true,
"enforce_distillable_text": false,
"order": ["anthropic", "amazon-bedrock", "google-vertex"],
"only": ["anthropic", "amazon-bedrock"],
"ignore": ["gmicloud", "friendli"],
"quantizations": ["fp16", "bf16"],
"sort": {
"by": "price",
"partition": "model"
},
"max_price": {
"prompt": 10,
"completion": 20
},
"preferred_min_throughput": {
"p50": 100,
"p90": 50
},
"preferred_max_latency": {
"p50": 1,
"p90": 3,
"p99": 5
}
}
}
}
]
}
}
}Exemple de Vercel AI Gateway:
{
"providers": {
"vercel-ai-gateway": {
"baseUrl": "https://ai-gateway.vercel.sh/v1",
"apiKey": "$AI_GATEWAY_API_KEY",
"api": "openai-completions",
"models": [
{
"id": "moonshotai/kimi-k2.5",
"name": "Kimi K2.5 (Fireworks via Vercel)",
"reasoning": true,
"input": ["text", "image"],
"cost": { "input": 0.6, "output": 3, "cacheRead": 0, "cacheWrite": 0 },
"contextWindow": 262144,
"maxTokens": 262144,
"compat": {
"vercelGatewayRouting": {
"only": ["fireworks", "novita"],
"order": ["fireworks", "novita"]
}
}
}
]
}
}
}