Перейти к содержимому

Помощь ИИ

Необязательная помощь ИИ с вашим собственным ключом: предложения заголовков и метаописаний, объяснения проблем сканирования простым языком, переработка описания в один клик и предложение структурированных данных schema.org. По умолчанию она выключена: при выключенном флаге никакой код ИИ не выполняется.

В основе три принципа:

  • Ваш ключ, ваш провайдер. Запросы идут с вашего сервера прямо к настроенному вами провайдеру: Anthropic, OpenAI, Google либо локальному или совместимому с OpenAI серверу. Если применима оплата, она списывается с вашего аккаунта. Ничего не проксируется, использование не тарифицируется и не перепродаётся пакетом; телеметрия никуда не отправляется.
  • Интерактивные предложения требуют явного принятия. Выбор предложения заполняет форму; исправления в панели требуют действия Apply — так в английском интерфейсе называется кнопка «Применить». Начиная с Pro 2.42 массовый CLI по умолчанию сохраняет приватные черновики. Используйте --auto-apply, только если намеренно хотите немедленную запись.
  • Ошибки не останавливают работу. Отсутствующий или неверный ключ, исчерпанный баланс, ограничение частоты или тайм-аут дают сообщение в интерфейсе. Они никогда не блокируют сохранение, отображение или сканирование.

Краткое сравнение провайдеров

Выбирайте по доступу к аккаунту, требованиям к данным и стоимости. Все четыре интеграции предоставляют одни и те же задачи, но поддержка моделей, формат вывода, скорость и качество могут различаться.

ПровайдерМодель в конфигурации по умолчаниюСтруктурированный выводПримерная стоимостьНазначение
Local — Ollama / LM Studio / vLLMllama3.1, задайте своюПо возможности, через response_format$0 за API при самостоятельном размещении; расходы на инфраструктуру остаютсяКонтроль назначения данных
OpenAIgpt-5.5Structured Outputs, если выбранная модель поддерживаетОколо $0,005 за предложение при допущениях примера нижеСуществующий аккаунт OpenAI
Anthropicclaude-opus-4-8output_config.format, где поддерживаетсяОколо $0,015 за предложение при тех же допущенияхСуществующий аккаунт Anthropic
Googlegemini-2.5-flashresponseSchema, где поддерживаетсяОколо $0,0005 за предложение при тех же допущенияхАккаунт Google; проверьте квоты моделей и цены

Эти названия описывают поставляемую конфигурацию и не гарантируют доступность моделей в вашем аккаунте сейчас. Стоимость основана на примерных допущениях пакета, а не на проверенных текущих ценах. Поведение интеграций и наблюдения из опубликованных испытаний:

  • Структурированный вывод. Поддерживаемые пути OpenAI, Google и Anthropic получают JSON-схему; некорректные ответы завершаются явной ошибкой. Локальным серверам передаётся response_format без гарантии соблюдения. Если параметр проигнорирован, гибкий разбор вернёт корректный список или ошибку, не применяя частичный результат.
  • Рассуждение меняет расход токенов. В описанном испытании Gemini на одно описание ушло около 500 скрытых токенов рассуждения и около 100 видимых; протестированные вызовы Anthropic не сообщали о скрытых токенах. Это не универсальное свойство этих семейств моделей. Скрытые токены могут оплачиваться как выходные, поэтому ниже предусмотрен минимальный бюджет для рассуждающих моделей.
  • Модели настраиваются. Задайте в SEO_PRO_AI_MODEL доступную модель, совместимую с API и параметрами адаптера. Примеры: claude-haiku-4-5, gpt-5.4-mini и gemma-3-12b-it. Перед применением ко всей коллекции проверьте поддержку и качество вывода.

Настройка

Включите возможность и поместите ключ провайдера в окружение. Для смены облачного провайдера обновите провайдера и ключ, также проверив переопределённую модель. Локальному адаптеру нужен ещё и URL сервера.

