Одна модель вместо трёх: DeepSeek убрал выбор из веб-морды

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
This commit is contained in:
Alex Cube
2026-09-11 10:26:03 +03:00
co-authored by Claude Opus 5
parent adbcedb485
commit 6ccb5dd46b
6 changed files with 162 additions and 337 deletions
+42 -36
View File
@@ -93,7 +93,7 @@ mkdir C:\Browsers\deepseek
> окна мешают сервису.
>
> **А вот чаты — это про аккаунт, не про профиль.** Перед каждым вопросом
> программа удаляет из сайдбара всё, чего нет в её `chats.json`. Чаты живут
> программа удаляет из сайдбара всё, кроме своего рабочего чата. Чаты живут
> на сервере DeepSeek и привязаны к аккаунту, поэтому другой профиль браузера
> с тем же логином не спасёт: две такие программы на одном аккаунте удаляют
> чаты друг друга, а ваша личная переписка в DeepSeek на этом аккаунте
@@ -140,7 +140,7 @@ start.cmd
> **Проверка:** в окне появилось
> ```
> DeepSeek прикидывается Ollama: http://localhost:11500
> Модели: deepseek:think, deepseek:search, deepseek:vision
> Модель: deepseek:chat
> ```
Это окно должно оставаться открытым — пока оно живо, работает и сервис.
@@ -167,10 +167,10 @@ curl http://localhost:11500/api/tags
его на другой рабочий стол или оставить позади других окон.
> **Проверка:** повторите `curl http://localhost:11500/api/tags` — теперь
> должен прийти список из трёх «моделей».
> должна прийти одна «модель».
**Готово.** Чаты под каждый режим программа заведёт сама при первом же
вопросе — создавать их руками не нужно.
**Готово.** Рабочий чат программа заведёт сама при первом же вопросе —
создавать его руками не нужно.
---
@@ -218,23 +218,23 @@ deepseek-api.exe
Откройте **вторую** командную строку (первая занята сервисом):
```cmd
curl http://localhost:11500/api/chat -d "{\"model\":\"deepseek:think\",\"stream\":false,\"messages\":[{\"role\":\"user\",\"content\":\"Ответь одним словом: столица Японии?\"}]}"
curl http://localhost:11500/api/chat -d "{\"model\":\"deepseek:chat\",\"stream\":false,\"messages\":[{\"role\":\"user\",\"content\":\"Ответь одним словом: столица Японии?\"}]}"
```
Через несколько секунд:
```json
{"model":"deepseek:think","created_at":"…","message":{"role":"assistant","content":"Токио"},"done":true,"done_reason":"stop"}
{"model":"deepseek:chat","created_at":"…","message":{"role":"assistant","content":"Токио"},"done":true,"done_reason":"stop"}
```
В окне сервиса при этом видно, что происходило:
```
[think] 37 симв.
чат think не найден, создаю сразу с вопросом
вопрос 37 симв.
рабочий чат не найден, создаю сразу с вопросом
открыт новый чат
создан новый чат think: 660347d5-…
[think] ответ 5 симв. за 9 с
создан новый чат: 660347d5-…
ответ 5 симв. за 9 с
```
Отдельная диагностика — что сейчас видно во вкладке:
@@ -243,8 +243,8 @@ curl http://localhost:11500/api/chat -d "{\"model\":\"deepseek:think\",\"stream\
curl http://localhost:11500/api/probe
```
Покажет адрес вкладки, найдено ли поле ввода, идёт ли генерация, список чатов
и не просит ли сайт залогиниться.
Покажет адрес вкладки, найдено ли поле ввода, идёт ли генерация, список чатов,
положение тумблеров DeepThink и Search и не просит ли сайт залогиниться.
---
@@ -256,29 +256,36 @@ curl http://localhost:11500/api/probe
http://localhost:11500
```
Моделью выберите `deepseek:think`.
Моделью выберите `deepseek:chat` — или оставьте, что стоит: имя модели
программа не смотрит вовсе.
Если программа работает на **другом компьютере** в вашей сети — вместо
`localhost` укажите адрес этого компьютера, например
`http://192.168.0.10:11500`. Сервис слушает все адреса, ничего дополнительно
настраивать не нужно.
### Три «модели» — это три режима
### Модель одна
| Модель | Что это | Когда брать |
|---|---|---|
| `deepseek:think` | обычный режим (expert) | почти всегда |
| `deepseek:search` | с поиском в интернете | нужны свежие данные |
| `deepseek:vision` | со зрением | разбор картинок |
Раньше их было три (`think`, `search`, `vision`) — по числу моделей, между
которыми давала выбирать веб-морда DeepSeek. **Выбора больше нет:** в сентябре
2026 DeepSeek убрал переключатель Instant / Expert / Vision, оставшаяся модель
универсальна и разбирает в том числе картинки. Вслед за этим ушли и три режима.
Картинку можно приложить к запросу так же, как это делает Ollama — в поле
`images` массивом base64. Тогда режим `vision` включится сам, независимо
от того, какую модель вы указали.
Осталось одно имя — `deepseek:chat`. **Имя модели вообще не смотрится:**
пришлёт программа свою `llama3` или `qwen3:8b` — запрос всё равно уйдёт
в DeepSeek. Это сделано нарочно: чужую программу можно переключить, не
разыскивая в её настройках поле с моделью. В ответе имя возвращается то же,
которое прислали, — иначе клиент решит, что ответила не та модель.
**Незнакомое имя модели — не ошибка.** Если программа настойчиво шлёт свою
`llama3` или `qwen3:8b`, запрос уйдёт в обычный чат. Это сделано нарочно:
чужую программу можно переключить на DeepSeek, не разыскивая в её настройках
поле с моделью.
Картинку прикладывайте так же, как это делает Ollama — в поле `images`
массивом base64.
**Тумблер Search остаётся вашим.** Рядом с полем ввода у DeepSeek два
тумблера: DeepThink и Search. DeepThink программа выключает перед каждым
вопросом — он только показывает размышления модели и раздувает ответ.
А Search не трогает: как поставите его во вкладке руками, так и будет
работать. Хотите ответы со свежими данными из интернета — включите его
в окне браузера один раз.
### Пример: помощник hlamingo
@@ -293,7 +300,7 @@ http://localhost:11500
| Адрес | Что делает |
|---|---|
| `GET /api/tags` | список «моделей». **Отвечает 503, пока браузер не поднят** — по этому клиенты понимают, что сервис не готов |
| `GET /api/tags` | список «моделей» — в нём одна. **Отвечает 503, пока браузер не поднят** — по этому клиенты понимают, что сервис не готов |
| `GET /api/version` | опознавательная строка |
| `GET /api/probe` | сверх протокола Ollama: что видно во вкладке прямо сейчас |
| `POST /api/chat` | сообщения → ответ |
@@ -343,7 +350,6 @@ http://localhost:11500
| `browserExe` | Яндекс.Браузер | путь к браузеру |
| `profileDir` | `C:\Browsers\deepseek` | папка профиля браузера |
| `chatUrl` | `https://chat.deepseek.com/` | что открывать во вкладке |
| `defaultRole` | `think` | режим для незнакомых имён моделей |
| `timeout` | `300` | сколько секунд ждать **бездействия** страницы |
Про `timeout`: это не «сколько ждать ответа». Пока DeepSeek печатает, ждём
@@ -383,7 +389,7 @@ start.cmd
| Ответ приходит **обрезанным**, без кода | окно браузера свёрнуто — Windows перестаёт его отрисовывать, а DeepSeek дорисовывает блоки кода лениво | Разверните окно. Не сворачивайте: уводите на другой рабочий стол или за другие окна |
| Ответ приходит **чужой**, не на ваш вопрос | вкладка не успела обновиться | Повторите запрос. Если повторяется — перезапустите браузер |
| В логе `правки в этом чате кончились, завожу новый` | исчерпан лимит в шесть правок одного сообщения | Ничего. Это штатная смена чата, см. [Чаты изнашиваются](#чаты-изнашиваются-и-меняются-сами) |
| Чаты пропадают сами, хотя вы их не удаляли | сайдбар подчищается от всего, чего нет в `chats.json`, а чаты привязаны к **аккаунту** DeepSeek, а не к профилю браузера | Держите на этом аккаунте только рабочие чаты. Другой программе, управляющей чатами, нужен другой аккаунт — разными профилями браузера тут не разойтись |
| Чаты пропадают сами, хотя вы их не удаляли | сайдбар подчищается от всего, кроме рабочего чата, а чаты привязаны к **аккаунту** DeepSeek, а не к профилю браузера | Держите на этом аккаунте только рабочие чаты. Другой программе, управляющей чатами, нужен другой аккаунт — разными профилями браузера тут не разойтись |
| `EADDRINUSE: address already in use` | сервис уже запущен в другом окне | Закройте то окно либо возьмите другой порт (`DEEPSEEK_API_PORT`) |
| `node не является внутренней или внешней командой` | Node не установлен или командная строка открыта до его установки | Поставьте Node, **закройте и откройте заново** командную строку |
| Просит войти в DeepSeek при каждом запуске | профиль каждый раз новый | Проверьте, что `profileDir` указывает на одну и ту же существующую папку |
@@ -426,11 +432,11 @@ node test.mjs
POST /api/chat
├─ склеить system + user в один текст (у веб-чата нет ролей)
├─ выбрать чат по имени модели (think / search / vision)
├─ встать в очередь (вкладка одна)
├─> поднять браузер, если он не отвечает
├─> Chrome DevTools Protocol
│ ├─> выключить DeepThink
│ └─> правка ПЕРВОГО сообщения чата
│ └─> дождаться, пока DeepSeek допечатает
@@ -452,17 +458,17 @@ POST /api/chat
правки кнопка перестаёт открывать поле ввода — и чат становится непригоден.
Ничего делать не нужно, это предусмотрено. На седьмом вопросе программа
заводит новый чат того же режима, задаёт вопрос сразу в нём, записывает новый
номер в `chats.json` и **удаляет отработавший чат**. Снаружи не видно ничего:
заводит новый чат, задаёт вопрос сразу в нём, записывает новый номер
в `chats.json` и **удаляет отработавший чат**. Снаружи не видно ничего:
тот же запрос, тот же ответ, разве что на несколько секунд дольше.
Отсюда следствия:
- **`chats.json` — не настройка, а переменная.** Номера в нём меняются сами
- **`chats.json` — не настройка, а переменная.** Номер в нём меняется сам
по мере работы. Не правьте его руками; в репозиторий он не попадает,
образец структуры — `chats.example.json`.
- **В сайдбаре DeepSeek не копится мусор.** Старые чаты удаляются, плюс перед
каждым вопросом сайдбар подчищается от всего, чего нет в `chats.json`:
каждым вопросом сайдбар подчищается от всего, кроме рабочего чата:
всё чужое программа считает мусором. Чистка идёт по **аккаунту** — чаты
хранятся на сервере DeepSeek, и сменой профиля браузера от неё не укрыться.
Поэтому аккаунт под сервис отдавайте целиком.
@@ -476,7 +482,7 @@ POST /api/chat
| `server.mjs` | HTTP, перевод формата Ollama, очередь |
| `browser.mjs` | всё про браузер: CDP, разметка DeepSeek, отправка, ожидание ответа, чаты |
| `config.json` | настройки; `config.local.json` рядом перебивает их |
| `chats.json` | рабочее состояние: id живых чатов (заводится сам) |
| `chats.json` | рабочее состояние: id рабочего чата (заводится сам) |
| `start.cmd` | запуск в консоли |
| `tray.cs`, `build.cmd`, `icon.ico` | окно с индикатором в трее; `.exe` собирается на месте |
| `test.mjs` | проверка перевода формата, браузер не нужен |