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

CreatorCore prompt generation endpoint #1591

Merged
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 fuel/app/classes/basetest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ protected function make_disposable_widget(string $name = 'TestWidget', bool $res
'is_editable' => true,
'in_catalog' => true,
'is_generable' => false,
'uses_prompt_generation' => false,
'restrict_publish' => $restrict_publish,
'api_version' => 2,
],
Expand Down
28 changes: 28 additions & 0 deletions fuel/app/classes/materia/api/v1.php
Original file line number Diff line number Diff line change
Expand Up @@ -894,6 +894,34 @@ static public function question_set_generate($inst_id, $widget_id, $topic, $incl
}
}

/**
* Endpoint to facilitate AI text generation for widgets
*
* @param string $prompt The prompt to generate.
* @return array An array to be passed back to the widget containing the response string
*/
static public function widget_prompt_generate($prompt)
{
// verify eligibility
if ( ! Widget_Question_Generator::is_enabled()) return Msg::failure();
if (\Service_User::verify_session() !== true) return Msg::no_login();

// prompt generation & response handling
$result = Widget_Question_Generator::generate_from_prompt($prompt);
if ( ! $result instanceof Msg && is_string($result))
{
return [
'success' => true,
'response' => $result
];
}
else
{
\Log::error(print_r($result, true));
return $result;
}
}

