Skip to content

Feat / Added Function Calling (tools) #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 40 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<p align="center">
<h1 align="center">DeepSeek PHP Client</h1>
<p align="center">🚀 Community-Driven PHP SDK for DeepSeek AI API Integration</p>

<p align="center">
<a href="https://packagist.org/packages/deepseek-php/deepseek-php-client">
<img src="https://img.shields.io/packagist/v/deepseek-php/deepseek-php-client" alt="Latest Version">
Expand Down Expand Up @@ -29,6 +29,7 @@
- [Advanced Configuration](#advanced-configuration)
- [Use with Symfony HttpClient](#use-with-symfony-httpclient)
- [Get Models List](#get-models-list)
- [Function Calling](#function-calling)
- [Framework Integration](#-framework-integration)
- [🆕 Migration Guide](#-migration-guide)
- [📝 Changelog](#-changelog)
Expand Down Expand Up @@ -103,7 +104,7 @@ echo 'API Response:'.$response;

### Use with Symfony HttpClient
the package already built with `symfony Http client`, if you need to use package with `symfony` Http Client , it is easy to achieve that, just pass `clientType:'symfony'` with `build` function.

ex with symfony:

```php
Expand All @@ -128,6 +129,42 @@ $response = DeepSeekClient::build('your-api-key')
echo $response; // {"object":"list","data":[{"id":"deepseek-chat","object":"model","owned_by":"deepseek"},{"id":"deepseek-reasoner","object":"model","owned_by":"deepseek"}]}
```

### Function Calling

Function Calling allows the model to call external tools to enhance its capabilities.

[please check original DeepSeek Doc](https://api-docs.deepseek.com/guides/function_calling)

```php
use DeepSeek\DeepSeekClient;
use DeepSeek\Enums\Models;

$response = DeepSeekClient::build('your-api-key')
->withModel(Models::CHAT)
->withTools([
[
'type' => 'function',
'function' => [
'name' => 'get_weather',
'description' => 'Get weather of an location, the user shoud supply a location first',
'parameters' => [
'type' => 'object',
'properties' => [
'location' => [
'type' => 'string',
'description' => 'The city and state, e.g. San Francisco, CA',
],
],
'required' => ['location'],
],
],
],
])
->run();

echo 'API Response:'.$response;
````

### 🛠 Framework Integration

### [Laravel Deepseek Package](https://github.com/deepseek-php/deepseek-laravel)
Expand Down Expand Up @@ -178,7 +215,7 @@ Click the button bellow or [join here](https://t.me/deepseek_php_community) to b

## 🔒 Security

**Report Vulnerabilities**: to [[email protected]](mailto:[email protected])
**Report Vulnerabilities**: to [[email protected]](mailto:[email protected])

---

Expand Down
4 changes: 2 additions & 2 deletions src/Contracts/ClientContract.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ interface ClientContract
{
public function run(): string;
public static function build(string $apiKey, ?string $baseUrl = null, ?int $timeout = null): self;
public function query(string $content, ?string $role = "user"): self;
public function query(?string $content = null, ?string $role = "user", ?string $toolCallId = null, ?array $toolCalls = null,): self;
public function getModelsList(): self;
public function withModel(?string $model = null): self;
public function withStream(bool $stream = true): self;
public function buildQuery(string $content, ?string $role = null): array;
public function buildQuery(?string $content = null, ?string $role = null, ?string $toolCallId = null, ?array $toolCalls = null,): array;
}
45 changes: 39 additions & 6 deletions src/DeepSeekClient.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class DeepSeekClient implements ClientContract

protected ?string $endpointSuffixes;

protected array $tools = [];

/**
* Initialize the DeepSeekClient with a PSR-compliant HTTP client.
*
Expand All @@ -81,6 +83,9 @@ public function run(): string
QueryFlags::STREAM->value => $this->stream,
QueryFlags::TEMPERATURE->value => $this->temperature,
];
if (count($this->tools)) {
$requestData[QueryFlags::TOOLS->value] = $this->tools;
}
// Clear queries after sending
$this->queries = [];
$this->setResult((new Resource($this->httpClient, $this->endpointSuffixes))->sendRequest($requestData, $this->requestMethod));
Expand Down Expand Up @@ -111,13 +116,20 @@ public static function build(string $apiKey, ?string $baseUrl = null, ?int $time
/**
* Add a query to the accumulated queries list.
*
* @param string $content
* @param string|null $content
* @param string|null $role
* @param string|null $toolCallId
* @param array|null $toolCalls
* @return self The current instance for method chaining.
*/
public function query(string $content, ?string $role = "user"): self
public function query(
?string $content = null,
?string $role = null,
?string $toolCallId = null,
?array $toolCalls = null,
): self
{
$this->queries[] = $this->buildQuery($content, $role);
$this->queries[] = $this->buildQuery($content, $role, $toolCallId, $toolCalls);
return $this;
}

Expand Down Expand Up @@ -163,12 +175,33 @@ public function setTemperature(float $temperature): self
return $this;
}

public function buildQuery(string $content, ?string $role = null): array
public function setTools(array $tools): self
{
$this->tools = $tools;
return $this;
}

public function buildQuery(
?string $content = null,
?string $role = null,
?string $toolCallId = null,
?array $toolCalls = null,
): array
{
return [
$query = [
'role' => $role ?: QueryRoles::USER->value,
'content' => $content
];
if ($content !== null) {
$query['content'] = $content;
}
if ($toolCallId !== null) {
$query['tool_call_id'] = $toolCallId;
}
if ($toolCalls !== null) {
$query['tool_calls'] = $toolCalls;
}

return $query;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/Enums/Queries/QueryRoles.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ enum QueryRoles: string
{
case USER = 'user';
case SYSTEM = 'system';
case ASSISTANT = 'assistant';
case TOOL = 'tool';
}
1 change: 1 addition & 0 deletions src/Enums/Requests/QueryFlags.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ enum QueryFlags: string
case MODEL = 'model';
case STREAM = 'stream';
case TEMPERATURE = 'temperature';
case TOOLS = 'tools';
}