Что случилось
Мы проверяли FreeDeepseekAPI как локальный public-only proxy для DeepSeek Web
Chat и наткнулись на стабильную проблему с deepseek-chat-search.
Обычный deepseek-chat работал, deepseek-reasoner-search тоже работал, но
deepseek-chat-search на публичных EN/RU search prompt'ах возвращал HTTP 502.
В body ошибки при этом лежала не техническая ошибка DeepSeek, а поисковая фраза
вроде:
Official Reuters website URL
Официальный сайт Reuters
То есть DeepSeek Web отвечал, но proxy неправильно разбирал stream.
Как воспроизводилось
Сервер запускался локально:
HOST=127.0.0.1 PORT=9655 NON_INTERACTIVE=1 npm start
Публичный EN prompt:
curl -X POST http://127.0.0.1:9655/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-chat-search",
"stream": false,
"messages": [
{
"role": "user",
"content": "Search the web. What is the official Reuters website URL? Answer in one sentence and include the URL."
}
]
}'
Публичный RU prompt:
curl -X POST http://127.0.0.1:9655/v1/chat/completions \
-H "Content-Type: application/json; charset=utf-8" \
-d '{
"model": "deepseek-chat-search",
"stream": false,
"messages": [
{
"role": "user",
"content": "Найди официальный сайт Reuters и дай URL. Ответь по-русски."
}
]
}'
До фикса оба запроса могли завершаться 502.
Причина
У DeepSeek Web search stream отличается от обычного chat stream:
- Часть ответа приходит как fragment с
type: "SEARCH".
- Первый кусок ответа может прийти не через
response/fragments/-1/content,
а как response-level patch:
{
"p": "response",
"v": [
{
"p": "fragments",
"o": "APPEND",
"v": [
{
"type": "RESPONSE",
"content": "The"
}
]
}
]
}
Старый parser:
- собирал в финальный ответ только fragments с
type: "RESPONSE";
- игнорировал content внутри
SEARCH fragments;
- не применял response-level
fragments APPEND patch;
- считал любой top-level
content в stream событии ошибкой модели.
Из-за этого fullContent оставался пустым, а служебная search-фраза попадала в
modelError, после чего proxy возвращал 502.
Что исправлено
В этом patch:
SEARCH fragments считаются assistant output наравне с RESPONSE;
- model error создаётся только для события
type: "error";
- response-level patch operations
p: "fragments", o: "APPEND" применяются к
списку fragments;
- добавлены unit tests на эти случаи;
server.js больше не читает auth config при require('../server.js') из
тестов, поэтому unit tests не шумят auth warning'ом.
Проверка
npm test:
Live smoke после фикса:
deepseek-chat-search, EN prompt: HTTP 200, ответ начинается с
The official Reuters website URL is ...
deepseek-chat-search, RU prompt: HTTP 200, ответ начинается с
Официальный сайт...
deepseek-chat: HTTP 200
deepseek-reasoner-search: HTTP 200
- tool parser smoke: HTTP 200, вернул
tool_calls
- Anthropic Messages shim: HTTP 200
- OpenAI Responses shim: HTTP 200
Важно: auth/token/cookie значения в отчёт не включались; проверялись только
публичные prompts.
Что случилось
Мы проверяли
FreeDeepseekAPIкак локальный public-only proxy для DeepSeek WebChat и наткнулись на стабильную проблему с
deepseek-chat-search.Обычный
deepseek-chatработал,deepseek-reasoner-searchтоже работал, ноdeepseek-chat-searchна публичных EN/RU search prompt'ах возвращал HTTP 502.В body ошибки при этом лежала не техническая ошибка DeepSeek, а поисковая фраза
вроде:
Official Reuters website URLОфициальный сайт ReutersТо есть DeepSeek Web отвечал, но proxy неправильно разбирал stream.
Как воспроизводилось
Сервер запускался локально:
Публичный EN prompt:
Публичный RU prompt:
До фикса оба запроса могли завершаться 502.
Причина
У DeepSeek Web search stream отличается от обычного chat stream:
type: "SEARCH".response/fragments/-1/content,а как response-level patch:
{ "p": "response", "v": [ { "p": "fragments", "o": "APPEND", "v": [ { "type": "RESPONSE", "content": "The" } ] } ] }Старый parser:
type: "RESPONSE";SEARCHfragments;fragments APPENDpatch;contentв stream событии ошибкой модели.Из-за этого
fullContentоставался пустым, а служебная search-фраза попадала вmodelError, после чего proxy возвращал 502.Что исправлено
В этом patch:
SEARCHfragments считаются assistant output наравне сRESPONSE;type: "error";p: "fragments",o: "APPEND"применяются ксписку fragments;
server.jsбольше не читает auth config приrequire('../server.js')изтестов, поэтому unit tests не шумят auth warning'ом.
Проверка
npm test:Live smoke после фикса:
deepseek-chat-search, EN prompt: HTTP 200, ответ начинается сThe official Reuters website URL is ...deepseek-chat-search, RU prompt: HTTP 200, ответ начинается сОфициальный сайт...deepseek-chat: HTTP 200deepseek-reasoner-search: HTTP 200tool_callsВажно: auth/token/cookie значения в отчёт не включались; проверялись только
публичные prompts.