/**
* Gets the question with the given QID or an array of questions
* with the given ids (passed as an array)
Expand Down
125 changes: 68 additions & 57 deletions fuel/app/classes/materia/widget.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,35 @@

class Widget
{
public $clean_name = '';
public $creator = '';
public $created_at = 0;
public $dir = '';
public $flash_version = 0;
public $api_version = 0;
public $height = 0;
public $id = 0;
public $is_answer_encrypted = true;
public $in_catalog = true;
public $is_editable = true;
public $is_playable = true;
public $is_qset_encrypted = true;
public $is_scalable = 0;
public $is_scorable = true;
public $is_storage_enabled = false;
public $is_generable = false;
public $package_hash = '';
public $meta_data = null;
public $name = '';
public $player = '';
public $question_types = '';
public $restrict_publish = false;
public $score_module = 'base';
public $score_screen = '';
public $width = 0;
public $creator_guide = '';
public $player_guide = '';
public $clean_name = '';
public $creator = '';
public $created_at = 0;
public $dir = '';
public $flash_version = 0;
public $api_version = 0;
public $height = 0;
public $id = 0;
public $is_answer_encrypted = true;
public $in_catalog = true;
public $is_editable = true;
public $is_playable = true;
public $is_qset_encrypted = true;
public $is_scalable = 0;
public $is_scorable = true;
public $is_storage_enabled = false;
public $is_generable = false;
public $uses_prompt_generation = false;
public $package_hash = '';
public $meta_data = null;
public $name = '';
public $player = '';
public $question_types = '';
public $restrict_publish = false;
public $score_module = 'base';
public $score_screen = '';
public $width = 0;
public $creator_guide = '';
public $player_guide = '';

public const PATHS_PLAYDATA = '_exports'.DS.'playdata_exporters.php';
public const PATHS_SCOREMOD = '_score-modules'.DS.'score_module.php';
Expand Down Expand Up @@ -90,32 +91,33 @@ public function get($id_or_clean_name)

// -------------- INIT OBJECT ---------------
$this->__construct([
'clean_name' => $w['clean_name'],
'created_at' => $w['created_at'],
'creator' => $w['creator'],
'is_answer_encrypted' => $w['is_answer_encrypted'],
'is_qset_encrypted' => $w['is_qset_encrypted'],
'flash_version' => $w['flash_version'],
'api_version' => $w['api_version'],
'height' => $w['height'],
'id' => $w['id'],
'in_catalog' => $w['in_catalog'],
'is_editable' => $w['is_editable'],
'name' => $w['name'],
'is_playable' => $w['is_playable'],
'player' => $w['player'],
'is_scorable' => $w['is_scorable'],
'is_scalable' => $w['is_scalable'],
'score_module' => $w['score_module'],
'score_screen' => $w['score_screen'],
'restrict_publish' => $w['restrict_publish'],
'is_storage_enabled' => $w['is_storage_enabled'],
'is_generable' => $w['is_generable'],
'package_hash' => $w['package_hash'],
'width' => $w['width'],
'creator_guide' => $w['creator_guide'],
'player_guide' => $w['player_guide'],
'meta_data' => static::db_get_metadata($w['id']),
'clean_name' => $w['clean_name'],
'created_at' => $w['created_at'],
'creator' => $w['creator'],
'is_answer_encrypted' => $w['is_answer_encrypted'],
'is_qset_encrypted' => $w['is_qset_encrypted'],
'flash_version' => $w['flash_version'],
'api_version' => $w['api_version'],
'height' => $w['height'],
'id' => $w['id'],
'in_catalog' => $w['in_catalog'],
'is_editable' => $w['is_editable'],
'name' => $w['name'],
'is_playable' => $w['is_playable'],
'player' => $w['player'],
'is_scorable' => $w['is_scorable'],
'is_scalable' => $w['is_scalable'],
'score_module' => $w['score_module'],
'score_screen' => $w['score_screen'],
'restrict_publish' => $w['restrict_publish'],
'is_storage_enabled' => $w['is_storage_enabled'],
'is_generable' => $w['is_generable'],
'uses_prompt_generation' => $w['uses_prompt_generation'],
'package_hash' => $w['package_hash'],
'width' => $w['width'],
'creator_guide' => $w['creator_guide'],
'player_guide' => $w['player_guide'],
'meta_data' => static::db_get_metadata($w['id']),
]);

// if creator is empty or set to 'default', use the default creator
Expand All @@ -124,8 +126,17 @@ public function get($id_or_clean_name)
$this->creator = \Config::get('materia.urls.static').'default-creator/creator.html';
}

if ( ! \Service_User::verify_session('basic_author')) $this->is_generable = '0';
else $this->is_generable = $this->is_generable == '1' && Widget_Question_Generator::is_enabled() ? '1' : '0';
// check if ai generation is available and adjust appropriate fields
if ( ! \Service_User::verify_session('basic_author'))
{
$this->is_generable = '0';
$this->uses_prompt_generation = '0';
}
else
{
$this->is_generable = $this->is_generable == '1' && Widget_Question_Generator::is_enabled() ? '1' : '0';
$this->uses_prompt_generation = $this->uses_prompt_generation == '1' && Widget_Question_Generator::is_enabled() ? '1' : '0';
}

return true;
}
Expand Down Expand Up @@ -183,7 +194,7 @@ public function get_property($prop)
->execute()[0]['value'];
}

if ($prop == 'is_generable')
if ($prop == 'is_generable' || $prop == 'uses_prompt_generation')
{
if ( ! \Service_User::verify_session('basic_author')) return '0';
elseif ( Widget_Question_Generator::is_enabled() && $val == '1') return '1';
Expand Down
47 changes: 24 additions & 23 deletions fuel/app/classes/materia/widget/installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -534,29 +534,30 @@ public static function generate_install_params(array $manifest_data, string $pac
$clean_name = \Materia\Widget::make_clean_name($manifest_data['general']['name']);
$package_hash = md5_file($package_file);
$params = [
'name' => $manifest_data['general']['name'],
'created_at' => time(),
'flash_version' => $manifest_data['files']['flash_version'],
'height' => $manifest_data['general']['height'],
'width' => $manifest_data['general']['width'],
'restrict_publish' => isset($manifest_data['general']['restrict_publish']) ? Util_Validator::cast_to_bool_enum($manifest_data['general']['restrict_publish']) : '0',
'is_qset_encrypted' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_qset_encrypted']),
'is_answer_encrypted' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_answer_encrypted']),
'is_storage_enabled' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_storage_enabled']),
'is_playable' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_playable']),
'is_editable' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_editable']),
'is_scorable' => Util_Validator::cast_to_bool_enum($manifest_data['score']['is_scorable']),
'in_catalog' => Util_Validator::cast_to_bool_enum($manifest_data['general']['in_catalog']),
'is_generable' => isset($manifest_data['general']['is_generable']) ? Util_Validator::cast_to_bool_enum($manifest_data['general']['is_generable']) : '0',
'clean_name' => $clean_name,
'api_version' => (string)(int)$manifest_data['general']['api_version'],
'package_hash' => $package_hash,
'score_module' => $manifest_data['score']['score_module'],
'creator' => isset($manifest_data['files']['creator']) ? $manifest_data['files']['creator'] : '',
'player' => isset($manifest_data['files']['player']) ? $manifest_data['files']['player'] : '' ,
'score_screen' => isset($manifest_data['score']['score_screen']) ? $manifest_data['score']['score_screen'] : '',
'creator_guide' => isset($manifest_data['files']['creator_guide']) ? $manifest_data['files']['creator_guide'] : '',
'player_guide' => isset($manifest_data['files']['player_guide']) ? $manifest_data['files']['player_guide'] : ''
'name' => $manifest_data['general']['name'],
'created_at' => time(),
'flash_version' => $manifest_data['files']['flash_version'],
'height' => $manifest_data['general']['height'],
'width' => $manifest_data['general']['width'],
'restrict_publish' => isset($manifest_data['general']['restrict_publish']) ? Util_Validator::cast_to_bool_enum($manifest_data['general']['restrict_publish']) : '0',
'is_qset_encrypted' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_qset_encrypted']),
'is_answer_encrypted' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_answer_encrypted']),
'is_storage_enabled' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_storage_enabled']),
'is_playable' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_playable']),
'is_editable' => Util_Validator::cast_to_bool_enum($manifest_data['general']['is_editable']),
'is_scorable' => Util_Validator::cast_to_bool_enum($manifest_data['score']['is_scorable']),
'in_catalog' => Util_Validator::cast_to_bool_enum($manifest_data['general']['in_catalog']),
'is_generable' => isset($manifest_data['general']['is_generable']) ? Util_Validator::cast_to_bool_enum($manifest_data['general']['is_generable']) : '0',
'uses_prompt_generation' => isset($manifest_data['general']['uses_prompt_generation']) ? Util_Validator::cast_to_bool_enum($manifest_data['general']['uses_prompt_generation']) : '0',
'clean_name' => $clean_name,
'api_version' => (string)(int)$manifest_data['general']['api_version'],
'package_hash' => $package_hash,
'score_module' => $manifest_data['score']['score_module'],
'creator' => isset($manifest_data['files']['creator']) ? $manifest_data['files']['creator'] : '',
'player' => isset($manifest_data['files']['player']) ? $manifest_data['files']['player'] : '' ,
'score_screen' => isset($manifest_data['score']['score_screen']) ? $manifest_data['score']['score_screen'] : '',
'creator_guide' => isset($manifest_data['files']['creator_guide']) ? $manifest_data['files']['creator_guide'] : '',
'player_guide' => isset($manifest_data['files']['player_guide']) ? $manifest_data['files']['player_guide'] : ''
];
return $params;
}
Expand Down
28 changes: 28 additions & 0 deletions fuel/app/classes/materia/widget/question/generator.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,34 @@ public static function query($prompt, $format='json')
return $client->chat()->create($params);
}

/**
* Generates a text response based on the provided prompt.
*
* @param string $prompt The prompt to send to the LLM.
* @return string The generated response.
*/
static public function generate_from_prompt($prompt)
{
if ( ! self::is_enabled()) return Msg::failure('Question generation is not enabled.');
if (empty($prompt) || strlen($prompt) > 10000) return Msg::invalid_input('Prompt text length invalid.');

try
{
$result = self::query($prompt, 'message');
$response = $result->choices[0]->message->content;

return $response;
}
catch (\Exception $e)
{
\Log::error('Error generating prompt:'.PHP_EOL
.'Prompt: '.$prompt.PHP_EOL
.'Exception: '.$e->getMessage().PHP_EOL);

return Msg::failure('Error generating question set.');
}
}

