Пользовательский Models
Добавляйте пользовательских поставщиков и модели (Ollama, vLLM, LM Studio, прокси) через ~/.pi/agent/models.json.
Оглавление
- Minimal Example
- Full Example
- Supported APIs
- Provider Configuration
- Model Configuration
- Overriding Built-in Providers
- Per-model Overrides
- Anthropic Messages Compatibility
- OpenAI Compatibility
Минимальный пример
Для локальных моделей (Ollama, LM Studio, vLLM) для каждой модели требуется только id:
{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [
{ "id": "llama3.1:8b" },
{ "id": "qwen2.5-coder:7b" }
]
}
}
}Значение apiKey является заполнителем, поскольку Оллама его игнорирует. pi по-прежнему рассматривает модели как требующие аутентификации, прежде чем они появятся в /model, поэтому локальные серверы без ключа должны сохранять фиктивное значение, сохранять ключ для этого провайдера с помощью /login или передавать --api-key при выборе модели.
Некоторые OpenAI-совместимые серверы не понимают роль developer, используемую для моделей, способных рассуждать. Для этих провайдеров установите для compat.supportsDeveloperRole значение false, чтобы pi вместо этого отправлял системное приглашение в виде сообщения system. Если сервер также не поддерживает reasoning_effort, установите также compat.supportsReasoningEffort на false.
Вы можете установить compat на уровне поставщика, чтобы применить его ко всем моделям, или на уровне модели, чтобы переопределить конкретную модель. Обычно это относится к Ollama, vLLM, SGLang и аналогичным серверам, совместимым с 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
}
]
}
}
}Полный пример
Переопределите значения по умолчанию, если вам нужны определенные значения:
{
"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 }
}
]
}
}
}Файл перезагружается каждый раз, когда вы открываете /model. Редактировать во время сеанса; перезагрузка не требуется.
Пример Google AI Studio
Используйте google-generative-ai с baseUrl, чтобы добавить модели из Google AI Studio, включая пользовательские записи Gemma 4:
{
"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
}
]
}
}
}baseUrl требуется при добавлении пользовательских моделей к типу google-generative-ai API.
Поддерживается APIс
| API | Описание |
|---|---|
openai-completions |
Завершения чата OpenAI (наиболее совместимые) |
openai-responses |
Ответы OpenAI API |
anthropic-messages |
Антропные сообщения API |
google-generative-ai |
Генеративный искусственный интеллект Google |
Установите api на уровне поставщика (по умолчанию для всех моделей) или уровне модели (переопределение для каждой модели).
Конфигурация поставщика
| Поле | Описание |
|---|---|
baseUrl |
API URL-адрес конечной точки |
api |
тип API (см. выше) |
apiKey |
Дополнительная конфигурация API key (см. разрешение значений ниже). Опустите его, если аутентификация обеспечивается с помощью /login/auth.json или CLI --api-key. |
oauth |
Динамический тип OAuth поставщика. В настоящее время поддерживает "radius"; требуется шлюз baseUrl. |
headers |
Пользовательские заголовки (см. разрешение значений ниже) |
authHeader |
Установите true, чтобы автоматически добавлять Authorization: Bearer <apiKey>. |
models |
Массив конфигураций модели |
modelOverrides |
Переопределения для каждой модели для встроенных или зарегистрированных в расширении моделей этого поставщика. |
Для поставщиков с models для конфигураций невстроенных поставщиков требуются baseUrl и значение api либо на уровне поставщика, либо на уровне модели. apiKey не требуется для загрузки файла: модели становятся доступными, когда аутентификация настроена через /login/auth.json, CLI --api-key или провайдера apiKey. Если аутентификация не настроена, модели загружаются, но остаются недоступными в /model и --list-models.
Разрешение значений
Поля apiKey и headers поддерживают выполнение команд, интерполяцию среды и литералы:
- Команда оболочки:
"!command"в начале выполняет все значение как команду и использует stdout"apiKey": "!security find-generic-password -ws 'anthropic'" "apiKey": "!op read 'op://vault/item/credential'" - Интерполяция среды:
"$ENV_VAR"или"${ENV_VAR}"использует значение именованной переменной. Интерполяция работает внутри больших литералов."apiKey": "$MY_API_KEY" "apiKey": "${KEY_PREFIX}_${KEY_SUFFIX}"$FOO_BAR— переменнаяFOO_BAR; используйте${FOO}_BAR, когдаBAR— это буквальный текст. Отсутствие переменных среды делает значение неразрешенным. - Эскейп:
"quot;выдает литерал"quot;;"$!"выдает литерал"!", не запуская выполнение команды."apiKey": "$literal-dollar-prefix" "apiKey": "$!literal-bang-prefix" - Буквальное значение: Используется напрямую. Обычные строки в верхнем регистре, такие как
MY_API_KEY, являются литералами; используйте$MY_API_KEYдля переменных среды."apiKey": "sk-..."
Для models.json команды оболочки обрабатываются во время запроса. pi намеренно не применяет встроенную логику TTL, устаревшего повторного использования или восстановления для произвольных команд. Разным командам нужны разные стратегии кэширования и отказов, и pi не может сделать правильный выбор.
Если ваша команда медленная, дорогая, ограничена по скорости или должна продолжать использовать предыдущее значение при временных сбоях, оберните ее в свой собственный сценарий или команду, которая реализует желаемое поведение кэширования или TTL.
/model проверки доступности используют настроенное присутствие аутентификации и не выполняют команды оболочки.
Пользовательские заголовки
{
"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": [...]
}
}
}Конфигурация модели
| Поле | Необходимый | По умолчанию | Описание |
|---|---|---|---|
id |
Да | — | Идентификатор модели (передается в API) |
name |
Нет | id |
Читаемая человеком этикетка модели. Используется для сопоставления (шаблоны --model) и отображается как вторичный подробный текст модели. |
api |
Нет | api провайдера |
Переопределить API поставщика для этой модели. |
reasoning |
Нет | false |
Поддерживает расширенное мышление |
thinkingLevelMap |
Нет | опущен | Сопоставляет уровни мышления «пи» со значениями поставщика и отмечает неподдерживаемые уровни (см. ниже). |
input |
Нет | ["text"] |
Типы ввода: ["text"] или ["text", "image"] |
contextWindow |
Нет | 128000 |
Размер контекстного окна в токенах |
maxTokens |
Нет | 16384 |
Максимальное количество токенов вывода |
samplingParams |
Нет | опущен | Параметры выборки дословно объединены в тело каждого запроса (см. ниже). |
cost |
Нет | все нули | Ставки за миллион токенов с дополнительными ценовыми уровнями входных данных для всего запроса |
compat |
Нет | провайдер compat |
Переопределяет совместимость поставщика. Объединяется с уровнем провайдера compat, если оба установлены. |
Уровень затрат предоставляет полный набор альтернативных тарифов и применяется к полному запросу, когда общее использование входных данных (input + cacheRead + cacheWrite) превышает inputTokensAbove. При совпадении нескольких уровней выигрывает наивысший порог.
{
"cost": {
"input": 5,
"output": 30,
"cacheRead": 0.5,
"cacheWrite": 6.25,
"tiers": [
{
"inputTokensAbove": 272000,
"input": 10,
"output": 45,
"cacheRead": 1,
"cacheWrite": 12.5
}
]
}
}Текущее поведение:
/model,--list-models, а в интерактивном нижнем колонтитуле записи отображаются по моделиid.- Настроенный
nameиспользуется для сопоставления модели и дополнительного подробного текста модели. Он не заменяет идентификатор модели нижнего колонтитула/строки состояния.
Параметры выборки
samplingParams — это объект свободной формы, дословно включаемый в каждое тело запроса модели после того, как поля pi задаются сами собой, поэтому его ключи выигрывают. Используйте его для отправки параметров выборки, которые pi не моделирует, включая специфичные для сервера, такие как min_p llama.cpp или top_k vLLM:
{
"id": "deepseek-v4-flash",
"samplingParams": {
"temperature": 1.0,
"top_p": 0.95,
"top_k": 0,
"min_p": 0.0
}
}Его применяют только OpenAI-совместимые API (openai-completions, openai-responses, azure-openai-responses); другие API игнорируют это. Ключи переопределяют именованные поля запроса pi (например, ключ temperature здесь превосходит температуру уровня запроса), поэтому предпочитайте его как единственный источник истинности выборки для модели. В modelOverrides, samplingParams объединяется по ключу со значением базовой модели.
Карта уровня мышления
Используйте thinkingLevelMap в модели, чтобы описать элементы управления мышлением, специфичные для модели. Ключи — это уровни Пи-мышления: off, minimal, low, medium, high, xhigh, max. Карты могут содержать дыры; например, модель может выставлять high и max, не выставляя xhigh.
Значения имеют три состояния:
| Ценить | Значение |
|---|---|
| опущен | Стандартные уровни до high используют сопоставление поставщика по умолчанию; расширенные уровни xhigh и max не поддерживаются |
| нить | Уровень поддерживается, и это значение отправляется провайдеру. |
null |
Уровень не поддерживается и скрыт/пропущен/зарезан |
Пример модели, которая поддерживает только рассуждения «выключено», «высокое» и «максимальное»:
{
"id": "deepseek-v4-pro",
"reasoning": true,
"thinkingLevelMap": {
"minimal": null,
"low": null,
"medium": null,
"high": "high",
"xhigh": null,
"max": "max"
}
}Пример модели, в которой мышление невозможно отключить:
{
"id": "always-thinking-model",
"reasoning": true,
"thinkingLevelMap": {
"off": null
}
}Миграция: старые конфигурации, использовавшие compat.reasoningEffortMap, должны переместить это сопоставление на уровень модели thinkingLevelMap. Используйте null для уровней, которые не должны отображаться в пользовательском интерфейсе.
Переопределение встроенного Providers
Направьте встроенного провайдера через прокси без переопределения модели:
{
"providers": {
"anthropic": {
"baseUrl": "https://my-proxy.example.com/v1"
}
}
}Все встроенные модели Anthropic остаются доступными. Существующая аутентификация OAuth или API key продолжает работать.
Чтобы объединить пользовательские модели со встроенным поставщиком, включите массив models:
{
"providers": {
"anthropic": {
"baseUrl": "https://my-proxy.example.com/v1",
"apiKey": "$ANTHROPIC_API_KEY",
"api": "anthropic-messages",
"models": [...]
}
}
}Семантика слияния:
- Встроенные модели сохраняются.
- Пользовательские модели обновляются с помощью
idвнутри поставщика. - Если пользовательская модель
idсоответствует встроенной моделиid, пользовательская модель заменяет эту встроенную модель. - Если пользовательская модель
idновая, она добавляется вместе со встроенными моделями.
Переопределения для каждой модели
Используйте modelOverrides, чтобы настроить встроенные модели и соответствующие модели, зарегистрированные в расширении, без замены полного списка моделей поставщика.
{
"providers": {
"openrouter": {
"modelOverrides": {
"anthropic/claude-sonnet-4": {
"name": "Claude Sonnet 4 (Bedrock Route)",
"compat": {
"openRouterRouting": {
"only": ["amazon-bedrock"]
}
}
}
}
}
}
}modelOverrides поддерживает следующие поля для каждой модели: name, reasoning, thinkingLevelMap, input, cost (частично), contextWindow, maxTokens, samplingParams (объединены по ключу), headers, compat.
Direct OpenAI GPT-5.6 Sol, Terra и Luna по умолчанию используют контекстное окно 272000, поэтому запросы остаются в пределах ценовой категории OpenAI с коротким контекстом. Чтобы включить контекстное окно OpenAI размером 1,05M, увеличьте его для каждой используемой вами модели:
{
"providers": {
"openai": {
"modelOverrides": {
"gpt-5.6-sol": {
"contextWindow": 1050000
}
}
}
}
}При переопределении сохраняются встроенные метаданные цен. Запросы с общим количеством входных токенов более 272 000 используют скорость GPT-5.6 для длинного контекста для всего запроса. При необходимости примените то же переопределение к gpt-5.6-terra или gpt-5.6-luna.
Замечания по поведению:
modelOverridesприменяются к моделям встроенных поставщиков и соответствующим моделям поставщиков, зарегистрированным в расширении.- Неизвестные идентификаторы моделей игнорируются.
- Вы можете комбинировать
baseUrl/headersуровня поставщика сmodelOverrides. - Переопределение
nameизменяет только соответствие модели и текст дополнительных сведений; в нижнем колонтитуле и списках основных моделей по-прежнему отображается модельid. - Если для поставщика также определено
models, пользовательские модели объединяются после встроенных переопределений. Пользовательская модель с тем жеidзаменяет переопределенную запись встроенной модели.
Совместимость антропных сообщений
Для провайдеров или прокси, использующих api: "anthropic-messages", используйте compat для управления совместимостью запросов, специфичных для Anthropic.
По умолчанию pi отправляет eager_input_streaming: true для каждого инструмента. Если прокси-сервер или серверная часть, совместимая с Anthropic, отклоняет это поле, установите для supportsEagerToolInputStreaming значение false. Pi будет опускать tools[].eager_input_streaming и вместо этого отправлять устаревший бета-заголовок fine-grained-tool-streaming-2025-05-14 для запросов с поддержкой инструментов.
Некоторые антропные модели требуют адаптивного мышления (thinking.type: "adaptive" плюс output_config.effort) вместо устаревшей полезной нагрузки мышления, основанной на бюджете. Встроенные модели устанавливают это автоматически. Для пользовательских поставщиков или псевдонимов, которые направляются к этим моделям, установите от forceAdaptiveThinking до true.
Некоторые провайдеры, совместимые с Anthropic, выдают блоки мышления с пустыми подписями и все равно ожидают их воспроизведения. Установите от allowEmptySignature до true только для этих поставщиков; настоящий Антропик отвергает пустые мыслительные сигнатуры.
Встроенные антропные модели включают supportsStrictTools в метаданных модели. Пользовательские модели, совместимые с Anthropic, должны установить для него значение true, если их конечная точка принимает строгие определения инструмента схемы 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"]
}
]
}
}
}| Поле | Описание |
|---|---|
supportsEagerToolInputStreaming |
Принимает ли поставщик eager_input_streaming для каждого инструмента. По умолчанию: true. Установите значение false, чтобы опустить это поле и использовать устаревший заголовок бета-версии детальной потоковой передачи инструмента для запросов с поддержкой инструмента. |
supportsLongCacheRetention |
Принимает ли поставщик Anthropic длительное хранение кэша (cache_control.ttl: "1h"), когда срок хранения кэша равен long. По умолчанию: true. |
sendSessionAffinityHeaders |
Отправлять ли x-session-affinity из идентификатора сеанса, когда кэширование включено. По умолчанию: определяется автоматически для известных поставщиков. |
supportsCacheControlOnTools |
Принимает ли поставщик маркеры cache_control в стиле Anthropic в определениях инструментов. По умолчанию: true. |
forceAdaptiveThinking |
Отправлять ли адаптивное мышление (thinking.type: "adaptive" плюс output_config.effort) для этой модели. Встроенные адаптивные модели устанавливают это автоматически. По умолчанию: false. |
allowEmptySignature |
Следует ли воспроизводить пустые мыслительные подписи как signature: "" вместо преобразования мыслей в текст. По умолчанию: false. |
supportsStrictTools |
Принимает ли поставщик строгие определения инструмента схемы JSON. По умолчанию: false; встроенные антропные модели позволяют использовать его в сгенерированных метаданных. |
Совместимость с OpenAI
Для провайдеров с частичной совместимостью с OpenAI используйте поле compat.
- На уровне поставщика
compatприменяет значения по умолчанию ко всем моделям этого поставщика. compatна уровне модели переопределяет значения уровня поставщика для этой модели.
{
"providers": {
"local-llm": {
"baseUrl": "http://localhost:8080/v1",
"api": "openai-completions",
"compat": {
"supportsUsageInStreaming": false,
"maxTokensField": "max_tokens"
},
"models": [...]
}
}
}| Поле | Описание |
|---|---|
supportsStore |
Провайдер поддерживает поле store |
supportsDeveloperRole |
Используйте роль developer и system |
supportsReasoningEffort |
Поддержка параметра reasoning_effort |
supportsUsageInStreaming |
Поддерживает stream_options: { include_usage: true } (по умолчанию: true) |
supportsFinishReason |
Включают ли потоковые ответы finish_reason. Когда false, pi выводит stop или toolUse, когда поток заканчивается. По умолчанию: true. |
maxTokensField |
Используйте max_completion_tokens или max_tokens. |
requiresToolResultName |
Включайте name в сообщения о результатах работы инструмента. |
requiresAssistantAfterToolResult |
Вставьте сообщение помощника перед сообщением пользователя после результатов инструмента. |
requiresThinkingAsText |
Преобразуйте мыслительные блоки в обычный текст |
requiresReasoningContentOnAssistantMessages |
Включать пустой reasoning_content во все воспроизводимые сообщения помощника, если включено рассуждение. |
thinkingFormat |
Используйте reasoning_effort, openrouter, deepseek, together, baseten, zai, qwen, chat-template или qwen-chat-template параметры мышления. |
chatTemplateKwargs |
значения chat_template_kwargs для thinkingFormat: "chat-template"; используйте { "$var": "thinking.enabled" } или { "$var": "thinking.effort" } для значений мышления, контролируемых числом Пи |
chatTemplateArgs |
значения chat_template_args для thinkingFormat: "baseten"; используйте { "$var": "thinking.enabled" } или { "$var": "thinking.effort" } для значений мышления, контролируемых числом Пи |
cacheControlFormat |
Используйте маркеры cache_control в стиле Anthropic в системной подсказке, последнем определении инструмента и текстовом содержимом последнего пользователя, помощника или результата инструмента. В настоящее время поддерживается только anthropic. |
sendSessionAffinityHeaders |
Для openai-completions отправляйте заголовки привязки сеанса из идентификатора сеанса, когда кэширование включено. По умолчанию: false. |
sessionAffinityFormat |
Для openai-completions и openai-responses формат заголовка привязки к сеансу: openai отправляет session_id/x-client-request-id (дополнения также x-session-affinity), openai-nosession опускает заголовок session_id, содержащий подчеркивание, openrouter отправляет x-session-id. Не влияет на параметр тела prompt_cache_key. По умолчанию: определяется автоматически. |
supportsStrictMode |
Принимает ли поставщик строгие определения инструмента функции схемы JSON. Значения по умолчанию зависят от API; встроенные модели OpenAI содержат явные метаданные о возможностях. |
supportsOpenAIGrammarTools |
Используют ли OpenAI-совместимые API пользовательские инструменты грамматики Lark/regex. Когда false, инструменты с грамматическими ограничениями возвращаются к обычным функциональным инструментам. По умолчанию: false; встроенный каталог моделей позволяет использовать его для моделей GPT-5+ на OpenAI, OpenAI Codex, Azure OpenAI, GitHub Copilot, opencode и Cloudflare AI Gateway. |
deferredToolsMode |
Используйте отложенную сериализацию инструмента для конкретного поставщика. В настоящее время для OpenAI-совместимого формата завершения чата Кими поддерживается только "kimi". |
supportsLongCacheRetention |
Принимает ли поставщик длительное хранение кэша, когда сохранение кэша равно long: prompt_cache_retention: "24h" для кэширования подсказок OpenAI или cache_control.ttl: "1h", когда cacheControlFormat равно anthropic. По умолчанию: true. |
openRouterRouting |
Настройки маршрутизации провайдера OpenRouter. Этот объект отправляется как есть в поле provider поля OpenRouter API request. |
vercelGatewayRouting |
Конфигурация маршрутизации Vercel AI Gateway для выбора провайдера (only, order) |
openrouter использует reasoning: { effort }. together использует reasoning: { enabled }, а также reasoning_effort, когда supportsReasoningEffort включено. qwen использует верхний уровень enable_thinking. Используйте qwen-chat-template для локальных Qwen-совместимых серверов, которым требуются chat_template_kwargs.enable_thinking и preserve_thinking. Используйте chat-template для шаблонов чатов vLLM/Hugging Face, для которых требуется настраиваемый chat_template_kwargs, например chatTemplateKwargs: { "thinking": { "$var": "thinking.enabled" } } для шаблонов DeepSeek V3.x. Используйте thinkingFormat: "baseten" с chatTemplateArgs для поставщиков, которые предоставляют элементы управления переключением через chat_template_args и при необходимости поддерживают reasoning_effort верхнего уровня.
cacheControlFormat: "anthropic" предназначен для поставщиков, совместимых с OpenAI, которые предоставляют кэширование подсказок в стиле Anthropic с помощью маркеров cache_control в текстовом содержимом и определениях инструментов.
Пример:
{
"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
}
}
}
}
]
}
}
}Пример шлюза Vercel AI:
{
"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"]
}
}
}
]
}
}
}