feat(server): приём dynamic_samples, выбор DYNAMIC_PROMPT
This commit is contained in:
+14
-3
@@ -92,7 +92,19 @@ def register(app):
|
||||
return jsonify({"error": "missing 'responses'"}), 400
|
||||
|
||||
responses = data["responses"]
|
||||
logger.info(f"Upload: {len(responses)} responses")
|
||||
|
||||
# Динамический тест: если есть — добавляем к обычным ответам
|
||||
dynamic_samples = data.get("dynamic_samples")
|
||||
has_dynamic = bool(dynamic_samples)
|
||||
if has_dynamic:
|
||||
# Прикрепляем все сэмплы к responses для парсинга
|
||||
all_samples = []
|
||||
for sample in dynamic_samples:
|
||||
all_samples.extend(sample)
|
||||
logger.info(f"Upload: {len(responses)} обычных + {len(all_samples)} динамических ответов")
|
||||
responses = responses + all_samples
|
||||
else:
|
||||
logger.info(f"Upload: {len(responses)} responses")
|
||||
|
||||
# ── Идемпотентность: проверяем request_id ─────
|
||||
request_id = (data.get("request_id") or "").strip()
|
||||
@@ -132,8 +144,7 @@ def register(app):
|
||||
base_url=cfg["llm"].get("base_url", "https://api.aillm.ru/v1"),
|
||||
)
|
||||
try:
|
||||
is_dynamic = client_info.get("script_mode") == "dynamic"
|
||||
prompt = DYNAMIC_PROMPT if is_dynamic else SYSTEM_PROMPT
|
||||
prompt = DYNAMIC_PROMPT if has_dynamic else SYSTEM_PROMPT
|
||||
diagnosis = diagnoser.diagnose(prompt, _build_diagnosis_prompt(parsed, car_info))
|
||||
llm_success = True
|
||||
except LLMError as e:
|
||||
|
||||
+32
-34
@@ -6,48 +6,46 @@
|
||||
## Концепция
|
||||
|
||||
Два теста: **на месте** и **в движении**. Разница — только в подсказке юзеру.
|
||||
Физически оба делают одно: опрашивают 12 PID каждые 250мс, копят в памяти, отправляют на сервер одной пачкой.
|
||||
Физически оба делают одно: опрашивают 12 PID каждые 250мс, копят в памяти.
|
||||
|
||||
## Flow
|
||||
## Алгоритм работы (user flow)
|
||||
|
||||
```
|
||||
Юзер → кнопка «⏱ На месте» / «🚗 В движении»
|
||||
→ подсказка в окне вывода
|
||||
→ кнопка «▶ Старт»
|
||||
→ опрос 12 PID каждые 250мс, вывод: «запись... N отсчётов»
|
||||
→ кнопка «⏹ Стоп»
|
||||
→ отправка на сервер POST /api/v1/session/upload
|
||||
→ LLM-анализ → вывод в чат
|
||||
1. Ошибки → scanDtc() — считывание DTC
|
||||
2. Диагностика → обычный скрипт L0/L1/L2 на сервер → LLM
|
||||
3. LLM сказал сделать тест на месте →
|
||||
⏱ На месте → СТАРТ → ... → СТОП → данные в памяти
|
||||
4. Диагностика → обычный скрипт + динамические данные → LLM
|
||||
5. LLM сказал сделать тест в движении →
|
||||
🚗 В движении → СТАРТ → ... → СТОП → данные в памяти
|
||||
6. Диагностика → обычный скрипт + динамические данные → LLM (финал)
|
||||
```
|
||||
|
||||
## Скрипт (сервер)
|
||||
## Android → Сервер
|
||||
|
||||
Новый режим `?mode=dynamic` в `api/scripts.py`:
|
||||
При нажатии **Диагностика**:
|
||||
1. Выполняется обычный скрипт (AT-команды, PID'ы)
|
||||
2. Если есть `dynamicSamples` (данные теста) — прикрепляются к тому же запросу
|
||||
3. POST `/api/v1/session/upload` с полем `dynamic_samples`
|
||||
4. Сервер по наличию `dynamic_samples` понимает, что пришёл динамический тест
|
||||
5. Выбирает промпт: `DYNAMIC_PROMPT` если только динамика, или `SYSTEM_PROMPT + DYNAMIC_PROMPT` если и то и то
|
||||
|
||||
```json
|
||||
{
|
||||
"version": 1,
|
||||
"title": "Динамический тест",
|
||||
"mode": "dynamic",
|
||||
"interval_ms": 250,
|
||||
"steps": [
|
||||
{"id": "pid_04", "cmd": "0104", "desc": "Нагрузка"},
|
||||
{"id": "pid_05", "cmd": "0105", "desc": "ОЖ"},
|
||||
{"id": "pid_06", "cmd": "0106", "desc": "STFT"},
|
||||
{"id": "pid_07", "cmd": "0107", "desc": "LTFT"},
|
||||
{"id": "pid_0B", "cmd": "010B", "desc": "MAP"},
|
||||
{"id": "pid_0C", "cmd": "010C", "desc": "RPM"},
|
||||
{"id": "pid_0D", "cmd": "010D", "desc": "Скорость"},
|
||||
{"id": "pid_0E", "cmd": "010E", "desc": "Зажигание"},
|
||||
{"id": "pid_0F", "cmd": "010F", "desc": "IAT"},
|
||||
{"id": "pid_10", "cmd": "0110", "desc": "MAF"},
|
||||
{"id": "pid_11", "cmd": "0111", "desc": "Дроссель"},
|
||||
{"id": "pid_1F", "cmd": "011F", "desc": "Время работы"}
|
||||
]
|
||||
}
|
||||
```
|
||||
## Что надо сделать
|
||||
|
||||
## Хранение данных (Android)
|
||||
### Уже сделано (написан код, не проверен)
|
||||
- [x] Сервер: `build_dynamic_script()` — скрипт 12 PID 250мс
|
||||
- [x] Сервер: `?mode=dynamic` в routes.py
|
||||
- [x] Сервер: `DYNAMIC_PROMPT` в prompts.py
|
||||
- [x] Android: кнопки «⏱ На месте» / «🚗 В движении» (layout)
|
||||
- [x] Android: `DynamicCollector.kt` — сбор 12 PID 250мс
|
||||
- [x] Android: `ElmChecker.kt` — добавлены методы для работы с DynamicCollector
|
||||
- [x] Android: MainActivity — СТАРТ/СТОП, данные в памяти
|
||||
- [x] Android: общий таймер `tv_timer`
|
||||
|
||||
### Надо доделать
|
||||
- [ ] Android: при старте Диагностики — прикрепить `dynamicSamples` к upload
|
||||
- [ ] Сервер: принимать `dynamic_samples` в upload_session, выбирать промпт
|
||||
- [ ] Отладка на реальной машине
|
||||
|
||||
### До отправки — в памяти
|
||||
```kotlin
|
||||
|
||||
Reference in New Issue
Block a user