feat(probe): live-проверка api.aillm.ru (response_format/stream/reasoning_effort/контекст/пустой content)

This commit is contained in:
Repinoid
2026-10-07 13:43:54 +03:00
parent e419b38a25
commit e5817ff7f3
2 changed files with 243 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
# Результаты live-проверки api.aillm.ru (шаг 1)
Дата: 2026-10-07
Модель: `gpt-oss-120b` (vLLM 0.22.0, tp4), прокси litellm 1.82.3
Base URL: `https://api.aillm.ru`
Ключ: из `/home/naeel/nubes/llm.key` (первый `sk-*` после метки `https`)
## Итоги по пунктам
| # | Параметр | Результат | Что делать |
|---|---|---|---|
| 1 | `response_format: {type:"json_object"}` | ✅ поддерживается, валидный JSON в `content` | использовать для этапа 1 |
| 2 | `stream: true` | ✅ SSE `data:`-чанки; сначала `reasoning_content`, потом `content` | v1 стрим НЕ нужен (обычный JSON-ответ) |
| 3 | `reasoning_effort: "low"` | ❌ 400 `UnsupportedParamsError` | НЕ передавать этот параметр |
| 3b | `reasoning_content` | ✅ есть в ответе (дублируется в `provider_specific_fields`) | игнорировать, брать только `content` |
| 4 | `/v1/models` | ✅ 200, модели: gpt-oss-120b, qwen3.8-27b-fp8(-rtx6000), user-bge-m3, bge-reranker-v2-m3, whisper | — |
| 5 | размер контекста | ✅ 2000/8000/16000 слов принято без ошибки (200) | лимит контекста не упёрся, дефолт max_tokens с запасом |
| 6 | пустой content | ⚠️ при `max_tokens:1` и `finish_reason:"length"` → `content:null` | обрабатывать пустой content как ошибку + повтор с бо́льшим max_tokens |
| 7 | задержка этап-1 | ~1.0–1.3 с (3 замера: 1339/1081/1096 ms; повторно 723-1013ms на контекст-тесте) | укладываемся в `ASSIST_TOTAL_DEADLINE_MS=40000` с большим запасом |
## Детали
### response_format (п.1)
Запрос с `response_format:{type:"json_object"}` → `content` = `{"resource_type":"nubes_vc_vdc"}` (валидный JSON, без markdown-ограждений).
### reasoning_effort (п.3)
Ошибка 400:
```
litellm.UnsupportedParamsError: openai does not support parameters: ['reasoning_effort'],
for model=gpt-oss-120b-113
```
→ В `llmChat` параметр `reasoning_effort` НЕ слать.
### reasoning_content (п.3b)
В ответе присутствуют одновременно:
- `choices[0].message.content` — основной ответ
- `choices[0].message.reasoning_content` — рассуждения (по-английски)
- `choices[0].message.provider_specific_fields.reasoning_content` — дубль
→ Разбор строится ТОЛЬКО на `content`.
### контекст (п.5)
16000 повторяющихся слов (~16k токенов) принято, 200 OK, ~1.7 с. Лимит запроса не упёрся.
### пустой content (п.6)
`max_tokens:1` → `finish_reason:"length"`, `content:null`, `completion_tokens:1` (ушло в reasoning).
→ `llmChat` уже выбрасывает `empty_content`; на уровне этапа 1 — делать повтор с бо́льшим `max_tokens`.
### stream (п.2)
SSE чанки вида `data: {...}` / `data: [DONE]`. Первые дельты — `delta.reasoning_content`.
## Выводы для реализации
1. Этап 1: `response_format json_object`, `temperature 0`, брать `content`.
2. Этап 2: без `response_format` (текстовый промпт со строгим шаблоном), `max_tokens` с запасом (не 1).
3. НЕ использовать `reasoning_effort` нигде.
4. Пустой `content` → ошибка `empty_content` → один повтор с `max_tokens` x2.
5. Дедлайн 40 с достаточен с 20+x запасом; можно уменьшить `ASSIST_LLM_TIMEOUT_MS`, но оставить 25 с безопасно.