Passed
Pull Request — master (#6087)
by
unknown
07:41
created

DeepSeekAiProvider   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 44
dl 0
loc 70
rs 10
c 1
b 0
f 0
wmc 7

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 21 3
A generateQuestions() 0 36 4
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Service\AI;
8
9
use Chamilo\CoreBundle\Settings\SettingsManager;
10
use Symfony\Contracts\HttpClient\HttpClientInterface;
11
12
class DeepSeekAiProvider implements AiProviderInterface
13
{
14
    private string $apiUrl;
15
    private string $apiKey;
16
    private string $model;
17
    private float $temperature;
18
    private string $organizationId;
19
    private int $monthlyTokenLimit;
20
    private HttpClientInterface $httpClient;
21
22
    public function __construct(HttpClientInterface $httpClient, SettingsManager $settingsManager)
23
    {
24
        $this->httpClient = $httpClient;
25
26
        // Get AI providers from settings
27
        $configJson = $settingsManager->getSetting('ai_helpers.ai_providers', true);
28
        $config = json_decode($configJson, true) ?? [];
29
30
        if (!isset($config['deepseek'])) {
31
            throw new \RuntimeException('DeepSeek configuration is missing.');
32
        }
33
34
        $this->apiUrl = $config['deepseek']['url'] ?? 'https://api.deepseek.com/chat/completions';
35
        $this->apiKey = $config['deepseek']['api_key'] ?? '';
36
        $this->model = $config['deepseek']['model'] ?? 'deepseek-chat';
37
        $this->temperature = $config['deepseek']['temperature'] ?? 0.7;
38
        $this->organizationId = $config['deepseek']['organization_id'] ?? '';
39
        $this->monthlyTokenLimit = $config['deepseek']['monthly_token_limit'] ?? 5000;
40
41
        if (empty($this->apiKey)) {
42
            throw new \RuntimeException('DeepSeek API key is missing.');
43
        }
44
    }
45
46
    public function generateQuestions(string $topic, int $numQuestions, string $questionType, string $language): ?string
47
    {
48
        $prompt = sprintf(
49
            'Generate %d "%s" questions in Aiken format in the %s language about "%s", making sure there is a \'ANSWER\' line for each question. \'ANSWER\' lines must only mention the letter of the correct answer, not the full answer text and not a parenthesis. The line starting with \'ANSWER\' must not be separated from the last possible answer by a blank line. Each answer starts with an uppercase letter, a dot, one space and the answer text without quotes. Include an \'ANSWER_EXPLANATION\' line after the \'ANSWER\' line for each question. The terms between single quotes above must not be translated. There must be a blank line between each question.',
50
            $numQuestions, $questionType, $language, $topic
51
        );
52
53
        try {
54
            $response = $this->httpClient->request('POST', $this->apiUrl, [
55
                'headers' => [
56
                    'Authorization' => 'Bearer ' . $this->apiKey,
57
                    'Content-Type' => 'application/json',
58
                ],
59
                'json' => [
60
                    'model' => $this->model,
61
                    'messages' => [
62
                        ['role' => 'system', 'content' => 'You are a helpful assistant that generates Aiken format questions.'],
63
                        ['role' => 'user', 'content' => $prompt]
64
                    ],
65
                    'temperature' => $this->temperature,
66
                    'max_tokens' => 1000,
67
                ],
68
            ]);
69
70
            $statusCode = $response->getStatusCode();
71
            $data = $response->toArray();
72
73
            if ($statusCode === 200 && isset($data['choices'][0]['message']['content'])) {
74
                return $data['choices'][0]['message']['content'];
75
            }
76
77
            return null;
78
79
        } catch (\Exception $e) {
80
            error_log("ERROR - DeepSeek Request failed: " . $e->getMessage());
81
            return null;
82
        }
83
    }
84
}
85