commit
1b935a872e
@ -1,46 +1,68 @@ |
|||||||
AI Helper plugin |
AI Helper Plugin |
||||||
====== |
====== |
||||||
|
|
||||||
Version 1.1 |
Version 1.2 |
||||||
|
|
||||||
> This plugin is meant to be later integrated into Chamilo (in a major version |
> This plugin is designed to integrate AI functionality into Chamilo, providing tools for generating educational content, such as quizzes or learning paths, using AI providers like OpenAI or DeepSeek. |
||||||
release). |
|
||||||
|
|
||||||
The AI helper plugin integrates into parts of the platform that seem the most useful to teachers/trainers or learners. |
--- |
||||||
Because available Artificial Intelligence (to use the broad term) now allows us to ask for meaningful texts to be generated, we can use those systems to pre-generate content, then let the teacher/trainer review the content before publication. |
|
||||||
|
|
||||||
Currently, this plugin is only integrated into: |
### Overview |
||||||
|
|
||||||
- exercises: in the Aiken import form, scrolling down |
The AI Helper plugin integrates into parts of the Chamilo platform that are most useful to teachers/trainers or learners. It allows pre-generating content, letting teachers/trainers review it before publishing. |
||||||
- learnpaths: option to create one with openai |
|
||||||
|
|
||||||
### OpenAI/ChatGPT |
Currently, this plugin is integrated into: |
||||||
|
|
||||||
The plugin, created in early 2023, currently only supports OpenAI's ChatGPT API. |
- **Exercises:** In the Aiken import form, with options to generate questions using OpenAI or DeepSeek. |
||||||
Create an account at https://platform.openai.com/signup (if you already have an API account, go |
- **Learnpaths:** Option to create structured learning paths with OpenAI or DeepSeek. |
||||||
to https://platform.openai.com/login), then generate a secret key at https://platform.openai.com/account/api-keys |
|
||||||
or click on "Personal" -> "View API keys". |
|
||||||
Click the "Create new secret key" button, copy the key and use it to fill the "API key" field on the |
|
||||||
plugin configuration page. |
|
||||||
|
|
||||||
# Changelog |
--- |
||||||
|
|
||||||
## v1.1 |
### Supported AI Providers |
||||||
|
|
||||||
Added tracking for requests and differential settings to enable only in exercises, only in learning paths, or both. |
#### OpenAI/ChatGPT |
||||||
|
The plugin, created in early 2023, supports OpenAI's ChatGPT API. |
||||||
|
- **Setup:** |
||||||
|
1. Create an account at [OpenAI](https://platform.openai.com/signup) (or login if you already have one). |
||||||
|
2. Generate a secret key at [API Keys](https://platform.openai.com/account/api-keys). |
||||||
|
3. Click "Create new secret key", copy the key, and paste it into the "API key" field in the plugin configuration. |
||||||
|
|
||||||
|
#### DeepSeek |
||||||
|
DeepSeek is an alternative Open Source AI provider. |
||||||
|
- **Setup:** |
||||||
|
1. Create an account at [DeepSeek](https://www.deepseek.com/) (or login if you already have one). |
||||||
|
2. Generate an API key at [API Keys](https://platform.deepseek.com/api_keys). |
||||||
|
3. Click "Create new API key", copy the key, and paste it into the "API key" field in the plugin configuration. |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Features |
||||||
|
|
||||||
|
- Generate quizzes in the Aiken format using AI. |
||||||
|
- Create structured learning paths with AI assistance. |
||||||
|
- Support for multiple AI providers, enabling easy switching between OpenAI and DeepSeek. |
||||||
|
- Tracks API requests for monitoring usage and limits. |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
### Database Requirements |
||||||
|
|
||||||
|
No additional database changes are required for v1.2. |
||||||
|
The existing table `plugin_ai_helper_requests` is sufficient for tracking requests from both OpenAI and DeepSeek. |
||||||
|
|
||||||
|
If you're updating from **v1.0**, ensure the following table exists: |
||||||
|
|
||||||
To update from v1.0, execute the following queries manually. |
|
||||||
```sql |
```sql |
||||||
CREATE TABLE plugin_ai_helper_requests ( |
CREATE TABLE plugin_ai_helper_requests ( |
||||||
id int(11) NOT NULL AUTO_INCREMENT, |
id int(11) NOT NULL AUTO_INCREMENT, |
||||||
user_id int(11) NOT NULL, |
user_id int(11) NOT NULL, |
||||||
tool_name varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
tool_name varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
||||||
requested_at datetime DEFAULT NULL, |
requested_at datetime DEFAULT NULL, |
||||||
request_text varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
request_text varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
||||||
prompt_tokens int(11) NOT NULL, |
prompt_tokens int(11) NOT NULL, |
||||||
completion_tokens int(11) NOT NULL, |
completion_tokens int(11) NOT NULL, |
||||||
total_tokens int(11) NOT NULL, |
total_tokens int(11) NOT NULL, |
||||||
PRIMARY KEY (id) |
PRIMARY KEY (id) |
||||||
) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; |
) DEFAULT CHARACTER SET utf8 COLLATE `utf8_unicode_ci` ENGINE = InnoDB; |
||||||
``` |
``` |
||||||
If you got this update through Git, you will also need to run `composer install` to update the autoload mechanism. |
If you got this update through Git, you will also need to run `composer install` to update the autoload mechanism. |
||||||
|
@ -0,0 +1,87 @@ |
|||||||
|
<?php |
||||||
|
/* For license terms, see /license.txt */ |
||||||
|
|
||||||
|
require_once 'Url.php'; |
||||||
|
|
||||||
|
class DeepSeek |
||||||
|
{ |
||||||
|
private $apiKey; |
||||||
|
private $headers; |
||||||
|
|
||||||
|
public function __construct(string $apiKey) |
||||||
|
{ |
||||||
|
$this->apiKey = $apiKey; |
||||||
|
$this->headers = [ |
||||||
|
'Content-Type: application/json', |
||||||
|
"Authorization: Bearer {$this->apiKey}", |
||||||
|
]; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Generate questions using the DeepSeek API. |
||||||
|
* |
||||||
|
* @param array $payload Data to send to the API |
||||||
|
* @return string Decoded response from the API |
||||||
|
* @throws Exception If an error occurs during the request |
||||||
|
*/ |
||||||
|
public function generateQuestions(array $payload): string |
||||||
|
{ |
||||||
|
$url = Url::completionsUrl(); |
||||||
|
$response = $this->sendRequest($url, 'POST', $payload); |
||||||
|
|
||||||
|
if (empty($response)) { |
||||||
|
throw new Exception('The DeepSeek API returned no response.'); |
||||||
|
} |
||||||
|
|
||||||
|
$result = json_decode($response, true); |
||||||
|
|
||||||
|
// Validate errors returned by the API |
||||||
|
if (isset($result['error'])) { |
||||||
|
throw new Exception("DeepSeek API Error: {$result['error']['message']}"); |
||||||
|
} |
||||||
|
|
||||||
|
// Ensure the response contains the expected "choices" field |
||||||
|
if (!isset($result['choices'][0]['message']['content'])) { |
||||||
|
throw new Exception('Unexpected response format from the DeepSeek API.'); |
||||||
|
} |
||||||
|
|
||||||
|
return $result['choices'][0]['message']['content']; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Send a request to the DeepSeek API. |
||||||
|
* |
||||||
|
* @param string $url Endpoint to send the request to |
||||||
|
* @param string $method HTTP method (e.g., GET, POST) |
||||||
|
* @param array $data Data to send as JSON |
||||||
|
* @return string Raw response from the API |
||||||
|
* @throws Exception If a cURL error occurs |
||||||
|
*/ |
||||||
|
private function sendRequest(string $url, string $method, array $data = []): string |
||||||
|
{ |
||||||
|
$ch = curl_init($url); |
||||||
|
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); |
||||||
|
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); |
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); |
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->headers); |
||||||
|
|
||||||
|
$response = curl_exec($ch); |
||||||
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); |
||||||
|
|
||||||
|
if (curl_errno($ch)) { |
||||||
|
$errorMessage = curl_error($ch); |
||||||
|
curl_close($ch); |
||||||
|
throw new Exception("cURL Error: {$errorMessage}"); |
||||||
|
} |
||||||
|
|
||||||
|
curl_close($ch); |
||||||
|
|
||||||
|
// Validate HTTP status codes |
||||||
|
if ($httpCode < 200 || $httpCode >= 300) { |
||||||
|
throw new Exception("Request to DeepSeek failed with HTTP status code: {$httpCode}"); |
||||||
|
} |
||||||
|
|
||||||
|
return $response; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
<?php |
||||||
|
/* For license terms, see /license.txt */ |
||||||
|
|
||||||
|
class Url |
||||||
|
{ |
||||||
|
private const BASE_URL = 'https://api.deepseek.com/chat'; |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the endpoint URL for chat completions. |
||||||
|
* |
||||||
|
* @return string URL for the chat completions endpoint |
||||||
|
*/ |
||||||
|
public static function completionsUrl(): string |
||||||
|
{ |
||||||
|
return self::BASE_URL . '/completions'; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue