diff --git a/README.md b/README.md index a5932b1..07da757 100644 --- a/README.md +++ b/README.md @@ -321,7 +321,7 @@ protected $temperature; protected $message; ``` -The agent also provides two core methods that you can override: +The agent also provides three core methods that you can override: ```php /** @@ -343,6 +343,15 @@ public function prompt(string $message) { return $message; } + +/** + * Decide which model to use dynamically with custom logic + * Or use property $model to statically set the model + */ +public function model() +{ + return $this->model; +} ``` Example: @@ -410,6 +419,12 @@ public function message(string $message); */ public function withImages(array $imageUrls); +/** + * Decide model dynamically in your controller + * @param string $model Model identifier (e.g., 'gpt-4o', 'gpt-3.5-turbo') + */ +public function withModel(string $model); + /** * Clear the chat history * This removes all messages from the chat history diff --git a/src/Agent.php b/src/Agent.php index 29e19c2..a46ad5f 100644 --- a/src/Agent.php +++ b/src/Agent.php @@ -54,7 +54,7 @@ class Agent // Driver configs /** @var string */ - protected $model = 'gpt-4o-mini'; + protected $model; /** @var int */ protected $contextWindowSize; @@ -156,6 +156,8 @@ public function respond(?string $message = null): string|array $this->message($message); } + $this->setupBeforeRespond(); + $this->onConversationStart(); $message = Message::user($this->prompt($this->message)); @@ -193,6 +195,16 @@ public function instructions() return $this->instructions; } + /** + * Get the model for the agent + * + * @return string The agent's model + */ + public function model() + { + return $this->model; + } + /** * Process a message before sending to the agent * @@ -353,6 +365,13 @@ public function temperature(float $temp): static return $this; } + public function withModel(string $model): static + { + $this->model = $model; + + return $this; + } + /** * Convert Agent to DTO * // @todo mention DTO in the documentation as state for events @@ -360,7 +379,7 @@ public function temperature(float $temp): static public function toDTO(): AgentDTO { $driverConfigs = array_filter([ - 'model' => $this->model, + 'model' => $this->model(), 'contextWindowSize' => $this->contextWindowSize ?? null, 'maxCompletionTokens' => $this->maxCompletionTokens ?? null, 'temperature' => $this->temperature ?? null, @@ -399,7 +418,7 @@ protected function buildSessionId(string $id) return sprintf( '%s_%s_%s', class_basename(static::class), - $this->model, + $this->model(), $id ); } @@ -462,7 +481,7 @@ protected function setupAgent(): void protected function buildConfigsForLaragent() { $config = [ - 'model' => $this->model, + 'model' => $this->model(), ]; if (isset($this->maxCompletionTokens)) { $config['max_completion_tokens'] = $this->maxCompletionTokens; @@ -550,6 +569,10 @@ protected function setup(): void $this->setupProviderData(); $chatHistory = $this->createChatHistory($this->getChatSessionId()); $this->setChatHistory($chatHistory); + } + + protected function setupBeforeRespond(): void + { $this->setupAgent(); $this->registerEvents(); } diff --git a/test-agent.php b/test-agent.php index 631f3bd..ada578a 100644 --- a/test-agent.php +++ b/test-agent.php @@ -59,7 +59,6 @@ enum Unit: string class WeatherAgent extends LarAgent\Agent { - protected $model = 'gpt-4o-mini'; protected $provider = 'default'; @@ -124,7 +123,9 @@ public static function weatherToolForNewYork(Unit $unit) echo WeatherAgent::for('test_chat')->respond('What\'s the weather like in Boston and Los Angeles? I prefer fahrenheit'); echo "\n---\n"; -// Using "celsus" instead of "celsius" to check correct pick of enum value -echo WeatherAgent::for('test_chat')->respond('Thanks for the info. What about New York? I prefer celsus'); +// // Using "celsus" instead of "celsius" to check correct pick of enum value +// echo WeatherAgent::for('test_chat')->respond('Thanks for the info. What about New York? I prefer celsus'); +// echo "\n---\n"; +// echo WeatherAgent::for('test_chat')->message('Where am I now?')->respond(); echo "\n---\n"; -echo WeatherAgent::for('test_chat')->message('Where am I now?')->respond(); +echo WeatherAgent::for('test_chat')->model(); diff --git a/tests/AgentTest.php b/tests/AgentTest.php index 876650b..b864cbc 100644 --- a/tests/AgentTest.php +++ b/tests/AgentTest.php @@ -133,3 +133,19 @@ protected function afterToolExecution($tool, &$result) 'image_url' => ['url' => 'http://example.com/image2.jpg'], ]); }); + +it('can dynamically change model', function () { + $agent = new TestAgent('test_session'); + + // Check default model + expect($agent->model())->toBe('gpt-4o-mini'); + + // Change model dynamically + $agent->withModel('gpt-3.5-turbo'); + + // Verify model was changed + expect($agent->model())->toBe('gpt-3.5-turbo'); + + // Verify chainable method returns agent instance + expect($agent->withModel('gpt-4'))->toBeInstanceOf(Agent::class); +});