dotenv
SEO_PRO_AI_ENABLED=true
SEO_PRO_AI_PROVIDER=local
SEO_PRO_AI_MODEL=llama3.1          # a model the server has pulled
SEO_PRO_AI_LOCAL_BASE_URL=http://localhost:11434/v1
SEO_PRO_AI_LOCAL_ALLOW_PRIVATE=true   # required for a localhost server
# no API key needed for a local server
dotenv
SEO_PRO_AI_ENABLED=true
SEO_PRO_AI_PROVIDER=openai
SEO_PRO_AI_API_KEY=sk-...
# optional: SEO_PRO_AI_MODEL=gpt-5.4-mini  (default: gpt-5.5)
dotenv
SEO_PRO_AI_ENABLED=true
SEO_PRO_AI_PROVIDER=anthropic
SEO_PRO_AI_API_KEY=sk-ant-...
# optional: SEO_PRO_AI_MODEL=claude-haiku-4-5  (default: claude-opus-4-8)
dotenv
SEO_PRO_AI_ENABLED=true
SEO_PRO_AI_PROVIDER=google
SEO_PRO_AI_API_KEY=AIza...        # AI Studio key: aistudio.google.com/apikey
# use a paid (billing-enabled) key for real use — the free tier is heavily rate-limited
# optional: SEO_PRO_AI_MODEL=gemma-3-12b-it  (default: gemini-2.5-flash)

Ключ API провайдера не связан с подпиской Claude или ChatGPT

Подписка Claude Code, Claude.ai или ChatGPT не оплачивает API. В SEO_PRO_AI_API_KEY нужен ключ API с оплатой по использованию из консоли разработчика провайдера либо ключ Google AI Studio с отдельным балансом. Аккаунт только с подпиской или без средств может пройти аутентификацию, но вернуть ошибку исчерпанного баланса или квоты: см. Устранение неполадок.

В файле конфигурации config/seo-pro.php, блоке ai, доступны timeout, max_input_chars, max_output_tokens, token_budgets, reasoning_models и reasoning_min_output_tokens, suggestion_count, bulk_model — дешёвая модель для массового заполнения, см. Стоимость, — retry, таблица pricing и подраздел local. Они описаны в разделе Лимиты и настройка.

Ключ при кешированной конфигурации

Конфигурация хранит только имя переменной окружения — api_key_env, — но не ключ. Поэтому php artisan config:cache никогда не записывает ключ в bootstrap/cache/config.php. Обратная сторона: при кешированной конфигурации .env не загружается, поэтому задайте SEO_PRO_AI_API_KEY как настоящую переменную окружения на сервере.

Локальный инференс и облачные варианты

  • Самостоятельное размещение инференса избавляет от оплаты API провайдера за токены. Оборудование, электричество и эксплуатация всё равно стоят денег. Контент остаётся в вашей сети, только если настроенный сервер инференса и его зависимости тоже находятся в ней.
  • У Google квоты и цены зависят от модели и тарифа. Ключ AI Studio — aistudio.google.com/apikey, формат AIza… — может позволять испытания на бесплатном тарифе. Проверьте, подходят ли лимиты вашей нагрузке, прежде чем при необходимости включать оплату. По умолчанию поставляется gemini-2.5-flash. Возможности рассуждения у Gemini и Gemma неодинаковы: reasoning_models использует настроенные шаблоны имён, а не проверку возможностей.

Чтобы контролировать место выполнения инференса:

  • Local / совместимость с OpenAI. Используйте provider=local с сервером, совместимым с OpenAI Chat Completions: Ollama, LM Studio, vLLM, LocalAI — или удалённым шлюзом, например OpenRouter. Укажите корень API в SEO_PRO_AI_LOCAL_BASE_URL, к нему добавляется /chat/completions, и выберите доступную SEO_PRO_AI_MODEL. Удалённый шлюз получает данные за пределами вашей сети и может брать плату: название адаптера local не означает локальный инференс.

Локальный base_url проверяется: localhost нужно разрешить явно

base_url — привилегированная настройка, проверяемая тем же SsrfGuard, что и остальные исходящие загрузки: только http/https, без userinfo и по умолчанию с разрешением хоста в публичный адрес. Поэтому ошибочный или вредоносный base_url нельзя использовать для исследования внутренних сервисов. Настоящий локальный сервер находится на приватном адресе 127.0.0.1, поэтому ему нужно явное разрешение seo-pro.ai.local.allow_local_addressesSEO_PRO_AI_LOCAL_ALLOW_PRIVATE=true. Для публичного шлюза вроде OpenRouter оставьте его выключенным. Путь запроса фиксирован, редиректы не выполняются, поэтому ключ нельзя перенаправить на другой хост.

Управление рассуждением в поддерживаемых моделях Ollama

Локальная рассуждающая модель может превысить стандартный тайм-аут. Если модель и версия сервера поддерживают это, ['think' => false] в seo-pro.ai.local.extra_body отключает рассуждение для предложений. Поддержка различается: проверьте документацию Ollama. При необходимости увеличьте seo-pro.ai.timeout. Пакет не отправляет temperature, поскольку некоторые модели отклоняют этот параметр.

Стоимость

