xref: /plugin/aichat/Model/Anthropic/ChatModel.php (revision 9d0b3322235bbe0983565364adb2ee2d670351fd)
1dce0dee5SAndreas Gohr<?php
2dce0dee5SAndreas Gohr
3dce0dee5SAndreas Gohrnamespace dokuwiki\plugin\aichat\Model\Anthropic;
4dce0dee5SAndreas Gohr
5dce0dee5SAndreas Gohruse dokuwiki\plugin\aichat\Model\AbstractModel;
6dce0dee5SAndreas Gohruse dokuwiki\plugin\aichat\Model\ChatInterface;
72e22aefbSAndreas Gohruse dokuwiki\plugin\aichat\Model\ModelException;
8dce0dee5SAndreas Gohr
9dce0dee5SAndreas Gohrclass ChatModel extends AbstractModel implements ChatInterface
10dce0dee5SAndreas Gohr{
11dce0dee5SAndreas Gohr    /** @inheritdoc */
127c3b69cbSAndreas Gohr    protected function getHttpClient()
13dce0dee5SAndreas Gohr    {
147c3b69cbSAndreas Gohr        $http = parent::getHttpClient();
157c3b69cbSAndreas Gohr        $http->headers['x-api-key'] = $this->getFromConf('apikey');
167c3b69cbSAndreas Gohr        $http->headers['anthropic-version'] = '2023-06-01';
177c3b69cbSAndreas Gohr        return $http;
18dce0dee5SAndreas Gohr    }
19dce0dee5SAndreas Gohr
207c3b69cbSAndreas Gohr
21dce0dee5SAndreas Gohr    /** @inheritdoc */
22*9d0b3322SAndreas Gohr    function loadUnknownModelInfo(): array
23*9d0b3322SAndreas Gohr    {
24*9d0b3322SAndreas Gohr        $info = parent::loadUnknownModelInfo();
25*9d0b3322SAndreas Gohr        $info['outputTokens'] = 32000;
26*9d0b3322SAndreas Gohr        return $info;
27*9d0b3322SAndreas Gohr    }
28*9d0b3322SAndreas Gohr
29*9d0b3322SAndreas Gohr    /** @inheritdoc */
30dce0dee5SAndreas Gohr    public function getAnswer(array $messages): string
31dce0dee5SAndreas Gohr    {
325f71c9bbSAndreas Gohr        // system message is separate from the messages array
33dce0dee5SAndreas Gohr        $system = '';
34dce0dee5SAndreas Gohr        $chat = [];
35dce0dee5SAndreas Gohr        foreach ($messages as $message) {
36dce0dee5SAndreas Gohr            if ($message['role'] === 'system') {
37dce0dee5SAndreas Gohr                $system .= $message['content'] . "\n";
38dce0dee5SAndreas Gohr            } else {
39dce0dee5SAndreas Gohr                $chat[] = $message;
40dce0dee5SAndreas Gohr            }
41dce0dee5SAndreas Gohr        }
42dce0dee5SAndreas Gohr
43dce0dee5SAndreas Gohr        $data = [
44dce0dee5SAndreas Gohr            'messages' => $chat,
45dce0dee5SAndreas Gohr            'model' => $this->getModelName(),
46cfd76f4aSAndreas Gohr            'max_tokens' => $this->getMaxOutputTokenLength(),
47dce0dee5SAndreas Gohr            'stream' => false,
48dce0dee5SAndreas Gohr            'temperature' => 0.0,
49dce0dee5SAndreas Gohr        ];
50dce0dee5SAndreas Gohr
51dce0dee5SAndreas Gohr        if ($system) {
52dce0dee5SAndreas Gohr            $data['system'] = $system;
53dce0dee5SAndreas Gohr        }
54dce0dee5SAndreas Gohr
55dce0dee5SAndreas Gohr        $response = $this->request('messages', $data);
56dce0dee5SAndreas Gohr        return $response['content'][0]['text'];
57dce0dee5SAndreas Gohr    }
58dce0dee5SAndreas Gohr
59dce0dee5SAndreas Gohr    /**
60eaa2c59dSAndreas Gohr     * Send a request to the API
61dce0dee5SAndreas Gohr     *
62dce0dee5SAndreas Gohr     * @param string $endpoint
63dce0dee5SAndreas Gohr     * @param array $data Payload to send
64dce0dee5SAndreas Gohr     * @return array API response
65dce0dee5SAndreas Gohr     * @throws \Exception
66dce0dee5SAndreas Gohr     */
67dce0dee5SAndreas Gohr    protected function request($endpoint, $data)
68dce0dee5SAndreas Gohr    {
69dce0dee5SAndreas Gohr        $url = 'https://api.anthropic.com/v1/' . $endpoint;
70dce0dee5SAndreas Gohr        return $this->sendAPIRequest('POST', $url, $data);
71dce0dee5SAndreas Gohr    }
72dce0dee5SAndreas Gohr
73dce0dee5SAndreas Gohr    /** @inheritdoc */
74dce0dee5SAndreas Gohr    protected function parseAPIResponse($response)
75dce0dee5SAndreas Gohr    {
76dce0dee5SAndreas Gohr        if (isset($response['usage'])) {
775f71c9bbSAndreas Gohr            $this->inputTokensUsed += $response['usage']['input_tokens'];
785f71c9bbSAndreas Gohr            $this->outputTokensUsed += $response['usage']['output_tokens'];
79dce0dee5SAndreas Gohr        }
80dce0dee5SAndreas Gohr
81dce0dee5SAndreas Gohr        if (isset($response['error'])) {
822e22aefbSAndreas Gohr            throw new ModelException('Anthropic API error: ' . $response['error']['message'], 3002);
83dce0dee5SAndreas Gohr        }
84dce0dee5SAndreas Gohr
85dce0dee5SAndreas Gohr        return $response;
86dce0dee5SAndreas Gohr    }
87dce0dee5SAndreas Gohr}
88