Skip to content

Commit

Permalink
Tidying and lint compliance
Browse files Browse the repository at this point in the history
  • Loading branch information
marcusgreen committed May 6, 2024
1 parent d3f6f6a commit 8c364b1
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 100 deletions.
2 changes: 0 additions & 2 deletions CHANGES.txt

This file was deleted.

6 changes: 3 additions & 3 deletions backup/moodle2/backup_qtype_aitext_plugin.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,15 @@
* Aitext backup
*
* @package qtype_aitext
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @copyright 2024 Marcus Green
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/


/**
* Provides the information to backup aitext questions
*
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @copyright 2024 Marcus Green
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class backup_qtype_aitext_plugin extends backup_qtype_plugin {
Expand All @@ -48,7 +48,7 @@ protected function define_question_plugin_structure() {
// Now create the qtype own structures.

$aitext = new backup_nested_element('aitext', ['id'], [
'aiprompt','markscheme','sampleanswer', 'responseformat', 'responsefieldlines', 'minwordlimit', 'maxwordlimit',
'aiprompt', 'markscheme', 'sampleanswer', 'responseformat', 'responsefieldlines', 'minwordlimit', 'maxwordlimit',
'graderinfo', 'graderinfoformat', 'responsetemplate',
'responsetemplateformat', 'maxbytes']);

Expand Down
11 changes: 6 additions & 5 deletions backup/moodle2/restore_qtype_aitext_plugin.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
*
* @package qtype_aitext
* @subpackage backup-moodle2
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @copyright 2024 Marcus Green
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

Expand All @@ -30,7 +31,7 @@
* restore plugin class that provides the necessary information
* needed to restore one aitext qtype plugin
*
* @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
* @copyright 2024 Marcus Green
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class restore_qtype_aitext_plugin extends restore_qtype_plugin {
Expand All @@ -39,9 +40,9 @@ class restore_qtype_aitext_plugin extends restore_qtype_plugin {
* Returns the paths to be handled by the plugin at question level
*/
protected function define_question_plugin_structure() {
return array(
new restore_path_element('aitext', $this->get_pathfor('/aitext'))
);
return [
new restore_path_element('aitext', $this->get_pathfor('/aitext')),
];
}

/**
Expand Down
7 changes: 7 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Release 0.01 of the Moodle AIText question type May 2024
Version 2024050300
Many thanks to Justin Hunt of Poodll fame https://poodll.com/moodle for contributing code
to allw the testing of prompts from within the question editing form.

Refined the default prompt settings to ensure Ollama/mistral returns a number when grading

175 changes: 101 additions & 74 deletions classes/external.php
Original file line number Diff line number Diff line change
@@ -1,74 +1,101 @@
<?php
/**
* External.
*
* @package qtype_aitext
* @author Justin Hunt - poodll.com
*/


global $CFG;
require_once($CFG->libdir . '/externallib.php');
require_once($CFG->dirroot . '/question/engine/bank.php');

use tool_aiconnect\ai;



/**
* External class.
*
* @package qtype_aitext
* @author Justin Hunt - poodll.com
*/
class qtype_aitext_external extends external_api
{

public static function fetch_ai_grade_parameters()
{
return new external_function_parameters(
array('response' => new external_value(PARAM_TEXT, 'The students response to question'),
'defaultmark' => new external_value(PARAM_INT, 'The total possible score'),
'prompt' => new external_value(PARAM_TEXT, 'The AI Prompt'),
'marksscheme' => new external_value(PARAM_TEXT, 'The marks scheme')
)
);

}

public static function fetch_ai_grade($response,$defaultmark,$prompt,$marksscheme)
{
//get our AI helper
$ai = new ai\ai();

//build an aitext question instance so we can call the same code that the question type uses when it grades
$type = 'aitext';
\question_bank::load_question_definition_classes($type);
$aiquestion = new qtype_aitext_question();
$aiquestion->qtype = \question_bank::get_qtype('aitext');

//make sure we have the right data for AI to work with
if (!empty($response) && !empty($prompt) && $defaultmark > 0) {
$full_ai_prompt = $aiquestion->build_full_ai_prompt($response, $prompt, $defaultmark, $marksscheme);
$llmresponse = $ai->prompt_completion($full_ai_prompt);
$feedback = $llmresponse['response']['choices'][0]['message']['content'];
$contentobject = $aiquestion->process_feedback($feedback);
}else{
$contentobject = ["feedback" => "Invalid parameters. Check that you have a sample answer and prompt","marks" => 0];
}

//return whatever we have got
return $contentobject;

}

public static function fetch_ai_grade_returns()
{
return new external_single_structure([
'feedback' => new external_value(PARAM_TEXT, 'text feedback for display to student', VALUE_DEFAULT),
'marks' => new external_value(PARAM_FLOAT, 'AI grader awarded marks for student response', VALUE_DEFAULT),
]);

}

}
<?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
*
* @package qtype_aitext
* @author Justin Hunt - poodll.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();

