fix: reasoning_field на каждом assistant-сообщении (не только с tool_calls)
Build LLM Proxy / Build and push (release) Successful in 41s
Build LLM Proxy / Build and push (release) Successful in 41s
Console Go (deepseek в thinking-режиме) в stateful-сессиях требует reasoning_content на КАЖДОМ assistant-сообщении истории — живые 400 «The reasoning_content in the thinking mode must be passed back to the API» (19:01, session 890fc602) шли именно на чистых ассистент-турах без tool_calls, которые старый гейт пропускал. Снял гейт: поле дописывается на каждом assistant-сообщении (текст из reasoning / reasoning_details, пустая строка при reasoning_empty_ok) — как это делает сам opencode («Deepseek requires all assistant messages to have reasoning on them»). Тесты переписаны под новое поведение.
This commit is contained in:
@@ -231,12 +231,15 @@ upstreams:
|
||||
### Нативное поле рассуждений (`reasoning_field`)
|
||||
|
||||
Некоторые шлюзы-апстримы (например, **Console Go / deepseek в thinking-режиме**)
|
||||
в thinking-режиме **требуют** вернуть им нативное поле рассуждений в каждом
|
||||
assistant-сообщении с непустым `tool_calls`. Если его нет — апстрим отвечает
|
||||
`400` (`The `reasoning_content` in the thinking mode must be passed back to the
|
||||
в thinking-режиме **требуют** вернуть им нативное поле рассуждений в **каждом**
|
||||
assistant-сообщении истории (не только в тех, что с `tool_calls`). Если его нет —
|
||||
апстрим отвечает `400`
|
||||
(`The `reasoning_content` in the thinking mode must be passed back to the
|
||||
API.`). Клиенты при этом рассуждения держат в своих форматах: `reasoning`
|
||||
(строка) и/или `reasoning_details` (массив `{type:"reasoning.text", text, ...}`)
|
||||
— а нативное поле `reasoning_content` в истории могут и не передавать.
|
||||
(Точно так же делает и сам opencode: для deepseek он добавляет reasoning-часть
|
||||
на каждом assistant-сообщении, даже пустую.)
|
||||
|
||||
Поля (только на уровне **провайдера**, это свойство шлюза, а не модели):
|
||||
|
||||
@@ -245,15 +248,15 @@ API.`). Клиенты при этом рассуждения держат в с
|
||||
| `providers[].reasoning_field` | строка / отсутствует | Имя нативного поля рассуждений у шлюза-апстрима (пример: `reasoning_content`) |
|
||||
| `providers[].reasoning_empty_ok` | булево / `false` | Писать ли пустую строку, если текста рассуждений нет вовсе |
|
||||
|
||||
Зачем: при отправке запроса прокси **аддитивно** достраивает это поле в каждом
|
||||
assistant-сообщении с непустым `tool_calls` — берёт текст из `reasoning`
|
||||
Зачем: при отправке запроса прокси **аддитивно** достраивает это поле в
|
||||
**каждом** assistant-сообщении — берёт текст из `reasoning`
|
||||
(если это непустая строка), иначе склеивает `reasoning_details[*].text`
|
||||
(только элементы без `type` или с `type == "reasoning.text"`, через `"\n"`) и
|
||||
записывает в поле `reasoning_field`, **если его там ещё нет**. Существующее
|
||||
непустое поле не перезаписывается. Ничего при этом не убирается и не
|
||||
переименовывается — клиентский `reasoning`/`reasoning_details` остаются на месте,
|
||||
поле просто дополняется. Тронуто только assistant-сообщение с непустым
|
||||
`tool_calls`; сообщения без `tool_calls` и `user`/`tool`/`system` не меняются.
|
||||
поле просто дополняется. Тронуты только assistant-сообщения; `user`/`tool`/
|
||||
`system` не меняются.
|
||||
Если текста рассуждений нет вовсе — поле не добавляется, кроме случая
|
||||
`reasoning_empty_ok: true` (тогда пишется пустая строка `""`). Если
|
||||
`reasoning_field` не задан — тело не меняется вовсе.
|
||||
|
||||
Reference in New Issue
Block a user