Выбор мозгов: Ollama или веб-версия DeepSeek
Разбор свободных фраз, теги и подсказку по фотографии теперь может делать не своя модель, а веб-версия DeepSeek. Своего клиента DeepSeek здесь нет и не нужно: рядом живёт отдельный сервис deepseek-api, который держит вкладку браузера и отдаёт наружу протокол Ollama. Для hlamingo вся разница сводится к тому, по какому адресу спрашивать. HLAMINGO_ENGINE=ollama|deepseek HLAMINGO_DEEPSEEK_HOST=http://localhost:11500 Эмбеддинги в выбор не входят и всегда идут на OLLAMA_HOST: веб-чат векторов не отдаёт, а подделать их нечем. Поэтому адрес Ollama нужен и в режиме DeepSeek, иначе молча умирает поиск по смыслу. Предохранитель в ollama.py теперь считается по каждому адресу отдельно. Иначе лежачая Ollama гасила бы живой DeepSeek: неудача по одному адресу на полминуты объявляла мёртвым и второй. Проба адреса больше не подменяет config.OLLAMA_HOST на время проверки — адрес передаётся явным параметром. Запросы идут в несколько потоков, и подмена задевала чужие. В настройках (вкладка "шестерёнка") появился выбор "Кто думает", поле адреса DeepSeek и вторая кнопка проверки связи. Списка моделей теперь два: для разбора фраз — у выбранного движка, для поиска по смыслу — у Ollama. Замер на разборе фразы и генерации тегов: Ollama qwen3:8b 2-3 с, DeepSeek 8-12 с плюс 15 с на подъём браузера при первом запросе. Тесты: 115 успешно, 0 провалено. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
1ae98b0b6f
commit
4d8175931b
+53
-1
@@ -263,7 +263,7 @@ try:
|
||||
r.check("поиск работает без ИИ", d["items"] and _time.time() - t0 < 3, d)
|
||||
|
||||
r.check("смена адреса сбрасывает паузу",
|
||||
(ollama.reset_breaker() or True) and ollama._down_until == 0)
|
||||
(ollama.reset_breaker() or True) and ollama._down_until == {})
|
||||
finally:
|
||||
config.OLLAMA_HOST = _was_host
|
||||
ollama.reset_breaker()
|
||||
@@ -393,6 +393,58 @@ r.check("инъекция в имя модели — 400",
|
||||
c.post("/api/config",
|
||||
json={"ollama_host": "http://127.0.0.1:11434",
|
||||
"chat_model": "модель\nOLLAMA_HOST=http://зло"}).status_code == 400)
|
||||
|
||||
# ---- выбор мозгов: Ollama или веб-DeepSeek ----
|
||||
# Проверяем не сам DeepSeek (для него нужен браузер с логином), а развилку:
|
||||
# куда уходит разбор фраз и куда — эмбеддинги. Перепутать их значит тихо
|
||||
# сломать поиск по смыслу, и это не видно, пока не начнёшь искать.
|
||||
was_engine = config.ENGINE
|
||||
DS = "http://127.0.0.1:11500"
|
||||
try:
|
||||
d = j("POST", "/api/config", engine="deepseek", deepseek_host=DS)
|
||||
r.check("движок переключился", d.get("ok") and config.ENGINE == "deepseek", d)
|
||||
r.check("думает DeepSeek", config.chat_host() == DS, config.chat_host())
|
||||
r.check("здоровье докладывает движок",
|
||||
c.get("/api/health").get_json()["engine"] == "deepseek")
|
||||
r.check("ждём DeepSeek дольше", config.chat_timeout() > config.CHAT_TIMEOUT,
|
||||
config.chat_timeout())
|
||||
|
||||
# Куда реально уходят запросы. Предохранитель и сеть отключаем: важно не
|
||||
# то, ответил ли кто-то, а по какому адресу постучались.
|
||||
tried = []
|
||||
|
||||
def _spy(req, **kw):
|
||||
tried.append(req.full_url)
|
||||
raise OSError("в тесте наружу не ходим")
|
||||
|
||||
real_urlopen = ollama.urllib.request.urlopen
|
||||
real_available = ollama.available
|
||||
ollama.urllib.request.urlopen = _spy
|
||||
ollama.available = lambda host=None: True
|
||||
try:
|
||||
ollama.embed("гвозди")
|
||||
ollama.chat(config.CHAT_MODEL, [{"role": "user", "content": "привет"}])
|
||||
finally:
|
||||
ollama.urllib.request.urlopen = real_urlopen
|
||||
ollama.available = real_available
|
||||
ollama.reset_breaker()
|
||||
r.check("эмбеддинги идут в Ollama",
|
||||
any(u.startswith(config.OLLAMA_HOST) and "embed" in u for u in tried), tried)
|
||||
r.check("разбор фраз идёт в DeepSeek",
|
||||
any(u.startswith(DS) and u.endswith("/api/chat") for u in tried), tried)
|
||||
|
||||
r.check("чужой движок — 400",
|
||||
c.post("/api/config", json={"engine": "chatgpt"}).status_code == 400)
|
||||
r.check("мусорный адрес DeepSeek — 400",
|
||||
c.post("/api/config", json={"deepseek_host": "не адрес"}).status_code == 400)
|
||||
r.check("проба берёт адрес из запроса, а не из настроек",
|
||||
c.post("/api/config/probe",
|
||||
json={"host": "http://192.0.2.1:11434"}).get_json()["ok"] is False
|
||||
and config.OLLAMA_HOST != "http://192.0.2.1:11434")
|
||||
finally:
|
||||
j("POST", "/api/config", engine=was_engine)
|
||||
ollama.reset_breaker()
|
||||
r.check("движок вернулся", config.ENGINE == was_engine, config.ENGINE)
|
||||
# Отказ должен быть полным: адрес из того же запроса применяться не должен,
|
||||
# иначе половина настроек принята, а половина отвергнута.
|
||||
r.check("при отказе НИЧЕГО не применилось",
|
||||
|
||||
Reference in New Issue
Block a user