api/app/Ai/Agents/MealMaker.php

98 lines
3.4 KiB
PHP

<?php
namespace App\Ai\Agents;
use App\Enums\IngredientUnit;
use App\Enums\MealPostType;
use Illuminate\Contracts\JsonSchema\JsonSchema;
use Laravel\Ai\Contracts\Agent;
use Laravel\Ai\Contracts\Conversational;
use Laravel\Ai\Contracts\HasStructuredOutput;
use Laravel\Ai\Contracts\HasTools;
use Laravel\Ai\Contracts\Tool;
use Laravel\Ai\Messages\Message;
use Laravel\Ai\Promptable;
use Stringable;
class MealMaker implements Agent, Conversational, HasStructuredOutput, HasTools
{
use Promptable;
public function instructions(): Stringable|string
{
return <<<'INSTRUCTIONS'
You create varied fictional meal posts for a French food tracking app.
Return one realistic meal only. Vary cuisines, seasons, ingredients, and meal types between requests. The meal must be plausible as a single serving.
Use French for title, caption, and ingredient names.
Use one of these units for ingredients: g, kg, ml, l, piece, tsp, tbsp.
Use one of these meal types: breakfast, lunch, dinner, brunch, snack, drink, supplement, other.
Nutrition values must be coherent with the ingredients and portion size.
The image prompt should be in English, optimized for photorealistic food photography, and must describe the exact generated dish.
INSTRUCTIONS;
}
/**
* @return Message[]
*/
public function messages(): iterable
{
return [];
}
/**
* Get the tools available to the agent.
*
* @return Tool[]
*/
public function tools(): iterable
{
return [];
}
public function schema(JsonSchema $schema): array
{
return [
'title' => $schema->string()
->description('Short French meal title.')
->required(),
'caption' => $schema->string()
->description('One concise French sentence describing the meal.')
->required(),
'type' => $schema->string()
->enum(MealPostType::class)
->description('Best matching meal type.')
->required(),
'calories' => $schema->integer()
->min(0)
->description('Estimated calories for the whole serving.')
->required(),
'proteins' => $schema->number()
->min(0)
->description('Estimated proteins in grams.')
->required(),
'carbs' => $schema->number()
->min(0)
->description('Estimated carbohydrates in grams.')
->required(),
'fats' => $schema->number()
->min(0)
->description('Estimated fats in grams.')
->required(),
'ingredients' => $schema->array()
->items($schema->object([
'position' => $schema->integer()->min(1)->required(),
'ingredient' => $schema->string()->required(),
'quantity' => $schema->integer()->min(1)->required(),
'unit' => $schema->string()->enum(IngredientUnit::class)->required(),
]))
->description('Ingredients ordered by importance.')
->required(),
'image_prompt' => $schema->string()
->description('English photorealistic image generation prompt for the exact meal.')
->required(),
];
}
}