Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAICI Updates for Capstone Project #11

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/completion.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
$block_settings ['assistant'] = $moduleinstance->assistant;
$block_settings ['model'] = $moduleinstance->model;
$block_settings ['apikey'] = $moduleinstance->apikey ?:get_config('mod_maici','apikey');
$block_settings ['apiurl'] = $moduleinstance->apiurl;
$block_settings ['maxlength'] = get_config('mod_maici', 'maxtokens');
$block_settings ['cmid'] = $cm_id;
$block_settings ['maiciid'] = $moduleinstance->id;
Expand Down
1 change: 1 addition & 0 deletions classes/completion.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
class completion {

protected $apikey;
protected $apiurl;
protected $message;
protected $history;
protected $cmid;
Expand Down
4 changes: 2 additions & 2 deletions classes/completion/chat.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ private function format_history() {
* @return JSON: The response from OpenAI
*/
private function make_api_call($history) {
// echo "Make API Call";
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clean up comment

$curlbody = [
"model" => $this->model,
"messages" => $history,
Expand All @@ -93,9 +94,8 @@ private function make_api_call($history) {
),
));

$response = $curl->post("https://api.openai.com/v1/chat/completions", json_encode($curlbody));
$response = $curl->post("http://prujuai:6500/chat", json_encode($curlbody));
$response = json_decode($response);

return $response;
}
}
73 changes: 73 additions & 0 deletions classes/mod_maici_observer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* External Class
*
* @package
* @author Tay Moss <[email protected]>
* @copyright 2024 CHURCHx at TUCC <https://churchx.ca>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_maici; // Replace with your actual plugin namespace

defined('MOODLE_INTERNAL') || die();

