Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
9 ariadna 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
/**
18
 * Class providing completions for chat models (3.5 and up)
19
 *
20
 * @package    block_openai_chat
21
 * @copyright  2023 Bryce Yoder <me@bryceyoder.com>
22
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23
*/
24
 
25
namespace block_openai_chat\completion;
26
 
27
use block_openai_chat\completion;
28
defined('MOODLE_INTERNAL') || die;
29
 
30
class chat extends \block_openai_chat\completion {
31
 
32
    public function __construct($model, $message, $history, $block_settings, $thread_id = null) {
33
        parent::__construct($model, $message, $history, $block_settings);
34
    }
35
 
36
    /**
37
     * Given everything we know after constructing the parent, create a completion by constructing the prompt and making the api call
38
     * @return JSON: The API response from OpenAI
39
     */
40
    public function create_completion($context) {
41
        if ($this->sourceoftruth) {
42
            $this->sourceoftruth = format_string($this->sourceoftruth, true, ['context' => $context]);
43
            $this->prompt .= get_string('sourceoftruthreinforcement', 'block_openai_chat');
44
        }
45
        $this->prompt .= "\n\n";
46
 
47
        $history_json = $this->format_history();
48
        array_unshift($history_json, ["role" => "system", "content" => $this->prompt]);
49
        array_unshift($history_json, ["role" => "system", "content" => $this->sourceoftruth]);
50
 
51
        array_push($history_json, ["role" => "user", "content" => $this->message]);
52
 
53
        $response_data = $this->make_api_call($history_json);
54
        return $response_data;
55
    }
56
 
57
    /**
58
     * Format the history JSON into a string that we can pass in the prompt
59
     * @return string: The string representing the chat history to add to the prompt
60
     */
61
    protected function format_history() {
62
        $history = [];
63
        foreach ($this->history as $index => $message) {
64
            $role = $index % 2 === 0 ? 'user' : 'assistant';
65
            array_push($history, ["role" => $role, "content" => $message["message"]]);
66
        }
67
        return $history;
68
    }
69
 
70
    /**
71
     * Make the actual API call to OpenAI
72
     * @return JSON: The response from OpenAI
73
     */
74
    private function make_api_call($history) {
75
        $curlbody = [
76
            "model" => $this->model,
77
            "messages" => $history,
78
            "temperature" => (float) $this->temperature,
79
            "max_tokens" => (int) $this->maxlength,
80
            "top_p" => (float) $this->topp,
81
            "frequency_penalty" => (float) $this->frequency,
82
            "presence_penalty" => (float) $this->presence,
83
            "stop" => $this->username . ":"
84
        ];
85
 
86
        $curl = new \curl();
87
        $curl->setopt(array(
88
            'CURLOPT_HTTPHEADER' => array(
89
                'Authorization: Bearer ' . $this->apikey,
90
                'Content-Type: application/json'
91
            ),
92
        ));
93
 
94
        $response = $curl->post("https://api.openai.com/v1/chat/completions", json_encode($curlbody));
95
        $response = json_decode($response);
96
 
97
        $message = null;
98
        if (property_exists($response, 'error')) {
99
            $message = 'ERROR: ' . $response->error->message;
100
        } else {
101
            $message = $response->choices[0]->message->content;
102
        }
103
 
104
        return [
105
            "id" => property_exists($response, 'id') ? $response->id : 'error',
106
            "message" => $message
107
        ];
108
    }
109
}