Пакет не делает наценку: вы платите провайдеру напрямую. При самостоятельном размещении инференса платы за API провайдера нет, но инфраструктурные расходы остаются. Важны две суммы: стоимость одного предложения при интерактивной работе и массового заполнения всей коллекции.

Таблица seo-pro.ai.pricing в долларах США за 1 000 000 токенов переводит оценку токенов в сумму, которую показывает подтверждение массового заполнения. Это поставляемые допущения для расчёта, а не проверенные текущие публичные цены. Для точной оценки замените их текущими опубликованными ценами вашего провайдера:

Шаблон моделиВход, $/1 млнВыход, $/1 млн
claude-opus-*15,0075,00
claude-sonnet-*3,0015,00
claude-haiku-*1,005,00
gpt-5*mini*0,501,50
gpt-5*5,0015,00
gemini-2.5-pro*1,2510,00
gemini-*flash*0,150,60

Опубликованный пример использует расход токенов протестированной страницы — один заголовок и одно описание — с этими допущениями. Последний столбец применяет примерную скидку 50% за пакетную обработку в поддерживаемых адаптерах. Это не актуальные ценовые предложения.

Провайдер / модельПримерно за пару предложенийПримерно за 1 000 записей, массовое заполнениеПримерно за 1 000 записей, --batch
Local gemma/llama — Ollama$0 за API$0 за APIНеприменимо: адаптер не реализует
Google gemini-2.5-flash — платныйОколо $0,001Около $0,40Неприменимо: адаптер Rankbeam не реализует
OpenAI gpt-5.5Около $0,008Около $5,25Около $2,63, скидка 50%
Anthropic claude-opus-4-8Около $0,03Около $20Около $10, скидка 50%

Команда помечает оценку как приблизительную, ±50%, но это не лимит расходов и не гарантированный диапазон ошибки. Реальные входные данные, ответы и цены меняют итог. Расчёт учитывает видимый вывод; оплачиваемое скрытое рассуждение может увеличить стоимость сверх него. Для моделей без записи в таблице цен показывается только оценка токенов.

Более дешёвая массовая генерация

Задайте seo-pro.ai.bulk_modelSEO_PRO_AI_BULK_MODEL, — чтобы использовать другую модель только для массового заполнения через seo-pro:ai-fill / SeoPro::aiFill(). Filament и seo-pro:ai-suggest сохраняют model. При null массовое заполнение тоже использует model. Оценка стоимости берёт ценовой шаблон выбранной модели. Перед увеличением объёма оцените типичные результаты: более дешёвая модель не обязательно подходит.

dotenv
SEO_PRO_AI_MODEL=claude-opus-4-8        # interactive: highest quality
SEO_PRO_AI_BULK_MODEL=claude-haiku-4-5  # bulk-fill: cheap tier

В примерах пакета используются anthropic claude-haiku-4-5, openai gpt-5.5-mini, google gemini-2.5-flash либо меньшая локальная модель. Ценовой шаблон может совпасть с именем, даже если провайдер не предлагает такую модель. Перед настройкой подтвердите настоящий идентификатор, совместимость API и цену.

Заполнение 100 страниц, у каждой отсутствуют и заголовок, и описание, — это 200 вызовов провайдера. Ниже сравнение качественной модели и её дешёвого варианта bulk_model по поставляемым значениям pricing и расчётному расходу на вызов: 600 входных и 150 выходных токенов.

ПровайдерКачественная модель — 100 страницДешёвая bulk_model — 100 страниц
Anthropicclaude-opus-4-8$4,05claude-haiku-4-5$0,27
OpenAIgpt-5.5$1,05gpt-5.5-mini$0,11
Googlegemini-2.5-pro$0,45gemini-2.5-flash$0,04
Local — Ollama / vLLMЛюбая модель — $0 за APIЛюбая модель — $0 за API

Это иллюстративные оценки без гарантированного диапазона ±50% и без запаса на скрытое рассуждение. Прежде чем полагаться на расчёт, обновите seo-pro.ai.pricing по опубликованным ценам выбранного провайдера.

Язык результата

Каждый промпт называет язык страницы и его код BCP-47, например: «на бразильском португальском (pt-BR), языке страницы, независимо от других языков во фрагменте». Контекст страницы, передаваемый модели, содержит строку Language:, начиная с Pro 2.34. Раньше промпты говорили «на том же языке, что и исходный контент», оставляя модели выбор по короткому или смешанному фрагменту: турецкая страница с английским названием бренда могла получить ответ по-английски. Используется локаль, в которой определены метаданные страницы, либо локаль приложения, если у страницы её нет. Для неё же выбирается лимит длины, поэтому японская страница запрашивает заголовки примерно из 30 символов на японском.

