using AIStudio.Models.Plugins; using Lua; namespace AIStudio.Tools.PluginSystem; /// /// A plugin which tells AI Studio about models it does not know, or knows wrongly. /// /// /// Organizations run models nobody outside them has ever heard of: their own fine-tunes, a model /// behind an internal name, an engine an operator configured differently from the model card. Until /// now the only way to tell AI Studio about those was the expert settings of each configured /// provider, one person and one provider at a time. /// /// A model plugin describes, and that is all it does. It names no endpoint, carries no key, runs no /// code of its own and reaches nothing over the network, which is why it needs none of the checks an /// assistant plugin goes through. Where it was deployed is what says how much it may claim, exactly /// as for every other kind of plugin. /// public sealed class PluginModels(bool isInternal, LuaState state, PluginType type) : PluginBase(isInternal, state, type), ILivePluginContentSource { private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(nameof(PluginModels)); private readonly List declarations = []; /// /// The models this plugin declares. /// public IReadOnlyList Declarations => this.declarations; /// public int Priority { get; } = ReadPriority(state); /// /// Reads the MODELS table of the plugin. /// /// /// An entry which cannot be read is reported and skipped, and the rest of the table still /// counts. A single mistyped capability in the twentieth entry must not take the nineteen /// working ones with it -- the plugin would then be silently doing nothing at all. /// public void TryLoad() { if (!this.State.Environment["MODELS"].TryRead(out var modelsTable)) { this.PluginIssues.Add(TB("The table MODELS does not exist or is using an invalid syntax.")); return; } for (var i = 1; i <= modelsTable.ArrayLength; i++) { if (!modelsTable[i].TryRead(out var modelTable)) { LOG.LogWarning("The table 'MODELS' entry at index {Index} is not a valid table (model plugin id: {PluginId}).", i, this.Id); continue; } if (ModelDeclaration.TryParse(i, modelTable, this.Id, this.Name, LOG, out var declaration)) this.declarations.Add(declaration); else LOG.LogWarning("The table 'MODELS' entry at index {Index} does not contain a valid model declaration and is ignored (model plugin id: {PluginId}).", i, this.Id); } if (this.declarations.Count is 0) LOG.LogWarning("The model plugin '{PluginId}' declares no model AI Studio could read. It has no effect.", this.Id); } private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(PluginModels).Namespace, nameof(PluginModels)); private static int ReadPriority(LuaState state) => state.Environment["PRIORITY"].TryRead(out var priority) ? priority : 0; }