Проблема: розбирати вільний текст моделі регулярними виразами - крихко. Модель може додати пояснення, змінити формат чи забути поле.
Структурований вивід: агент описує JSON-схему відповіді, а провайдер змушує модель повернути дані саме в такій формі.
php artisan make:agent ReviewClassifier --structured
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasStructuredOutput;
use Laravel\Ai\Promptable;
class ReviewClassifier implements Agent, HasStructuredOutput
{
use Promptable;
public function instructions(): string
{
return 'Класифікуй відгук покупця. Не вигадуй фактів, яких немає у тексті.';
}
public function schema(JsonSchema $schema): array
{
return [
'sentiment' => $schema->string()->enum(['positive', 'neutral', 'negative'])->required(),
'topics' => $schema->array()->items($schema->string())->required(),
'needs_reply' => $schema->boolean()->required(),
'score' => $schema->integer()->min(1)->max(5)->required(),
];
}
}
Відповідь поводиться як масив:
$result = (new ReviewClassifier)->prompt($review->body);
$review->update([
'sentiment' => $result['sentiment'],
'needs_reply' => $result['needs_reply'],
]);
Що дає схема:
enumобмежує значення - у базу не потрапить"Positive!"замістьpositive;- типи й межі (
integer,min,max) - менше перевірок у коді; - вкладені об'єкти й масиви об'єктів - для витягання списків (позиції з рахунку, контакти з листа).
Чого схема не гарантує:
- правильності змісту: модель поверне валідний JSON з неправильною класифікацією чи вигаданим значенням. Схема перевіряє форму, а не правду;
- однакової підтримки в усіх провайдерів - строгий режим відрізняється, і частина обмежень схеми може ігноруватися.
Тому дані від моделі - це вхідні дані користувача:
- валідувати перед збереженням (
Validator::make($result->toArray(), [...])чи enum PHP зtryFrom); - не використовувати як SQL, шлях до файлу чи HTML без екранування;
- для критичних рішень (повернення коштів, блокування) - людина в процесі.
Практичні поради:
- описи полів (
->description('...')) у схемі допомагають моделі так само, як інструкції; - низька температура (
#[Temperature(0)]) для класифікації й витягання даних - стабільніші результати; - у тестах
ReviewClassifier::fake([['sentiment' => 'negative', ...]])повертає структуровану відповідь без звернення до API.