С Pro 2.36 явно заданная локаль контента совместно управляет строкой метаданных, хуками контента и языком промпта. Язык интерфейса оператора не меняется.

php
$ai = app(\Rankbeam\Seo\Pro\Ai\SeoSuggestionService::class);
$titles = $ai->suggestTitles($post, locale: 'it');
$descriptions = $ai->suggestDescriptions($post, locale: 'ja');
$rewrite = $ai->rewriteDescription($post, locale: 'it');
$schema = $ai->suggestSchemaType($post, locale: 'it');
$request = $ai->suggestionRequest($post, 'title', locale: 'ja');

Существующие позиционные аргументы не изменены. Если не передавать locale:, используется значение по умолчанию из seoData() модели, что позволяет отдельным моделям переводов объявлять свой язык. Для выдержки используется getContentForSEO(), если он возвращает непустой контент, иначе — настроенные поля контента. Filament 1.11 автоматически передаёт локаль выбранной вкладки, в том числе в одноязычном режиме и режиме переключения страниц.

bash
php artisan seo-pro:ai-suggest "App\Models\Post" 42 --locale=it
php artisan seo-pro:suggest-schema "App\Models\Post" 42 --locale=ja
php artisan seo-pro:ai-fill "App\Models\Post" --field=description --locale=it --batch

Массовые plan(), fill() и submitBatchFill() тоже принимают завершающий locale:. Используйте одну локаль при создании FillProgress(..., locale: 'it') и отправке запуска. Каждый элемент пакета сохраняет локаль контента; сбор результатов использует её и повторно проверяет строку метаданных перед записью. Запуски с явной локалью имеют отдельные файлы контрольных точек, а маркеры обработки различают языки. Для сбора результатов повторите ту же команду. Собственные задачи должны сериализовать и передавать локаль контента.

Контрольные точки до Pro 2.36 не сохраняли локаль контента. Незавершённый старый пакет сохраняется, но автоматический сбор его результатов отклоняется. Перед удалением через --fresh сопоставьте результаты провайдера и нужную локаль, иначе повторная отправка может привести к повторной оплате той же работы. Старая последовательная контрольная точка с уже обработанными записями тоже требует сверки перед сбросом.

Оценка по языкам

Репозиторий исходного кода Pro содержит 170 входных страниц на 17 локалях и явно включаемый стенд оценки. Входные страницы проверяются структурно и эвристически по базовому языку; независимое одобрение носителями пока не получено.

Стенд проверяет и заголовки, и описания, записывает длину в графемах и сведения о языке и письменности, а также сохраняет каждый ответ провайдера до проверок. Короткие заголовки, смешанный текст и общие китайские и японские иероглифы могут оставаться неоднозначными. Определение португальского языка не подтверждает бразильский вариант, а частичные проверки китайских иероглифов не удостоверяют качество региональной письменной речи.

Для реальных запусков нужны SEO_PRO_AI_EVAL=1, явный выбор SEO_PRO_AI_EVAL_LOCALES и идентификатор SEO_PRO_AI_EVAL_RUN. Они могут повлечь оплату провайдеру; по умолчанию ничего не запускается. Доказательства каждого запуска привязаны к провайдеру, запрошенной и возвращённой модели, хешам тестовых данных, запроса и кода, а также времени. Неудачные попытки сохраняются. Возобновление использует сохранённые ответы; прерванный запрос нужно повторить явно, поскольку он уже мог дойти до провайдера.

Доказательства хранятся в storage/app/seo-ai-evals/<run-id>/ тестового окружения исходного проекта. В README.md тестовых данных описаны версионируемая схема и команды. Носители языка оценивают точные хеши результатов в отдельных записях рецензирования. Успешная автоматическая проверка не является одобрением носителя или гарантией готовности текста к публикации.

Лимиты и настройка

