1<?php 2 3namespace dokuwiki\plugin\aichatlocal\Model\Local; 4 5use dokuwiki\plugin\aichat\Model\AbstractModel; 6use dokuwiki\plugin\aichat\Model\ChatInterface; 7 8class ChatModel extends AbstractModel implements ChatInterface 9{ 10 /** @inheritdoc */ 11 public function __construct(string $name, array $config) 12 { 13 parent::__construct($name, $config); 14 15 if (empty($config['local_llm_baseurl'])) { 16 throw new \Exception('Local LLM base URL not configured'); 17 } 18 19 $this->http->baseURL = trim($config['local_llm_baseurl'], '/'); 20 21 if (!empty($config['local_llm_apikey'])) { 22 $this->http->headers['Authorization'] = 'Bearer ' . $config['local_llm_apikey']; 23 } 24 25 $this->http->headers['Content-Type'] = 'application/json'; 26 } 27 28 /** @inheritdoc */ 29 public function getAnswer(array $messages): string 30 { 31 $data = [ 32 'model' => $this->getModelName(), 33 'messages' => $messages, 34 'max_tokens' => $this->getMaxOutputTokenLength(), 35 'temperature' => 0.7, 36 'stream' => false, 37 ]; 38 39 $response = $this->request('chat/completions', $data); 40 return $response['choices'][0]['message']['content']; 41 } 42 43 /** 44 * Send a request to the API 45 * 46 * @param string $endpoint 47 * @param array $data Payload to send 48 * @return array API response 49 * @throws \Exception 50 */ 51 protected function request($endpoint, $data) 52 { 53 $url = $this->http->baseURL . '/v1/' . $endpoint; 54 return $this->sendAPIRequest('POST', $url, $data); 55 } 56 57 /** @inheritdoc */ 58 protected function parseAPIResponse($response) 59 { 60 if (isset($response['usage'])) { 61 $this->inputTokensUsed += $response['usage']['prompt_tokens']; 62 $this->outputTokensUsed += $response['usage']['completion_tokens']; 63 } 64 65 if (isset($response['error'])) { 66 throw new \Exception('Local LLM API error: ' . $response['error']['message']); 67 } 68 69 return $response; 70 } 71} 72