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 |
||||
release). |
||||
> 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. |
||||
|
||||
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 |
||||
- learnpaths: option to create one with openai |
||||
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. |
||||
|
||||
### OpenAI/ChatGPT |
||||
Currently, this plugin is integrated into: |
||||
|
||||
The plugin, created in early 2023, currently only supports OpenAI's ChatGPT API. |
||||
Create an account at https://platform.openai.com/signup (if you already have an API account, go |
||||
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. |
||||
- **Exercises:** In the Aiken import form, with options to generate questions using OpenAI or DeepSeek. |
||||
- **Learnpaths:** Option to create structured learning paths with OpenAI or DeepSeek. |
||||
|
||||
# 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 |
||||
CREATE TABLE plugin_ai_helper_requests ( |
||||
id int(11) NOT NULL AUTO_INCREMENT, |
||||
user_id int(11) NOT NULL, |
||||
tool_name varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
||||
requested_at datetime DEFAULT NULL, |
||||
request_text varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
||||
prompt_tokens int(11) NOT NULL, |
||||
completion_tokens int(11) NOT NULL, |
||||
total_tokens int(11) NOT NULL, |
||||
PRIMARY KEY (id) |
||||
id int(11) NOT NULL AUTO_INCREMENT, |
||||
user_id int(11) NOT NULL, |
||||
tool_name varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
||||
requested_at datetime DEFAULT NULL, |
||||
request_text varchar(255) COLLATE utf8_unicode_ci NOT NULL, |
||||
prompt_tokens int(11) NOT NULL, |
||||
completion_tokens int(11) NOT NULL, |
||||
total_tokens int(11) NOT NULL, |
||||
PRIMARY KEY (id) |
||||
) 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. |
||||
|
@ -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