Все параметры находятся в блоке ai файла config/seo-pro.php:

  • timeout — по умолчанию 15 секунд, переменная SEO_PRO_AI_TIMEOUT. Это также предел синхронного вызова, который выполняет модальное окно предложений Filament при открытии, поэтому он короткий ради удобства работы. Медленная рассуждающая или локальная модель может превысить 15 секунд и завершиться тайм-аутом. Увеличьте значение через SEO_PRO_AI_TIMEOUT и учтите совет Ollama с think => false выше. Тайм-аут всегда некритичен: сообщение об ошибке в интерфейсе, а не блокировка сохранения.
  • max_input_chars — по умолчанию 6000. Ограничивает стоимость и объём раскрываемых данных: сколько контента страницы передаётся в одном запросе в виде обычного текста без HTML.
  • max_output_tokens — по умолчанию 1000. Базовый лимит генерируемых токенов. Ответ, достигший его, даёт отдельную ошибку truncated, а не незаметный полуответ.
  • token_budgets — выходные лимиты по задачам: suggestions 800, explanation 600, rewrite 300, schema_suggestion 700. Ни одной задаче не нужен полный общий лимит, но поверх него применяется нижняя граница для рассуждения.
  • reasoning_models и reasoning_min_output_tokens — по умолчанию 2000. У моделей с именем, совпадающим с шаблоном *gemma*, gemini-2.5-*, o1*/o3*/o4*, выходной бюджет повышается до этой границы. Рассуждающая модель расходует скрытые токены до видимого ответа, и малый бюджет обрезал бы результат.
  • suggestion_count — по умолчанию 3. Число запрашиваемых вариантов заголовка или описания.
  • retry — автоматические повторы только для временных ошибок: см. Обработка ответов.

В Filament

При установленных необязательных пакетах Filament — rankbeam/laravel-seo-filament >= 1.1 — включение помощи ИИ добавляет следующие действия. Ниже сохранены их названия в английском интерфейсе:

  • Suggest with AI у SEO-заголовка и описания каждого ресурса с SEO-разделом на страницах редактирования. Модальное окно показывает варианты со счётчиками символов; выбор заполняет поле для проверки.
  • Explain (AI) в таблице проблем панели: краткое объяснение проблемы простым языком и конкретное исправление.
  • Rewrite description (AI) в таблице проблем рядом с Explain: предлагает одно улучшенное метаописание в пределах лимита страницы — 160 символов для латиницы и примерно 80 для CJK, согласно политике длины ядра. Проверьте его в модальном окне; нажатие Apply rewrite записывает значение в seo_meta страницы. До применения ничего не записывается.
  • Suggest structured data (AI) в таблице проблем: предлагает наиболее подходящий тип расширенного результата schema.org — Product, Article или Breadcrumb — и показывает построенный JSON-LD. Нажатие Apply structured data добавляет его в seo_meta.schema_jsonld страницы, тот же столбец, которым управляет необязательный редактор структурированных данных. Данные сохраняют совместимость с этим редактором и остаются редактируемыми. Неполное предложение, например Article без автора или изображения, показывается со списком недостающих полей и не применяется.

Последние два действия — ограниченные исправления: см. соответствующий раздел.

Ограниченные исправления: только предложение, без автоприменения

Два действия идут дальше набора вариантов: они создают одно значение с ограничениями, которое можно применить одним кликом. Оба всё равно только предлагают: ничего не сохраняется без вашего явного принятия.

  • Rewrite descriptionSeoSuggestionService::rewriteDescription($model, $issue?) — возвращает одно метаописание всегда в пределах лимита ядра для письменности страницы: 160 для латиницы, около 80 для CJK. Тот же лимит передаётся в промптах предложений заголовков и описаний и выбирается по итоговому значению самой страницы. Если модель превышает его, текст детерминированно обрезается по границе предложения, затем слова. Поэтому принятая переработка сама по себе не может вызвать предупреждение description_too_long. Переданная проблема сканирования направляет переработку, например слишком длинное или отсутствующее описание.
  • Suggest structured dataSeoSuggestionService::suggestSchemaType($model) — запрашивает у модели только рекомендацию типа и значения конечных полей, никогда не сырой JSON-LD. Затем детерминированный код собирает документ конструкторами ядра ProductSchema / ArticleSchema / BreadcrumbSchema и проверяет через SchemaValidator. Поэтому выдуманные @type, @context или структура не попадут на страницу. Если в собранном документе нет обязательного поля, он показывается как неполный и не применяется. В реальном испытании один провайдер предложил Article для малосодержательной страницы; предложение корректно отклонили из-за отсутствующих автора и изображения, тогда как другие провайдеры вообще отказались предлагать тип.

Без интерфейса

Те же возможности в JSON для скриптов и приложений без Filament:

bash
# title + description suggestions for a model
php artisan seo-pro:ai-suggest "App\Models\Post" 42

# one field only
php artisan seo-pro:ai-suggest "App\Models\Post" 42 --field=description

# explain a scan issue (IDs from seo-pro:scan-status)
php artisan seo-pro:ai-suggest --issue=17

# suggest a schema.org type + built, validated JSON-LD for a model
php artisan seo-pro:suggest-schema "App\Models\Post" 42

