Интеграция AI в Django через AI Gateway: сервисный слой и фон
Как встроить AI в Django: OpenAI SDK с base_url AI Gateway в отдельном сервисном слое, вызов из view и вынос долгих запросов в фоновые задачи Celery, ключ в окружении.
Аккуратная интеграция AI в Django — это не вызов модели прямо во view, а тонкий сервисный слой, который прячет клиент OpenAI SDK за одной функцией. View дёргает сервис для быстрых запросов, а тяжёлые (разбор длинных текстов, пакетная обработка) уходят в фон. Модели берём из каталога AI Gateway по OpenAI-совместимому API.
Подготовка
Понадобится ключ sk-aigate-… и адрес https://ai-gatewey.ru/v1. Ключ читаем из окружения (os.environ или django-environ), а не из settings.py в репозитории.
pip install openaiРеализация
- Сервисный слой
Один модуль инкапсулирует клиент и все обращения к модели — остальной код Django ничего не знает про SDK:
pythonpython# ai/services.pyimport osfrom openai import OpenAIclient = OpenAI(base_url="https://ai-gatewey.ru/v1",api_key=os.environ["AIGATE_API_KEY"],)def ask(prompt: str, model: str = "deepseek/deepseek-v4-flash") -> str:resp = client.chat.completions.create(model=model,messages=[{"role": "user", "content": prompt}],)return resp.choices[0].message.content - Вызов из view
View остаётся тонким — принимает запрос, зовёт сервис, возвращает JSON:
pythonpython# ai/views.pyimport jsonfrom django.http import JsonResponsefrom django.views.decorators.http import require_POSTfrom .services import ask@require_POSTdef chat(request):prompt = json.loads(request.body)["message"]return JsonResponse({"reply": ask(prompt)}) - Долгие запросы — в фон
Запрос к модели может идти секунды, а под нагрузкой это заняло бы worker'ы Django. Выносим в задачу Celery и записываем результат в модель:
pythonpython# ai/tasks.pyfrom celery import shared_taskfrom .models import Ticketfrom .services import ask@shared_taskdef summarize_ticket(ticket_id: int):ticket = Ticket.objects.get(pk=ticket_id)ticket.summary = ask(f"Кратко изложи суть обращения:\n\n{ticket.body}")ticket.save(update_fields=["summary"]) - Запуск задачи
Из view или сигнала ставим задачу в очередь неблокирующе — пользователь получает ответ сразу, а саммари появляется позже:
pythonpythonsummarize_ticket.delay(ticket.id)
settings.py под контролем версий. Запрос к модели — сетевой вызов на секунды: в синхронном view под нагрузкой он свяжет worker, поэтому пакетную и фоновую работу отправляйте в Celery или другой воркер.Какие модели подойдут
Для массовых операций (классификация, саммари обращений) берут быструю дешёвую модель; сложные задачи можно точечно направить на флагман:
Частые вопросы
Обязателен ли Celery?
Нет. Для быстрых ответов хватает синхронного вызова сервиса прямо во view. Фон нужен там, где запрос долгий или их много: подойдёт Celery, RQ, Dramatiq или Django-Q — сервисный слой при этом не меняется.
Где хранить ключ в Django?
В переменной окружения, а в settings.py читать её через os.environ или django-environ. Так ключ не попадёт в репозиторий и легко меняется между стендами.
Как показать ответ модели «печатающимся»?
Включите stream=True в сервисе и отдавайте чанки через StreamingHttpResponse. На классическом WSGI это работает, но для устойчивого стриминга лучше ASGI-стек (Daphne/Uvicorn).