Реализовать роутер запросов между Groq и GPT-4 с делегированием по сложности
ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Реализовать роутер запросов между Groq и GPT-4 с делегированием по сложности
1. Цель задачи
Научиться строить систему интеллектуального делегирования между двумя LLM с разной стоимостью и качеством. Требуется реализовать классификатор сложности запроса]], который направляет простые запросы на быструю и дешёвую модель (Groq), а сложные — на более мощную (GPT-4). Итоговая система должна быть развёрнута как микросервис с эндпоинтом /chat и метриками для мониторинга.
Ключевой результат Снижение операционных затрат на 50% при падении accuracy не более 5% по сравнению с использованием только GPT-4 (замер accuracy: pass@1 на калибровочном датасете).
2. Исходные данные
| Что нужно | Откуда взять |
|---|---|
| Датасет запросов, размеченный по сложности (простые / сложные) | Сгенерировать самостоятельно (см. ниже) или взять открытые (например, SimpleQuestions, HotPotQA) |
| API-ключи Groq и OpenAI | Зарегистрироваться на console.groq.com и platform.openai.com |
| Baseline-метрики (accuracy, cost) для единственного GPT-4 | Прогнать датасет через GPT-4, зафиксировать accuracy и total cost |
| Инфраструктура для запуска роутера | Локальный Python 3.10+, или Docker контейнер |
Если нет реального инструмента — симулируем:
- Groq — если нет доступа, симулируем через любой локальный LLM (например, gpt-3.5-turbo с ограничением 0.5x стоимости или llama-3.1-8b через Ollama). Задержки можно эмулировать фиксированным time.sleep(0.3).
- GPT-4 — вместо платного GPT-4 использовать gpt-4o-mini (доступен через OpenAI API) или локальный
Qwen2.5-72Bчерез vLLM (если есть ресурсы). Важно, чтобы разница в качестве между моделями была значимой. - Классификатор сложности — если нет размеченного датасета, размечать можно автоматически: простые запросы — длина < 100 символов и нет вопросительных слов «почему», «как»; сложные — многословные, требуют рассуждений. Либо использовать LLM-as-judge (GPT-4) для разметки 200-300 примеров.
3. Технологический стек
| Компонент | Инструменты | Назначение |
|---|---|---|
| Язык программирования | Python 3.10+ | Разработка роутера и классификатора |
| API фреймворк | FastAPI | HTTP-сервер для эндпоинта /chat |
| Клиенты LLM | openai (v1+), groq | Вызов моделей |
| Классификатор | scikit-learn (LogisticRegression) или rule-based + LLM-as-judge | Определение сложности запроса |
| Логирование | loguru + structlog | Структурированные логи запросов/ответов |
| Метрики | Prometheus + клиент prometheus_client (счётчики accuracy, cost, latency) | Мониторинг в реальном времени |
| Эксперименты | MLflow (опционально) | Логирование accuracy и cost по версиям |
| Контейнеризация (опционально) | Docker + docker-compose | Упаковка сервиса |
4. Этапы выполнения
Этап 1: Подготовка данных и метрик (2 часа)
Действия
-
Собрать калибровочный датасет (минимум 200 запросов). Используйте комбинацию:
-
Добавить 200 запросов для валидации (смешанные, без разметки) — для финального A/B теста.
-
Запустить baseline на GPT-4 (или его симуляторе):
import openai client = openai.OpenAI(api_key="...") accuracy, total_cost = 0, 0 for row in dataset: resp = client.chat.completions.create(model="gpt-4", messages=[{"role": "user", "content": row["query"]}]) # оцениваем ответ по эталону (идеально — если датасет размечен)Зафиксировать
accuracy_baselineиcost_baseline. -
Создать скрипт metrics.py с функциями:
Ожидаемый результат этапа Скрипт baseline.py, который выводит Accuracy: 0.92, Cost: 15.4$. Датасет dataset.csv с 400 запросами.
Этап 2: Разработка классификатора сложности (3 часа)
Действия
-
Выбрать архитектуру классификатора:
- Вариант A (rule-based): Простое правило: длина > 150 символов ИЛИ содержит слова «объясни», «почему», «как работает» → сложный.
- Вариант B (ML): Использовать TF-IDF + LogisticRegression. Обучить на 200 размеченных запросах.
- Вариант C (LLM-as-judge): Отправлять запрос GPT-4 с промптом «Определи сложность запроса (прост/сложен), верни только одно слово».
-
Реализовать функцию classify(query: str) -> bool (True — сложный, False — простой). Для варианта B:
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.linear_model import LogisticRegression import joblib def train_classifier(dataset): vec = TfidfVectorizer(max_features=5000) X = vec.fit_transform(dataset["query"]) model = LogisticRegression() model.fit(X, dataset["complexity_label"]) joblib.dump((vec, model), "classifier.pkl") -
Протестировать точность классификатора на 100 размеченных запросах (hold-out). Цель: F1-score > 0.85.
Ожидаемый результат этапа Файл classifier.py с обученным классификатором (или правилами), файл classifier.pkl для варианта B.
Этап 3: Реализация роутера (3 часа)
Действия
-
Создать FastAPI приложение (router.py):
- Endpoint
POST /chatс телом {"query": str, "user_id": str}. - Логика:
from fastapi import FastAPI app = FastAPI() @app.post("/chat") async def chat(request: dict): is_complex = classify(request["query"]) if is_complex: model, client = "gpt-4", openai_client else: model, client = "mixtral-8x7b-32768", groq_client # Groq response = call_llm(client, model, request["query"]) log(request, response, model, compute_cost(response, model)) return {"response": response, "model_used": model}
- Endpoint
-
Добавить логирование — каждый запрос пишется в JSON-логи: timestamp, query, model, latency, cost, user_id.
-
Добавить метрики Prometheus:
-
Запустить сервис локально (uvicorn router:app --reload). Проверить curl-запросом.
Ожидаемый результат этапа Рабочий HTTP-сервер на localhost:8000, который отвечает разными моделями в зависимости от классификации.
Этап 4: Оценка качества и стоимости (2 часа)
Действия
-
Написать скрипт evaluate.py, который прогоняет все 400 запросов через роутер и собирает метрики:
-
Провести A/B тест:
-
Сравнить результаты:
print(f"Baseline accuracy: {acc_b}, cost: {cost_b}") print(f"Router accuracy: {acc_r}, cost: {cost_r}") print(f"Cost reduction: {(cost_b - cost_r)/cost_b*100:.1f}%") print(f"Accuracy delta: {(acc_r - acc_b)*100:.1f}pp")Убедиться, что cost reduction >= 50%, accuracy drop <= 5pp.
Ожидаемый результат этапа Файл results.md с таблицей метрик. Если условие не выполнено — перейти к этапу 5 (оптимизация).
Этап 5: Оптимизация порогов и деплой (2 часа)
Действия
-
Если accuracy упала больше 5% — изменить порог классификатора:
-
Если cost reduction меньше 50% — увеличить порог (направлять больше запросов на Groq), но следить за accuracy.
-
Провести повторную оценку (этап 4), пока не будет выполнено целевое условие.
-
Упаковать сервис в Docker:
FROM python:3.10 COPY . /app WORKDIR /app RUN pip install -r requirements.txt CMD ["uvicorn", "router:app", "--host", "0.0.0.0", "--port", "8000"]Запустить в docker-compose вместе с Prometheus и Grafana (опционально).
Ожидаемый результат этапа Docker-образ, готовый к деплою, и финальный results.md с подтверждением метрик.
5. Критерии приемки (Definition of Done)
- Разработан классификатор сложности с точностью F1 >= 0.85 (на hold-out).
- Роутер отвечает на
POST /chatи возвращает ответ и имя использованной модели. - Для простых запросов используется модель из пула Groq (или симуляция), для сложных — GPT-4.
- Общая стоимость обработки калибровочного датасета снижена не менее чем на 50% по сравнению с baseline.
- Accuracy (pass@1) снижена не более чем на 5 процентных пунктов от baseline.
- Все запросы и ответы логируются в структурированном виде.
- Метрики Prometheus доступны и показывают latency, cost, количество запросов по моделям.
- Сервис упакован в Docker и запускается одной командой
docker compose up. - Написан
README.mdс описанием архитектуры, инструкцией по запуску и результатами A/B теста. - Исходный код покрыт хотя бы базовыми unit-тестами (pytest) для классификатора и эндпоинта.
6. Ожидаемый результат
Основной артефакт
- Репозиторий с кодом (классификатор, роутер, скрипты оценки, Dockerfile, docker-compose.yml).
- Файл
results.md, содержащий:
Опциональные результаты
- Дашборд Grafana для визуализации метрик.
- Отчёт о влиянии порога классификатора на cost vs accuracy (график).
- Логирование с
trace_idдля отслеживания каждого запроса.
7. Возможные сложности и их решение
| Сложность | Решение |
|---|---|
| Нет доступа к Groq API | Использовать локальный Ollama с llama3.1:8b и эмулировать скорость и стоимость (снизить стоимость в коде в 10x). |
| Нет размеченного датасета | Сгенерировать 300 запросов с помощью GPT-4 (попросить придумать простые/сложные вопросы) и разметить автоматически (длина + ключевые слова). |
| Классификатор даёт низкую точность | Перейти на LLM-as-judge (запрос к GPT-4 за 10-20 токенов) — это повысит accuracy, но незначительно увеличит cost. |
| Accuracy роутера падает >5% | Уменьшить порог классификатора, сбалансировать датасет, добавить больше примеров сложных запросов, которые модель Groq плохо обрабатывает. |
| Разница в формате ответов между моделями | Постобработка: унифицировать вывод (один и тот же системный промпт) или использовать метрику LLM-judge для оценки качества. |
8. Бюджет времени (оценка)
| Этап | Время (часы) |
|---|---|
| Этап 1: Подготовка данных и метрик | 2 |
| Этап 2: Разработка классификатора | 3 |
| Этап 3: Реализация роутера | 3 |
| Этап 4: Оценка качества и стоимости | 2 |
| Этап 5: Оптимизация порогов и деплой | 2 |
| Итого | 12 часов |
Примечание Для первого раза (без опыта) заложите +50% времени (до 18 часов). Если классификатор ML — время на обучение может увеличиться (загрузка данных, подбор гиперпараметров).
9. Связанные вопросы из базы знаний
| Вопрос | Тема |
|---|---|
| 101 | Как метрики качества (accuracy, F1) применить к LLM-ответам? |
| 202 | Что такое A/B тестирование в контексте ML-сервисов? |
| 303 | Как логировать запросы и ответы в production LLM? |
| 404 | Как оценить стоимость инференса LLM (токены, цена)? |
| 505 | Чем отличается rule-based классификатор от ML модели? |
| 606 | Как настроить Prometheus метрики для FastAPI сервиса? |
| 707 | Какие бывают стратегии делегирования между LLM? |
| 808 | Как упаковать ML-приложение в Docker? |
| 909 | Что такое LLM-as-judge и когда его применять? |
10. Чек-лист самопроверки
- Я чётко понимаю условие задачи: снижение cost на 50% при accuracy drop <= 5%.
- Я собрал датасет минимум 200 запросов с разметкой сложности и эталонными ответами.
- Я запустил baseline (только GPT-4) и зафиксировал accuracy и cost.
- Я реализовал классификатор (rule или ML) и получил F1 > 0.85 на hold-out.
- Я написал роутер на FastAPI, протестировал его curl/postman.
- Я запустил скрипт evaluate.py и получил метрики, удовлетворяющие условию.
- Я залогировал каждый шаг эксперимента (что менял, какие пороги) в
experiments.log. - Я упаковал сервис в Docker и убедился, что он работает из контейнера.
- Я написал README с инструкцией по запуску и результатами.
- Я провёл финальную проверку: cost_reduction >= 50% AND accuracy_drop <= 5 pp.