Вывод содержит предложения либо рекомендуемый тип, собранный JSON-LD и результат проверки, использованную модель и расход токенов на запрос: вход, выход и рассуждение. Это помогает рассчитать стоимость по тарифам провайдера; число токенов не является счётом. При любой ошибке команда возвращает ненулевой код, а ошибку помещает в JSON-оболочку. Как и другие действия помощи, seo-pro:suggest-schema только предлагает: выводит документ и ничего не записывает.

Массовое заполнение недостающих метаданных

Pro 2.42 меняет поведение CLI по умолчанию: seo-pro:ai-fill сохраняет по одному приватному черновику для каждого сгенерированного поля. Опубликованные SEO-метаданные не меняются до утверждения. Существующие значения и вычисленные резервные значения пропускаются. Актуальный ожидающий черновик используется повторно вместо новой генерации.

bash
php artisan seo-pro:ai-fill "App\Models\Post" --field=description
php artisan seo-pro:ai-review
php artisan seo-pro:ai-review DRAFT_ID
php artisan seo-pro:ai-review DRAFT_ID --approve --reviewer="editor@example.com"
php artisan seo-pro:ai-review DRAFT_ID --reject --reviewer="editor@example.com"

seo-pro:ai-review перечисляет первые 100 ожидающих черновиков в JSON. Укажите ID, чтобы прочитать значение и приватные доказательства его получения. Утверждение и отклонение работают с выключенным ИИ и не вызывают провайдера. Для утверждения нужна метка оператора; оно отклоняет черновики, если исходная запись или целевые метаданные изменились либо запись удалена. Метка фиксирует, кем представился оператор, но не доказывает содержательную проверку человеком. Для настроенной нестандартной базы используйте --connection=NAME.

--auto-apply явно возвращает немедленную публикацию всё ещё отсутствующих полей. --force пропускает подтверждение, но не проверку. --dry-run генерирует и выводит значения без сохранения черновиков или метаданных, однако всё равно вызывает провайдера и может стоить денег. --field, --limit и --locale ограничивают область генерации. После обновления осознанно пересмотрите команды в расписании.

При больших объёмах: интервалы, оценка стоимости и продолжение после сбоя

По умолчанию seo-pro.ai.fill.throttle_ms равен 200 миллисекундам. При достижении confirm_over — по умолчанию 100 записей — команда показывает оценку из seo-pro.ai.pricing и запрашивает подтверждение перед генерацией. Контрольные точки сохраняют завершённые поля при прерываниях. Тайм-аут после принятия запроса провайдером всё ещё может привести к повторному списанию; перед --fresh сверьте работу с неопределённым результатом. Запускайте одновременно только одну соответствующую массовую задачу.

php
use Rankbeam\Seo\Pro\Facades\SeoPro;

$summary = SeoPro::aiFill()->fill([\App\Models\Post::class], 'all', limit: 50, review: true);

В собственных интеграциях передавайте review: true для подготовки черновиков. Низкоуровневый PHP API ради совместимости сохраняет apply: true, review: false, поэтому существующие вызовы всё ещё записывают сразу. apply: false даёт предпросмотр без сохранения. Ключ сводки filled считает обработанные записи, включая подготовленные в режиме проверки; CLI помечает их staged.

Пакетный режим: на 50% дешевле

--batch использует поддерживаемый асинхронный endpoint Anthropic или OpenAI. Заявленная ими скидка отражена в расчёте, но проверьте текущие цены моделей. Адаптеры Google и Local переходят к последовательной генерации. Отправьте пакет сейчас, а позже повторите ту же команду для сбора черновиков:

bash
php artisan seo-pro:ai-fill "App\Models\Post" --field=description --batch
# Re-run the same command to collect drafts.
php artisan seo-pro:ai-fill "App\Models\Post" --field=description --batch

Между отправкой и сбором не меняйте провайдера, локаль и режим публикации. Проверка и --auto-apply используют разные контрольные точки; CLI откажется запускать другой режим, пока соответствующий пакет не завершён. Отправка с неопределённым результатом останавливает работу для сверки. Частичные успехи сохраняются; временные ошибки можно повторить. При сборе снова проверяются отсутствующие поля, а при утверждении — также снимок источника, сделанный до отправки. seo-pro.ai.fill.batch.request_timeout по умолчанию равен 120 секундам. Сбор по расписанию по умолчанию сохраняет черновики.

Учёт происхождения, миграции и фильтрация данных

Требуются Core 3.21 и Pro 2.42. Core загружает свою миграцию автоматически. До генерации сохраняемых предложений опубликуйте миграции Pro и выполните их для каждой базы данных, используемой SEO-моделями:

bash
php artisan vendor:publish --tag=seo-pro-migrations
php artisan migrate

