DeepSeek больше не даёт выбирать модель: radiogroup Instant / Expert /
Vision (div[data-model-type][role="radio"]) со страницы исчез, оставшаяся
модель универсальна и разбирает в том числе картинки. Вместе с выбором
отпали и три роли — think, search, vision, — а с ними отдельный чат под
каждую: теперь чат один.
Заодно выяснилось, что тумблеры DeepThink и Search больше не пропадают
после первого сообщения — они видны и переключаются в любом чате, в том
числе начатом. На их исчезновении держалась вся прежняя схема с чатами
под роль, так что нужда в ней отпала и по этой причине тоже.
DeepThink выключается перед каждым вопросом: он только показывает
размышления модели и раздувает ответ. Search не трогаем намеренно — это
тумблер человека: как поставлен во вкладке, так мост и спрашивает.
Попутно два бага, которые вылезли на живом прогоне:
- data-virtual-list-item-key у вопросов теперь отрицательные (-4, 2, -11,
8 для двух обменов подряд), и __firstMsg сортировкой по возрастанию
отдавал последний вопрос вместо первого. Правка уходила в чужое
сообщение. Берём порядок DOM — список рисуется сверху вниз.
- Вопрос с картинкой уходил новым сообщением в рабочий чат и ломал
уговор «в чате ровно один обмен», на котором держится правка первого
сообщения. После такого чат оставался из двух обменов, и наружу
отдавался ответ на предыдущий вопрос. Теперь картинка всегда открывает
новый чат, а старый удаляется как обычно.
Снаружи: /api/tags отдаёт одну модель deepseek:chat, имя присланной
клиентом модели не смотрится вовсе, ключ defaultRole из config.json убран,
chats.json стал {"id": "..."} вместо карты ролей. /api/probe показывает
положение тумблеров.
Проверено живым прогоном: обычный вопрос, вопрос с картинкой, снова
обычный — ответы верные, чат ротируется, сайдбар чистится.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ez8B2cR3mbm1fjmAMa8JXS
30 KiB
deepseek-api
DeepSeek, притворяющийся Ollama.
У веб-версии DeepSeek нет API: ни ключа, ни эндпойнта — только вкладка в браузере, куда человек руками пишет вопросы. Эта программа открывает такую вкладку, пишет в неё за вас и отдаёт наружу обычный HTTP — тот самый протокол, на котором говорит Ollama.
Смысл: любая программа, которая уже умеет работать с Ollama, начинает работать с DeepSeek после смены одного адреса. Ни строчки кода в ней менять не нужно.
ваша программа ──HTTP──> deepseek-api ──> браузер ──> chat.deepseek.com
(думает, что │
говорит с Ollama) <──────────── ответ ───────────────┘
Платить не нужно — используется ваш обычный аккаунт DeepSeek. Взамен всё медленно (секунды, а не миллисекунды) и работает только пока открыт браузер.
Программа самодостаточна: кроме Node и браузера ей ничего не требуется, внешних пакетов нет.
Оглавление
- Что понадобится
- Установка по шагам
- Окно с индикатором
- Проверка, что всё работает
- Как подключить свою программу
- Что умеет и чего не умеет
- Настройка
- Если не работает
- Безопасность
- Как это устроено внутри
Что понадобится
| Что | Зачем | Как проверить, что есть |
|---|---|---|
| Windows | скрипт запуска написан под неё | — |
| Node.js 22 или новее | на нём написана программа | node --version → должно быть v22.… и выше |
| Браузер на движке Chromium | Яндекс.Браузер, Chrome, Edge — любой | — |
| Аккаунт DeepSeek | бесплатный, регистрация на chat.deepseek.com | — |
Node.js, если его нет, ставится с nodejs.org — берите
версию LTS, кнопка слева. После установки закройте и откройте заново
командную строку, иначе node в ней не найдётся.
Установка по шагам
Всего шагов пять. Делайте по порядку, каждый заканчивается проверкой — не переходите к следующему, пока предыдущий не дал ожидаемого результата.
Шаг 1. Скачать
cd C:\#Projects
git clone https://git.08h.ru/alex/deepseek-api.git
Без git можно скачать ZIP с той же страницы и распаковать. Папка может лежать где угодно.
Проверка: в папке есть
server.mjs,browser.mjsиstart.cmd.
Шаг 2. Завести отдельный профиль браузера
Браузером будет управлять программа, поэтому работать в нём вам не нужно — и не стоит: он будет сам открываться, переключать вкладки и удалять чаты. Заведите под него отдельный профиль — это просто пустая папка, браузер сам её заполнит:
mkdir C:\Browsers\deepseek
Имя любое, запомните путь — понадобится на следующем шаге.
Профиль отдельный — чтобы не мешать друг другу. Окно сервиса нельзя сворачивать, а к профилю, уже открытому без порта управления, программа подключиться не может. На своём рабочем профиле это неудобно вам, а ваши окна мешают сервису.
А вот чаты — это про аккаунт, не про профиль. Перед каждым вопросом программа удаляет из сайдбара всё, кроме своего рабочего чата. Чаты живут на сервере DeepSeek и привязаны к аккаунту, поэтому другой профиль браузера с тем же логином не спасёт: две такие программы на одном аккаунте удаляют чаты друг друга, а ваша личная переписка в DeepSeek на этом аккаунте пропадёт вместе с ними. На этом уже обжигались — см. OLD_DEEPSHIM.md. Нужен свой аккаунт — заводите второй.
Шаг 3. Указать путь к браузеру и профилю
Откройте config.json и поправьте два значения:
{
"browserExe": "C:\\Program Files\\Yandex\\YandexBrowser\\Application\\browser.exe",
"profileDir": "C:\\Browsers\\deepseek"
}
profileDir— папка из шага 2.browserExe— путь к браузеру. Типичные:Браузер Путь Яндекс.Браузер C:\Program Files\Yandex\YandexBrowser\Application\browser.exeGoogle Chrome C:\Program Files\Google\Chrome\Application\chrome.exeMicrosoft Edge C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe
Обратные слэши в JSON удваиваются — C:\\Browsers\\deepseek, а не
C:\Browsers\deepseek. С одинарными файл не прочитается.
Чтобы обновление программы не затирало ваши пути, их можно положить не в
config.json, а вconfig.local.jsonрядом — он перебивает основной и в репозиторий не попадает.
Проверка: перетащите
config.jsonв окно браузера. Показалась структура — JSON верный. Ошибка — ищите пропущенную запятую или одинарный слэш.
Шаг 4. Запустить
start.cmd
Проверка: в окне появилось
DeepSeek прикидывается Ollama: http://localhost:11500 Модель: deepseek:chat
Это окно должно оставаться открытым — пока оно живо, работает и сервис.
Останов — Ctrl+C или просто закрыть окно.
Чёрная консоль не обязательна: рядом лежит окно с индикатором в трее — см. Окно с индикатором.
Шаг 5. Войти в DeepSeek
Браузер поднимается сам, но в пустом профиле вы ещё не залогинены. Дайте сервису первый запрос — он откроет окно:
curl http://localhost:11500/api/tags
Первый вызов ответит 503 и поднимет браузер. Войдите в аккаунт DeepSeek
в открывшемся окне. Логин сохранится в профиле — больше делать это
не придётся.
Окно браузера не сворачивайте и не закрывайте. Свёрнутое окно Windows не отрисовывает, и программа не сможет прочитать ответ. Достаточно перевести его на другой рабочий стол или оставить позади других окон.
Проверка: повторите
curl http://localhost:11500/api/tags— теперь должна прийти одна «модель».
Готово. Рабочий чат программа заведёт сама при первом же вопросе — создавать его руками не нужно.
Окно с индикатором
Тем, кому чёрная консоль мешает, есть маленькое окно: тот же вывод, но сворачивается в трей, а цвет значка показывает состояние сервиса.
build.cmd
deepseek-api.exe
build.cmd собирает deepseek-api.exe (около 20 КБ) компилятором C# из
состава Windows — csc.exe, он есть на любой машине с .NET Framework 4.
Значок берётся из icon.ico и вшивается в exe, так что рядом с ним ничего
лежать не обязано.
Ставить ничего не нужно, прав администратора тоже. Сам .exe в репозиторий
не кладётся: собирается за секунду.
Окно запускает node server.mjs дочерним процессом и показывает его вывод.
Крестик прячет окно в трей, выход — из меню значка. Node уходит вместе с окном
в любом случае, даже если окно снять диспетчером задач; браузер переживает —
он отдельный процесс и нужен вам.
Цвет значка:
| Цвет | Что значит |
|---|---|
| зелёный | готов, вопросы принимаются |
| синий | идёт запрос: в подсказке — сколько секунд и длина очереди |
| жёлтый | браузер есть, а вкладки с чатом нет; или сервер не отвечает |
| красный | браузер не отвечает; текст беды — в подсказке и всплывающей записке |
| серый | node не запущен или снимок состояния устарел (сторож молчит) |
Второй запуск не поднимает второй сервер, а разворачивает уже открытое окно —
заодно не будет EADDRINUSE.
start.cmd никуда не делся: он для запуска без графики.
Проверка, что всё работает
Откройте вторую командную строку (первая занята сервисом):
curl http://localhost:11500/api/chat -d "{\"model\":\"deepseek:chat\",\"stream\":false,\"messages\":[{\"role\":\"user\",\"content\":\"Ответь одним словом: столица Японии?\"}]}"
Через несколько секунд:
{"model":"deepseek:chat","created_at":"…","message":{"role":"assistant","content":"Токио"},"done":true,"done_reason":"stop"}
В окне сервиса при этом видно, что происходило:
вопрос 37 симв.
рабочий чат не найден, создаю сразу с вопросом
открыт новый чат
создан новый чат: 660347d5-…
ответ 5 симв. за 9 с
Отдельная диагностика — что сейчас видно во вкладке:
curl http://localhost:11500/api/probe
Покажет адрес вкладки, найдено ли поле ввода, идёт ли генерация, список чатов, положение тумблеров DeepThink и Search и не просит ли сайт залогиниться.
Как подключить свою программу
Везде, где программа спрашивает адрес Ollama, укажите:
http://localhost:11500
Моделью выберите deepseek:chat — или оставьте, что стоит: имя модели
программа не смотрит вовсе.
Если программа работает на другом компьютере в вашей сети — вместо
localhost укажите адрес этого компьютера, например
http://192.168.0.10:11500. Сервис слушает все адреса, ничего дополнительно
настраивать не нужно.
Модель одна
Раньше их было три (think, search, vision) — по числу моделей, между
которыми давала выбирать веб-морда DeepSeek. Выбора больше нет: в сентябре
2026 DeepSeek убрал переключатель Instant / Expert / Vision, оставшаяся модель
универсальна и разбирает в том числе картинки. Вслед за этим ушли и три режима.
Осталось одно имя — deepseek:chat. Имя модели вообще не смотрится:
пришлёт программа свою llama3 или qwen3:8b — запрос всё равно уйдёт
в DeepSeek. Это сделано нарочно: чужую программу можно переключить, не
разыскивая в её настройках поле с моделью. В ответе имя возвращается то же,
которое прислали, — иначе клиент решит, что ответила не та модель.
Картинку прикладывайте так же, как это делает Ollama — в поле images
массивом base64.
Тумблер Search остаётся вашим. Рядом с полем ввода у DeepSeek два тумблера: DeepThink и Search. DeepThink программа выключает перед каждым вопросом — он только показывает размышления модели и раздувает ответ. А Search не трогает: как поставите его во вкладке руками, так и будет работать. Хотите ответы со свежими данными из интернета — включите его в окне браузера один раз.
Пример: помощник hlamingo
В hlamingo на вкладке ⚙ есть выбор «Кто думает» — переключите на «DeepSeek», укажите адрес, сохраните.
Что умеет и чего не умеет
Эндпойнты
| Адрес | Что делает |
|---|---|
GET /api/tags |
список «моделей» — в нём одна. Отвечает 503, пока браузер не поднят — по этому клиенты понимают, что сервис не готов |
GET /api/version |
опознавательная строка |
GET /api/probe |
сверх протокола Ollama: что видно во вкладке прямо сейчас |
POST /api/chat |
сообщения → ответ |
POST /api/generate |
то же, но вопрос одной строкой |
POST /api/embeddings |
501 — веб-чат векторов не отдаёт |
Чего нет и не будет
- Настоящего потока. Ollama печатает ответ по словам; здесь он приходит
целиком. Формат потока при этом соблюдается (клиент получит две строки JSON
вместо многих), поэтому программы, которые ждут поток, не ломаются —
просто ответ появляется разом. Хотите один объект вместо потока — присылайте
"stream": false. temperature,num_predictи прочих настроек генерации. Веб-чат их не принимает. Присланные — молча игнорируются.- Эмбеддингов (векторов для поиска по смыслу). Веб-чат их не считает. Вместо пустого вектора возвращается честная ошибка 501: молчаливая подделка испортила бы поиск так, что вы бы этого не заметили. Если вашей программе нужен и чат, и поиск по смыслу — оставьте поиск на настоящей Ollama.
- Параллельных запросов. Вкладка одна, и два запроса разом затрут друг другу поле ввода. Запросы встают в очередь и идут по одному.
Сколько ждать
Порядок величин, замерено на коротких вопросах:
| Ollama (qwen3:8b, локально) | DeepSeek (веб) | |
|---|---|---|
| короткий вопрос | 2–3 с | 7–12 с |
| запрос, на котором меняется чат | — | ~16 с |
| первый запрос после запуска браузера | — | +15 с на подъём окна |
Если ваша программа считает, что модель обязана ответить за пару секунд, — увеличьте в ней таймаут.
Настройка
config.json
| Ключ | По умолчанию | Смысл |
|---|---|---|
port |
11500 |
порт, на котором сервис слушает |
host |
0.0.0.0 |
какие адреса слушать; 127.0.0.1 — только этот компьютер |
cdpPort |
9333 |
порт, по которому программа управляет браузером |
browserExe |
Яндекс.Браузер | путь к браузеру |
profileDir |
C:\Browsers\deepseek |
папка профиля браузера |
chatUrl |
https://chat.deepseek.com/ |
что открывать во вкладке |
timeout |
300 |
сколько секунд ждать бездействия страницы |
Про timeout: это не «сколько ждать ответа». Пока DeepSeek печатает, ждём
сколько угодно; срок отсчитывается от последнего признака жизни страницы.
config.local.json рядом перебивает config.json и в репозиторий не
попадает — туда удобно класть пути конкретной машины.
Переменные окружения
Перебивают файлы, удобны для разовых запусков:
set DEEPSEEK_API_PORT=11501
set DEEPSEEK_CDP_PORT=9444
start.cmd
chats.json
Заводится сам, руками его трогать не нужно — см. Чаты изнашиваются.
Если не работает
Сначала посмотрите в окно сервиса — там пишется, что происходит.
| Что видно | В чём дело | Что делать |
|---|---|---|
Браузер с отладочным портом 9333 не отвечает в ответе на /api/tags |
браузер закрыт | Ничего: он поднимется сам при первом запросе к /api/chat. Если не поднялся — следующая строка |
Браузер так и не открыл отладочный порт |
этот профиль уже открыт без порта управления: новый процесс отдаёт ссылку старому окну и молча завершается | Закройте все окна браузера с этим профилем и повторите. Проверить, что не осталось: диспетчер задач |
Браузер не найден: … |
неверный browserExe |
Проверьте путь и удвоенные слэши |
не задан browserExe или profileDir |
шаг 3 пропущен | Заполните оба ключа |
Вкладка chat.deepseek.com не открыта |
вкладку закрыли руками | Сервис откроет её сам на следующем запросе; если нет — откройте chat.deepseek.com в том же окне |
| Ответ приходит обрезанным, без кода | окно браузера свёрнуто — Windows перестаёт его отрисовывать, а DeepSeek дорисовывает блоки кода лениво | Разверните окно. Не сворачивайте: уводите на другой рабочий стол или за другие окна |
| Ответ приходит чужой, не на ваш вопрос | вкладка не успела обновиться | Повторите запрос. Если повторяется — перезапустите браузер |
В логе правки в этом чате кончились, завожу новый |
исчерпан лимит в шесть правок одного сообщения | Ничего. Это штатная смена чата, см. Чаты изнашиваются |
| Чаты пропадают сами, хотя вы их не удаляли | сайдбар подчищается от всего, кроме рабочего чата, а чаты привязаны к аккаунту DeepSeek, а не к профилю браузера | Держите на этом аккаунте только рабочие чаты. Другой программе, управляющей чатами, нужен другой аккаунт — разными профилями браузера тут не разойтись |
EADDRINUSE: address already in use |
сервис уже запущен в другом окне | Закройте то окно либо возьмите другой порт (DEEPSEEK_API_PORT) |
node не является внутренней или внешней командой |
Node не установлен или командная строка открыта до его установки | Поставьте Node, закройте и откройте заново командную строку |
| Просит войти в DeepSeek при каждом запуске | профиль каждый раз новый | Проверьте, что profileDir указывает на одну и ту же существующую папку |
Проверить перевод формата, не поднимая браузер:
node test.mjs
Безопасность
Прочтите, это важнее, чем кажется.
- Сервис слушает все сетевые адреса (
0.0.0.0), а не только этот компьютер. Так задумано: подключаться должны и соседние машины, ровно как к самой Ollama. Аутентификации нет. - Он ходит в DeepSeek под вашим логином. Любой, кто достучится до порта 11500, задаёт вопросы от вашего имени и расходует ваши лимиты.
- Поэтому: только домашняя или доверенная сеть. Не пробрасывайте порт наружу и не открывайте его на публичном Wi-Fi.
- Всё, что вы отправляете, уходит на серверы DeepSeek — как если бы вы написали это в чат руками. Для приватных данных берите локальную Ollama.
Если сервис нужен только на этом компьютере, впишите в config.json:
"host": "127.0.0.1"
Тогда снаружи к нему не подключиться вовсе.
Как это устроено внутри
POST /api/chat
│
├─ склеить system + user в один текст (у веб-чата нет ролей)
├─ встать в очередь (вкладка одна)
│
├─> поднять браузер, если он не отвечает
├─> Chrome DevTools Protocol
│ ├─> выключить DeepThink
│ └─> правка ПЕРВОГО сообщения чата
│ └─> дождаться, пока DeepSeek допечатает
│
└─ отдать в формате Ollama
Почему правка первого сообщения, а не новое: DeepSeek отбрасывает всё, что было после отредактированного сообщения, и чат остаётся из одного обмена. Контекст не растёт, мусор между запросами не копится, каждый вопрос — с чистого листа.
Почему браузер запускается напрямую из программы, а не батником: батник рассчитан на человека за консолью — на занятом профиле он задаёт вопрос и ждёт ответа, а у сервиса некому отвечать.
Чаты изнашиваются и меняются сами
Одно сообщение DeepSeek разрешает править ровно шесть раз. После шестой правки кнопка перестаёт открывать поле ввода — и чат становится непригоден.
Ничего делать не нужно, это предусмотрено. На седьмом вопросе программа
заводит новый чат, задаёт вопрос сразу в нём, записывает новый номер
в chats.json и удаляет отработавший чат. Снаружи не видно ничего:
тот же запрос, тот же ответ, разве что на несколько секунд дольше.
Отсюда следствия:
chats.json— не настройка, а переменная. Номер в нём меняется сам по мере работы. Не правьте его руками; в репозиторий он не попадает, образец структуры —chats.example.json.- В сайдбаре DeepSeek не копится мусор. Старые чаты удаляются, плюс перед каждым вопросом сайдбар подчищается от всего, кроме рабочего чата: всё чужое программа считает мусором. Чистка идёт по аккаунту — чаты хранятся на сервере DeepSeek, и сменой профиля браузера от неё не укрыться. Поэтому аккаунт под сервис отдавайте целиком.
- Если вы удалите рабочий чат вручную — ничего страшного: следующий запрос заметит пропажу и создаст новый.
Файлы
| Файл | Что в нём |
|---|---|
server.mjs |
HTTP, перевод формата Ollama, очередь |
browser.mjs |
всё про браузер: CDP, разметка DeepSeek, отправка, ожидание ответа, чаты |
config.json |
настройки; config.local.json рядом перебивает их |
chats.json |
рабочее состояние: id рабочего чата (заводится сам) |
start.cmd |
запуск в консоли |
tray.cs, build.cmd, icon.ico |
окно с индикатором в трее; .exe собирается на месте |
test.mjs |
проверка перевода формата, браузер не нужен |
Зависимостей нет — только то, что есть в Node 22.
Движок управления вкладкой перенесён из проекта DeepShim, который на этом и закрылся: своего в нём не осталось ничего. Всё, что удалось выяснить про разметку DeepSeek замерами, лежит рядом с кодом комментариями, а разбор «почему именно так» — в OLD_DEEPSHIM.md. Это знание дороже кода: оно добывалось живыми прогонами и переоткрывается неделями.
Лицензия
MIT.