xref: /plugin/aichat/Model/VoyageAI/EmbeddingModel.php (revision 87e464844e8a4bc0fa03608147b1a25b9b20b678)
1*87e46484SAndreas Gohr<?php
2*87e46484SAndreas Gohr
3*87e46484SAndreas Gohrnamespace dokuwiki\plugin\aichat\Model\VoyageAI;
4*87e46484SAndreas Gohr
5*87e46484SAndreas Gohruse dokuwiki\plugin\aichat\Model\AbstractModel;
6*87e46484SAndreas Gohruse dokuwiki\plugin\aichat\Model\EmbeddingInterface;
7*87e46484SAndreas Gohr
8*87e46484SAndreas Gohrclass EmbeddingModel extends AbstractModel implements EmbeddingInterface
9*87e46484SAndreas Gohr{
10*87e46484SAndreas Gohr    /** @inheritdoc */
11*87e46484SAndreas Gohr    public function __construct(string $name, array $config)
12*87e46484SAndreas Gohr    {
13*87e46484SAndreas Gohr        parent::__construct($name, $config);
14*87e46484SAndreas Gohr
15*87e46484SAndreas Gohr        if (empty($config['voyageai_apikey'])) {
16*87e46484SAndreas Gohr            throw new \Exception('Voyage AI API key not configured');
17*87e46484SAndreas Gohr        }
18*87e46484SAndreas Gohr
19*87e46484SAndreas Gohr        $this->http->headers['Authorization'] = 'Bearer ' . $config['voyageai_apikey'];
20*87e46484SAndreas Gohr    }
21*87e46484SAndreas Gohr
22*87e46484SAndreas Gohr    /** @inheritdoc */
23*87e46484SAndreas Gohr    public function getEmbedding($text): array
24*87e46484SAndreas Gohr    {
25*87e46484SAndreas Gohr        $data = [
26*87e46484SAndreas Gohr            'model' => $this->getModelName(),
27*87e46484SAndreas Gohr            'input' => [$text],
28*87e46484SAndreas Gohr        ];
29*87e46484SAndreas Gohr        $response = $this->request('embeddings', $data);
30*87e46484SAndreas Gohr
31*87e46484SAndreas Gohr        return $response['data'][0]['embedding'];
32*87e46484SAndreas Gohr    }
33*87e46484SAndreas Gohr
34*87e46484SAndreas Gohr    /**
35*87e46484SAndreas Gohr     * Send a request to the Voyage API
36*87e46484SAndreas Gohr     *
37*87e46484SAndreas Gohr     * @param string $endpoint
38*87e46484SAndreas Gohr     * @param array $data Payload to send
39*87e46484SAndreas Gohr     * @return array API response
40*87e46484SAndreas Gohr     * @throws \Exception
41*87e46484SAndreas Gohr     */
42*87e46484SAndreas Gohr    protected function request($endpoint, $data)
43*87e46484SAndreas Gohr    {
44*87e46484SAndreas Gohr        $url = 'https://api.voyageai.com/v1/' . $endpoint;
45*87e46484SAndreas Gohr        return $this->sendAPIRequest('POST', $url, $data);
46*87e46484SAndreas Gohr    }
47*87e46484SAndreas Gohr
48*87e46484SAndreas Gohr    /** @inheritdoc */
49*87e46484SAndreas Gohr    protected function parseAPIResponse($response)
50*87e46484SAndreas Gohr    {
51*87e46484SAndreas Gohr        if (isset($response['usage'])) {
52*87e46484SAndreas Gohr            $this->inputTokensUsed += $response['usage']['prompt_tokens'];
53*87e46484SAndreas Gohr            $this->outputTokensUsed += $response['usage']['completion_tokens'] ?? 0;
54*87e46484SAndreas Gohr        }
55*87e46484SAndreas Gohr
56*87e46484SAndreas Gohr        if (isset($response['error'])) {
57*87e46484SAndreas Gohr            throw new \Exception('OpenAI API error: ' . $response['error']['message']);
58*87e46484SAndreas Gohr        }
59*87e46484SAndreas Gohr
60*87e46484SAndreas Gohr        return $response;
61*87e46484SAndreas Gohr    }
62*87e46484SAndreas Gohr
63*87e46484SAndreas Gohr}
64