global $CFG;
require_once($CFG->libdir . '/externallib.php');
require_once($CFG->dirroot . '/question/engine/bank.php');

use tool_aiconnect\ai;

/**
* External class.
*
* @package qtype_aitext
* @author Justin Hunt - poodll.com
*/
class qtype_aitext_external extends external_api {
/**
* Get the parameters and types
*
* @return void
*/
public static function fetch_ai_grade_parameters() {
return new external_function_parameters(
array('response' => new external_value(PARAM_TEXT, 'The students response to question'),
'defaultmark' => new external_value(PARAM_INT, 'The total possible score'),
'prompt' => new external_value(PARAM_TEXT, 'The AI Prompt'),
'marksscheme' => new external_value(PARAM_TEXT, 'The marks scheme')
)
);

}
/**
* Similar to clicking the submit button.
*
* @param array $response
* @param integer $defaultmark
* @param string $prompt
* @param string $marksscheme
* @return void
*/
public static function fetch_ai_grade($response, $defaultmark, $prompt, $marksscheme) {
// Get our AI helper.
$ai = new ai\ai();

// Build an aitext question instance so we can call the same code that the question type uses when it grades.
$type = 'aitext';
\question_bank::load_question_definition_classes($type);
$aiquestion = new qtype_aitext_question();
$aiquestion->qtype = \question_bank::get_qtype('aitext');

// Make sure we have the right data for AI to work with.
if (!empty($response) && !empty($prompt) && $defaultmark > 0) {
$fullaiprompt = $aiquestion->build_full_ai_prompt($response, $prompt, $defaultmark, $marksscheme);
$llmresponse = $ai->prompt_completion($fullaiprompt);
$feedback = $llmresponse['response']['choices'][0]['message']['content'];
$contentobject = $aiquestion->process_feedback($feedback);
} else {
$contentobject = ["feedback" => "Invalid parameters. Check that you have a sample answer and prompt", "marks" => 0];
}

// Return whatever we have got.
return $contentobject;

}

/**
* Get the structure for retuning grade feedbak and marks
*
* @return void
*/
public static function fetch_ai_grade_returns() {
return new external_single_structure([
'feedback' => new external_value(PARAM_TEXT, 'text feedback for display to student', VALUE_DEFAULT),
'marks' => new external_value(PARAM_FLOAT, 'AI grader awarded marks for student response', VALUE_DEFAULT),
]);

}

}
32 changes: 28 additions & 4 deletions db/services.php
Original file line number Diff line number Diff line change
@@ -1,18 +1,42 @@
<?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/>.

/**
* Aitext services definition
*
* @package qtype_aitext
* @author Justin Hunt - poodll.com
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

/**
* Services definition.
* External class.
*
* @package qtype_minispeak
* @package qtype_aitext
* @author Justin Hunt - poodll.com
*/
defined('MOODLE_INTERNAL') || die();

