Урок 04

Structured Output: типизированный JSON

Вместо парсинга текста — типизированный JSON по схеме.

Проблема

Обычный агент возвращает текст. Если нужны данные — приходится парсить:

$response = (new SalesCoach)->prompt('Оцени транскрипт от 1 до 10');

// Хрупкий парсинг
preg_match('/оценка[:\s]*(\d+)/i', (string) $response, $matches);
$score = (int) ($matches[1] ?? 0);

Решение: HasStructuredOutput

namespace App\Ai\Agents;

use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\HasStructuredOutput;
use Laravel\Ai\Promptable;

class SalesCoach implements Agent, HasStructuredOutput
{
    use Promptable;

    public function instructions(): string
    {
        return 'Ты — sales-коуч. Анализируй транскрипты и возвращай структурированную обратную связь.';
    }

    public function schema(JsonSchema $schema): array
    {
        return [
            'feedback' => $schema->string()->required(),
            'score' => $schema->integer()->min(1)->max(10)->required(),
        ];
    }
}

Использование

$response = (new SalesCoach)->prompt('Проанализируй транскрипт...');

$score = $response['score'];       // int, 1–10
$feedback = $response['feedback']; // string

Ответ — валидный JSON, гарантированно соответствующий схеме.

Создание с флагом

php artisan make:agent SalesCoach --structured

Типы в схеме

'score' => $schema->integer()->min(1)->max(10)->required(),
'feedback' => $schema->string()->required(),
'tags' => $schema->array()->items($schema->string()),
'published' => $schema->boolean(),
'rating' => $schema->number()->min(0)->max(5),

Вложенные объекты

return [
    'summary' => $schema->string()->required(),
    'analysis' => $schema->object(fn ($s) => [
        'strengths' => $s->array()->items($s->string()),
        'weaknesses' => $s->array()->items($s->string()),
    ])->required(),
];

Enum

'priority' => $schema->string()->enum(['low', 'medium', 'high'])->required(),

Преимущества

  • Надёжный парсинг — не нужен regex
  • Гарантия типов — схема проверяет
  • Готово для API — можно вернуть напрямую
  • Тестирование — fake-агенты генерируют совместимые данные

Итоги

  • HasStructuredOutput для JSON
  • schema() определяет форму
  • Ответ — как массив
  • Типы, enum, вложенность
  • Надёжнее парсинга текста