Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 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
namespace aiprovider_openai;
18
 
19
use core\http_client;
20
use core_ai\process_base;
21
use GuzzleHttp\Exception\RequestException;
22
use GuzzleHttp\Psr7\Uri;
23
use GuzzleHttp\RequestOptions;
24
use Psr\Http\Message\RequestInterface;
25
use Psr\Http\Message\ResponseInterface;
26
use Psr\Http\Message\UriInterface;
27
 
28
/**
29
 * Class process text generation.
30
 *
31
 * @package    aiprovider_openai
32
 * @copyright  2024 Matt Porritt <matt.porritt@moodle.com>
33
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34
 */
35
abstract class abstract_processor extends process_base {
36
    /**
37
     * Get the endpoint URI.
38
     *
39
     * @return UriInterface
40
     */
41
    protected function get_endpoint(): UriInterface {
42
        return new Uri($this->provider->actionconfig[$this->action::class]['settings']['endpoint']);
43
    }
44
 
45
    /**
46
     * Get the name of the model to use.
47
     *
48
     * @return string
49
     */
50
    protected function get_model(): string {
51
        return $this->provider->actionconfig[$this->action::class]['settings']['model'];
52
    }
53
 
54
    /**
55
     * Get the model settings.
56
     *
57
     * @return array
58
     */
59
    protected function get_model_settings(): array {
60
        $settings = $this->provider->actionconfig[$this->action::class]['settings'];
61
        if (!empty($settings['modelextraparams'])) {
62
            // Custom model settings.
63
            $params = json_decode($settings['modelextraparams'], true);
64
            foreach ($params as $key => $param) {
65
                $settings[$key] = $param;
66
            }
67
        }
68
 
69
        // Unset unnecessary settings.
70
        unset(
71
            $settings['model'],
72
            $settings['endpoint'],
73
            $settings['systeminstruction'],
74
            $settings['providerid'],
75
            $settings['modelextraparams'],
76
        );
77
        return $settings;
78
    }
79
 
80
    /**
81
     * Get the system instructions.
82
     *
83
     * @return string
84
     */
85
    protected function get_system_instruction(): string {
86
        return $this->action::get_system_instruction();
87
    }
88
 
89
    /**
90
     * Create the request object to send to the OpenAI API.
91
     *
92
     * This object contains all the required parameters for the request.
93
     *
94
     *
95
     *
96
     * @param string $userid The user id.
97
     * @return RequestInterface The request object to send to the OpenAI API.
98
     */
99
    abstract protected function create_request_object(
100
        string $userid,
101
    ): RequestInterface;
102
 
103
    /**
104
     * Handle a successful response from the external AI api.
105
     *
106
     * @param ResponseInterface $response The response object.
107
     * @return array The response.
108
     */
109
    abstract protected function handle_api_success(ResponseInterface $response): array;
110
 
111
    #[\Override]
112
    protected function query_ai_api(): array {
113
        $request = $this->create_request_object(
114
            userid: $this->provider->generate_userid($this->action->get_configuration('userid')),
115
        );
116
        $request = $this->provider->add_authentication_headers($request);
117
 
118
        $client = \core\di::get(http_client::class);
119
        try {
120
            // Call the external AI service.
121
            $response = $client->send($request, [
122
                'base_uri' => $this->get_endpoint(),
123
                RequestOptions::HTTP_ERRORS => false,
124
            ]);
125
        } catch (RequestException $e) {
126
            // Handle any exceptions.
127
            return [
128
                'success' => false,
129
                'errorcode' => $e->getCode(),
130
                'errormessage' => $e->getMessage(),
131
            ];
132
        }
133
 
134
        // Double-check the response codes, in case of a non 200 that didn't throw an error.
135
        $status = $response->getStatusCode();
136
        if ($status === 200) {
137
            return $this->handle_api_success($response);
138
        } else {
139
            return $this->handle_api_error($response);
140
        }
141
    }
142
 
143
    /**
144
     * Handle an error from the external AI api.
145
     *
146
     * @param ResponseInterface $response The response object.
147
     * @return array The error response.
148
     */
149
    protected function handle_api_error(ResponseInterface $response): array {
150
        $responsearr = [
151
            'success' => false,
152
            'errorcode' => $response->getStatusCode(),
153
        ];
154
 
155
        $status = $response->getStatusCode();
156
        if ($status >= 500 && $status < 600) {
157
            $responsearr['errormessage'] = $response->getReasonPhrase();
158
        } else {
159
            $bodyobj = json_decode($response->getBody()->getContents());
160
            $responsearr['errormessage'] = $bodyobj->error->message;
161
        }
162
 
163
        return $responsearr;
164
    }
165
}