doc: сага с LLM — HTTP/2, ddos-guard, httpx→curl
Задокументированы все 4 попытки, хеш-анализ, находка с Node.js fetch, хронология 12 коммитов за 14.06.2026.
This commit is contained in:
@@ -277,6 +277,69 @@ contracts-app/
|
||||
"DB_PASS": "****",
|
||||
"DB_PORT": "5432",
|
||||
"DB_USER": "contracts",
|
||||
"DB_SSLMODE": "disable"
|
||||
"DB_SSLMODE": "disable",
|
||||
"LLM_API_KEY": "sk-ucI...",
|
||||
"LLM_API_URL": "https://api.aillm.ru/v1/chat/completions"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Сага с LLM (aillm.ru + HTTP/2)
|
||||
|
||||
### Проблема
|
||||
Python-библиотеки (`requests`, `httpx`) не держат HTTP/2 из коробки.
|
||||
`api.aillm.ru` за ddos-guard, который **требует HTTP/2 от облачных IP**.
|
||||
С локальной машины (81.200.23.210) даже HTTP/1.1 работает — для этого IP ddos-guard делает исключение.
|
||||
|
||||
### Хронология попыток
|
||||
|
||||
| # | Подход | Результат |
|
||||
|---|---|---|
|
||||
| 1 | `requests` (HTTP/1.1) | ❌ 401 token_not_found_in_db (ложная ошибка от ddos-guard) |
|
||||
| 2 | `httpx` с `http2=True` | ❌ то же самое — `h2` пакет не установился в контейнере |
|
||||
| 3 | `httpx[http2]` + `h2` в requirements | ❌ `h2` не ставится через pip в slim-контейнере |
|
||||
| 4 | `subprocess.run(['curl', '-s', '--http2', ...])` | ⬜ ждёт редеплоя |
|
||||
|
||||
### Ключевые находки
|
||||
|
||||
1. **Хеш ключа не совпадал:** локально `5fad79ba...`, в облаке `c772c3e5...`.
|
||||
Оказалось — не разные ключи, а `ddos-guard` возвращает ложный 401 при HTTP/1.1,
|
||||
хешируя какой-то внутренний токен, а не наш ключ.
|
||||
|
||||
2. **Node.js `fetch()` работает** (проект `say`) — потому что undici (нативный fetch в Node)
|
||||
поддерживает HTTP/2 из коробки. Python — нет.
|
||||
|
||||
3. **`curl --http2`** — единственный гарантированный способ получить HTTP/2 в Python-контейнере,
|
||||
без дополнительных пакетов.
|
||||
|
||||
4. **Доступные модели:** `gpt-oss-120b`, `qwen3.6-27b-fp8`, `qwen3-6-27b-fp8-opt`, `whisper-large-v3-turbo`.
|
||||
|
||||
### Решение
|
||||
`llm_client.py` использует `subprocess.run(['curl', '-s', '--http2', ...])` вместо Python HTTP-библиотек.
|
||||
|
||||
---
|
||||
|
||||
## Хронология коммитов (14.06.2026)
|
||||
|
||||
### DB слой
|
||||
- `ba2e855` — `db.py`: `execute()` + `query_one()` для INSERT/UPDATE/DELETE и единичного SELECT
|
||||
- `4635ed4` — `test_routes`: action `exec` через `db.execute()` (DDL без fetch)
|
||||
- `9d01dba` — `schema.py`: `db.query → db.execute` для DDL
|
||||
|
||||
### Upload слой
|
||||
- `8db35e3` — `upload.py`: Blueprint `/upload`, поток bytes→parser→textify→DB
|
||||
- `db2f6cc` — fix MIME: приоритет расширения над content_type
|
||||
|
||||
### LLM слой
|
||||
- `44e53ed` — `llm_client.py`: HTTP-клиент (сначала `requests`)
|
||||
- `fe8a556` — `test_routes`: action `llm` для теста
|
||||
- `c580c93` — fix: модель `gpt-oss-120b` (не `deepseek-chat`)
|
||||
- `5904830` — fix: `httpx[http2]` вместо `requests`
|
||||
- `c97f26d` — fix: `h2` явно в requirements
|
||||
- `099edbc` — fix: `curl --http2` через `subprocess` вместо httpx
|
||||
|
||||
### Debug
|
||||
- `cc3203a` — `test_routes`: action `debug` для просмотра env vars
|
||||
- `0d0ba18` — debug показывает длину ключа
|
||||
- `b457de4` — debug показывает `h2_available` и `httpx_version`
|
||||
|
||||
Reference in New Issue
Block a user