Skip to content
Closed
66 changes: 61 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
<p align="center">
<img src="https://raw.githubusercontent.com/gemini-api-php/client/main/assets/example.png" width="800" alt="Gemini API PHP Client - Example">
<img src="https://raw.githubusercontent.com/alexandrevega/gemini-api-client/main/assets/example.png" width="800" alt="Gemini API PHP Client - Example">
</p>
<p align="center">
<a href="https://packagist.org/packages/gemini-api-php/client"><img alt="Total Downloads" src="https://img.shields.io/packagist/dt/gemini-api-php/client"></a>
<a href="https://packagist.org/packages/gemini-api-php/client"><img alt="Latest Version" src="https://img.shields.io/packagist/v/gemini-api-php/client"></a>
<a href="https://packagist.org/packages/gemini-api-php/client"><img alt="License" src="https://img.shields.io/github/license/gemini-api-php/client"></a>
<a href="https://packagist.org/packages/galexandrevega/gemini-api-client"><img alt="Total Downloads" src="https://img.shields.io/packagist/dt/alexandrevega/gemini-api-client"></a>
<a href="https://packagist.org/packages/alexandrevega/gemini-api-client"><img alt="Latest Version" src="https://img.shields.io/packagist/v/alexandrevega/gemini-api-client"></a>
<a href="https://packagist.org/packages/alexandrevega/gemini-api-client"><img alt="License" src="https://img.shields.io/github/license/alexandrevega/gemini-api-client"></a>
Comment on lines +2 to +7

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes do not apply to this project

</p>

# Gemini API PHP Client