/**
* Generate a question set for a widget instance
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Fuel\Migrations;

class Add_uses_prompt_generation_field_to_widget_table
{
public function up()
{
\DBUtil::add_fields('widget', array(
'uses_prompt_generation' => ['constraint' => "'0','1'", 'type' => 'enum', 'default' => '0'],
));
}

public function down()
{
\DBUtil::drop_fields('widget', array(
'uses_prompt_generation',
));
}
}
15 changes: 15 additions & 0 deletions fuel/app/tests/api/v1.php
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,21 @@ public function test_question_set_generate()
}
}

public function test_widget_prompt_generate()
{
if ( ! \Materia\Widget_Question_Generator::is_enabled())
{
$output = Api_V1::widget_prompt_generate('Provide a background story for Kogneato, the robot mascot of Materia, a platform for educational tools and games.');
$this->assert_failure_message($output);
}
else
{
// ======= AS NO ONE ========
$output = Api_V1::widget_prompt_generate('Provide a background story for Kogneato, the robot mascot of Materia, a platform for educational tools and games.');
$this->assert_invalid_login_message($output);
}
}

public function test_questions_get()
{
// ======= AS NO ONE ========
Expand Down
1 change: 1 addition & 0 deletions fuel/app/tests/widget_source/test_widget/src/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ general:
is_qset_encrypted: No
is_answer_encrypted: No
is_generable: No
uses_prompt_generation: No
api_version: 2
files:
player: player.html
Expand Down
24 changes: 13 additions & 11 deletions fuel/app/tests/widgets/installer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,18 @@ public function test_generate_install_params()

$manifest_data = [
'general' => [
'name' => 'THIS IS A Name!',
'height' => 55,
'width' => 100,
'is_qset_encrypted' => false,
'is_answer_encrypted' => true,
'is_storage_enabled' => '1',
'is_playable' => '0',
'is_editable' => 'true',
'in_catalog' => 'false',
'is_generable' => '0',
'api_version' => '2',
'name' => 'THIS IS A Name!',
'height' => 55,
'width' => 100,
'is_qset_encrypted' => false,
'is_answer_encrypted' => true,
'is_storage_enabled' => '1',
'is_playable' => '0',
'is_editable' => 'true',
'in_catalog' => 'false',
'is_generable' => '0',
'uses_prompt_generation' => '0',
'api_version' => '2',
],
'score' => [
'score_module' => 'scoreModule',
Expand All @@ -48,6 +49,7 @@ public function test_generate_install_params()
'is_answer_encrypted' => '1',
'is_storage_enabled' => '1',
'is_generable' => '0',
'uses_prompt_generation' => '0',
'is_playable' => '0',
'is_editable' => '0',
'is_scorable' => '1',
Expand Down
Loading
Loading