class mod_maici_observer {
public static function resource_created_handler(\core\event\course_module_created $event) {
global $CFG;

$fileinfo = $event->get_record_snapshot('course_modules', $event->objectid);
$filecontext = \context_module::instance($fileinfo->id);

// You might need to adjust this to get the actual file
$fs = get_file_storage();
$files = $fs->get_area_files($filecontext->id, 'mod_resource', 'content', false, 'timemodified', false);

foreach ($files as $file) {
if (!$file->is_directory()) {
// Get file content
$filecontent = $file->get_content();

// Send the file content to the remote server
$ch = curl_init();

// Get file content
$filecontent = $file->get_content();

// Prepare the file for upload
$tempfile = tempnam(sys_get_temp_dir(), 'moodle_upload_');
file_put_contents($tempfile, $filecontent);

// Send the file content to the remote server
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://prujuai:6500/uploadfile/");
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, [
'file' => new \CURLFile($tempfile, $file->get_mimetype(), $file->get_filename())
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

// Clean up temporary file
unlink($tempfile);

}
}
}
}

1 change: 1 addition & 0 deletions classes/output/aichat.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ public function export_for_template($output) {
$data->intro = $this->intro;
$data->username = $this->moduleinstance->username;
$data->assistantname = $this->moduleinstance->assistantname;
$data->apiurl = $this->moduleinstance->apiurl;
$data->conversation_logging = $this->moduleinstance->conversation_logging ? $OUTPUT->container(get_string('conversation_logging_info','mod_maici'), 'alert alert-info') : '';
}else{
$data->displayactivity = false;
Expand Down
11 changes: 11 additions & 0 deletions db/events.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
defined('MOODLE_INTERNAL') || die();

$observers = array(
array (
'eventname' => '\core\event\course_module_created',
'callback' => '\mod_maici\mod_maici_observer::resource_created_handler',
'internal' => false,
'priority' => 1000,
),
);
124 changes: 59 additions & 65 deletions db/install.xml
Original file line number Diff line number Diff line change
@@ -1,70 +1,64 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/maici/db" VERSION="20240111" COMMENT="XMLDB file for Moodle mod_maici"
<XMLDB PATH="mod/maici/db" VERSION="20240722" COMMENT="XMLDB file for Moodle mod_maici"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>

<TABLES>
<TABLE NAME="maici" COMMENT="Stores the maici activity module instances.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the course this activity is part of."/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="intro" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the intro field."/>
<FIELD NAME="instructions_submit" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Instruction block (HTML)"/>
<FIELD NAME="instructionsformat" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Instruction block (HTML)"/>
<FIELD NAME="apikey" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="apitype" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="username" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="assistantname" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="assistant" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/><!-- ASSISTANT -->
<FIELD NAME="persistconvo" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="1" COMMENT="Max number of tokens per day for this instance."/><!-- ASSISTANT -->
<FIELD NAME="model" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/><!-- CHAT -->
<FIELD NAME="maxperday" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" COMMENT="Max number of tokens per day for this instance."/><!-- CHAT -->
<FIELD NAME="maxperuser" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" COMMENT="Max number of tokens per user for this instance."/><!-- CHAT -->
<FIELD NAME="maxpermonth" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" COMMENT="Max number of tokens per calendar month for this instance."/><!-- CHAT -->
<FIELD NAME="prompt" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the activity module instance"/><!-- CHAT -->
<FIELD NAME="sourceoftruth" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the activity module instance"/><!-- CHAT -->
<FIELD NAME="instructiontokens" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" COMMENT="Max number of tokens per day for this instance."/>
<FIELD NAME="assistantfile" TYPE="int" LENGTH="11" NOTNULL="false" UNSIGNED="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="assistantfileid" TYPE="char" LENGTH="255" NOTNULL="false" UNSIGNED="false" DEFAULT="" SEQUENCE="false"/>
<FIELD NAME="conversation_logging" TYPE="int" DEFAULT="0" LENGTH="1" NOTNULL="false" COMMENT="Flag for conversation logging for this instance."/>
<FIELD NAME="completionai" TYPE="int" LENGTH="11" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/><!-- CHAT -->
<FIELD NAME="completionaiexchanges" TYPE="int" LENGTH="11" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/><!-- CHAT -->
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was added to the course."/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was last modified."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fk_course" TYPE="foreign" FIELDS="course" REFTABLE="course" REFFIELDS="id"/>
</KEYS>
</TABLE>

<!-- Table for storing usage and logs -->
<TABLE NAME="maici_logs" COMMENT="Stores usage and logs for the Simple AI Chat activity module.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="maiciid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the associated configuration."/>
<FIELD NAME="cmid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the course module."/>
<FIELD NAME="apitype" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="logging" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" COMMENT="Max number of tokens per day for this instance."/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the course this activity is part of."/>
<FIELD NAME="prompt_tokens" TYPE="int" LENGTH="10" NOTNULL="true" COMMENT="Token usage: prompt"/>
<FIELD NAME="completion_tokens" TYPE="int" LENGTH="10" NOTNULL="true" COMMENT="Token usage: completion"/>
<FIELD NAME="total_tokens" TYPE="int" LENGTH="10" NOTNULL="true" COMMENT="Token usage: total"/>
<FIELD NAME="message" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Message send to AI"/>
<FIELD NAME="completion" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Completion message from AI"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was added to the course."/>
<!-- Add other fields based on your criteria -->
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fk_maici" TYPE="foreign" FIELDS="maiciid" REFTABLE="maici" REFFIELDS="id"/>
<!-- Add foreign keys if needed -->
</KEYS>
</TABLE>

</TABLES>

<TABLES>
<TABLE NAME="maici" COMMENT="Stores the maici activity module instances.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the course this activity is part of."/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="intro" TYPE="text" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="The format of the intro field."/>
<FIELD NAME="instructions_submit" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Instruction block (HTML)"/>
<FIELD NAME="instructionsformat" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Instruction block (HTML)"/>
<FIELD NAME="apikey" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="apitype" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="username" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="assistantname" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="assistant" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="persistconvo" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="1" SEQUENCE="false" COMMENT="Max number of tokens per day for this instance."/>
<FIELD NAME="model" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="maxperday" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Max number of tokens per day for this instance."/>
<FIELD NAME="maxperuser" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Max number of tokens per user for this instance."/>
<FIELD NAME="maxpermonth" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Max number of tokens per calendar month for this instance."/>
<FIELD NAME="prompt" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="sourceoftruth" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="instructiontokens" TYPE="int" LENGTH="10" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Max number of tokens per day for this instance."/>
<FIELD NAME="assistantfile" TYPE="int" LENGTH="11" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="assistantfileid" TYPE="char" LENGTH="255" NOTNULL="false" DEFAULT="" SEQUENCE="false"/>
<FIELD NAME="conversation_logging" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Flag for conversation logging for this instance."/>
<FIELD NAME="completionai" TYPE="int" LENGTH="11" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="completionaiexchanges" TYPE="int" LENGTH="11" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was added to the course."/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was last modified."/>
<FIELD NAME="apiurl" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fk_course" TYPE="foreign" FIELDS="course" REFTABLE="course" REFFIELDS="id"/>
</KEYS>
</TABLE>
<TABLE NAME="maici_logs" COMMENT="Stores usage and logs for the Simple AI Chat activity module.">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true"/>
<FIELD NAME="maiciid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the associated configuration."/>
<FIELD NAME="cmid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the course module."/>
<FIELD NAME="apitype" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false" COMMENT="The name of the activity module instance"/>
<FIELD NAME="logging" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Max number of tokens per day for this instance."/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="ID of the course this activity is part of."/>
<FIELD NAME="prompt_tokens" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Token usage: prompt"/>
<FIELD NAME="completion_tokens" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Token usage: completion"/>
<FIELD NAME="total_tokens" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="Token usage: total"/>
<FIELD NAME="message" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Message send to AI"/>
<FIELD NAME="completion" TYPE="text" NOTNULL="false" SEQUENCE="false" COMMENT="Completion message from AI"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Timestamp of when the instance was added to the course."/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
<KEY NAME="fk_maici" TYPE="foreign" FIELDS="maiciid" REFTABLE="maici" REFFIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
12 changes: 12 additions & 0 deletions db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,5 +67,17 @@ function xmldb_maici_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2024030500, 'maici');
}

