deepseek-1.x-dev/src/Plugin/AiProviders/DeepseekProvider.php
src/Plugin/AiProviders/DeepseekProvider.php
<?php
namespace Drupal\deepseek\Plugin\AiProviders;
use DeepSeek\DeepSeekClient;
use Drupal\Core\Config\Config;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\deepseek\AiProvidersInterface;
use Drupal\deepseek\Attribute\AiProviders;
use GuzzleHttp\Client;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provider for communicating with Deepseek api.
*/
#[AiProviders(
id: "deepseek",
label: new TranslatableMarkup("DeepSeek"),
url: "https://api.deepseek.com/v1",
model: "deepseek-chat",
api_key: "sk-",
embedding: "",
)]
class DeepseekProvider implements AiProvidersInterface, ContainerFactoryPluginInterface {
/**
* Constructs a Deepseek Provider object.
*
* @param string $plugin_id
* The plugin_id for the formatter.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param mixed $field_definition
* The definition of the field to which the formatter is associated.
* @param \Drupal\Core\Config\Config $configFactory
* The config factory service.
*/
public function __construct($plugin_id, $plugin_definition, $field_definition, protected Config $configFactory) {
unset($plugin_id, $plugin_definition, $field_definition);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration,
$container->get('config.factory')->get('deepseek.settings'),
);
}
/**
* Models list of available from the provider.
*/
public function models($url = '', $api_key = ''): array {
$client = !empty($url) ? DeepSeekClient::build(apiKey: $api_key, baseUrl: $url, timeout: 30, clientType: 'guzzle') : DeepSeekClient::build($api_key);
$response = $client->getModelsList()->run();
if (!empty($response)) {
$data = json_decode($response);
return $data?->data ?? [];
}
return [];
}
/**
* Sends a prompt and receives a chat-style response.
*/
public function chat(array $messages, array $options = [], $files = []) {
$baseUrl = $this->configFactory->get('base_url') ?: 'https://api.deepseek.com/v1';
$model = $this->configFactory->get('model') ?: 'deepseek-chat';
$api_key = $this->configFactory->get('api_key');
// Variable API.
$apiData = array_merge([
'model' => $model ,
'messages' => $messages,
'temperature' => 1.3,
'stream' => TRUE,
], $options);
$client = \OpenAI::factory()
->withApiKey($api_key)
->withBaseUri($baseUrl)
->withHttpClient(new Client([
'timeout' => 360,
'http_errors' => FALSE,
]))
->make();
return $client->chat()->createStreamed($apiData);
}
/**
* Sends a raw text prompt for single-shot completions (not chat).
*/
public function completions(string $prompt, array $options = []) {
$url = $this->configFactory->get('base_url');
$api_key = $this->configFactory->get('api_key');
$model = $this->configFactory->get('model');
$client = !empty($url) ? DeepSeekClient::build(apiKey: $api_key, baseUrl: $url, timeout: 30, clientType: 'guzzle') :
DeepSeekClient::build($api_key);
if (!empty($model)) {
$client->withModel($model)->withStream()->setTemperature(1.3);
$client->query($prompt, 'user');
}
return $client->run();
}
/**
* Generates embeddings not available for deepseek.
*/
public function embeddings(array|string $input, array $options = []) {
$model = $this->configFactory->get('embedding');
if (empty($input) || empty($model)) {
return [];
}
$apiKey = $this->configFactory->get('api_key');
$baseUrl = $this->configFactory->get('base_url');
$client = \OpenAI::factory()->withApiKey($apiKey)->withBaseUri($baseUrl);
$apiData = [
'model' => $model,
'input' => $input,
];
$data = $client->embeddings()->create($apiData)->toArray()['data'];
return $data[0]['embedding'] ?? [];
}
/**
* Get mime type of file.
*/
public function getMimeType(string $mimeType): null {
return NULL;
}
}