$functions = array(
'qtype_aitext_fetch_ai_grade' => array(
'classname' => 'qtype_aitext_external',
'methodname' => 'fetch_ai_grade',
'description' => 'checks a response with the AI grader' ,
'capabilities'=> 'mod/quiz:grade',
'capabilities' => 'mod/quiz:grade',
'type' => 'read',
'ajax' => true,
),
);
);
7 changes: 3 additions & 4 deletions db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,10 @@
/**
* AI Text question type upgrade code.
*
* @package qtype
* @subpackage aitext
* @package qtype_aitext
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

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

/**
* Upgrade code for the aitext question type.
Expand All @@ -37,12 +35,13 @@ function xmldb_qtype_aitext_upgrade($oldversion) {
if ($oldversion < 2024050300) {

$table = new xmldb_table('qtype_aitext');
// Used for prompt testing in the edit form.
$field = new xmldb_field('sampleanswer', XMLDB_TYPE_TEXT, 'small', null, null, null, null);
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}

// cloudpoodll savepoint reached
// Savepoint reached.
upgrade_plugin_savepoint(true, 2024050300, 'qtype', 'aitext');

}
Expand Down
6 changes: 3 additions & 3 deletions edit_aitext_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/


/**
* aitext question type editing form.
*
Expand Down Expand Up @@ -69,7 +68,8 @@ protected function definition_inner($mform) {
['maxlen' => 50, 'rows' => 6, 'size' => 30]);
$mform->setType('sampleanswer', PARAM_RAW);
$mform->addHelpButton('sampleanswer', 'sampleanswer', 'qtype_aitext');
$mform->addElement('static','sampleanswereval','', '<a class="qtype_aitext_sampleanswerbtn btn btn-secondary" id="id_sampleanswerbtn">'
$mform->addElement('static', 'sampleanswereval', '', '<a class="qtype_aitext_sampleanswerbtn btn btn-secondary"
id="id_sampleanswerbtn">'
. get_string('sampleanswerevaluate', 'qtype_aitext') . '</a>' .
'<div class="qtype_aitext_sampleanswereval" id="id_sampleanswereval"></div>');

Expand Down Expand Up @@ -115,7 +115,7 @@ protected function definition_inner($mform) {
$mform->addElement('editor', 'graderinfo', get_string('graderinfo', 'qtype_aitext'),
array('rows' => 10), $this->editoroptions);

//load any JS that we need to make things happen, specifically the prompt tester
// Load any JS that we need to make things happen, specifically the prompt tester.
$PAGE->requires->js_call_amd('qtype_aitext/editformhelper', 'init', []);
}

Expand Down
17 changes: 13 additions & 4 deletions question.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ class qtype_aitext_question extends question_graded_automatically_with_countback
/** @var int indicates whether the maximum number of words required */
public $maxwordlimit;


/**
* used in the question editing interface
*
* @var string
*/
public $sampleanswer;

/**
* Information on how to manually grade
*
Expand Down Expand Up @@ -140,8 +148,9 @@ public function grade_response(array $response) : array {
}
$ai = new ai\ai();
if (is_array($response)) {
$full_ai_prompt = $this->build_full_ai_prompt($response['answer'], $this->aiprompt, $this->defaultmark, $this->markscheme);
$llmresponse = $ai->prompt_completion($full_ai_prompt);
$fullaiprompt = $this->build_full_ai_prompt($response['answer'], $this->aiprompt,
$this->defaultmark, $this->markscheme);
$llmresponse = $ai->prompt_completion($fullaiprompt);
$feedback = $llmresponse['response']['choices'][0]['message']['content'];
}

Expand All @@ -155,7 +164,7 @@ public function grade_response(array $response) : array {
$grade = [$fraction, question_state::graded_state_for_fraction($fraction)];
}
// The -aicontent data is used in question preview. Only needs to happen in preview.
$this->insert_attempt_step_data('-aiprompt', $full_ai_prompt);
$this->insert_attempt_step_data('-aiprompt', $fullaiprompt);
$this->insert_attempt_step_data('-aicontent', $contentobject->feedback);

$this->insert_attempt_step_data('-comment', $contentobject->feedback);
Expand All @@ -173,7 +182,7 @@ public function build_full_ai_prompt($response, $aiprompt, $defaultmark, $marksc
$prompt .= ' '.trim($aiprompt);

if ($markscheme > '') {
//Tell the LLM how to mark the submission
// Tell the LLM how to mark the submission.
$prompt .= " The total score is: $defaultmark .";
$prompt .= ' '.$markscheme;
} else {
Expand Down
Loading

0 comments on commit 8c364b1

Please sign in to comment.