Skip to content
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
58 changes: 51 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ This package is used in 100k+ production installs. We take backward compatibilit
- No published interface ([`ClientContract`](src/Contracts/ClientContract.php), `ResourceContract`, `ResultContract`, `ApiFactoryContract`) will gain new required methods. New methods on the client implementation will be exposed via separate, additive interfaces.
- Default behavior of existing methods will not silently change in ways that affect cost, output, or correctness (e.g. raising default `max_tokens`).

**What's coming in `v2.1.x`:** Every new DeepSeek API feature (V4 models, thinking mode, FIM completion, Anthropic format, user balance, `stop` / `top_p` / `tool_choice` / `logprobs` / `user_id`, chat prefix completion, etc.) will be delivered as **additive** new methods, optional parameters, and enum cases. Bug fixes (`/v3` base URL, ignored params in `chat()` / `code()`, keep-alive line stripping) are also in scope.
**What's been delivered in the `v2.x` line so far:**
- **v2.1.0** — V4 models, base-URL fix, `chat()` / `code()` parameter wiring, keep-alive line stripping.
- **v2.2.0** — thinking mode (`setThinking`, `setReasoningEffort`), `setStop`, `setTopP`, `setToolChoice` (including the previously missing `"required"` mode), `setLogprobs`, `setTopLogprobs`, `setUserId`, OpenAI-spec `name` field on messages, and the `setStrictTool` helper.

**What's still coming in the `v2.x` line:** FIM completion, real SSE streaming, chat prefix completion (Beta), user balance endpoint, rate-limit handling, response-introspection accessors, and additional DX helpers — all additive.

**What's reserved for `v3.0.0`:** Removing deprecated `Models::CODER` / `Models::R1` / `Models::R1Zero`, removing the `Coder` class and `HasCoder` trait, raising default `max_tokens`, retyping `run()` to return a structured DTO, expanding `ClientContract` to match the implementation. All of these will be announced via `@deprecated` notices throughout `v2.x` and shipped with a complete migration guide in [MIGRATION.md](MIGRATION.md).

See [TODO.md](TODO.md) for the full feature gap analysis with per-item BC classification.

---

## [Unreleased] - v2.2.0 (planned)
## [Unreleased] - v2.2.x (planned follow-ups)

> Additive only. Zero breaking changes from v2.x. See [TODO.md](TODO.md) for the source list.

### Generation parameters and DX
- Thinking mode setters: `setThinking(array $config)` and `setReasoningEffort(string $effort)`.
- New sampling / generation parameter setters: `setStop()`, `setTopP()`, `setToolChoice()`, `setLogprobs()`, `setTopLogprobs()`, `setUserId()`.
- Optional `?string $name` parameter on `query()` and `buildQuery()` for the OpenAI message `name` field.
### Still planned for the v2.2.x line
- `setSystemMessage(string $content)` convenience method.
- Tool `strict` mode helper for function definitions.
- Response introspection accessors on `SuccessResult`: `getMessage()`, `getUsage()`, `getReasoningContent()`, `getToolCalls()`, `getFinishReason()`, `getCacheHitTokens()` — `run()` continues to return `string`.
- `getQueries()`, `getConfig()`, `reset()` introspection helpers.
- `DefaultConfigs::MAX_TOKENS` and `DefaultConfigs::RESPONSE_FORMAT_TYPE` cases (`TemperatureValues::MAX_TOKENS` / `RESPONSE_FORMAT_TYPE` deprecated).
Expand All @@ -54,6 +54,50 @@ See [TODO.md](TODO.md) for the full feature gap analysis with per-item BC classi

---

## [2.2.0] - 2026-05-25

> Additive parameter setters. Zero breaking changes from `v2.1.x`. Existing callers who do not opt into any of the new setters receive a byte-identical request body compared to v2.1.x — this is enforced by the regression tests in [`tests/Feature/V220ChangesTest.php`](tests/Feature/V220ChangesTest.php).

### Added

