У веб-версии DeepSeek нет API: ни ключа, ни эндпойнта, только вкладка
в браузере. Этот сервис держит такую вкладку и отдаёт наружу протокол
Ollama, поэтому любая программа, которая уже умеет ходить в Ollama,
подключается к DeepSeek сменой одного адреса.
GET /api/tags три "модели" по числу режимов чата;
503, пока браузер с чатом не поднят
GET /api/version
POST /api/chat images в сообщении уводят в чат со зрением
POST /api/generate
POST /api/embeddings 501: веб-чат векторов не отдаёт
Внутри — ollama_orchestro/ask.mjs дочерним процессом: он ничего не
экспортирует и выполняется при импорте, это программа командной строки.
Браузер поднимается напрямую из Node, а не через browser-launch.ps1 из
DeepShim: тот рассчитан на человека за консолью и на занятом профиле
спрашивает Read-Host, а у сервиса некому отвечать. Флаги окна оттуда
перенесены: у неактивного окна DeepSeek не дорисовывает блоки кода.
Чего нет: настоящего потока (формат соблюдается, но ответ приходит
целиком), temperature и num_predict, эмбеддингов, параллельных запросов —
вкладка одна, запросы идут очередью по одному.
Сервис слушает все адреса и ходит в DeepSeek под вашим логином. Только
доверенная сеть; сузить до этого компьютера — host в config.json.
Проверка перевода формата без браузера: node test.mjs
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
30 lines
1.7 KiB
JavaScript
30 lines
1.7 KiB
JavaScript
// Проверка перевода формата Ollama в один вопрос для веб-чата.
|
|
// Браузер и сам DeepSeek тут не нужны: node test.mjs
|
|
import assert from 'node:assert/strict';
|
|
import { roleOf, flatten, imageOf } from './server.mjs';
|
|
|
|
// Имя модели → чат DeepSeek. Незнакомое имя не ошибка: чужую программу можно
|
|
// переключить на DeepSeek, не трогая в ней настройку модели.
|
|
assert.equal(roleOf('deepseek:search'), 'search');
|
|
assert.equal(roleOf('deepseek:VISION'), 'vision');
|
|
assert.equal(roleOf('qwen3:8b'), 'think');
|
|
assert.equal(roleOf(undefined), 'think');
|
|
|
|
// У Ollama роли — отдельные сообщения, у веб-чата их нет: склеиваем по порядку,
|
|
// пустые выбрасываем. Потеря system означала бы потерю всей инструкции.
|
|
assert.equal(
|
|
flatten([{ role: 'system', content: 'Отвечай JSON' },
|
|
{ role: 'user', content: ' где кусачки? ' },
|
|
{ role: 'user', content: '' }]),
|
|
'Отвечай JSON\n\nгде кусачки?');
|
|
assert.equal(flatten([]), '');
|
|
assert.equal(flatten(undefined), '');
|
|
|
|
// Картинка приезжает в base64 внутри сообщения — так её кладёт Ollama.
|
|
const bytes = Buffer.from([0xff, 0xd8, 0xff]);
|
|
assert.deepEqual(imageOf([{ role: 'user', content: 'что это?',
|
|
images: [bytes.toString('base64')] }]), bytes);
|
|
assert.equal(imageOf([{ role: 'user', content: 'без картинки' }]), null);
|
|
|
|
console.log('OK: перевод формата работает');
|