From d56e712f0579c4571510ea6920159201e656ef59 Mon Sep 17 00:00:00 2001 From: erdemkose Date: Fri, 5 Jan 2024 14:48:50 +0100 Subject: [PATCH] Add streaming chat session --- README.md | 52 +++++++++++++++++++++++++++++++++++++++++ src/ChatSession.php | 31 ++++++++++++++++++++++++ src/GenerativeModel.php | 14 ++++++++++- 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e6978d5..91f0df9 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ _This library is not developed or endorsed by Google._ - [Chat Session (Multi-Turn Conversations)](#chat-session-multi-turn-conversations) - [Chat Session with history](#chat-session-with-history) - [Streaming responses](#streaming-responses) + - [Streaming Chat Session](#streaming-chat-session) - [Tokens counting](#tokens-counting) - [Listing models](#listing-models) @@ -153,6 +154,8 @@ This code will print "Hello World!" to the standard output. ### Streaming responses +> Requires `curl` extension to be enabled + In the streaming response, the callback function will be called whenever a response is returned from the server. Long responses may be broken into separate responses, and you can start receiving responses faster using a content stream. @@ -178,6 +181,55 @@ $client->geminiPro()->generateContentStream( // its simple syntax and rich library of functions. ``` +### Streaming Chat Session + +> Requires `curl` extension to be enabled + +```php +$client = new GeminiAPI\Client('GEMINI_API_KEY'); + +$history = [ + Content::text('Hello World in PHP', Role::User), + Content::text( + << + + This code will print "Hello World!" to the standard output. + TEXT, + Role::Model, + ), +]; +$chat = $client->geminiPro() + ->startChat() + ->withHistory($history); + +$callback = function (GenerateContentResponse $response): void { + static $count = 0; + + print "\nResponse #{$count}\n"; + print $response->text(); + $count++; +}; + +$chat->sendMessageStream($callback, new TextPart('in Go')); +``` + +```text +Response #0 +package main + +import "fmt" + +func main() { + +Response #1 + fmt.Println("Hello World!") +} + +This code will print "Hello World!" to the standard output. +``` ### Embed Content diff --git a/src/ChatSession.php b/src/ChatSession.php index 43e1dfe..013b9c7 100644 --- a/src/ChatSession.php +++ b/src/ChatSession.php @@ -45,6 +45,37 @@ public function sendMessage(PartInterface ...$parts): GenerateContentResponse return $response; } + /** + * @param callable(GenerateContentResponse): void $callback + * @param PartInterface ...$parts + * @return void + */ + public function sendMessageStream( + callable $callback, + PartInterface ...$parts, + ): void { + $this->history[] = new Content($parts, Role::User); + + $parts = []; + $partsCollectorCallback = function (GenerateContentResponse $response) use ($callback, &$parts) { + if(!empty($response->candidates)) { + array_push($parts, ...$response->parts()); + } + + $callback($response); + }; + + $config = (new GenerationConfig()) + ->withCandidateCount(1); + $this->model + ->withGenerationConfig($config) + ->generateContentStreamWithContents($partsCollectorCallback, $this->history); + + if (!empty($parts)) { + $this->history[] = new Content($parts, Role::Model); + } + } + /** * @return Content[] */ diff --git a/src/GenerativeModel.php b/src/GenerativeModel.php index a065734..216a886 100644 --- a/src/GenerativeModel.php +++ b/src/GenerativeModel.php @@ -72,9 +72,21 @@ public function generateContentStream( ): void { $content = new Content($parts, Role::User); + $this->generateContentStreamWithContents($callback, [$content]); + } + + /** + * @param callable(GenerateContentResponse): void $callback + * @param Content[] $contents + * @return void + */ + public function generateContentStreamWithContents(callable $callback, array $contents): void + { + $this->ensureArrayOfType($contents, Content::class); + $request = new GenerateContentStreamRequest( $this->modelName, - [$content], + $contents, $this->safetySettings, $this->generationConfig, );