1*f6ef2e50SAndreas Gohr<?php 2*f6ef2e50SAndreas Gohr 3*f6ef2e50SAndreas Gohrnamespace dokuwiki\plugin\aichat\Model; 4*f6ef2e50SAndreas Gohr 5*f6ef2e50SAndreas Gohr 6*f6ef2e50SAndreas Gohrabstract class AbstractModel { 7*f6ef2e50SAndreas Gohr 8*f6ef2e50SAndreas Gohr 9*f6ef2e50SAndreas Gohr /** @var int total tokens used by this instance */ 10*f6ef2e50SAndreas Gohr protected $tokensUsed = 0; 11*f6ef2e50SAndreas Gohr /** @var int total cost used by this instance (multiplied by 1000*10000) */ 12*f6ef2e50SAndreas Gohr protected $costEstimate = 0; 13*f6ef2e50SAndreas Gohr /** @var int total time spent in requests by this instance */ 14*f6ef2e50SAndreas Gohr protected $timeUsed = 0; 15*f6ef2e50SAndreas Gohr /** @var int total number of requests made by this instance */ 16*f6ef2e50SAndreas Gohr protected $requestsMade = 0; 17*f6ef2e50SAndreas Gohr 18*f6ef2e50SAndreas Gohr 19*f6ef2e50SAndreas Gohr /** 20*f6ef2e50SAndreas Gohr * @param array $authConfig Any configuration this Model/Service may need to authenticate 21*f6ef2e50SAndreas Gohr * @throws \Exception 22*f6ef2e50SAndreas Gohr */ 23*f6ef2e50SAndreas Gohr abstract public function __construct($authConfig); 24*f6ef2e50SAndreas Gohr 25*f6ef2e50SAndreas Gohr /** 26*f6ef2e50SAndreas Gohr * Maximum size of chunks this model can handle 27*f6ef2e50SAndreas Gohr * 28*f6ef2e50SAndreas Gohr * @return int 29*f6ef2e50SAndreas Gohr */ 30*f6ef2e50SAndreas Gohr abstract public function getMaxEmbeddingTokenLength(); 31*f6ef2e50SAndreas Gohr 32*f6ef2e50SAndreas Gohr /** 33*f6ef2e50SAndreas Gohr * Maximum number of tokens to use when creating context info. Should be smaller than the absolute 34*f6ef2e50SAndreas Gohr * token limit of the model, so that prompts and questions can be added. 35*f6ef2e50SAndreas Gohr * 36*f6ef2e50SAndreas Gohr * @return int 37*f6ef2e50SAndreas Gohr */ 38*f6ef2e50SAndreas Gohr abstract public function getMaxContextTokenLength(); 39*f6ef2e50SAndreas Gohr 40*f6ef2e50SAndreas Gohr /** 41*f6ef2e50SAndreas Gohr * Maximum number of tokens to use as context when rephrasing a question. Should be smaller than the 42*f6ef2e50SAndreas Gohr * absolute token limit of the model, so that prompts and questions can be added. 43*f6ef2e50SAndreas Gohr * 44*f6ef2e50SAndreas Gohr * @return int 45*f6ef2e50SAndreas Gohr */ 46*f6ef2e50SAndreas Gohr public function getMaxRephrasingTokenLength() { 47*f6ef2e50SAndreas Gohr return $this->getMaxContextTokenLength(); 48*f6ef2e50SAndreas Gohr } 49*f6ef2e50SAndreas Gohr 50*f6ef2e50SAndreas Gohr /** 51*f6ef2e50SAndreas Gohr * Get the embedding vectors for a given text 52*f6ef2e50SAndreas Gohr * 53*f6ef2e50SAndreas Gohr * @param string $text 54*f6ef2e50SAndreas Gohr * @return float[] 55*f6ef2e50SAndreas Gohr * @throws \Exception 56*f6ef2e50SAndreas Gohr */ 57*f6ef2e50SAndreas Gohr abstract public function getEmbedding($text); 58*f6ef2e50SAndreas Gohr 59*f6ef2e50SAndreas Gohr /** 60*f6ef2e50SAndreas Gohr * Answer a given question. 61*f6ef2e50SAndreas Gohr * 62*f6ef2e50SAndreas Gohr * Any prompt, chat history, context etc. will already be included in the $messages array. 63*f6ef2e50SAndreas Gohr * 64*f6ef2e50SAndreas Gohr * @param array $messages Messages in OpenAI format (with role and content) 65*f6ef2e50SAndreas Gohr * @return string The answer 66*f6ef2e50SAndreas Gohr * @throws \Exception 67*f6ef2e50SAndreas Gohr */ 68*f6ef2e50SAndreas Gohr abstract public function getAnswer($messages); 69*f6ef2e50SAndreas Gohr 70*f6ef2e50SAndreas Gohr /** 71*f6ef2e50SAndreas Gohr * This is called to let the LLM rephrase a question using given context 72*f6ef2e50SAndreas Gohr * 73*f6ef2e50SAndreas Gohr * Any prompt, chat history, context etc. will already be included in the $messages array. 74*f6ef2e50SAndreas Gohr * This calls getAnswer() by default, but you may want to use a different model instead. 75*f6ef2e50SAndreas Gohr * 76*f6ef2e50SAndreas Gohr * @param array $messages Messages in OpenAI format (with role and content) 77*f6ef2e50SAndreas Gohr * @return string The new question 78*f6ef2e50SAndreas Gohr * @throws \Exception 79*f6ef2e50SAndreas Gohr */ 80*f6ef2e50SAndreas Gohr public function getRephrasedQuestion($messages) { 81*f6ef2e50SAndreas Gohr return $this->getAnswer($messages); 82*f6ef2e50SAndreas Gohr } 83*f6ef2e50SAndreas Gohr 84*f6ef2e50SAndreas Gohr /** 85*f6ef2e50SAndreas Gohr * Reset the usage statistics 86*f6ef2e50SAndreas Gohr * 87*f6ef2e50SAndreas Gohr * Usually not needed when only handling one operation per request, but useful in CLI 88*f6ef2e50SAndreas Gohr */ 89*f6ef2e50SAndreas Gohr public function resetUsageStats() 90*f6ef2e50SAndreas Gohr { 91*f6ef2e50SAndreas Gohr $this->tokensUsed = 0; 92*f6ef2e50SAndreas Gohr $this->costEstimate = 0; 93*f6ef2e50SAndreas Gohr $this->timeUsed = 0; 94*f6ef2e50SAndreas Gohr $this->requestsMade = 0; 95*f6ef2e50SAndreas Gohr } 96*f6ef2e50SAndreas Gohr 97*f6ef2e50SAndreas Gohr /** 98*f6ef2e50SAndreas Gohr * Get the usage statistics for this instance 99*f6ef2e50SAndreas Gohr * 100*f6ef2e50SAndreas Gohr * @return string[] 101*f6ef2e50SAndreas Gohr */ 102*f6ef2e50SAndreas Gohr public function getUsageStats() 103*f6ef2e50SAndreas Gohr { 104*f6ef2e50SAndreas Gohr return [ 105*f6ef2e50SAndreas Gohr 'tokens' => $this->tokensUsed, 106*f6ef2e50SAndreas Gohr 'cost' => round($this->costEstimate / 1000 / 10000, 4), 107*f6ef2e50SAndreas Gohr 'time' => round($this->timeUsed, 2), 108*f6ef2e50SAndreas Gohr 'requests' => $this->requestsMade, 109*f6ef2e50SAndreas Gohr ]; 110*f6ef2e50SAndreas Gohr } 111*f6ef2e50SAndreas Gohr} 112