ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç base_test.php000064400000006661152267210470007245 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_base; use core_ai\aiactions; use ReflectionClass; /** * Test response_base action methods. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\base */ final class base_test extends \advanced_testcase { /** * Test get_basename. */ public function test_get_basename(): void { $basename = aiactions\generate_text::get_basename(); $this->assertEquals('generate_text', $basename); } /** * Test get_name. */ public function test_get_name(): void { $this->assertEquals( get_string('action_generate_text', 'core_ai'), aiactions\generate_text::get_name() ); } /** * Test get_description. */ public function test_get_description(): void { $this->assertEquals( get_string('action_generate_text_desc', 'core_ai'), aiactions\generate_text::get_description() ); } /** * Test that every action class implements a constructor. */ public function test_constructor(): void { $classes = []; $contextid = 1; // Create an anonymous class that extends the base class. $base = new class($contextid) extends \core_ai\aiactions\base { /** * Store the response. * @param response_base $response * @return int */ public function store(response_base $response): int { return 0; } }; $reflection = new ReflectionClass($base); // Create a ReflectionClass for the anonymous class. // Use the location of the base class to get the AI action classes. $filepath = $reflection->getParentClass()->getFileName(); $directory = dirname($filepath); $files = scandir($directory); foreach ($files as $file) { // Match files that are PHP files and not specifically just 'base.*.php'. if (str_ends_with($file, '.php')) { $classname = str_replace('.php', '', $file); $classes[] = 'core_ai\\aiactions\\' . $classname; } } // Ensure that some classes were found. $this->assertNotEmpty($classes, 'No classes were found for testing.'); // For each action class, check that they have a constructor. foreach ($classes as $class) { $reflection = new ReflectionClass($class); $constructor = $reflection->getConstructor(); $this->assertNotNull($constructor, 'Class ' . $class . ' does not have a constructor.'); } } } generate_image_test.php000064400000007254152267210470011266 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_generate_image; use core_ai\aiactions\generate_image; /** * Test generate_image action methods. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\base */ final class generate_image_test extends \advanced_testcase { /** * Test constructor method. */ public function test_constructor(): void { $contextid = 1; $userid = 1; $prompttext = 'This is a test prompt'; $aspectratio = 'square'; $quality = 'hd'; $numimages = 1; $style = 'vivid'; $action = new generate_image( contextid: $contextid, userid: $userid, prompttext: $prompttext, quality: $quality, aspectratio: $aspectratio, numimages: $numimages, style: $style ); $this->assertEquals($userid, $action->get_configuration('userid')); $this->assertEquals($prompttext, $action->get_configuration('prompttext')); $this->assertEquals($aspectratio, $action->get_configuration('aspectratio')); $this->assertEquals($quality, $action->get_configuration('quality')); $this->assertEquals($numimages, $action->get_configuration('numimages')); $this->assertEquals($style, $action->get_configuration('style')); } /** * Test store method. */ public function test_store(): void { $this->resetAfterTest(); global $DB; $contextid = 1; $userid = 1; $prompttext = 'This is a test prompt'; $aspectratio = 'square'; $quality = 'hd'; $numimages = 1; $style = 'vivid'; $action = new generate_image( contextid: $contextid, userid: $userid, prompttext: $prompttext, quality: $quality, aspectratio: $aspectratio, numimages: $numimages, style: $style ); $body = [ 'revisedprompt' => 'This is a revised prompt', 'sourceurl' => 'https://example.com/image.png', 'model' => 'dall-e-3', ]; $actionresponse = new response_generate_image( success: true, ); $actionresponse->set_response_data($body); $storeid = $action->store($actionresponse); // Check the stored record. $record = $DB->get_record('ai_action_generate_image', ['id' => $storeid]); $this->assertEquals($prompttext, $record->prompt); $this->assertEquals($numimages, $record->numberimages); $this->assertEquals($quality, $record->quality); $this->assertEquals($aspectratio, $record->aspectratio); $this->assertEquals($style, $record->style); $this->assertEquals($body['sourceurl'], $record->sourceurl); $this->assertEquals($body['revisedprompt'], $record->revisedprompt); } } responses/response_generate_image_test.php000064400000005763152267210470015230 0ustar00. namespace core_ai\aiactions\responses; use core\exception\coding_exception; use core_ai\aiactions\responses\response_generate_image; /** * Test response_generate_image_test action methods. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\responses\response_generate_image */ final class response_generate_image_test extends \advanced_testcase { /** * Test get_basename. */ public function test_get_success(): void { $actionresponse = new response_generate_image( success: true, ); $this->assertTrue($actionresponse->get_success()); $this->assertEquals('generate_image', $actionresponse->get_actionname()); } /** * Test constructor with error. */ public function test_construct_error(): void { $this->expectException(coding_exception::class); $this->expectExceptionMessage('Error code and message must exist in an error response.'); new response_generate_image( success: false, ); } /** * Test set_response_data. */ public function test_set_response_data(): void { $this->resetAfterTest(); // Create a file to store. $fs = get_file_storage(); $filerecord = new \stdClass(); $filerecord->contextid = 1; $filerecord->component = 'core_ai'; $filerecord->filearea = 'draft'; $filerecord->itemid = 0; $filerecord->filepath = '/'; $filerecord->filename = 'test.txt'; $file = $fs->create_file_from_string($filerecord, 'This is a test file'); $body = [ 'draftfile' => $file, 'revisedprompt' => 'This is a revised prompt', 'sourceurl' => 'https://example.com/image.png', ]; $actionresponse = new response_generate_image( success: true, ); $actionresponse->set_response_data($body); $this->assertEquals($file, $actionresponse->get_response_data()['draftfile']); $this->assertEquals('This is a revised prompt', $actionresponse->get_response_data()['revisedprompt']); $this->assertEquals('https://example.com/image.png', $actionresponse->get_response_data()['sourceurl']); } } responses/response_explain_text_test.php000064400000005702152267210470014771 0ustar00. namespace core_ai\aiactions\responses; use core_ai\aiactions\responses\response_explain_text; /** * Test response_generate_image_test action methods. * * @package core_ai * @copyright 2024 David Woloszyn * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\responses\response_explain_text */ final class response_explain_text_test extends \advanced_testcase { /** * Test get_basename. */ public function test_get_success(): void { $actionresponse = new response_explain_text( success: true, ); $this->assertTrue($actionresponse->get_success()); $this->assertEquals('explain_text', $actionresponse->get_actionname()); } /** * Test constructor with error. */ public function test_construct_error(): void { $this->expectException(\coding_exception::class); $this->expectExceptionMessage('Error code and message must exist in an error response.'); new response_explain_text( success: false, ); } /** * Test set_response_data. */ public function test_set_response_data(): void { $this->resetAfterTest(); $body = [ 'id' => 'chatcmpl-123', 'fingerprint' => 'fp_44709d6fcb', 'generatedcontent' => 'This is the generated content', 'finishreason' => 'stop', 'prompttokens' => 9, 'completiontokens' => 12, ]; $actionresponse = new response_explain_text( success: true, ); $actionresponse->set_response_data($body); $this->assertEquals($body['id'], $actionresponse->get_response_data()['id']); $this->assertEquals($body['fingerprint'], $actionresponse->get_response_data()['fingerprint']); $this->assertEquals($body['generatedcontent'], $actionresponse->get_response_data()['generatedcontent']); $this->assertEquals($body['finishreason'], $actionresponse->get_response_data()['finishreason']); $this->assertEquals($body['prompttokens'], $actionresponse->get_response_data()['prompttokens']); $this->assertEquals($body['completiontokens'], $actionresponse->get_response_data()['completiontokens']); } } responses/response_summarise_text_test.php000064400000005714152267210470015341 0ustar00. namespace core_ai\aiactions\responses; use core_ai\aiactions\responses\response_summarise_text; /** * Test response_generate_image_test action methods. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\responses\response_summarise_text */ final class response_summarise_text_test extends \advanced_testcase { /** * Test get_basename. */ public function test_get_success(): void { $actionresponse = new response_summarise_text( success: true, ); $this->assertTrue($actionresponse->get_success()); $this->assertEquals('summarise_text', $actionresponse->get_actionname()); } /** * Test constructor with error. */ public function test_construct_error(): void { $this->expectException(\coding_exception::class); $this->expectExceptionMessage('Error code and message must exist in an error response.'); new response_summarise_text( success: false, ); } /** * Test set_response_data. */ public function test_set_response_data(): void { $this->resetAfterTest(); $body = [ 'id' => 'chatcmpl-123', 'fingerprint' => 'fp_44709d6fcb', 'generatedcontent' => 'This is the generated content', 'finishreason' => 'stop', 'prompttokens' => 9, 'completiontokens' => 12, ]; $actionresponse = new response_summarise_text( success: true, ); $actionresponse->set_response_data($body); $this->assertEquals($body['id'], $actionresponse->get_response_data()['id']); $this->assertEquals($body['fingerprint'], $actionresponse->get_response_data()['fingerprint']); $this->assertEquals($body['generatedcontent'], $actionresponse->get_response_data()['generatedcontent']); $this->assertEquals($body['finishreason'], $actionresponse->get_response_data()['finishreason']); $this->assertEquals($body['prompttokens'], $actionresponse->get_response_data()['prompttokens']); $this->assertEquals($body['completiontokens'], $actionresponse->get_response_data()['completiontokens']); } } responses/response_generate_text_test.php000064400000005705152267210470015126 0ustar00. namespace core_ai\aiactions\responses; use core_ai\aiactions\responses\response_generate_text; /** * Test response_generate_image_test action methods. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\responses\response_generate_text */ final class response_generate_text_test extends \advanced_testcase { /** * Test get_basename. */ public function test_get_success(): void { $actionresponse = new response_generate_text( success: true, ); $this->assertTrue($actionresponse->get_success()); $this->assertEquals('generate_text', $actionresponse->get_actionname()); } /** * Test constructor with error. */ public function test_construct_error(): void { $this->expectException(\coding_exception::class); $this->expectExceptionMessage('Error code and message must exist in an error response.'); new response_generate_text( success: false, ); } /** * Test set_response_data. */ public function test_set_response_data(): void { $this->resetAfterTest(); $body = [ 'id' => 'chatcmpl-123', 'fingerprint' => 'fp_44709d6fcb', 'generatedcontent' => 'This is the generated content', 'finishreason' => 'stop', 'prompttokens' => 9, 'completiontokens' => 12, ]; $actionresponse = new response_generate_text( success: true, ); $actionresponse->set_response_data($body); $this->assertEquals($body['id'], $actionresponse->get_response_data()['id']); $this->assertEquals($body['fingerprint'], $actionresponse->get_response_data()['fingerprint']); $this->assertEquals($body['generatedcontent'], $actionresponse->get_response_data()['generatedcontent']); $this->assertEquals($body['finishreason'], $actionresponse->get_response_data()['finishreason']); $this->assertEquals($body['prompttokens'], $actionresponse->get_response_data()['prompttokens']); $this->assertEquals($body['completiontokens'], $actionresponse->get_response_data()['completiontokens']); } } summarise_text_test.php000064400000006124152267210470011376 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_summarise_text; use core_ai\aiactions\summarise_text; /** * Test summarise_text action methods. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\base */ final class summarise_text_test extends \advanced_testcase { /** * Test configure method. */ public function test_configure(): void { $contextid = 1; $userid = 1; $prompttext = 'This is a test prompt'; $action = new summarise_text( contextid: $contextid, userid: $userid, prompttext: $prompttext ); $this->assertEquals($userid, $action->get_configuration('userid')); $this->assertEquals($prompttext, $action->get_configuration('prompttext')); } /** * Test store method. */ public function test_store(): void { $this->resetAfterTest(); global $DB; $contextid = 1; $userid = 1; $prompttext = 'This is a test prompt'; $action = new summarise_text( contextid: $contextid, userid: $userid, prompttext: $prompttext ); $body = [ 'id' => 'chatcmpl-123', 'fingerprint' => 'fp_44709d6fcb', 'generatedcontent' => 'This is the generated content', 'finishreason' => 'stop', 'prompttokens' => 9, 'completiontokens' => 12, 'model' => 'gpt-4o', ]; $actionresponse = new response_summarise_text( success: true, ); $actionresponse->set_response_data($body); $storeid = $action->store($actionresponse); // Check the stored record. $record = $DB->get_record('ai_action_summarise_text', ['id' => $storeid]); $this->assertEquals($prompttext, $record->prompt); $this->assertEquals($body['id'], $record->responseid); $this->assertEquals($body['fingerprint'], $record->fingerprint); $this->assertEquals($body['generatedcontent'], $record->generatedcontent); $this->assertEquals($body['finishreason'], $record->finishreason); $this->assertEquals($body['prompttokens'], $record->prompttokens); $this->assertEquals($body['completiontokens'], $record->completiontoken); } } generate_text_test.php000064400000006114152267210470011162 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_generate_text; use core_ai\aiactions\generate_text; /** * Test generate_text action methods. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @covers \core_ai\aiactions\base */ final class generate_text_test extends \advanced_testcase { /** * Test configure method. */ public function test_configure(): void { $contextid = 1; $userid = 1; $prompttext = 'This is a test prompt'; $action = new generate_text( contextid: $contextid, userid: $userid, prompttext: $prompttext ); $this->assertEquals($userid, $action->get_configuration('userid')); $this->assertEquals($prompttext, $action->get_configuration('prompttext')); } /** * Test store method. */ public function test_store(): void { $this->resetAfterTest(); global $DB; $contextid = 1; $userid = 1; $prompttext = 'This is a test prompt'; $action = new generate_text( contextid: $contextid, userid: $userid, prompttext: $prompttext ); $body = [ 'id' => 'chatcmpl-123', 'fingerprint' => 'fp_44709d6fcb', 'generatedcontent' => 'This is the generated content', 'finishreason' => 'stop', 'prompttokens' => 9, 'completiontokens' => 12, 'model' => 'gpt-4o', ]; $actionresponse = new response_generate_text( success: true, ); $actionresponse->set_response_data($body); $storeid = $action->store($actionresponse); // Check the stored record. $record = $DB->get_record('ai_action_generate_text', ['id' => $storeid]); $this->assertEquals($prompttext, $record->prompt); $this->assertEquals($body['id'], $record->responseid); $this->assertEquals($body['fingerprint'], $record->fingerprint); $this->assertEquals($body['generatedcontent'], $record->generatedcontent); $this->assertEquals($body['finishreason'], $record->finishreason); $this->assertEquals($body['prompttokens'], $record->prompttokens); $this->assertEquals($body['completiontokens'], $record->completiontoken); } } summarise_text.php000064400000004711152267233270010342 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_base; /** * Summarise text class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class summarise_text extends base { /** * Create a new instance of the summarise_text action. * * It’s responsible for performing any setup tasks, * such as getting additional data from the database etc. * * @param int $contextid The context id the action was created in. * @param int $userid The user id making the request. * @param string $prompttext The prompt text used to generate the image. */ public function __construct( int $contextid, /** @var int The user id requesting the action. */ protected int $userid, /** @var string The prompt text used to generate the summary text */ protected string $prompttext, ) { parent::__construct($contextid); } #[\Override] public function store(response_base $response): int { global $DB; $responsearr = $response->get_response_data(); $record = new \stdClass(); $record->prompt = $this->prompttext; $record->responseid = $responsearr['id']; // Can be null. $record->fingerprint = $responsearr['fingerprint']; // Can be null. $record->generatedcontent = $responsearr['generatedcontent']; // Can be null. $record->finishreason = $responsearr['finishreason']; // Can be null. $record->prompttokens = $responsearr['prompttokens']; // Can be null. $record->completiontoken = $responsearr['completiontokens']; // Can be null. return $DB->insert_record($this->get_tablename(), $record); } } generate_text.php000064400000004676152267233270010141 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_base; /** * Generate text class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class generate_text extends base { /** * Create a new instance of the generate_text action. * * It’s responsible for performing any setup tasks, * such as getting additional data from the database etc. * * @param int $contextid The context id the action was created in. * @param int $userid The user id making the request. * @param string $prompttext The prompt text used to generate the image. */ public function __construct( int $contextid, /** @var int The user id requesting the action. */ protected int $userid, /** @var string The prompt text used to generate the text */ protected string $prompttext, ) { parent::__construct($contextid); } #[\Override] public function store(response_base $response): int { global $DB; $responsearr = $response->get_response_data(); $record = new \stdClass(); $record->prompt = $this->prompttext; $record->responseid = $responsearr['id']; // Can be null. $record->fingerprint = $responsearr['fingerprint']; // Can be null. $record->generatedcontent = $responsearr['generatedcontent']; // Can be null. $record->finishreason = $responsearr['finishreason']; // Can be null. $record->prompttokens = $responsearr['prompttokens']; // Can be null. $record->completiontoken = $responsearr['completiontokens']; // Can be null. return $DB->insert_record($this->get_tablename(), $record); } } explain_text.php000064400000004707152267233270010002 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_base; /** * Explain text class. * * @package core_ai * @copyright 2024 David Woloszyn * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class explain_text extends base { /** * Create a new instance of the explain_text action. * * It’s responsible for performing any setup tasks, * such as getting additional data from the database etc. * * @param int $contextid The context id the action was created in. * @param int $userid The user id making the request. * @param string $prompttext The prompt text used to generate the image. */ public function __construct( int $contextid, /** @var int The user id requesting the action. */ protected int $userid, /** @var string The prompt text used to generate the summary text */ protected string $prompttext, ) { parent::__construct($contextid); } #[\Override] public function store(response_base $response): int { global $DB; $responsearr = $response->get_response_data(); $record = new \stdClass(); $record->prompt = $this->prompttext; $record->responseid = $responsearr['id']; // Can be null. $record->fingerprint = $responsearr['fingerprint']; // Can be null. $record->generatedcontent = $responsearr['generatedcontent']; // Can be null. $record->finishreason = $responsearr['finishreason']; // Can be null. $record->prompttokens = $responsearr['prompttokens']; // Can be null. $record->completiontoken = $responsearr['completiontokens']; // Can be null. return $DB->insert_record($this->get_tablename(), $record); } } generate_image.php000064400000005730152267233270010227 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_base; /** * Generate images class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class generate_image extends base { /** * Create a new instance of the generate_image action. * * It’s responsible for performing any setup tasks, * such as getting additional data from the database etc. * * @param int $contextid The context id the action was created in. * @param int $userid The user id making the request. * @param string $prompttext The prompt text used to generate the image. * @param string $quality The quality of the generated image. * @param string $aspectratio The aspect ratio of the generated image. * @param int $numimages The number of images to generate. * @param string $style The visual style of the generated image. */ public function __construct( int $contextid, /** @var int The user id requesting the action. */ protected int $userid, /** @var string The prompt text used to generate the image */ protected string $prompttext, /** @var string The quality of the generated image */ protected string $quality, /** @var string The aspect ratio of the generated image */ protected string $aspectratio, /** @var int The number of images to generate */ protected int $numimages, /** @var string The visual style of the generated image */ protected string $style, ) { parent::__construct($contextid); } #[\Override] public function store(response_base $response): int { global $DB; $responsearr = $response->get_response_data(); $record = new \stdClass(); $record->prompt = $this->prompttext; $record->numberimages = $this->numimages; $record->quality = $this->quality; $record->aspectratio = $this->aspectratio; $record->style = $this->style; $record->sourceurl = $responsearr['sourceurl']; // Can be null. $record->revisedprompt = $responsearr['revisedprompt']; // Can be null. return $DB->insert_record($this->get_tablename(), $record); } } responses/response_generate_image.php000064400000005056152267233270014167 0ustar00. namespace core_ai\aiactions\responses; /** * Generate image action response class. * * Any method that processes an action must return an instance of this class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class response_generate_image extends response_base { /** @var \stored_file|null The URL of the generated image. */ private ?\stored_file $draftfile = null; /** @var string|null The revised prompt generated by the AI. */ private ?string $revisedprompt = null; /** @var string|null The URL of the source image used to generate the image. */ private ?string $sourceurl = null; /** * Constructor. * * @param bool $success The success status of the action. * @param int $errorcode Error code. Must exist if success is false. * @param string $errormessage Error message. Must exist if success is false */ public function __construct( bool $success, int $errorcode = 0, string $errormessage = '', ) { parent::__construct( success: $success, actionname: 'generate_image', errorcode: $errorcode, errormessage: $errormessage, ); } #[\Override] public function set_response_data(array $response): void { $this->draftfile = $response['draftfile'] ?? null; $this->revisedprompt = $response['revisedprompt'] ?? null; $this->sourceurl = $response['sourceurl'] ?? null; $this->model = $response['model'] ?? null; } #[\Override] public function get_response_data(): array { return [ 'draftfile' => $this->draftfile, 'revisedprompt' => $this->revisedprompt, 'sourceurl' => $this->sourceurl, 'model' => $this->model, ]; } } responses/response_summarise_text.php000064400000006423152267233270014303 0ustar00. namespace core_ai\aiactions\responses; /** * Summarise text action response class. * * Any method that processes an action must return an instance of this class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class response_summarise_text extends response_base { /** @var string|null A unique identifier for the chat completion, returned by the AI. */ private ?string $id = null; /** @var string|null This fingerprint represents the backend configuration that the model runs with. */ private ?string $fingerprint = null; /** @var string|null The contents of the generated message. */ private ?string $generatedcontent = null; /** @var string|null The reason the model stopped generating tokens. */ private ?string $finishreason = null; /** @var string|null Number of tokens in the prompt. */ private ?string $prompttokens = null; /** @var string|null Number of tokens in the generated completion. */ private ?string $completiontokens = null; /** * Constructor. * * @param bool $success The success status of the action. * @param int $errorcode Error code. Must exist if success is false. * @param string $errormessage Error message. Must exist if success is false */ public function __construct( bool $success, int $errorcode = 0, string $errormessage = '', ) { parent::__construct( success: $success, actionname: 'summarise_text', errorcode: $errorcode, errormessage: $errormessage, ); } #[\Override] public function set_response_data(array $response): void { $this->id = $response['id'] ?? null; $this->fingerprint = $response['fingerprint'] ?? null; $this->generatedcontent = $response['generatedcontent'] ?? null; $this->finishreason = $response['finishreason'] ?? null; $this->prompttokens = $response['prompttokens'] ?? null; $this->completiontokens = $response['completiontokens'] ?? null; $this->model = $response['model'] ?? null; } #[\Override] public function get_response_data(): array { return [ 'id' => $this->id, 'fingerprint' => $this->fingerprint, 'generatedcontent' => $this->generatedcontent, 'finishreason' => $this->finishreason, 'prompttokens' => $this->prompttokens, 'completiontokens' => $this->completiontokens, 'model' => $this->model, ]; } } responses/response_base.php000064400000007431152267233270012144 0ustar00. namespace core_ai\aiactions\responses; use core\exception\coding_exception; /** * Action response base class. * Any method that processes an action must return an instance of this class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class response_base { /** @var int The timestamp of when the response was created. */ private int $timecreated; /** * Constructor. * * @param bool $success The success status of the action. * @param string $actionname The name of the action that was processed. * @param int $errorcode Error code. Must exist if success is false. * @param string $errormessage Error message. Must exist if success is false * @param string $model The model used to generate the response. */ public function __construct( /** @var bool The success status of the action. */ private bool $success, /** @var string The name of the action that was processed. */ private string $actionname, /** @var int Error code. Must exist if status is error. */ private int $errorcode = 0, /** @var string Error message. Must exist if status is error */ private string $errormessage = '', /** @var string The model used to generate the response (if available). */ protected ?string $model = null, ) { $this->timecreated = \core\di::get(\core\clock::class)->time(); if (!$success && ($errorcode == 0 || empty($errormessage))) { throw new coding_exception('Error code and message must exist in an error response.'); } } /** * Set the response data returned by the AI provider. * * @param array $response The response data returned by the AI provider. */ abstract public function set_response_data(array $response): void; /** * Get the response data returned by the AI provider. * * @return array */ abstract public function get_response_data(): array; /** * Get the success status of the action. * * @return bool */ public function get_success(): bool { return $this->success; } /** * Get the timestamp of when the response was created. * * @return int */ public function get_timecreated(): int { return $this->timecreated; } /** * Get the name of the action that was processed. * * @return string */ public function get_actionname(): string { return $this->actionname; } /** * Get the error code. * * @return int */ public function get_errorcode(): int { return $this->errorcode; } /** * Get the error message. * * @return string */ public function get_errormessage(): string { return $this->errormessage; } /** * Get the model used to generate the response (if available). * * @return ?string */ public function get_model_used(): ?string { return $this->model; } } responses/response_explain_text.php000064400000006421152267233270013734 0ustar00. namespace core_ai\aiactions\responses; /** * Explain text action response class. * * Any method that processes an action must return an instance of this class. * * @package core_ai * @copyright 2024 David Woloszyn * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class response_explain_text extends response_base { /** @var string|null A unique identifier for the chat completion, returned by the AI. */ private ?string $id = null; /** @var string|null This fingerprint represents the backend configuration that the model runs with. */ private ?string $fingerprint = null; /** @var string|null The contents of the generated message. */ private ?string $generatedcontent = null; /** @var string|null The reason the model stopped generating tokens. */ private ?string $finishreason = null; /** @var string|null Number of tokens in the prompt. */ private ?string $prompttokens = null; /** @var string|null Number of tokens in the generated completion. */ private ?string $completiontokens = null; /** * Constructor. * * @param bool $success The success status of the action. * @param int $errorcode Error code. Must exist if success is false. * @param string $errormessage Error message. Must exist if success is false */ public function __construct( bool $success, int $errorcode = 0, string $errormessage = '', ) { parent::__construct( success: $success, actionname: 'explain_text', errorcode: $errorcode, errormessage: $errormessage, ); } #[\Override] public function set_response_data(array $response): void { $this->id = $response['id'] ?? null; $this->fingerprint = $response['fingerprint'] ?? null; $this->generatedcontent = $response['generatedcontent'] ?? null; $this->finishreason = $response['finishreason'] ?? null; $this->prompttokens = $response['prompttokens'] ?? null; $this->completiontokens = $response['completiontokens'] ?? null; $this->model = $response['model'] ?? null; } #[\Override] public function get_response_data(): array { return [ 'id' => $this->id, 'fingerprint' => $this->fingerprint, 'generatedcontent' => $this->generatedcontent, 'finishreason' => $this->finishreason, 'prompttokens' => $this->prompttokens, 'completiontokens' => $this->completiontokens, 'model' => $this->model, ]; } } responses/response_generate_text.php000064400000006420152267233270014065 0ustar00. namespace core_ai\aiactions\responses; /** * Generate text action response class. * * Any method that processes an action must return an instance of this class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class response_generate_text extends response_base { /** @var string|null A unique identifier for the chat completion, returned by the AI. */ private ?string $id = null; /** @var string|null This fingerprint represents the backend configuration that the model runs with. */ private ?string $fingerprint = null; /** @var string|null The contents of the generated message. */ private ?string $generatedcontent = null; /** @var string|null The reason the model stopped generating tokens. */ private ?string $finishreason = null; /** @var string|null Number of tokens in the prompt. */ private ?string $prompttokens = null; /** @var string|null Number of tokens in the generated completion. */ private ?string $completiontokens = null; /** * Constructor. * * @param bool $success The success status of the action. * @param int $errorcode Error code. Must exist if success is false. * @param string $errormessage Error message. Must exist if success is false */ public function __construct( bool $success, int $errorcode = 0, string $errormessage = '', ) { parent::__construct( success: $success, actionname: 'generate_text', errorcode: $errorcode, errormessage: $errormessage, ); } #[\Override] public function set_response_data(array $response): void { $this->id = $response['id'] ?? null; $this->fingerprint = $response['fingerprint'] ?? null; $this->generatedcontent = $response['generatedcontent'] ?? null; $this->finishreason = $response['finishreason'] ?? null; $this->prompttokens = $response['prompttokens'] ?? null; $this->completiontokens = $response['completiontokens'] ?? null; $this->model = $response['model'] ?? null; } #[\Override] public function get_response_data(): array { return [ 'id' => $this->id, 'fingerprint' => $this->fingerprint, 'generatedcontent' => $this->generatedcontent, 'finishreason' => $this->finishreason, 'prompttokens' => $this->prompttokens, 'completiontokens' => $this->completiontokens, 'model' => $this->model, ]; } } base.php000064400000007577152267233270006220 0ustar00. namespace core_ai\aiactions; use core_ai\aiactions\responses\response_base; /** * Base Action class. * * @package core_ai * @copyright 2024 Matt Porritt * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class base { /** @var int Timestamp the action object was created. */ protected readonly int $timecreated; /** * Constructor for the class. * * @param int $contextid The context ID where the action was created. */ public function __construct( /** @var int The context ID the action was created in */ protected int $contextid, ) { $this->timecreated = \core\di::get(\core\clock::class)->time(); } /** * Responsible for storing any action specific data in the database. * * @param response_base $response The response object to store. * @return int The id of the stored action. */ abstract public function store(response_base $response): int; /** * Get the basename of the class. * * This is used to generate the action name and description. * * @return string The basename of the class. */ public static function get_basename(): string { return basename(str_replace('\\', '/', static::class)); } /** * Get the action name. * * Defaults to the action name string. * * @return string */ public static function get_name(): string { $stringid = 'action_' . self::get_basename(); return get_string($stringid, 'core_ai'); } /** * Get the action description. * * Defaults to the action description string. * * @return string */ public static function get_description(): string { $stringid = 'action_' . self::get_basename() . '_desc'; return get_string($stringid, 'core_ai'); } /** * Get the system instruction for the action. * * @return string The system instruction for the action. */ public static function get_system_instruction(): string { $stringid = 'action_' . self::get_basename() . '_instruction'; // If the string doesn't exist, return an empty string. if (!get_string_manager()->string_exists($stringid, 'core_ai')) { return ''; } return get_string($stringid, 'core_ai'); } /** * Get a configuration option. * * @param string $name The name of the configuration option to get. * @return mixed The value of the configuration option. */ public function get_configuration(string $name): mixed { return $this->$name; } /** * Return the correct table name for the action. * * @return string The correct table name for the action. */ protected function get_tablename(): string { // Table name should always be in this format. return 'ai_action_' . $this->get_basename(); } /** * Get the class name of the response object. * * @return string The class name of the response object. */ public static function get_response_classname(): string { return responses::class . '\\response_' . self::get_basename(); } }