feat: cron

This commit is contained in:
2026-05-18 20:32:32 +02:00
parent 19d106a3ed
commit f5a3e79c8a
16 changed files with 547 additions and 9 deletions
+60 -7
View File
@@ -2,29 +2,38 @@
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, HasTools
class MealMaker implements Agent, Conversational, HasStructuredOutput, HasTools
{
use Promptable;
/**
* Get the instructions that the agent should follow.
*/
public function instructions(): Stringable|string
{
return 'You are a helpful assistant.';
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;
}
/**
* Get the list of messages comprising the conversation so far.
*
* @return Message[]
*/
public function messages(): iterable
@@ -41,4 +50,48 @@ class MealMaker implements Agent, Conversational, HasTools
{
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(),
];
}
}