Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
90.91% |
20 / 22 |
|
50.00% |
1 / 2 |
CRAP | |
0.00% |
0 / 1 |
AiClient | |
90.91% |
20 / 22 |
|
50.00% |
1 / 2 |
3.01 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
ask | |
89.47% |
17 / 19 |
|
0.00% |
0 / 1 |
2.00 |
1 | <?php |
2 | namespace Apie\AiInstructor; |
3 | |
4 | use cebe\openapi\spec\Schema; |
5 | use Symfony\Component\HttpClient\HttpClient; |
6 | use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; |
7 | use Symfony\Contracts\HttpClient\HttpClientInterface; |
8 | |
9 | class AiClient |
10 | { |
11 | private HttpClientInterface $client; |
12 | private string $apiKey; |
13 | private string $baseUrl; |
14 | |
15 | public function __construct(?HttpClientInterface $client = null, string $apiKey = 'ignored', string $baseUrl = 'https://api.openai.com/v1') |
16 | { |
17 | $this->client = $client ?? HttpClient::create([]); |
18 | $this->apiKey = $apiKey; |
19 | $this->baseUrl = $baseUrl; |
20 | } |
21 | |
22 | public function ask(string $systemMessage, string $prompt, Schema $schema, string $model = 'gpt-4'): string |
23 | { |
24 | try { |
25 | $response = $this->client->request('POST', $this->baseUrl . '/api/chat', [ |
26 | 'headers' => [ |
27 | 'Authorization' => 'Bearer ' . $this->apiKey, |
28 | 'Content-Type' => 'application/json', |
29 | ], |
30 | 'json' => [ |
31 | 'model' => $model, |
32 | 'stream' => false, |
33 | 'format' => $schema->getSerializableData(), |
34 | 'messages' => [ |
35 | ['role' => 'system', 'content' => $systemMessage], |
36 | ['role' => 'user', 'content' => $prompt], |
37 | ], |
38 | ], |
39 | ]); |
40 | |
41 | $data = $response->toArray(); |
42 | |
43 | return $data['message']['content'] ?? 'No response'; |
44 | } catch (TransportExceptionInterface $e) { |
45 | return 'Request failed: ' . $e->getMessage(); |
46 | } |
47 | } |
48 | } |