Skip to content

Commit

Permalink
支持 Google Gemini
Browse files Browse the repository at this point in the history
  • Loading branch information
Yurunsoft committed Mar 16, 2024
1 parent cfacf7b commit aecc386
Show file tree
Hide file tree
Showing 3 changed files with 146 additions and 3 deletions.
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ imi-ai 是一个 ChatGPT 开源项目,支持聊天、问答、写代码、写

### 支持的模型厂商

* [x] OpenAI
* [x] Swoole AI
* [x] ChatGLM3
* [x] [OpenAI](https://openai.com/)
* [x] [Swoole AI](https://ai.swoole.com/)
* [x] [ChatGLM3](https://github.com/THUDM/ChatGLM3)
* [x] [Google Gemini](https://aistudio.google.com/)

### 其它

Expand Down Expand Up @@ -265,6 +266,8 @@ npm run build-only

### 管理后台

后台默认账号密码都是 `admin`

**目录:**`admin`

**环境要求:**
Expand Down
139 changes: 139 additions & 0 deletions server/Module/OpenAI/Client/Gemini/Client.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<?php

declare(strict_types=1);

namespace app\Module\OpenAI\Client\Gemini;

use app\Module\OpenAI\Client\Annotation\OpenAIClient;
use app\Module\OpenAI\Client\Contract\IClient;
use app\Module\OpenAI\Model\Redis\Api;
use Gemini\Data\Content;
use Gemini\Data\GenerationConfig;
use Gemini\Enums\Role;
use Imi\Config;
use Imi\Util\Text;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

#[
OpenAIClient(title: 'Gemini'),
]
class Client implements IClient
{
private \Gemini\Client $client;

public function __construct(private Api $api)
{
$httpConfig = Config::get('@app.openai.http', []);
if ($proxy = $api->getProxy())
{
$httpConfig['proxy'] = $proxy;
}
$factory = \Gemini::factory()->withApiKey($api->getApiKey())
->withHttpClient($client = new \GuzzleHttp\Client($httpConfig))
->withStreamHandler(fn (RequestInterface $request): ResponseInterface => $client->send($request, [
'stream' => true, // Allows to provide a custom stream handler for the http client.
]));
$baseUrl = $api->getBaseUrl();
if (!Text::isEmpty($baseUrl))
{
$factory->withBaseUrl($baseUrl);
}
$this->client = $factory->make();
}

public function getApi(): Api
{
return $this->api;
}

public function chat(array $params, ?int &$inputTokens = null, ?int &$outputTokens = null): \Iterator
{
try
{
$inputTokens = $outputTokens = 0;
$model = $this->client->generativeModel($params['model']);
$history = [];
$prevContent = null;
foreach ($params['messages'] as $message)
{
if ('system' === $message['role'])
{
$prevContent = $message['content'];
continue;
}
$content = $message['content'];
if (null !== $prevContent)
{
$content = $prevContent . \PHP_EOL . $content;
}
$history[] = Content::parse($content, 'user' === $message['role'] ? Role::USER : Role::MODEL);
$inputTokens += mb_strlen($content);
}

$generationConfig = new GenerationConfig(
// stopSequences: [
// 'Title',
// ],
// maxOutputTokens: 800,
temperature: $params['temperature'] ?? null,
topP: $params['top_p'] ?? null,
// topK: 10
);

$stream = $model->withGenerationConfig($generationConfig)
->streamGenerateContent(...$history);

yield [
'choices' => [
[
'delta' => [
'role' => Role::MODEL->value,
'content' => '',
],
],
],
];

$contents = '';
foreach ($stream as $response)
{
yield [
'choices' => [
[
'delta' => [
'content' => $content = $response->text(),
],
],
],
];
$contents .= $content;
$content = '';
}
$outputTokens = mb_strlen($contents);
yield [
'choices' => [
[
'delta' => [],
'finish_reason' => 'stop',
],
],
];
}
catch (\Throwable $th)
{
$this->api->failed();
throw $th;
}
}

public function embedding(array $params): array
{
throw new \RuntimeException('Unsupport method ' . __METHOD__);
}

public function calcTokens(string $string, string $model): int
{
return mb_strlen($string);
}
}
1 change: 1 addition & 0 deletions server/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"ext-swoole": ">=5.0",
"ankane/pgvector": "^0.1.2",
"gemorroj/archive7z": "^5.6",
"google-gemini-php/client": "^1.0",
"guzzlehttp/guzzle": "^7.5",
"hashids/hashids": "^5.0",
"imiphp/imi": "~2.1.0",
Expand Down

0 comments on commit aecc386

Please sign in to comment.