This library is a fork of [gemini-api-php/client](https://github.com/gemini-api-php/client) adding system instructions and updating api to v1beta.

Comment on lines +12 to +13

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes do not apply to this project

Gemini API PHP Client allows you to use the Google's generative AI models, like Gemini Pro and Gemini Pro Vision.

_This library is not developed or endorsed by Google._

- Erdem Köse - **[github.com/erdemkose](https://github.com/erdemkose)**
- Alexandre Vega - **[github.com/alexandrevega](https://github.com/alexandrevega)**

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes do not apply to this project


## Table of Contents
- [Installation](#installation)
Expand All @@ -24,6 +27,7 @@ _This library is not developed or endorsed by Google._
- [Chat Session with history](#chat-session-with-history)
- [Streaming responses](#streaming-responses)
- [Streaming Chat Session](#streaming-chat-session)
- [System Instruction](#system-instruction)
- [Tokens counting](#tokens-counting)
- [Listing models](#listing-models)
- [Advanced Usages](#advanced-usages)
Expand All @@ -39,7 +43,7 @@ _This library is not developed or endorsed by Google._
First step is to install the Gemini API PHP client with Composer.

```shell
composer require gemini-api-php/client
composer require alexandrevega/gemini-api-client

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes do not apply to this project

```

Gemini API PHP client does not come with an HTTP client.
Expand Down Expand Up @@ -257,6 +261,58 @@ Response #1
This code will print "Hello World!" to the standard output.
```

### System Instruction
You can add [System Instructions](https://ai.google.dev/gemini-api/docs/system-instructions?hl=en&lang=web) to steer the behaviour of Gemini.

```php
use GeminiAPI\Client;
use GeminiAPI\Enums\Role;
use GeminiAPI\Resources\Content;
use GeminiAPI\Resources\Parts\TextPart;

$history = [
Content::text('Hello World in PHP', Role::User),
Content::text(
<<<TEXT
<?php
echo "Hello World!";
?>

This code will print "Hello World!" to the standard output.
TEXT,
Role::Model,
),
];

$client = new Client('GEMINI_API_KEY');
$chat = $client->geminiPro()
->withSystemInstruction("You're an expert developer")
->startChat()
->withHistory($history);

$response = $chat->sendMessage(new TextPart('in Go'));
print $response->text();
```

```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

```php
Expand Down
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "gemini-api-php/client",
"name": "alexandrevega/gemini-api-client",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes do not apply to this project

"description": "API client for Google's Gemini API",
"keywords": [
"php",
Expand All @@ -17,6 +17,10 @@
{
"name": "Erdem Köse",
"email": "erdemkose@gmail.com"
},
{
"name": "Carlos Ramos",
"email": "contact@cramos.dev"
Comment on lines +20 to +23

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes do not apply to this project

}
],
"require": {
Expand Down
6 changes: 3 additions & 3 deletions src/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public function embeddingModel(ModelName $modelName): EmbeddingModel
);
}

/**
/**x

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo

* @throws ClientExceptionInterface
*/
public function generateContent(GenerateContentRequest $request): GenerateContentResponse
Expand Down Expand Up @@ -163,7 +163,7 @@ public function generateContentStream(
}
}

curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/v1/{$request->getOperation()}");
curl_setopt($ch, CURLOPT_URL, "{$this->baseUrl}/v1beta/{$request->getOperation()}");

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can the version be configurable ?

curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($request));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerLines);
Expand Down Expand Up @@ -250,7 +250,7 @@ private function doRequest(RequestInterface $request): string
throw new RuntimeException('Missing client or factory for Gemini API operation');
}

$uri = "{$this->baseUrl}/v1/{$request->getOperation()}";
$uri = "{$this->baseUrl}/v1beta/{$request->getOperation()}";
$httpRequest = $this->requestFactory
->createRequest($request->getHttpMethod(), $uri);

Expand Down
14 changes: 14 additions & 0 deletions src/GenerativeModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use GeminiAPI\Requests\CountTokensRequest;
use GeminiAPI\Requests\GenerateContentRequest;
use GeminiAPI\Requests\GenerateContentStreamRequest;
use GeminiAPI\Resources\Parts\TextPart;
use GeminiAPI\Responses\CountTokensResponse;
use GeminiAPI\Responses\GenerateContentResponse;
use GeminiAPI\Resources\Content;
Expand All @@ -25,6 +26,8 @@ class GenerativeModel
/** @var SafetySetting[] */
private array $safetySettings = [];

private ?array $systemInstruction = null;

private ?GenerationConfig $generationConfig = null;

public function __construct(
Expand Down Expand Up @@ -56,6 +59,7 @@ public function generateContentWithContents(array $contents): GenerateContentRes
$contents,
$this->safetySettings,
$this->generationConfig,
$this->systemInstruction
);

return $this->client->generateContent($request);
Expand Down Expand Up @@ -97,6 +101,7 @@ public function generateContentStreamWithContents(
$contents,
$this->safetySettings,
$this->generationConfig,
$this->systemInstruction
);

$this->client->generateContentStream($request, $callback, $ch);
Expand Down Expand Up @@ -136,4 +141,13 @@ public function withGenerationConfig(GenerationConfig $generationConfig): self

return $clone;
}

public function withSystemInstruction(?string $instruction = null): self
{

$clone = clone $this;
$clone->systemInstruction['parts'] = [new TextPart($instruction)];

return $clone;
}
}
6 changes: 6 additions & 0 deletions src/Requests/GenerateContentRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ class GenerateContentRequest implements JsonSerializable, RequestInterface
* @param Content[] $contents
* @param SafetySetting[] $safetySettings
* @param GenerationConfig|null $generationConfig
* @param string|null $systemInstructions
*/
public function __construct(
public readonly ModelName $modelName,
public readonly array $contents,
public readonly array $safetySettings = [],
public readonly ?GenerationConfig $generationConfig = null,
public ?array $systemInstructions = null
) {
$this->ensureArrayOfType($this->contents, Content::class);
$this->ensureArrayOfType($this->safetySettings, SafetySetting::class);
Expand Down Expand Up @@ -71,6 +73,10 @@ public function jsonSerialize(): array
$arr['generationConfig'] = $this->generationConfig;
}

if ($this->systemInstructions) {
$arr['systemInstruction'] = $this->systemInstructions;
}

return $arr;
}

Expand Down
7 changes: 7 additions & 0 deletions src/Requests/GenerateContentStreamRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,15 @@ class GenerateContentStreamRequest implements JsonSerializable, RequestInterface
* @param Content[] $contents
* @param SafetySetting[] $safetySettings
* @param GenerationConfig|null $generationConfig
* @param string|null $systemInstruction
*/
public function __construct(
public readonly ModelName $modelName,
public readonly array $contents,
public readonly array $safetySettings = [],
public readonly ?GenerationConfig $generationConfig = null,
public ?array $systemInstructions = null

) {
$this->ensureArrayOfType($this->contents, Content::class);
$this->ensureArrayOfType($this->safetySettings, SafetySetting::class);
Expand Down Expand Up @@ -71,6 +74,10 @@ public function jsonSerialize(): array
$arr['generationConfig'] = $this->generationConfig;
}

if ($this->systemInstructions) {
$arr['systemInstruction'] = $this->systemInstructions;
}

return $arr;
}

Expand Down
16 changes: 8 additions & 8 deletions tests/Unit/ClientTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public function testGenerateContent()
{
$httpRequest = new Request(
'POST',
'https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent',
'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent',
);
$httpResponse = new Response(
body: <<<BODY
Expand Down Expand Up @@ -117,7 +117,7 @@ public function testGenerateContent()
$requestFactory = $this->createMock(RequestFactoryInterface::class);
$requestFactory->expects(self::once())
->method('createRequest')
->with('POST', 'https://generativelanguage.googleapis.com/v1/models/gemini-pro:generateContent')
->with('POST', 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent')
->willReturn($httpRequest);

$httpRequest = $httpRequest
Expand Down Expand Up @@ -155,7 +155,7 @@ public function testEmbedContent()
{
$httpRequest = new Request(
'POST',
'https://generativelanguage.googleapis.com/v1/models/embedding-001:embedContent',
'https://generativelanguage.googleapis.com/v1beta/models/embedding-001:embedContent',
);
$httpResponse = new Response(
body: <<<BODY
Expand All @@ -172,7 +172,7 @@ public function testEmbedContent()
$requestFactory = $this->createMock(RequestFactoryInterface::class);
$requestFactory->expects(self::once())
->method('createRequest')
->with('POST', 'https://generativelanguage.googleapis.com/v1/models/embedding-001:embedContent')
->with('POST', 'https://generativelanguage.googleapis.com/v1beta/models/embedding-001:embedContent')
->willReturn($httpRequest);

$httpRequest = $httpRequest
Expand Down Expand Up @@ -210,7 +210,7 @@ public function testCountTokens()
{
$httpRequest = new Request(
'POST',
'https://generativelanguage.googleapis.com/v1/models/gemini-pro:countTokens',
'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:countTokens',
);
$httpResponse = new Response(
body: <<<BODY
Expand All @@ -222,7 +222,7 @@ public function testCountTokens()
$requestFactory = $this->createMock(RequestFactoryInterface::class);
$requestFactory->expects(self::once())
->method('createRequest')
->with('POST', 'https://generativelanguage.googleapis.com/v1/models/gemini-pro:countTokens')
->with('POST', 'https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:countTokens')
->willReturn($httpRequest);

$httpRequest = $httpRequest
Expand Down Expand Up @@ -260,7 +260,7 @@ public function testListModels()
{
$httpRequest = new Request(
'GET',
'https://generativelanguage.googleapis.com/v1/models',
'https://generativelanguage.googleapis.com/v1beta/models',
);
$httpResponse = new Response(
body: <<<BODY
Expand Down Expand Up @@ -303,7 +303,7 @@ public function testListModels()
$requestFactory = $this->createMock(RequestFactoryInterface::class);
$requestFactory->expects(self::once())
->method('createRequest')
->with('GET', 'https://generativelanguage.googleapis.com/v1/models')
->with('GET', 'https://generativelanguage.googleapis.com/v1beta/models')
->willReturn($httpRequest);

$httpRequest = $httpRequest
Expand Down