diff --git a/classes/base_instance.php b/classes/base_instance.php index 0419cb0..c0ece5c 100644 --- a/classes/base_instance.php +++ b/classes/base_instance.php @@ -521,6 +521,8 @@ final public function store_formdata(stdClass $data): void { $this->set_connector($data->connector); $this->set_tenant($data->tenant); if (empty($data->model)) { + // This is only a fallback. If the connector does not support the selection of a model, + // it is supposed to overwrite this default value in the extend_store_formdata function. $data->model = self::PRECONFIGURED_MODEL; } $this->set_model($data->model); diff --git a/classes/local/aitool_option_azure.php b/classes/local/aitool_option_azure.php index 83c0f6f..94d0990 100644 --- a/classes/local/aitool_option_azure.php +++ b/classes/local/aitool_option_azure.php @@ -16,6 +16,7 @@ namespace local_ai_manager\local; +use local_ai_manager\base_connector; use stdClass; /** @@ -111,4 +112,21 @@ public static function validate_azure_options(array $data): array { } return $errors; } + + /** + * Define the model name in case we are using azure. + * + * When using azure we cannot select a model, because it is preconfigured in the azure resource. + * This function defines the string to use as model for logging etc. + * + * @param ?string $connectorname The name of the connector, will be included into the model name + * @return string the string defining the name of the model + * @throws \coding_exception if the $connectorname is null or empty + */ + public static function get_azure_model_name(?string $connectorname): string { + if (empty($connectorname)) { + throw new \coding_exception('Azure model name cannot be empty or null'); + } + return $connectorname . '_preconfigured_azure'; + } } diff --git a/classes/manager.php b/classes/manager.php index 0ab581e..3f685fa 100644 --- a/classes/manager.php +++ b/classes/manager.php @@ -217,6 +217,7 @@ public function log_request(string $prompttext, prompt_response $promptcompletio $data = new stdClass(); $data->userid = $USER->id; $data->value = $promptcompletion->get_usage()->value; + $data->connector = $this->connector->get_instance()->get_connector(); if ($this->connector->has_customvalue1()) { $data->customvalue1 = $promptcompletion->get_usage()->customvalue1; } diff --git a/db/install.xml b/db/install.xml index 4d5e018..c10cb1c 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,5 +1,5 @@ - @@ -49,6 +49,7 @@ + diff --git a/db/upgrade.php b/db/upgrade.php index b9de70e..dce5ff1 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -54,5 +54,53 @@ function xmldb_local_ai_manager_upgrade($oldversion) { // Ai_manager savepoint reached. upgrade_plugin_savepoint(true, 2024080900, 'local', 'ai_manager'); } + + if ($oldversion < 2024091800) { + $table = new xmldb_table('local_ai_manager_request_log'); + $field = new xmldb_field('connector', XMLDB_TYPE_CHAR, '50', null, null, null, null, 'purpose'); + + // Conditionally launch add field connector. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Migrate existing records. + $rs = $DB->get_recordset('local_ai_manager_request_log'); + foreach ($rs as $record) { + if ($record->model === 'preconfigured') { + if ($record->purpose === 'tts') { + $record->model = 'openaitts_preconfigured_azure'; + } else if ($record->purpose === 'imggen') { + $record->model = 'dalle_preconfigured_azure'; + } else { + $record->model = 'chatgpt_preconfigured_azure'; + } + } + if ($record->purpose === 'tts') { + if (str_contains($record->model, 'preconfigured') || str_contains($record->model, 'tts-1')) { + $record->connector = 'openaitts'; + } else { + $record->connector = 'googlesynthesize'; + } + } else if ($record->purpose === 'imggen') { + $record->connector = 'dalle'; + } else { + // We have a text based language model. + if (str_starts_with($record->model, 'gemini-')) { + $record->connector = 'gemini'; + } else if (str_starts_with($record->model, 'gpt-')) { + $record->connector = 'chatgpt'; + } else { + $record->connector = 'ollama'; + } + } + $DB->update_record('local_ai_manager_request_log', $record); + } + + $rs = $DB->get_recordset('local_ai_manager_request_log'); + + $rs->close(); + upgrade_plugin_savepoint(true, 2024091800, 'local', 'ai_manager'); + } return true; } diff --git a/tools/chatgpt/classes/instance.php b/tools/chatgpt/classes/instance.php index 66d096d..0b920d4 100644 --- a/tools/chatgpt/classes/instance.php +++ b/tools/chatgpt/classes/instance.php @@ -63,6 +63,9 @@ protected function extend_store_formdata(stdClass $data): void { $endpoint = 'https://' . $resourcename . '.openai.azure.com/openai/deployments/' . $deploymentid . '/chat/completions?api-version=' . $apiversion; + // We have an empty model because the model is preconfigured if we're using azure. + // So we overwrite the default "preconfigured" value by a better model name. + $this->set_model(aitool_option_azure::get_azure_model_name($this->get_connector())); } else { $endpoint = 'https://api.openai.com/v1/chat/completions'; } diff --git a/tools/dalle/classes/instance.php b/tools/dalle/classes/instance.php index 2b61176..eba72bb 100644 --- a/tools/dalle/classes/instance.php +++ b/tools/dalle/classes/instance.php @@ -54,6 +54,9 @@ protected function extend_store_formdata(stdClass $data): void { $endpoint = 'https://' . $resourcename . '.openai.azure.com/openai/deployments/' . $deploymentid . '/images/generations?api-version=' . $apiversion; + // We have an empty model because the model is preconfigured if we're using azure. + // So we overwrite the default "preconfigured" value by a better model name. + $this->set_model(aitool_option_azure::get_azure_model_name($this->get_connector())); } else { $endpoint = 'https://api.openai.com/v1/images/generations'; } diff --git a/tools/openaitts/classes/instance.php b/tools/openaitts/classes/instance.php index 3c48c2d..dedf291 100644 --- a/tools/openaitts/classes/instance.php +++ b/tools/openaitts/classes/instance.php @@ -54,6 +54,9 @@ protected function extend_store_formdata(stdClass $data): void { $endpoint = 'https://' . $resourcename . '.openai.azure.com/openai/deployments/' . $deploymentid . '/audio/speech?api-version=' . $apiversion; + // We have an empty model because the model is preconfigured if we're using azure. + // So we overwrite the default "preconfigured" value by a better model name. + $this->set_model(aitool_option_azure::get_azure_model_name($this->get_connector())); } else { $endpoint = 'https://api.openai.com/v1/audio/speech'; } diff --git a/version.php b/version.php index adcb402..60c6ab7 100644 --- a/version.php +++ b/version.php @@ -24,7 +24,7 @@ */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2024082600; +$plugin->version = 2024091800; $plugin->requires = 2024042200; $plugin->release = '0.0.1'; $plugin->component = 'local_ai_manager';