mirror of
https://github.com/moodle/moodle.git
synced 2025-04-16 14:02:32 +02:00
MDL-82627 AI: Privacy provider
Originally implemented in MDL-82781
This commit is contained in:
parent
086ac975f0
commit
67e6898853
@ -16,6 +16,14 @@
|
||||
|
||||
namespace core_ai\privacy;
|
||||
|
||||
use core_privacy\local\metadata\collection;
|
||||
use core_privacy\local\request\approved_contextlist;
|
||||
use core_privacy\local\request\approved_userlist;
|
||||
use core_privacy\local\request\contextlist;
|
||||
use core_privacy\local\request\transform;
|
||||
use core_privacy\local\request\userlist;
|
||||
use core_privacy\local\request\writer;
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for core_ai implementing null_provider.
|
||||
*
|
||||
@ -24,17 +32,627 @@ namespace core_ai\privacy;
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements
|
||||
\core_privacy\local\metadata\null_provider {
|
||||
|
||||
// TODO: Will be implemented in MDL-82781.
|
||||
\core_privacy\local\metadata\provider,
|
||||
\core_privacy\local\request\subsystem\provider,
|
||||
\core_privacy\local\request\core_userlist_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
* Returns meta data about this system.
|
||||
*
|
||||
* @return string
|
||||
* @param collection $collection The initialised collection to add items to.
|
||||
* @return collection A listing of user data stored through this system.
|
||||
*/
|
||||
public static function get_reason(): string {
|
||||
return 'privacy:metadata';
|
||||
public static function get_metadata(collection $collection): collection {
|
||||
$collection->add_database_table('ai_policy_register', [
|
||||
'userid' => 'privacy:metadata:ai_policy_register:userid',
|
||||
'contextid' => 'privacy:metadata:ai_policy_register:contextid',
|
||||
'timeaccepted' => 'privacy:metadata:ai_policy_register:timeaccepted',
|
||||
], 'privacy:metadata:ai_policy_register');
|
||||
$collection->add_database_table('ai_action_register', [
|
||||
'actionname' => 'privacy:metadata:ai_action_register:actionname',
|
||||
'actionid' => 'privacy:metadata:ai_action_register:actionid',
|
||||
'success' => 'privacy:metadata:ai_action_register:success',
|
||||
'userid' => 'privacy:metadata:ai_action_register:userid',
|
||||
'provider' => 'privacy:metadata:ai_action_register:provider',
|
||||
'timecreated' => 'privacy:metadata:ai_action_register:timecreated',
|
||||
'timecompleted' => 'privacy:metadata:ai_action_register:timecompleted',
|
||||
], 'privacy:metadata:ai_action_register');
|
||||
$collection->add_database_table('ai_action_generate_image', [
|
||||
'prompt' => 'privacy:metadata:ai_action_generate_image:prompt',
|
||||
'numberimages' => 'privacy:metadata:ai_action_generate_image:numberimages',
|
||||
'quality' => 'privacy:metadata:ai_action_generate_image:quality',
|
||||
'aspectratio' => 'privacy:metadata:ai_action_generate_image:aspectratio',
|
||||
'style' => 'privacy:metadata:ai_action_generate_image:style',
|
||||
'sourceurl' => 'privacy:metadata:ai_action_generate_image:sourceurl',
|
||||
'revisedprompt' => 'privacy:metadata:ai_action_generate_image:revisedprompt',
|
||||
], 'privacy:metadata:ai_action_generate_image');
|
||||
$collection->add_database_table('ai_action_generate_text', [
|
||||
'prompt' => 'privacy:metadata:ai_action_generate_text:prompt',
|
||||
'responseid' => 'privacy:metadata:ai_action_generate_text:responseid',
|
||||
'fingerprint' => 'privacy:metadata:ai_action_generate_text:fingerprint',
|
||||
'generatedcontent' => 'privacy:metadata:ai_action_generate_text:generatedcontent',
|
||||
'prompttokens' => 'privacy:metadata:ai_action_generate_text:prompttokens',
|
||||
'completiontoken' => 'privacy:metadata:ai_action_generate_text:completiontoken',
|
||||
], 'privacy:metadata:ai_action_generate_text');
|
||||
$collection->add_database_table('ai_action_summarise_text', [
|
||||
'prompt' => 'privacy:metadata:ai_action_summarise_text:prompt',
|
||||
'responseid' => 'privacy:metadata:ai_action_summarise_text:responseid',
|
||||
'fingerprint' => 'privacy:metadata:ai_action_summarise_text:fingerprint',
|
||||
'generatedcontent' => 'privacy:metadata:ai_action_summarise_text:generatedcontent',
|
||||
'prompttokens' => 'privacy:metadata:ai_action_summarise_text:prompttokens',
|
||||
'completiontoken' => 'privacy:metadata:ai_action_summarise_text:completiontoken',
|
||||
], 'privacy:metadata:ai_action_summarise_text');
|
||||
|
||||
return $collection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of contexts that contain user information for the specified user.
|
||||
*
|
||||
* @param int $userid The user to search.
|
||||
* @return contextlist $contextlist The contextlist containing the list of contexts used in this plugin.
|
||||
*/
|
||||
public static function get_contexts_for_userid(int $userid): contextlist {
|
||||
$contextlist = new contextlist();
|
||||
|
||||
// AI policy.
|
||||
$sql = 'SELECT DISTINCT ctx.id
|
||||
FROM {context} ctx
|
||||
JOIN {ai_policy_register} apr
|
||||
ON apr.contextid = ctx.id
|
||||
WHERE apr.userid = :userid';
|
||||
$contextlist->add_from_sql($sql, ['userid' => $userid]);
|
||||
|
||||
// AI action generate text.
|
||||
$sql = "SELECT DISTINCT ctx.id
|
||||
FROM {context} ctx
|
||||
JOIN {ai_action_register} aar
|
||||
ON aar.contextid = ctx.id
|
||||
JOIN {ai_action_generate_text} aagt
|
||||
ON aagt.id = aar.actionid
|
||||
WHERE aar.actionname = 'generate_text'
|
||||
AND aar.userid = :userid";
|
||||
$contextlist->add_from_sql($sql, ['userid' => $userid]);
|
||||
|
||||
// AI action generate image.
|
||||
$sql = "SELECT DISTINCT ctx.id
|
||||
FROM {context} ctx
|
||||
JOIN {ai_action_register} aar
|
||||
ON aar.contextid = ctx.id
|
||||
JOIN {ai_action_generate_image} aagi
|
||||
ON aagi.id = aar.actionid
|
||||
WHERE aar.actionname = 'generate_image'
|
||||
AND aar.userid = :userid";
|
||||
$contextlist->add_from_sql($sql, ['userid' => $userid]);
|
||||
|
||||
// AI action summarise text.
|
||||
$sql = "SELECT DISTINCT ctx.id
|
||||
FROM {context} ctx
|
||||
JOIN {ai_action_register} aar
|
||||
ON aar.contextid = ctx.id
|
||||
JOIN {ai_action_summarise_text} aast
|
||||
ON aast.id = aar.actionid
|
||||
WHERE aar.actionname = 'summarise_text'
|
||||
AND aar.userid = :userid";
|
||||
$contextlist->add_from_sql($sql, ['userid' => $userid]);
|
||||
|
||||
return $contextlist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts to export information for.
|
||||
*/
|
||||
public static function export_user_data(approved_contextlist $contextlist): void {
|
||||
global $DB;
|
||||
// AI policy.
|
||||
$userid = $contextlist->get_user()->id;
|
||||
[$contextsql, $contextparams] = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
|
||||
|
||||
$sql = 'SELECT apr.timeaccepted, ctx.id AS contextid
|
||||
FROM {context} ctx
|
||||
JOIN {ai_policy_register} apr
|
||||
ON apr.contextid = ctx.id
|
||||
WHERE apr.userid = :userid
|
||||
AND ctx.id ' . $contextsql;
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
];
|
||||
$params += $contextparams;
|
||||
$policydetails = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($policydetails as $policydetail) {
|
||||
$subcontexts = [
|
||||
get_string('ai', 'core_ai'),
|
||||
];
|
||||
$name = 'policy';
|
||||
$details = (object) [
|
||||
'contextid' => $policydetail->contextid,
|
||||
'timeaccepted' => transform::datetime($policydetail->timeaccepted),
|
||||
];
|
||||
$context = \context::instance_by_id($policydetail->contextid);
|
||||
writer::with_context($context)->export_related_data($subcontexts, $name, $details);
|
||||
}
|
||||
$policydetails->close();
|
||||
|
||||
// AI action generate text.
|
||||
$sql = "SELECT aar.actionname, aar.success, aar.provider, aar.timecreated, aar.timecompleted, aar.contextid,
|
||||
aagt.prompt, aagt.responseid, aagt.fingerprint, aagt.generatedcontent,
|
||||
aagt.prompttokens, aagt.completiontoken
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_text} aagt
|
||||
ON aar.actionid = aagt.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_text'
|
||||
AND aar.userid = :userid
|
||||
AND ctx.id " . $contextsql;
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
];
|
||||
$params += $contextparams;
|
||||
$textgeneratedetails = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($textgeneratedetails as $textgeneratedetail) {
|
||||
$subcontexts = [
|
||||
get_string('ai', 'core_ai'),
|
||||
get_string('action_generate_text', 'core_ai'),
|
||||
date('c', $textgeneratedetail->timecreated),
|
||||
];
|
||||
$details = (object) [
|
||||
'actionname' => $textgeneratedetail->actionname,
|
||||
'contextid' => $textgeneratedetail->contextid,
|
||||
'prompt' => $textgeneratedetail->prompt,
|
||||
'responseid' => $textgeneratedetail->responseid,
|
||||
'fingerprint' => $textgeneratedetail->fingerprint,
|
||||
'generatedcontent' => $textgeneratedetail->generatedcontent,
|
||||
'prompttokens' => $textgeneratedetail->prompttokens,
|
||||
'completiontoken' => $textgeneratedetail->completiontoken,
|
||||
'success' => transform::yesno($textgeneratedetail->success),
|
||||
'provider' => $textgeneratedetail->provider,
|
||||
'timecreated' => transform::datetime($textgeneratedetail->timecreated),
|
||||
'timecompleted' => transform::datetime($textgeneratedetail->timecompleted),
|
||||
];
|
||||
$name = 'action_generate_text';
|
||||
$context = \context::instance_by_id($textgeneratedetail->contextid);
|
||||
writer::with_context($context)->export_related_data($subcontexts, $name, $details);
|
||||
}
|
||||
$textgeneratedetails->close();
|
||||
|
||||
// AI action generate image.
|
||||
$sql = "SELECT aar.actionname, aar.success, aar.provider, aar.timecreated, aar.timecompleted, aar.contextid,
|
||||
aagi.prompt, aagi.numberimages, aagi.quality, aagi.aspectratio, aagi.style, aagi.sourceurl,
|
||||
aagi.revisedprompt
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_image} aagi
|
||||
ON aar.actionid = aagi.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_image'
|
||||
AND aar.userid = :userid
|
||||
AND ctx.id " . $contextsql;
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
];
|
||||
$params += $contextparams;
|
||||
$imagegeneratedetails = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($imagegeneratedetails as $imagegeneratedetail) {
|
||||
$subcontexts = [
|
||||
get_string('ai', 'core_ai'),
|
||||
get_string('action_generate_image', 'core_ai'),
|
||||
date('c', $imagegeneratedetail->timecreated),
|
||||
];
|
||||
$details = (object) [
|
||||
'actionname' => $imagegeneratedetail->actionname,
|
||||
'contextid' => $imagegeneratedetail->contextid,
|
||||
'prompt' => $imagegeneratedetail->prompt,
|
||||
'numberimages' => $imagegeneratedetail->numberimages,
|
||||
'quality' => $imagegeneratedetail->quality,
|
||||
'aspectratio' => $imagegeneratedetail->aspectratio,
|
||||
'style' => $imagegeneratedetail->style,
|
||||
'sourceurl' => $imagegeneratedetail->sourceurl,
|
||||
'revisedprompt' => $imagegeneratedetail->revisedprompt,
|
||||
'success' => transform::yesno($imagegeneratedetail->success),
|
||||
'provider' => $imagegeneratedetail->provider,
|
||||
'timecreated' => transform::datetime($imagegeneratedetail->timecreated),
|
||||
'timecompleted' => transform::datetime($imagegeneratedetail->timecompleted),
|
||||
];
|
||||
$name = 'action_generate_image';
|
||||
$context = \context::instance_by_id($imagegeneratedetail->contextid);
|
||||
writer::with_context($context)->export_related_data($subcontexts, $name, $details);
|
||||
}
|
||||
$imagegeneratedetails->close();
|
||||
|
||||
// AI action summarise text.
|
||||
$sql = "SELECT aar.actionname, aar.success, aar.provider, aar.timecreated, aar.timecompleted, aar.contextid,
|
||||
aast.prompt, aast.responseid, aast.fingerprint, aast.generatedcontent,
|
||||
aast.prompttokens, aast.completiontoken
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_summarise_text} aast
|
||||
ON aar.actionid = aast.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'summarise_text'
|
||||
AND aar.userid = :userid
|
||||
AND ctx.id " . $contextsql;
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
];
|
||||
$params += $contextparams;
|
||||
$textsummarisedetails = $DB->get_recordset_sql($sql, $params);
|
||||
foreach ($textsummarisedetails as $textsummarisedetail) {
|
||||
$subcontexts = [
|
||||
get_string('ai', 'core_ai'),
|
||||
get_string('action_summarise_text', 'core_ai'),
|
||||
date('c', $textsummarisedetail->timecreated),
|
||||
];
|
||||
$details = (object) [
|
||||
'actionname' => $textsummarisedetail->actionname,
|
||||
'contextid' => $textsummarisedetail->contextid,
|
||||
'prompt' => $textsummarisedetail->prompt,
|
||||
'responseid' => $textsummarisedetail->responseid,
|
||||
'fingerprint' => $textsummarisedetail->fingerprint,
|
||||
'generatedcontent' => $textsummarisedetail->generatedcontent,
|
||||
'prompttokens' => $textsummarisedetail->prompttokens,
|
||||
'completiontoken' => $textsummarisedetail->completiontoken,
|
||||
'success' => transform::yesno($textsummarisedetail->success),
|
||||
'provider' => $textsummarisedetail->provider,
|
||||
'timecreated' => transform::datetime($textsummarisedetail->timecreated),
|
||||
'timecompleted' => transform::datetime($textsummarisedetail->timecompleted),
|
||||
];
|
||||
$name = 'action_summarise_text';
|
||||
$context = \context::instance_by_id($textsummarisedetail->contextid);
|
||||
writer::with_context($context)->export_related_data($subcontexts, $name, $details);
|
||||
}
|
||||
$textsummarisedetails->close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all data for all users in the specified context.
|
||||
*
|
||||
* @param \context $context The specific context to delete data for.
|
||||
*/
|
||||
public static function delete_data_for_all_users_in_context(\context $context): void {
|
||||
global $DB;
|
||||
|
||||
// Policy.
|
||||
$sql = 'SELECT DISTINCT apr.id
|
||||
FROM {ai_policy_register} apr
|
||||
JOIN {context} ctx
|
||||
ON apr.contextid = ctx.id
|
||||
WHERE ctx.id = :contextid';
|
||||
$params = [
|
||||
'contextid' => $context->id,
|
||||
];
|
||||
$policydetails = $DB->get_records_sql($sql, $params);
|
||||
if ($policydetails) {
|
||||
$DB->delete_records_list('ai_policy_register', 'id', array_keys($policydetails));
|
||||
}
|
||||
|
||||
// AI action generate text.
|
||||
$sql = "SELECT DISTINCT aagt.id
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_text} aagt
|
||||
ON aar.actionid = aagt.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_text'
|
||||
AND ctx.id = :contextid";
|
||||
$params = [
|
||||
'contextid' => $context->id,
|
||||
];
|
||||
$aagtids = $DB->get_records_sql_menu($sql, $params);
|
||||
if ($aagtids) {
|
||||
[$aagtidsql, $aagtidparams] = $DB->get_in_or_equal(array_keys($aagtids), SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_generate_text}
|
||||
SET prompt = '',
|
||||
responseid = '',
|
||||
fingerprint = '',
|
||||
generatedcontent = ''
|
||||
WHERE id " . $aagtidsql;
|
||||
$DB->execute($sql, $aagtidparams);
|
||||
}
|
||||
|
||||
// AI action generate image.
|
||||
$sql = "SELECT DISTINCT aagi.id
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_image} aagi
|
||||
ON aar.actionid = aagi.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_image'
|
||||
AND ctx.id = :contextid";
|
||||
$params = [
|
||||
'contextid' => $context->id,
|
||||
];
|
||||
$aagiids = $DB->get_records_sql_menu($sql, $params);
|
||||
if ($aagiids) {
|
||||
[$aagiidsql, $aagiidparams] = $DB->get_in_or_equal(array_keys($aagiids), SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_generate_image}
|
||||
SET prompt = '',
|
||||
sourceurl = '',
|
||||
revisedprompt = ''
|
||||
WHERE id " . $aagiidsql;
|
||||
$DB->execute($sql, $aagiidparams);
|
||||
}
|
||||
|
||||
// AI action summarise text.
|
||||
$sql = "SELECT DISTINCT aast.id
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_summarise_text} aast
|
||||
ON aar.actionid = aast.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'summarise_text'
|
||||
AND ctx.id = :contextid";
|
||||
$params = [
|
||||
'contextid' => $context->id,
|
||||
];
|
||||
$aastids = $DB->get_records_sql_menu($sql, $params);
|
||||
if ($aastids) {
|
||||
[$aastidsql, $aastidparams] = $DB->get_in_or_equal(array_keys($aastids), SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_summarise_text}
|
||||
SET prompt = '',
|
||||
responseid = '',
|
||||
fingerprint = '',
|
||||
generatedcontent = ''
|
||||
WHERE id " . $aastidsql;
|
||||
$DB->execute($sql, $aastidparams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all user data for the specified user, in the specified contexts.
|
||||
*
|
||||
* @param approved_contextlist $contextlist The approved contexts and user information to delete information for.
|
||||
*/
|
||||
public static function delete_data_for_user(approved_contextlist $contextlist): void {
|
||||
global $DB;
|
||||
|
||||
// Policy.
|
||||
$userid = $contextlist->get_user()->id;
|
||||
[$contextsql, $contextparams] = $DB->get_in_or_equal($contextlist->get_contextids(), SQL_PARAMS_NAMED);
|
||||
|
||||
$sql = "SELECT DISTINCT apr.id AS policyid
|
||||
FROM {context} ctx
|
||||
JOIN {ai_policy_register} apr
|
||||
ON apr.contextid = ctx.id
|
||||
WHERE apr.userid = :userid
|
||||
AND ctx.id " . $contextsql;
|
||||
$params = [
|
||||
'userid' => $userid,
|
||||
];
|
||||
$params += $contextparams;
|
||||
$policydetails = $DB->get_recordset_sql($sql, $params);
|
||||
$policyids = [];
|
||||
foreach ($policydetails as $policydetail) {
|
||||
$policyids[] = $policydetail->policyid;
|
||||
}
|
||||
$policydetails->close();
|
||||
$DB->delete_records_list('ai_policy_register', 'id', $policyids);
|
||||
|
||||
// AI action generate text.
|
||||
$sql = "SELECT DISTINCT aagt.id AS textgenerateid
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_text} aagt
|
||||
ON aar.actionid = aagt.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_text'
|
||||
AND aar.userid = :userid
|
||||
AND ctx.id " . $contextsql;
|
||||
$textgeneratedetails = $DB->get_recordset_sql($sql, $params);
|
||||
$aagtids = [];
|
||||
foreach ($textgeneratedetails as $textgeneratedetail) {
|
||||
$aagtids[] = $textgeneratedetail->textgenerateid;
|
||||
}
|
||||
$textgeneratedetails->close();
|
||||
if ($aagtids) {
|
||||
[$aagtidsql, $aagtidparams] = $DB->get_in_or_equal($aagtids, SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_generate_text}
|
||||
SET prompt = '',
|
||||
responseid = '',
|
||||
fingerprint = '',
|
||||
generatedcontent = ''
|
||||
WHERE id " . $aagtidsql;
|
||||
$DB->execute($sql, $aagtidparams);
|
||||
}
|
||||
|
||||
// AI action generate image.
|
||||
$sql = "SELECT DISTINCT aagi.id AS imagegenerateid
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_image} aagi
|
||||
ON aar.actionid = aagi.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_image'
|
||||
AND aar.userid = :userid
|
||||
AND ctx.id " . $contextsql;
|
||||
$imagegeneratedetails = $DB->get_recordset_sql($sql, $params);
|
||||
$aagiids = [];
|
||||
foreach ($imagegeneratedetails as $imagegeneratedetail) {
|
||||
$aagiids[] = $imagegeneratedetail->imagegenerateid;
|
||||
}
|
||||
$imagegeneratedetails->close();
|
||||
if ($aagiids) {
|
||||
[$aagiidsql, $aagiidparams] = $DB->get_in_or_equal($aagiids, SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_generate_image}
|
||||
SET prompt = '',
|
||||
sourceurl = '',
|
||||
revisedprompt = ''
|
||||
WHERE id " . $aagiidsql;
|
||||
$DB->execute($sql, $aagiidparams);
|
||||
}
|
||||
|
||||
// AI action summarise text.
|
||||
$sql = "SELECT DISTINCT aast.id AS textsummariseid
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_summarise_text} aast
|
||||
ON aar.actionid = aast.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'summarise_text'
|
||||
AND aar.userid = :userid
|
||||
AND ctx.id " . $contextsql;
|
||||
$textsummarisedetails = $DB->get_recordset_sql($sql, $params);
|
||||
$aastids = [];
|
||||
foreach ($textsummarisedetails as $textsummarisedetail) {
|
||||
$aastids[] = $textsummarisedetail->textsummariseid;
|
||||
}
|
||||
$textsummarisedetails->close();
|
||||
if ($aastids) {
|
||||
[$aastidsql, $aastidparams] = $DB->get_in_or_equal($aastids, SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_summarise_text}
|
||||
SET prompt = '',
|
||||
responseid = '',
|
||||
fingerprint = '',
|
||||
generatedcontent = ''
|
||||
WHERE id " . $aastidsql;
|
||||
$DB->execute($sql, $aastidparams);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of users who have data within a context.
|
||||
*
|
||||
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
|
||||
*/
|
||||
public static function get_users_in_context(userlist $userlist): void {
|
||||
$context = $userlist->get_context();
|
||||
|
||||
// AI policy.
|
||||
$sql = 'SELECT DISTINCT apr.userid
|
||||
FROM {context} ctx
|
||||
JOIN {ai_policy_register} apr
|
||||
ON apr.contextid = ctx.id
|
||||
WHERE apr.contextid = :contextid';
|
||||
$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);
|
||||
|
||||
// AI action generate text.
|
||||
$sql = "SELECT DISTINCT aar.userid
|
||||
FROM {context} ctx
|
||||
JOIN {ai_action_register} aar
|
||||
ON aar.contextid = ctx.id
|
||||
JOIN {ai_action_generate_text} aagt
|
||||
ON aagt.id = aar.actionid
|
||||
WHERE aar.actionname = 'generate_text'
|
||||
AND aar.contextid = :contextid";
|
||||
$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);
|
||||
|
||||
// AI action generate image.
|
||||
$sql = "SELECT DISTINCT aar.userid
|
||||
FROM {context} ctx
|
||||
JOIN {ai_action_register} aar
|
||||
ON aar.contextid = ctx.id
|
||||
JOIN {ai_action_generate_image} aagi
|
||||
ON aagi.id = aar.actionid
|
||||
WHERE aar.actionname = 'generate_image'
|
||||
AND aar.contextid = :contextid";
|
||||
$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);
|
||||
|
||||
// AI action summarise text.
|
||||
$sql = "SELECT DISTINCT aar.userid
|
||||
FROM {context} ctx
|
||||
JOIN {ai_action_register} aar
|
||||
ON aar.contextid = ctx.id
|
||||
JOIN {ai_action_summarise_text} aast
|
||||
ON aast.id = aar.actionid
|
||||
WHERE aar.actionname = 'summarise_text'
|
||||
AND aar.contextid = :contextid";
|
||||
$userlist->add_from_sql('userid', $sql, ['contextid' => $context->id]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete multiple users within a single context.
|
||||
*
|
||||
* @param approved_userlist $userlist The approved context and user information to delete information for.
|
||||
*/
|
||||
public static function delete_data_for_users(approved_userlist $userlist) {
|
||||
global $DB;
|
||||
$context = $userlist->get_context();
|
||||
$userids = $userlist->get_userids();
|
||||
|
||||
[$useridssql, $useridsparams] = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
|
||||
|
||||
$params = [
|
||||
'contextid' => $context->id,
|
||||
];
|
||||
$params += $useridsparams;
|
||||
|
||||
// Policy.
|
||||
$sql = "SELECT DISTINCT apr.id
|
||||
FROM {ai_policy_register} apr
|
||||
JOIN {context} ctx
|
||||
ON apr.contextid = ctx.id
|
||||
WHERE ctx.id = :contextid
|
||||
AND apr.userid " . $useridssql;
|
||||
$policydetails = $DB->get_records_sql($sql, $params);
|
||||
if ($policydetails) {
|
||||
$DB->delete_records_list('ai_policy_register', 'id', array_keys($policydetails));
|
||||
}
|
||||
|
||||
// AI action generate text.
|
||||
$sql = "SELECT DISTINCT aagt.id
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_text} aagt
|
||||
ON aar.actionid = aagt.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_text'
|
||||
AND ctx.id = :contextid
|
||||
AND aar.userid " . $useridssql;
|
||||
$aagtids = $DB->get_records_sql_menu($sql, $params);
|
||||
if ($aagtids) {
|
||||
[$aagtidsql, $aagtidparams] = $DB->get_in_or_equal(array_keys($aagtids), SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_generate_text}
|
||||
SET prompt = '',
|
||||
responseid = '',
|
||||
fingerprint = '',
|
||||
generatedcontent = ''
|
||||
WHERE id " . $aagtidsql;
|
||||
$DB->execute($sql, $aagtidparams);
|
||||
}
|
||||
|
||||
// AI action generate image.
|
||||
$sql = "SELECT DISTINCT aagi.id
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_generate_image} aagi
|
||||
ON aar.actionid = aagi.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'generate_image'
|
||||
AND ctx.id = :contextid
|
||||
AND aar.userid " . $useridssql;
|
||||
$aagiids = $DB->get_records_sql_menu($sql, $params);
|
||||
if ($aagiids) {
|
||||
[$aagiidsql, $aagiidparams] = $DB->get_in_or_equal(array_keys($aagiids), SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_generate_image}
|
||||
SET prompt = '',
|
||||
sourceurl = '',
|
||||
revisedprompt = ''
|
||||
WHERE id " . $aagiidsql;
|
||||
$DB->execute($sql, $aagiidparams);
|
||||
}
|
||||
|
||||
// AI action summarise text.
|
||||
$sql = "SELECT DISTINCT aast.id
|
||||
FROM {ai_action_register} aar
|
||||
JOIN {ai_action_summarise_text} aast
|
||||
ON aar.actionid = aast.id
|
||||
JOIN {context} ctx
|
||||
ON aar.contextid = ctx.id
|
||||
WHERE aar.actionname = 'summarise_text'
|
||||
AND ctx.id = :contextid
|
||||
AND aar.userid " . $useridssql;
|
||||
$aastids = $DB->get_records_sql_menu($sql, $params);
|
||||
if ($aastids) {
|
||||
[$aastidsql, $aastidparams] = $DB->get_in_or_equal(array_keys($aastids), SQL_PARAMS_NAMED);
|
||||
$sql = "UPDATE {ai_action_summarise_text}
|
||||
SET prompt = '',
|
||||
responseid = '',
|
||||
fingerprint = '',
|
||||
generatedcontent = ''
|
||||
WHERE id " . $aastidsql;
|
||||
$DB->execute($sql, $aastidparams);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,8 +73,6 @@ final class manager_test extends \advanced_testcase {
|
||||
*/
|
||||
public function test_get_providers_for_actions(): void {
|
||||
$this->resetAfterTest();
|
||||
// Invoke the plugin manager and disable the AzureAI plugin.
|
||||
set_config('disabled', 1, 'aiprovider_azureai');
|
||||
set_config('enabled', 1, 'aiprovider_openai');
|
||||
|
||||
$manager = new manager();
|
||||
@ -89,13 +87,6 @@ final class manager_test extends \advanced_testcase {
|
||||
// Assert that the providers array is indexed by action name.
|
||||
$this->assertEquals($actions, array_keys($providers));
|
||||
|
||||
// Assert that there are two providers for each action.
|
||||
$this->assertCount(2, $providers['core_ai\\aiactions\\generate_text']);
|
||||
$this->assertCount(2, $providers['core_ai\\aiactions\\summarise_text']);
|
||||
|
||||
// Assert that the AzureAI provider is not included in the list of providers for the actions when only selecting active.
|
||||
$providers = $manager->get_providers_for_actions($actions, true);
|
||||
|
||||
// Assert that there is only one provider for each action.
|
||||
$this->assertCount(1, $providers['core_ai\\aiactions\\generate_text']);
|
||||
$this->assertCount(1, $providers['core_ai\\aiactions\\summarise_text']);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -17,7 +17,7 @@
|
||||
/**
|
||||
* Strings for component 'ai', language 'en'
|
||||
*
|
||||
* @package core_ai
|
||||
* @package core
|
||||
* @category string
|
||||
* @copyright 2024 Matt Porritt <matt.porritt@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
@ -61,7 +61,40 @@ Each action can be enabled or disabled for this placement.';
|
||||
$string['placementsettings'] = 'Placement specific settings';
|
||||
$string['placementsettings_desc'] = 'These settings control various aspects of this AI placement.<br/>
|
||||
They control how the placement connects to the AI service, and related operations';
|
||||
$string['privacy:metadata'] = 'The AI subsystem currently does not store any user data.';
|
||||
$string['privacy:metadata:ai_action_generate_image'] = 'A table storing the image generation requests made by users.';
|
||||
$string['privacy:metadata:ai_action_generate_image:aspectratio'] = 'The aspect ratio of the generated images.';
|
||||
$string['privacy:metadata:ai_action_generate_image:numberimages'] = 'The number of images generated.';
|
||||
$string['privacy:metadata:ai_action_generate_image:prompt'] = 'The prompt for the image generation request.';
|
||||
$string['privacy:metadata:ai_action_generate_image:quality'] = 'The quality of the generated images.';
|
||||
$string['privacy:metadata:ai_action_generate_image:revisedprompt'] = 'The revised prompt of the generated images.';
|
||||
$string['privacy:metadata:ai_action_generate_image:sourceurl'] = 'The source URL of the generated images.';
|
||||
$string['privacy:metadata:ai_action_generate_image:style'] = 'The style of the generated images.';
|
||||
$string['privacy:metadata:ai_action_generate_text'] = 'A table storing the text generation requests made by users.';
|
||||
$string['privacy:metadata:ai_action_generate_text:completiontoken'] = 'The completion tokens used to generate the text.';
|
||||
$string['privacy:metadata:ai_action_generate_text:fingerprint'] = 'The unique hash representing the state/version of the model and content.';
|
||||
$string['privacy:metadata:ai_action_generate_text:generatedcontent'] = 'The actual text generated by the AI model based on the input prompt.';
|
||||
$string['privacy:metadata:ai_action_generate_text:prompt'] = 'The prompt for the text generation request.';
|
||||
$string['privacy:metadata:ai_action_generate_text:prompttokens'] = 'The prompt tokens used to generate the text.';
|
||||
$string['privacy:metadata:ai_action_generate_text:responseid'] = 'The ID of the response.';
|
||||
$string['privacy:metadata:ai_action_register'] = 'A table storing the action requests made by users.';
|
||||
$string['privacy:metadata:ai_action_register:actionid'] = 'The ID of the action request.';
|
||||
$string['privacy:metadata:ai_action_register:actionname'] = 'The action name of the request.';
|
||||
$string['privacy:metadata:ai_action_register:provider'] = 'The name of the provider that handled the request.';
|
||||
$string['privacy:metadata:ai_action_register:success'] = 'The state of the action request.';
|
||||
$string['privacy:metadata:ai_action_register:timecreated'] = 'The created time of the request.';
|
||||
$string['privacy:metadata:ai_action_register:timecompleted'] = 'The completed time of the request.';
|
||||
$string['privacy:metadata:ai_action_register:userid'] = 'The ID of the user who made the request.';
|
||||
$string['privacy:metadata:ai_policy_register'] = 'A table storing the status of the AI policy acceptance for each user.';
|
||||
$string['privacy:metadata:ai_policy_register:userid'] = 'The ID of the user whose data was saved.';
|
||||
$string['privacy:metadata:ai_policy_register:contextid'] = 'The ID of the context whose data was saved.';
|
||||
$string['privacy:metadata:ai_policy_register:timeaccepted'] = 'The time the user accepted the AI policy.';
|
||||
$string['privacy:metadata:ai_action_summarise_text'] = 'A table storing the summarise text requests made by users.';
|
||||
$string['privacy:metadata:ai_action_summarise_text:completiontoken'] = 'The completion tokens used to summarise the text.';
|
||||
$string['privacy:metadata:ai_action_summarise_text:fingerprint'] = 'The unique hash representing the state/version of the model and content.';
|
||||
$string['privacy:metadata:ai_action_summarise_text:generatedcontent'] = 'The actual text generated by the AI model based on the input prompt.';
|
||||
$string['privacy:metadata:ai_action_summarise_text:prompt'] = 'The prompt for the summarise text request.';
|
||||
$string['privacy:metadata:ai_action_summarise_text:prompttokens'] = 'The prompt tokens used to summarise the text.';
|
||||
$string['privacy:metadata:ai_action_summarise_text:responseid'] = 'The ID of the response.';
|
||||
$string['provideractionsettings'] = 'Provider actions';
|
||||
$string['provideractionsettings_desc'] = 'These settings are for the actions that are supported by this AI provider.<br/>
|
||||
Each action can be enabled or disabled for this provider.<br/>
|
||||
|
Loading…
x
Reference in New Issue
Block a user