#### Generation parameter setters (all optional, all omitted from the request body until explicitly invoked)

- **Thinking mode** (`TODO.md` #4) — [`setThinking(array $config)`](src/Traits/Client/HasGenerationParams.php) and [`setReasoningEffort(string $effort)`](src/Traits/Client/HasGenerationParams.php). See the [DeepSeek reasoning_model docs](https://api-docs.deepseek.com/guides/reasoning_model).
- **Stop sequences** (`TODO.md` #5) — `setStop(string|array $stop)`. Single strings are normalized to a one-element array.
- **Nucleus sampling** (`TODO.md` #6) — `setTopP(float $topP)`.
- **Tool choice** (`TODO.md` #7) — `setToolChoice(string|array $toolChoice)`. Accepts `"none"`, `"auto"`, `"required"`, or the named-function array shape `['type' => 'function', 'function' => ['name' => '...']]`. The previously missing `"required"` mode is now reachable.
- **Log probabilities** (`TODO.md` #8) — `setLogprobs(bool $enabled)` and `setTopLogprobs(int $count)`.
- **End-user identifier** (`TODO.md` #9) — `setUserId(string $userId)`. Sent on the wire as the OpenAI-spec `user` field.

#### Message-level additions

- **OpenAI-spec `name` field on messages** (`TODO.md` #10) — optional 3rd parameter `?string $name = null` added to [`DeepSeekClient::query()`](src/DeepSeekClient.php) and [`DeepSeekClient::buildQuery()`](src/DeepSeekClient.php). The `name` key is omitted entirely from the message when null, preserving the existing 2-argument behavior byte-for-byte.

#### Function-calling additions

- **Structured tool `strict` mode helper** (`TODO.md` #13) — new [`setStrictTool(string $name, array $parameters, ?string $description = null)`](src/Traits/Client/HasToolsFunctionCalling.php) appends a function tool with `strict: true` to the existing `tools` array. The existing `setTools(array)` API is unchanged.

#### Enums and helpers

- New `QueryFlags` cases: `STOP`, `TOP_P`, `TOOL_CHOICE`, `LOGPROBS`, `TOP_LOGPROBS`, `USER`, `THINKING`, `REASONING_EFFORT`.
- New [`DeepSeek\Enums\Configs\ReasoningEffort`](src/Enums/Configs/ReasoningEffort.php) enum with `HIGH` and `MAX` cases.
- New [`DeepSeek\Enums\Configs\ThinkingType`](src/Enums/Configs/ThinkingType.php) enum with `ENABLED` and `DISABLED` cases.
- New [`DeepSeek\Enums\Queries\ToolChoiceMode`](src/Enums/Queries/ToolChoiceMode.php) enum with `NONE`, `AUTO`, and `REQUIRED` cases.
- New [`DeepSeek\Traits\Client\HasGenerationParams`](src/Traits/Client/HasGenerationParams.php) trait composed into [`DeepSeekClient`](src/DeepSeekClient.php). Holds all eight new setters and their backing nullable state.

### Internal

- `run()`, `chat()`, `code()` now merge the new optional parameters via an omit-when-null loop. The original seven request-body keys (`messages`, `model`, `stream`, `temperature`, `max_tokens`, `tools`, `response_format`) remain in their original order and are sent unchanged regardless of whether any new setter is called. This is verified by the three "byte-identical when no new setters called" tests at the top of [`tests/Feature/V220ChangesTest.php`](tests/Feature/V220ChangesTest.php).
- 23 new tests cover BC guards, every new setter, the `name` field, the strict-tool helper, and the new enum surface. The existing test suite (DeepSeekClientTest, V210ChangesTest, FunctionCallingTest) continues to pass unchanged.

### Backward-compatibility notes

- No public method, class, trait, enum case, or constant was removed or renamed.
- No existing method signature changed in a breaking way. The new optional `?string $name` parameter on `query()` / `buildQuery()` follows the same additive pattern as the `?string $clientType = null` parameter added to `build()` in v2.1.0.
- `ClientContract` is untouched; the new setters are introduced via the additive `HasGenerationParams` trait on the concrete client.

---

## [2.1.0] - 2026-05-22

> Foundation + Bug Fixes. Zero breaking changes from `v2.0.x`. All deprecated symbols remain fully functional throughout the `v2.x` line.
Expand Down
161 changes: 151 additions & 10 deletions README-AR.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@
- [الاستخدام مع عميل HTTP من Symfony](#الاستخدام-مع-عميل-http-من-symfony)
- [الحصول على قائمة النماذج](#الحصول-على-قائمة-النماذج)
- [استدعاء الدوال](#استدعاء-الدوال)
- [معلمات التوليد (v2.2.0)](#معلمات-التوليد-v220)
- [وضع التفكير ومستوى الاستدلال](#وضع-التفكير-ومستوى-الاستدلال)
- [تسلسلات الإيقاف (stop)](#تسلسلات-الإيقاف-stop)
- [أخذ العينات بالنواة (top_p)](#أخذ-العينات-بالنواة-top_p)
- [التحكم باختيار الأداة (tool_choice)](#التحكم-باختيار-الأداة-tool_choice)
- [الاحتمالات اللوغاريتمية (logprobs)](#الاحتمالات-اللوغاريتمية-logprobs)
- [معرّف المستخدم النهائي](#معرّف-المستخدم-النهائي)
- [حقل name على الرسائل](#حقل-name-على-الرسائل)
- [أدوات الوضع الصارم (strict)](#أدوات-الوضع-الصارم-strict)
- [تكامل مع الأطر](#-تكامل-مع-الأطر)
- [🆕 دليل الترحيل](#-دليل-الترحيل)
- [📝 سجل التغييرات](#-سجل-التغييرات)
Expand All @@ -46,11 +55,19 @@
- **تكامل API سلس**: واجهة تعتمد على PHP لميزات الذكاء الاصطناعي في DeepSeek.
- **نمط الباني السلس**: أساليب قابلة للسلسلة لبناء الطلبات بطريقة بديهية.
- **جاهز للمؤسسات**: تكامل مع عميل HTTP متوافق مع PSR-18.
- **مرونة النماذج**: دعم لعدة نماذج من DeepSeek (Coder, Chat, وغيرها).
- **أحدث نماذج DeepSeek V4**: دعم مباشر لـ `deepseek-v4-pro` و `deepseek-v4-flash` بنافذة سياق تصل إلى مليون رمز ووضعَي التفكير وعدم التفكير.
- **تحكم كامل بمعلمات التوليد (v2.2.0)**: واجهات سلسلة لوضع التفكير، مستوى الاستدلال، تسلسلات الإيقاف، `top_p`، اختيار الأداة (`none` / `auto` / `required` / دالة مسماة)، `logprobs`، معرّف المستخدم النهائي، حقل `name` للرسائل، وأدوات الوضع الصارم.
- **جاهز للبث**: دعم مدمج للتعامل مع الردود في الوقت الفعلي.
- **العديد من عملاء HTTP**: يمكنك استخدام عميل `Guzzle http client` (افتراضي) أو `symfony http client` بسهولة.
- **متوافق مع الأطر**: حزم Laravel و Symfony متاحة.

> **النماذج المدعومة**
>
> - `Models::V4_PRO` — النموذج الرائد، أقصى عدد رموز للإخراج 384K.
> - `Models::V4_FLASH` — سريع وموفّر، أقصى عدد رموز للإخراج 384K.
>
> النماذج القديمة `Models::CHAT`، `Models::CODER`، `Models::R1`، و `Models::R1Zero` مهملة وستتم إزالتها في v3.0.0. الأسماء البديلة `deepseek-chat` و `deepseek-reasoner` ستنسحب من DeepSeek API بتاريخ **2026-07-24**.

---

## 📦 التثبيت
Expand Down Expand Up @@ -83,23 +100,25 @@ echo $response;
```

📌 الإعدادات الافتراضية المستخدمة:
- النموذج: `deepseek-chat`
- الحرارة: 0.8
- النموذج: الافتراضي من API (لا يُرسل حقل `model` ما لم تستدعِ `withModel()`).
- الحرارة: 1.3 (`TemperatureValues::GENERAL_CONVERSATION`).
- أقصى عدد رموز: 4096.
- صيغة الاستجابة: `text`.

### التكوين المتقدم

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

$client = DeepSeekClient::build(apiKey:'your-api-key', baseUrl:'https://api.deepseek.com/v3', timeout:30, clientType:'guzzle');
$client = DeepSeekClient::build(apiKey:'your-api-key', baseUrl:'https://api.deepseek.com', timeout:30, clientType:'guzzle');

$response = $client
->withModel(Models::CODER->value)
->withModel(Models::V4_PRO->value)
->withStream()
->withTemperature(1.2)
->setTemperature(1.2)
->setMaxTokens(8192)
->setResponseFormat('text')
->setResponseFormat('text') // أو "json_object" بحذر.
->query('Explain quantum computing in simple terms')
->run();

Expand Down Expand Up @@ -150,7 +169,7 @@ echo 'API Response:'.$response;
// مع القيم الافتراضية للـ baseUrl و timeout
$client = DeepSeekClient::build('your-api-key', clientType:'symfony')
// مع التخصيص
$client = DeepSeekClient::build(apiKey:'your-api-key', baseUrl:'https://api.deepseek.com/v3', timeout:30, clientType:'symfony');
$client = DeepSeekClient::build(apiKey:'your-api-key', baseUrl:'https://api.deepseek.com', timeout:30, clientType:'symfony');

$client->query('Explain quantum computing in simple terms')
->run();
Expand All @@ -165,7 +184,16 @@ $response = DeepSeekClient::build('your-api-key')
->getModelsList()
->run();

echo $response; // {"object":"list","data":[{"id":"deepseek-chat","object":"model","owned_by":"deepseek"},{"id":"deepseek-reasoner","object":"model","owned_by":"deepseek"}]}
echo $response;
// {
// "object": "list",
// "data": [
// {"id": "deepseek-v4-pro", "object": "model", "owned_by": "deepseek"},
// {"id": "deepseek-v4-flash", "object": "model", "owned_by": "deepseek"},
// {"id": "deepseek-chat", "object": "model", "owned_by": "deepseek"}, // مهمل، ينسحب بتاريخ 2026-07-24
// {"id": "deepseek-reasoner", "object": "model", "owned_by": "deepseek"} // مهمل، ينسحب بتاريخ 2026-07-24
// ]
// }
```

### استدعاء الدوال
Expand All @@ -176,8 +204,121 @@ echo $response; // {"object":"list","data":[{"id":"deepseek-chat","object":"mode

---

هل ترغب في أن أضع النسخ الثلاث (الإنجليزية + العربية + الصينية) ضمن ملف Markdown موحد؟
### معلمات التوليد (v2.2.0)

منذ الإصدار `v2.2.0` تُتيح الحزمة كامل واجهة معلمات التوليد عبر دوال سلسلة. **كل دالة جديدة اختيارية**: إذا لم تستدعِها، يبقى جسم الطلب مطابقًا حرفيًا لإصدار v2.1.x — لا يوجد ما يستوجب الترحيل.

#### وضع التفكير ومستوى الاستدلال

تدعم نماذج V4 خطوة "تفكير" مخصصة. استخدم [`setThinking()`](src/Traits/Client/HasGenerationParams.php) لتشغيلها أو إيقافها، و [`setReasoningEffort()`](src/Traits/Client/HasGenerationParams.php) لاختيار `high` (الافتراضي للطلبات العادية) أو `max` (موصى به لمسارات الوكلاء).

```php
use DeepSeek\DeepSeekClient;
use DeepSeek\Enums\Configs\ReasoningEffort;
use DeepSeek\Enums\Configs\ThinkingType;
use DeepSeek\Enums\Models;

$response = DeepSeekClient::build('your-api-key')
->withModel(Models::V4_PRO->value)
->setThinking(['type' => ThinkingType::ENABLED->value])
->setReasoningEffort(ReasoningEffort::MAX->value)
->query('Prove that there are infinitely many primes.')
->run();
```

> ⚠️ في وضع التفكير يتجاهل DeepSeek API بصمت كلًّا من `temperature` و `top_p`، كما تُعيد `logprobs` / `top_logprobs` خطأ HTTP 400. انظر [وثائق نموذج الاستدلال](https://api-docs.deepseek.com/guides/reasoning_model).

#### تسلسلات الإيقاف (stop)

ما يصل إلى 16 تسلسلًا. مرّر سلسلة نصية واحدة أو مصفوفة؛ السلاسل المفردة تُحوَّل تلقائيًا إلى مصفوفة من عنصر واحد.

```php
$response = DeepSeekClient::build('your-api-key')
->query('Write a haiku')
->setStop(['###', "\n\n"])
->run();
```

#### أخذ العينات بالنواة (top_p)

```php
$response = DeepSeekClient::build('your-api-key')
->query('Tell me a short story')
->setTopP(0.95)
->run();
```

#### التحكم باختيار الأداة (tool_choice)

تقبل [`setToolChoice()`](src/Traits/Client/HasGenerationParams.php) القيم `"none"` و `"auto"` و `"required"` (إجبار استدعاء أداة)، أو شكل الدالة المسماة. وضع `"required"` المفقود سابقًا أصبح متاحًا الآن.

```php
use DeepSeek\Enums\Queries\ToolChoiceMode;

// إجبار النموذج على استدعاء أي أداة
$client->setTools($tools)
->setToolChoice(ToolChoiceMode::REQUIRED->value);

// إجبار النموذج على استدعاء دالة محددة بالاسم
$client->setTools($tools)
->setToolChoice([
'type' => 'function',
'function' => ['name' => 'get_weather'],
]);
```

#### الاحتمالات اللوغاريتمية (logprobs)

```php
$response = DeepSeekClient::build('your-api-key')
->query('Hello')
->setLogprobs(true)
->setTopLogprobs(5)
->run();
```

#### معرّف المستخدم النهائي

لعزل حدود المعدل، السلامة، وعزل ذاكرة التخزين المؤقت (KV-cache). يُرسل على السلك باسم حقل `user` وفق مواصفة OpenAI.

```php
$response = DeepSeekClient::build('your-api-key')
->setUserId('user-42')
->query('Hello')
->run();
```

#### حقل name على الرسائل

معامل ثالث اختياري على `query()` (و `buildQuery()`) للتمييز بين المشاركين الذين يحملون نفس الدور وفق مواصفة OpenAI. الاستدعاءات القديمة بمعاملين لا تتأثر.

```php
$response = DeepSeekClient::build('your-api-key')
->query('Hello, I am Alice.', 'user', 'alice')
->query('Hello, I am Bob.', 'user', 'bob')
->run();
```

#### أدوات الوضع الصارم (strict)

تُضيف [`setStrictTool()`](src/Traits/Client/HasToolsFunctionCalling.php) دالة بأداة مع `strict: true`، مما يُلزم النموذج بإنتاج وسائط مطابقة تمامًا لمخطط JSON. تتكامل بأمان مع `setTools()` — تُلحِق ولا تستبدل.

```php
$response = DeepSeekClient::build('your-api-key')
->setStrictTool(
name: 'get_weather',
parameters: [
'type' => 'object',
'properties' => ['city' => ['type' => 'string']],
'required' => ['city'],
],
description: 'Get the current weather for a city.',
)
->query('What is the weather like in Cairo?')
->run();
```

---

### 🛠 تكامل مع الأطر

Expand Down
Loading
Loading