if ($oldversion < 2024072300) {
$table = new xmldb_table('maici');
$field->set_attributes('apiurl', XMLDB_TYPE_TEXT, 'big', null, false, null, null);

if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// maici savepoint reached.
upgrade_mod_savepoint(true, 2024072300, 'maici');
}

return true;
}
2 changes: 2 additions & 0 deletions lang/en/maici.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
$string['defaultapikey'] = 'Default API key is set. You can still provide your API key.';
$string['apikey'] = 'Open AI api key';
$string['apikey_help'] = 'Open AI api key to be used for this instance.';
$string['apiurl'] = 'Chat URL';
$string['apiurl_help'] = 'Chat URL used to get responses';
$string['apikeyerror'] = 'API key is not set or is not valid. {$a}';
$string['descapikey'] = 'Default api key for OpenAI';
$string['askaquestion'] = 'Ask question.';
Expand Down
5 changes: 5 additions & 0 deletions mod_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ public function definition() {
$mform->addRule('apikey', null, 'required', null, 'client');
}

$mform->addElement('text', 'apiurl', get_string('apiurl', 'mod_maici'),array('size'=>45));
$mform->setType('apiurl', PARAM_TEXT);
$mform->addHelpButton('apiurl', 'apiurl', 'mod_maici');

$mform->addElement('text', 'assistantname', get_string('assistantname','mod_maici'),array('size'=>40));
$mform->setType('assistantname', PARAM_TEXT);
$mform->addRule('assistantname', null, 'required', null, 'client');
Expand Down Expand Up @@ -290,6 +294,7 @@ public function data_preprocessing(&$defaultvalues) {
* @param stdClass $data the form data to be modified.
*/
public function data_postprocessing($data) {
error_log('DATA URL '.$data->apiurl);
parent::data_postprocessing($data);
if (isset($data->instructions)) {
$data->instructionsformat = $data->instructions['format'];
Expand Down
2 changes: 1 addition & 1 deletion version.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@

$plugin->component = 'mod_maici';
$plugin->release = '1.5';
$plugin->version = 2024051300;
$plugin->version = 2024072300;
$plugin->requires = 2022112800; // Moodle 4.1.0 and up.
$plugin->maturity = MATURITY_STABLE;