mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 23:18:00 +00:00
Added tool calling support (#731)
Co-authored-by: krut_ni <nils.kruthoff@dlr.de> Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
266 files changed
+11186
-740
No files matched your search
@@ -35,6 +35,19 @@ else
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
@*
|
||||
The plugin names the tools, so there is nothing for the user to switch on or off. What is
|
||||
left is to say which tools run here, and to warn when the selected provider keeps one of
|
||||
them out of reach.
|
||||
*@
|
||||
@if (this.assistantToolIds is { Count: > 0 } toolIds && this.SettingsManager.AreToolsEnabled())
|
||||
{
|
||||
<MudPaper Class="pa-4 ma-4" Elevation="0">
|
||||
<ManagedToolsWarning Component="@this.Component" ToolIds="@toolIds" ProviderSettings="@this.ProviderSettings"/>
|
||||
<ToolSelectionField Component="@this.Component" SelectedToolIds="@toolIds" ReadOnly="@true" Label="@T("Tools of this assistant")" Help="@T("The author of this assistant chose these tools, so they cannot be changed here. Every tool has to meet the confidence requirements of the selected provider, so a tool may stay unavailable even when this assistant names it.")"/>
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
@foreach (var component in this.RootComponent.Children)
|
||||
{
|
||||
@this.RenderComponent(component)
|
||||
|
||||
@@ -9,6 +9,7 @@ using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
using AIStudio.Tools.Services;
|
||||
using AIStudio.Tools.ToolCallingSystem;
|
||||
using Lua;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.WebUtilities;
|
||||
@@ -34,6 +35,13 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
protected override bool ShowProfileSelection => this.showFooterProfileSelection;
|
||||
protected override string SubmitText => this.submitText;
|
||||
protected override Func<Task> SubmitAction => this.Submit;
|
||||
|
||||
/// <remarks>
|
||||
/// A plugin that names its tools has decided for the user: its author wrote and tested the
|
||||
/// assistant with exactly these. Null keeps the footer selection for every other plugin.
|
||||
/// </remarks>
|
||||
protected override IReadOnlySet<string>? AssistantManagedToolIds => this.assistantToolIds;
|
||||
|
||||
protected override bool SubmitDisabled => this.isSecurityBlocked;
|
||||
// Dynamic assistants do not have dedicated settings yet. Their internal identity keeps their
|
||||
// session and media state separate while ComponentsExtensions derives their defaults from chat.
|
||||
@@ -50,6 +58,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
private bool allowProfiles = true;
|
||||
private string submitText = string.Empty;
|
||||
private bool showFooterProfileSelection = true;
|
||||
private HashSet<string>? assistantToolIds;
|
||||
private PluginAssistants? assistantPlugin;
|
||||
|
||||
private readonly AssistantState assistantState = new();
|
||||
@@ -69,6 +78,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
private static readonly AssistantSessionStateKey<bool> ALLOW_PROFILES_STATE_KEY = new(nameof(allowProfiles));
|
||||
private static readonly AssistantSessionStateKey<string> SUBMIT_TEXT_STATE_KEY = new(nameof(submitText));
|
||||
private static readonly AssistantSessionStateKey<bool> SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY = new(nameof(showFooterProfileSelection));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>?> ASSISTANT_TOOL_IDS_STATE_KEY = new(nameof(assistantToolIds));
|
||||
private static readonly AssistantSessionStateKey<PluginAssistants?> ASSISTANT_PLUGIN_STATE_KEY = new(nameof(assistantPlugin));
|
||||
private static readonly AssistantSessionStateKey<AssistantState> ASSISTANT_STATE_STATE_KEY = new(nameof(assistantState));
|
||||
private static readonly AssistantSessionStateKey<Dictionary<string, string>> IMAGE_CACHE_STATE_KEY = new(nameof(imageCache));
|
||||
@@ -90,6 +100,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
state.Set(ALLOW_PROFILES_STATE_KEY, this.allowProfiles);
|
||||
state.Set(SUBMIT_TEXT_STATE_KEY, this.submitText);
|
||||
state.Set(SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY, this.showFooterProfileSelection);
|
||||
state.Set(ASSISTANT_TOOL_IDS_STATE_KEY, this.assistantToolIds);
|
||||
state.Set(ASSISTANT_PLUGIN_STATE_KEY, this.assistantPlugin);
|
||||
state.Set(ASSISTANT_STATE_STATE_KEY, this.assistantState.Clone());
|
||||
state.SetDictionary(IMAGE_CACHE_STATE_KEY, this.imageCache);
|
||||
@@ -110,6 +121,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
state.Restore(ALLOW_PROFILES_STATE_KEY, value => this.allowProfiles = value);
|
||||
state.Restore(SUBMIT_TEXT_STATE_KEY, value => this.submitText = value);
|
||||
state.Restore(SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY, value => this.showFooterProfileSelection = value);
|
||||
state.Restore(ASSISTANT_TOOL_IDS_STATE_KEY, value => this.assistantToolIds = value);
|
||||
state.Restore(ASSISTANT_PLUGIN_STATE_KEY, value => this.assistantPlugin = value);
|
||||
state.Restore(ASSISTANT_STATE_STATE_KEY, value => this.assistantState.CopyFrom(value));
|
||||
state.RestoreDictionary(IMAGE_CACHE_STATE_KEY, this.imageCache);
|
||||
@@ -159,6 +171,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
this.systemPrompt = pluginAssistant.SystemPrompt;
|
||||
this.submitText = pluginAssistant.SubmitText;
|
||||
this.allowProfiles = pluginAssistant.AllowProfiles;
|
||||
this.assistantToolIds = ReadPluginToolIds(pluginAssistant);
|
||||
this.showFooterProfileSelection = !pluginAssistant.HasEmbeddedProfileSelection;
|
||||
this.pluginPath = pluginAssistant.PluginPath;
|
||||
var pluginHash = pluginAssistant.ComputeAuditHash();
|
||||
@@ -353,6 +366,7 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
this.systemPrompt = updatedPlugin.SystemPrompt;
|
||||
this.submitText = updatedPlugin.SubmitText;
|
||||
this.allowProfiles = updatedPlugin.AllowProfiles;
|
||||
this.assistantToolIds = ReadPluginToolIds(updatedPlugin);
|
||||
this.showFooterProfileSelection = !updatedPlugin.HasEmbeddedProfileSelection;
|
||||
this.pluginPath = updatedPlugin.PluginPath;
|
||||
var pluginHash = updatedPlugin.ComputeAuditHash();
|
||||
@@ -369,6 +383,16 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Reads the tools this plugin names for its assistant.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An ID this installation does not know stays in the set on purpose: the tool may arrive with
|
||||
/// a plugin installed later, and dropping it here would silently turn a plugin that names tools
|
||||
/// into one that lets the user choose.
|
||||
/// </remarks>
|
||||
private static HashSet<string>? ReadPluginToolIds(PluginAssistants plugin) => plugin.AssistantToolIds is { } toolIds ? ToolSelectionRules.NormalizeSelection(toolIds) : null;
|
||||
|
||||
private string ResolveImageSource(AssistantImage image)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(image.Src))
|
||||
|
||||
Reference in new issue
Block a user