Приватная таблица seo_ai_proposals хранит сгенерированные значения и сведения о провайдере, модели и запросе через зашифрованные приведения типов Laravel. Надёжно храните APP_KEY и его резервную копию: потеря ключа делает эти значения нечитаемыми. Идентификаторы записей, статус и сведения о решении остаются обычными столбцами базы. Варианты формы могут остаться в состоянии offered или selected, если форму бросили. Автоматической очистки нет: задайте политику хранения приложения, сохраняйте ожидающие черновики и доказательства, на которые ещё ссылается seo_meta.ai_provenance, ограничьте доступ к экспортам БД и выводу команды проверки.

Принятые предложения формы, исправления панели и массовые значения несут сведения о происхождении поля. Последующие изменения через Eloquent сохраняют origin: ai и устанавливают edited: true. Это означает, что значение изменено, а не проверено человеком. Очистка поля удаляет маркер. HTML, массивы, JSON и Inertia-вывод ядра раскрывают только имя поля, происхождение и состояние редактирования; где применимо, используется собственный метатег rankbeam:ai-origin. Идентификаторы генерации и подробности провайдера остаются приватными. Не отдавайте сырые модели SEOMeta в публичном API.

Учёт охватывает будущие поддерживаемые пути сохранения, а не исторический контент или каждую редакцию. Прямой SQL, обновления через query builder и собственные компоненты вывода могут обходить эти меры. Явно сбрасывайте происхождение, когда это оправдано независимо написанной заменой; обычные правки его сохраняют. Этот маркер не является стандартным водяным знаком, защищённой от подделки атрибуцией или заявлением о соответствии статье 50. Качество реальных ответов и собственные маркировки провайдеров требуют отдельной оценки.

При необходимости реализуйте AiPromptFilter и настройте seo-pro.ai.context_filter. Фильтр обрабатывает собранный пользовательский промпт перед синхронной или пакетной отправкой. Его ошибка предотвращает отправку и возвращает очищенное сообщение. Системные инструкции не меняются. По умолчанию стоит null, автоматического удаления чувствительных данных нет. Этот пример заменяет только одно известное значение; реализуйте и проверьте правила для своего приложения:

php
namespace App\Support;

use Rankbeam\Seo\Pro\Ai\AiPromptFilter;

final class RedactAiContext implements AiPromptFilter
{
    public function filter(string $prompt): string
    {
        return str_replace('internal@example.com', '[redacted]', $prompt);
    }
}

// Configure seo-pro.ai.context_filter with this class in config/seo-pro.php.
// Runtime equivalent:
config(['seo-pro.ai.context_filter' => RedactAiContext::class]);

Обработка ответов

Каждый вызов возвращает единую, независимую от провайдера оболочку, поэтому поведение одинаково для всех провайдеров, включая будущие:

  • Структурированный вывод, где его поддерживает провайдер. В OpenAI — нативные Structured Outputs, Google — Gemini responseSchema, Anthropic — output_config.format — форму JSON обеспечивает API. Некорректный JSON даёт явную ошибку, без извлечения данных из произвольного текста. Локальному или совместимому с OpenAI серверу тоже передаётся response_format без гарантии соблюдения. Сервер, игнорирующий поле, всё ещё может вернуть пригодный текст, который разбирается гибким резервным парсером. В любом случае результат — корректный список или понятная ошибка, никогда не наполовину разобранный ответ.
  • Обрезка — явная ошибка с понятным действием. Если ответ оборвался на лимите выходных токенов, вы получаете truncated с предложением увеличить seo-pro.ai.max_output_tokens, а не незаметно укороченный заголовок. Чаще всего это случается с рассуждающими моделями; для них автоматически применяется повышенная нижняя граница reasoning_min_output_tokens.
  • Временные ошибки повторяются автоматически. Ограничение частоты 429 или 5xx вызывает повтор с ограниченной экспоненциальной задержкой. Если есть заголовок Retry-After, он учитывается в заданных пределах, чтобы вредоносное значение не могло надолго остановить запрос. Детерминированные ошибки не повторяются: неверный ключ, некорректный запрос, слишком большой объём данных, тайм-аут или исчерпанный баланс/квота. Повтор запроса с неоплаченным аккаунтом лишь тратит время ожидания. Настройте или отключите повторы через retry; для отключения установите max_attempts в 0.
  • Ошибки типизированы и очищены. У каждой есть стабильный код: unauthorized, quota_exceeded, rate_limited, timeout, content_too_large, bad_request, truncated, content_filtered, provider_error и другие. Временные ошибки имеют флаг retryable. Сообщение — короткая очищенная строка. Обычный путь приложения не показывает и не записывает в журнал сырое тело ответа провайдера; явно включаемый стенд оценки выше сохраняет ответы как доказательства. В Filament ошибка отображается в оформленном частичном шаблоне модального окна с подходящей подсказкой следующего шага для распространённых случаев: см. Устранение неполадок.

