xref: /plugin/aichat/Model/AbstractModel.php (revision f6ef2e505783ac17f756e44bf15c66238362377a)
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