1- # Prompt generator for LLM Agents
1+ # LLM Agents Prompt Generator
22
33[ ![ PHP] ( https://img.shields.io/packagist/php-v/llm-agents-php/agent-site-status-checker.svg?style=flat-square )] ( https://packagist.org/packages/llm-agents/prompt-generator )
44[ ![ Latest Version on Packagist] ( https://img.shields.io/packagist/v/llm-agents/prompt-generator.svg?style=flat-square )] ( https://packagist.org/packages/llm-agents/prompt-generator )
55[ ![ Total Downloads] ( https://img.shields.io/packagist/dt/llm-agents/prompt-generator.svg?style=flat-square )] ( https://packagist.org/packages/llm-agents/prompt-generator )
66
7+ This package provides a flexible and extensible system for generating chat prompts with all required system and user
8+ messages for LLM agents. It uses an interceptor-based approach to expand generator abilities.
9+
710### Installation
811
9- First things first, let's get this package installed :
12+ You can install the package via Composer :
1013
1114``` bash
1215composer require llm-agents/prompt-generator
@@ -30,9 +33,250 @@ bootloader.
3033 ];
3134 }
3235 ```
36+ 3 . Create a bootloader for the prompt generator. Create a file named ` PromptGeneratorBootloader.php `
37+ in your ` app/src/Application/Bootloader ` directory:
38+
39+ ``` php
40+ namespace App\Application\Bootloader;
41+
42+ use Spiral\Boot\Bootloader\Bootloader;
43+
44+ use LLM\Agents\PromptGenerator\Interceptors\AgentMemoryInjector;
45+ use LLM\Agents\PromptGenerator\Interceptors\InstructionGenerator;
46+ use LLM\Agents\PromptGenerator\Interceptors\LinkedAgentsInjector;
47+ use LLM\Agents\PromptGenerator\Interceptors\UserPromptInjector;
48+ use LLM\Agents\PromptGenerator\PromptGeneratorPipeline;
49+
50+ class PromptGeneratorBootloader extends Bootloader
51+ {
52+ public function defineSingletons(): array
53+ {
54+ return [
55+ PromptGeneratorPipeline::class => static function (
56+ LinkedAgentsInjector $linkedAgentsInjector,
57+ ): PromptGeneratorPipeline {
58+ $pipeline = new PromptGeneratorPipeline();
59+
60+ return $pipeline->withInterceptor(
61+ new InstructionGenerator(),
62+ new AgentMemoryInjector(),
63+ $linkedAgentsInjector,
64+ new UserPromptInjector(),
65+ // ...
66+ );
67+ },
68+ ];
69+ }
70+ }
71+ ```
3372
3473And that's it! Your Spiral app is now ready to use the agent.
3574
75+ ## Usage
76+
77+ Here's an example of how to initialize the prompt generator and generate a prompt:
78+
79+ ``` php
80+ use App\Domain\Chat\PromptGenerator\SessionContextInjector;
81+ use LLM\Agents\PromptGenerator\Interceptors\AgentMemoryInjector;
82+ use LLM\Agents\PromptGenerator\Interceptors\InstructionGenerator;
83+ use LLM\Agents\PromptGenerator\Interceptors\LinkedAgentsInjector;
84+ use LLM\Agents\PromptGenerator\Interceptors\UserPromptInjector;
85+ use LLM\Agents\PromptGenerator\PromptGeneratorPipeline;
86+
87+ $generator = new PromptGeneratorPipeline();
88+
89+ $generator = $generator->withInterceptor(
90+ new InstructionGenerator(),
91+ new AgentMemoryInjector(),
92+ new LinkedAgentsInjector($agents, $schemaMapper),
93+ new SessionContextInjector(),
94+ new UserPromptInjector()
95+ );
96+
97+ $prompt = $generator->generate($agent, $userPrompt, $context, $initialPrompt);
98+ ```
99+
100+ ## Interceptors
101+
102+ The package comes with several built-in interceptors:
103+
104+ ### InstructionGenerator
105+
106+ This interceptor adds the agent's instruction to the prompt. It includes important rules like responding in markdown
107+ format and thinking before responding to the user.
108+
109+ ### AgentMemoryInjector
110+
111+ This interceptor adds the agent's memory to the prompt. It includes both static memory (defined when creating the agent)
112+ and dynamic memory (which can be updated during the conversation).
113+
114+ ### LinkedAgentsInjector
115+
116+ This interceptor adds information about linked agents to the prompt. It provides details about other agents that the
117+ current agent can call for help, including their keys, descriptions, and output schemas.
118+
119+ ### UserPromptInjector
120+
121+ This interceptor adds the user's input to the prompt as a user message.
122+
123+ ## Creating Custom Interceptors
124+
125+ You can create custom interceptors by implementing the ` LLM\Agents\PromptGenerator\PromptInterceptorInterface ` :
126+
127+ Let's create a ` ContextAwarePromptInjector ` that adds relevant context to the prompt based on the current time of day
128+ and
129+ user preferences. This example will demonstrate how to create a more sophisticated interceptor that interacts with
130+ external services and modifies the prompt accordingly.
131+
132+ ``` php
133+ namespace App\PromptGenerator\Interceptors;
134+
135+ use LLM\Agents\LLM\Prompt\Chat\MessagePrompt;
136+ use LLM\Agents\LLM\Prompt\Chat\Prompt;
137+ use LLM\Agents\LLM\Prompt\Chat\PromptInterface;
138+ use LLM\Agents\PromptGenerator\InterceptorHandler;
139+ use LLM\Agents\PromptGenerator\PromptGeneratorInput;
140+ use LLM\Agents\PromptGenerator\PromptInterceptorInterface;
141+ use App\Services\UserPreferenceService;
142+ use App\Services\WeatherService;
143+
144+ class ContextAwarePromptInjector implements PromptInterceptorInterface
145+ {
146+ public function __construct(
147+ private UserPreferenceService $userPreferenceService,
148+ private WeatherService $weatherService,
149+ ) {}
150+
151+ public function generate(PromptGeneratorInput $input, InterceptorHandler $next): PromptInterface
152+ {
153+ $userId = $input->context->getUserId(); // Assuming we have this method in our context
154+ $userPreferences = $this->userPreferenceService->getPreferences($userId);
155+ $currentTime = new \DateTime();
156+ $currentWeather = $this->weatherService->getCurrentWeather($userPreferences->getLocation());
157+
158+ $contextMessage = $this->generateContextMessage($currentTime, $userPreferences, $currentWeather);
159+
160+ $modifiedPrompt = $input->prompt;
161+ if ($modifiedPrompt instanceof Prompt) {
162+ $modifiedPrompt = $modifiedPrompt->withAddedMessage(
163+ MessagePrompt::system($contextMessage),
164+ );
165+ }
166+
167+ return $next($input->withPrompt($modifiedPrompt));
168+ }
169+
170+ private function generateContextMessage(\DateTime $currentTime, $userPreferences, $currentWeather): string
171+ {
172+ $timeOfDay = $this->getTimeOfDay($currentTime);
173+ $greeting = $this->getGreeting($timeOfDay);
174+
175+ return <<<PROMPT
176+ {$greeting} Here ' s some context for this conversation:
177+ - It' s currently {$timeOfDay}.
178+ - The weather is {$currentWeather- >getDescription()} with a temperature of {$currentWeather->getTemperature()}°C.
179+ - The user prefers {$userPreferences->getCommunicationStyle()} communication.
180+ - The user's interests include: {$this->formatInterests($userPreferences->getInterests())}.
181+
182+ Please take this context into account when generating responses.
183+ PROMPT;
184+ }
185+
186+ private function getTimeOfDay(\DateTime $time): string
187+ {
188+ $hour = (int) $time->format('G');
189+ return match (true) {
190+ $hour >= 5 && $hour < 12 => 'morning',
191+ $hour >= 12 && $hour < 18 => 'afternoon',
192+ $hour >= 18 && $hour < 22 => 'evening',
193+ default => 'night',
194+ };
195+ }
196+
197+ private function getGreeting(string $timeOfDay): string
198+ {
199+ return match ($timeOfDay) {
200+ 'morning' => 'Good morning!',
201+ 'afternoon' => 'Good afternoon!',
202+ 'evening' => 'Good evening!',
203+ 'night' => 'Hello!',
204+ };
205+ }
206+
207+ private function formatInterests(array $interests): string
208+ {
209+ return \implode(', ', \array_map(fn($interest) => \strtolower($interest), $interests));
210+ }
211+ }
212+ ```
213+
214+ Then, add your custom interceptor to the pipeline:
215+
216+ ``` php
217+ $generator = $generator->withInterceptor(new ContextAwarePromptInjector(...));
218+ ```
219+
220+ ## Implementing PromptContextInterface
221+
222+ The ` PromptGeneratorInput ` includes a ` context ` property of type ` PromptContextInterface ` . This interface allows you to
223+ pass custom context data to your interceptors. To use it effectively, you need to create your own implementation of this
224+ interface.
225+
226+ Here's an example of how you might implement the ` PromptContextInterface ` :
227+
228+ ``` php
229+ use LLM\Agents\LLM\PromptContextInterface;
230+
231+ class ChatContext implements PromptContextInterface
232+ {
233+ public function __construct(
234+ private string $userId,
235+ private array $sessionData = [],
236+ ) {}
237+
238+ public function getUserId(): string
239+ {
240+ return $this->userId;
241+ }
242+
243+ public function getSessionData(): array
244+ {
245+ return $this->sessionData;
246+ }
247+
248+ // Add any other methods you need for your specific use case
249+ }
250+ ```
251+
252+ Then, when generating a prompt, you would pass an instance of your custom context:
253+
254+ ``` php
255+ $context = new ChatContext($userId, $sessionData);
256+ $prompt = $generator->generate($agent, $userPrompt, $context);
257+ ```
258+
259+ In your custom interceptors, you can then access this context data:
260+
261+ ``` php
262+ class ContextAwarePromptInjector implements PromptInterceptorInterface
263+ {
264+ public function generate(PromptGeneratorInput $input, InterceptorHandler $next): PromptInterface
265+ {
266+ $userId = $input->context->getUserId();
267+ $sessionData = $input->context->getSessionData();
268+
269+ // Use this data to customize your prompt
270+ // ...
271+
272+ return $next($input);
273+ }
274+ }
275+ ```
276+
277+ By implementing your own ` PromptContextInterface ` , you can pass any necessary data from your application to your
278+ interceptors, allowing for highly customized and context-aware prompt generation.
279+
36280## Want to help out? 🤝
37281
38282We love contributions! If you've got ideas to make this agent even cooler, here's how you can chip in:
0 commit comments