Устранение неполадок

Каждая ошибка некритична и показывается в интерфейсе с типизированным кодом и очищенным сообщением. Ниже распространённые случаи и способы исправления; английские сообщения сохранены как диагностические строки:

Симптом и кодЗначениеИсправление
quota_exceeded"the provider account is out of credit or quota"Ключ корректен, но у API-аккаунта нет средств или квоты. Это не ограничение частоты: повторы не помогут. У провайдеров разные сообщения: Anthropic — "credit balance is too low", OpenAI — "exceeded your current quota… check your plan and billing" (insufficient_quota), Google — "prepayment credits are depleted".Пополните баланс или включите оплату в консоли провайдера либо перейдите на локальную модель без платы за API провайдера. Подписка Claude/ChatGPT не оплачивает API.
unauthorized"authentication failed"Ключ отсутствует, неверен или не подходит настроенному провайдеру.Проверьте ключ в переменной, имя которой задаёт seo-pro.ai.api_key_env, по умолчанию SEO_PRO_AI_API_KEY: он должен быть задан, актуален и соответствовать SEO_PRO_AI_PROVIDER.
rate_limited"the provider rate limit was reached"Настоящее временное ограничение частоты; сначала выполняются автоматические повторы.Подождите и повторите либо используйте локальную модель с учётом мощности своего сервера. Для массовых запусков на младшем тарифе увеличьте seo-pro.ai.fill.throttle_ms.
timeout"the request timed out"Провайдер не ответил за seo-pro.ai.timeout, по умолчанию 15 секунд. Часто бывает с медленной локальной рассуждающей моделью.Увеличьте предел через SEO_PRO_AI_TIMEOUT; для Ollama также задайте ['think' => false] в seo-pro.ai.local.extra_body.
truncated"hit the max_output_tokens limit"Ответ достиг выходного бюджета, возможно вместе со скрытым рассуждением.Увеличьте seo-pro.ai.max_output_tokens, рассуждающим моделям может понадобиться 2000+, либо убедитесь, что имя совпадает с шаблоном reasoning_models и применяется нижняя граница.
content_too_large — HTTP 413Отправленный контент страницы превысил лимит провайдера.Уменьшите seo-pro.ai.max_input_chars, чтобы отправлять более короткую выдержку.
bad_requestНекорректный запрос: обычно имя модели, недоступной аккаунту, или неподдерживаемый параметр.Проверьте, что модель в SEO_PRO_AI_MODEL доступна вашему ключу или серверу у настроенного провайдера.
content_filteredФильтр безопасности провайдера отказался отвечать.Проверьте содержимое и рекомендации провайдера; не повторяйте отклонённый запрос автоматически.

Локальному инференсу всё равно нужен рабочий сервер

SEO_PRO_AI_PROVIDER=local с самостоятельно размещённым инференсом устраняет проблемы баланса облачного провайдера. Оборудование, модель, совместимость API, тайм-аут и производительность всё ещё важны. Удалённый шлюз с этим адаптером может требовать ключ и оплату.

Что покидает ваш сервер

Только перечисленное ниже, только настроенному провайдеру и только по явному действию: нажатию действия или запуску команды.

  • Предложения: короткое имя класса модели и ключ, например "Post #3", текущие итоговые заголовок и описание, канонический URL и выдержка контента обычным текстом без HTML, ограниченная max_input_chars, по умолчанию 6000 символов.
  • Объяснения проблем: тип, серьёзность, поле, сообщение и URL цели; если доступна модель — также её класс и ключ, итоговые заголовок и описание, канонический URL и ограниченная текстовая выдержка.
  • Переработка описания: тот же минимальный контекст страницы, что и для предложения, а при передаче проблемы сканирования — также её тип и сообщение.
  • Предложение структурированных данных: тот же минимальный контекст страницы. Модель возвращает только тип и значения конечных полей; JSON-LD собирается локально.

Пакет не собирает намеренно данные посетителей, IP-адреса, заголовки запросов или учётные данные в промпты и не отправляет полный HTML. Поля контента и выдержки сами могут содержать чувствительную информацию: проверьте, что раскрывает ваше приложение. Учётные данные провайдера используются для аутентификации запроса. Правила обработки данных описаны в SECURITY.md репозитория Pro.

rankbeam/laravel-seo распространяется под лицензией MIT.