1<?php
2
3namespace dokuwiki\plugin\aichat\Model\OpenAI;
4
5use dokuwiki\plugin\aichat\Model\AbstractModel;
6
7/**
8 * Abstract OpenAI Model
9 *
10 * This class provides a basic interface to the OpenAI API
11 */
12abstract class AbstractOpenAIModel extends AbstractModel
13{
14    /** @inheritdoc */
15    public function __construct(string $name, array $config)
16    {
17        parent::__construct($name, $config);
18
19        if (empty($config['openai_apikey'])) {
20            throw new \Exception('OpenAI API key not configured');
21        }
22
23        $openAIKey = $config['openai_apikey'];
24        $openAIOrg = $config['openai_org'] ?? '';
25
26        $this->http->headers['Authorization'] = 'Bearer ' . $openAIKey;
27        if ($openAIOrg) {
28            $this->http->headers['OpenAI-Organization'] = $openAIOrg;
29        }
30    }
31
32    /**
33     * Send a request to the OpenAI API
34     *
35     * @param string $endpoint
36     * @param array $data Payload to send
37     * @return array API response
38     * @throws \Exception
39     */
40    protected function request($endpoint, $data)
41    {
42        $url = 'https://api.openai.com/v1/' . $endpoint;
43        return $this->sendAPIRequest('POST', $url, $data);
44    }
45
46    /** @inheritdoc */
47    protected function parseAPIResponse($response)
48    {
49        if (isset($response['usage'])) {
50            $this->inputTokensUsed += $response['usage']['prompt_tokens'];
51            $this->outputTokensUsed += $response['usage']['completion_tokens'] ?? 0;
52        }
53
54        if (isset($response['error'])) {
55            throw new \Exception('OpenAI API error: ' . $response['error']['message']);
56        }
57
58        return $response;
59    }
60
61    /**
62     * @internal for checking available models
63     */
64    public function listUpstreamModels()
65    {
66        $url = 'https://api.openai.com/v1/models';
67        return $this->http->get($url);
68    }
69}
70