Тема
AI / LLM-интеграции для Laravel
Как встраивать языковые модели в Laravel-проекты: абстракция над провайдерами, RAG, эмбеддинги, tool-calling и специфика РФ (GigaChat, YandexGPT, доступ к зарубежным API).
Общий принцип тот же, что в ru-specific.md: официальный SDK/чистый HTTP-клиент + тонкая своя интеграция переживает капризы провайдеров лучше, чем толстая community-обёртка. Но для LLM появился зрелый общий слой (Prism / Laravel AI SDK) — его брать стоит, он снимает разнобой провайдеров.
Абстракция над провайдерами (ядро)
| Пакет | Что даёт | Статус | Когда |
|---|---|---|---|
| prism-php/prism | Провайдер-агностик слой: text, structured output, tool-calling, streaming, эмбеддинги. Один fluent-интерфейс к OpenAI/Anthropic/Gemini/Ollama/Mistral/DeepSeek/xAI | 🟢 | Дефолт для LLM-фич в Laravel |
| laravel/ai (Laravel AI SDK) | Официальная first-party обёртка поверх Prism: агенты, персистентность диалогов, более «ларавельный» API, интеграция с очередями/событиями | 🟢 | Когда нужны агенты/диалоги «из коробки» и first-party-поддержка |
| openai-php/laravel | Тонкий фасад именно к OpenAI-совместимым API (config, streaming) | 🟢 | Один провайдер, минимум абстракции; или OpenAI-совместимые эндпоинты (в т.ч. проксирующие) |
| inspector-dev/neuron-ai | Фреймворк агентов/воркфлоу с трейсингом | 🟡 | Сложные агентные пайплайны с наблюдаемостью |
Prism vs Laravel AI SDK: это как Query Builder vs Eloquent. Prism — нижний движок, нормализует провайдеров и сырые вызовы; Laravel AI SDK — надстройка с агентами и хранением диалогов, и она использует Prism под капотом. Начинать с Prism; переходить/добавлять Laravel AI SDK, когда нужны его агентные абстракции. Не тащить оба ради простого «сгенерируй текст» — хватит Prism.
РФ-провайдеры LLM
Зарубежные API (OpenAI/Anthropic) из РФ напрямую нестабильны — либо прокси/зарубежный хостинг, либо отечественные модели. Prism/openai-php работают с любым OpenAI-совместимым эндпоинтом — часто это самый простой мост.
| Провайдер | Как подключать | Заметка |
|---|---|---|
| GigaChat (Сбер) | Официальный REST API + свой тонкий клиент; community-обёртки (edvardpotter/gigachat-php-sdk, tigusigalpa/gigachat-php) — нишевые (сотни загрузок), проверять свежесть | OAuth-токен по сертификату НУЦ Минцифры; часть моделей OpenAI-совместимы — тогда через Prism custom endpoint |
| YandexGPT (Yandex Cloud) | REST API Yandex Cloud (Foundation Models) + свой клиент | Авторизация по IAM-токену/API-ключу сервисного аккаунта; on-premise Pro-версии нет — только облако |
| GigaChain (Сбер) | Python-стек (форк LangChain) | Для PHP-проекта не тянуть — брать голый API |
| OpenAI-совместимые прокси | Prism/openai-php с кастомным base_url | Когда есть легальный шлюз к зарубежным моделям |
Паттерн для РФ: доменный интерфейс LlmProvider (методы generate, embed) + реализации GigaChatProvider / YandexGptProvider / PrismProvider. Смена провайдера — без переписывания бизнес-логики. Ключи — только config() из .env, никогда env() в коде (правило студии).
RAG (retrieval-augmented generation)
Классический стек «поиск по своим данным + ответ модели» полностью собирается на Laravel:
| Слой | Решение | Заметка |
|---|---|---|
| Хранилище векторов | pgvector (расширение PostgreSQL) | У студии PostgreSQL уже основной; не тащить отдельную векторную БД |
| Работа с pgvector в Eloquent | pgvector/pgvector (PHP) + свои casts / raw-запросы | Тип vector, оператор <=> (косинус), индекс HNSW/IVFFlat |
| Генерация эмбеддингов | Prism embeddings() (OpenAI/Ollama/…) или API GigaChat/YandexGPT | Размерность вектора фиксировать в миграции под модель |
| Полнотекст как дополнение/фолбэк | PostgreSQL FTS (tsvector + GIN) | Уже отработано в catalog → ../specs/migrations.md |
| Гибридный поиск | pgvector similarity + FTS ранжирование | Часто точнее чистого вектора |
Схема RAG-пайплайна:
- Чанкинг документов → эмбеддинг каждого чанка →
INSERTв таблицу с колонкойvector. - Индекс HNSW на векторной колонке (см. правила больших индексов в ../specs/migrations.md:
CREATE INDEX CONCURRENTLY). - Запрос → эмбеддинг запроса → top-k ближайших (
ORDER BY embedding <=> :q LIMIT k). - Найденные чанки → в промпт как контекст → генерация ответа.
- Тяжёлые шаги (эмбеддинг больших корпусов) — в очередь (Job +
chunk()), не в HTTP.
Локальные / self-hosted модели
| Инструмент | Что | Когда |
|---|---|---|
| Ollama | Локальный рантайм LLM (один бинарь/Docker), OpenAI-совместимый API | Прайваси, отсутствие интернет-зависимости, дешёвые эмбеддинги; Prism его поддерживает нативно |
| llama.cpp / LM Studio | Ручной инференс | Когда нужен точный контроль над моделью/железом |
Ollama в Docker-стек студии добавляется отдельным сервисом; Laravel ходит в него по HTTP (имя сервиса в сети compose). Для эмбеддингов RAG локальная модель часто выгоднее платного API.
Практические паттерны и грабли
- Всё общение с LLM — через очередь, если не нужен синхронный ответ пользователю: API медленные и падучие.
$tries+$backoff+failed()обязательны (правило ../specs/services.md). - Структурированный вывод, а не парсинг текста: Prism
->withSchema()/ structured output вместо регексов по ответу. Модель заставляют вернуть валидный JSON под схему. - Кеширование ответов по хешу промпта (Redis) — LLM-вызовы дорогие; одинаковый запрос не гонять дважды.
- Стоимость и лимиты логировать (токены на запрос) — иначе счёт за API неожиданный.
- Секреты провайдеров —
.env→config(); ключи GigaChat/OpenAI в коде = утечка. - Промпт-инъекции: пользовательский ввод в промпте — источник инъекций; не давать модели инструменты с побочными эффектами без валидации её выхода (особенно tool-calling с записью в БД).
- PII в промптах: не отправлять перс. данные в зарубежные API без согласия/анонимизации — для РФ-данных предпочтительны GigaChat/YandexGPT/локальный Ollama.
Антипаттерны
| Паттерн | Проблема | Решение |
|---|---|---|
| Своя обёртка над каждым провайдером с нуля | Дублирование, разнобой | Prism / Laravel AI SDK |
| Синхронный вызов LLM в контроллере | Блокировка запроса на секунды, таймауты | Job + очередь |
| Парсинг ответа модели регексами | Хрупко, ломается на вариациях | Structured output по схеме |
| Отдельная векторная БД ради RAG | Лишний сервис в стеке | pgvector в имеющемся PostgreSQL |
| Зарубежный API для РФ-персданных | Юр. риски, нестабильность из РФ | GigaChat/YandexGPT/Ollama |
| tool-calling с записью в БД без проверки | Промпт-инъекция → нежелательные действия | Валидировать выход модели перед сайд-эффектом |
env('OPENAI_KEY') в сервисе | Ключ теряется при кеше конфига | config('services.openai.key') |