mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-09-27 00:53:37 +00:00
Let a configured chat template carry tools and data sources
This commit is contained in:
parent
c95cc5bacc
commit
6a2a8c4e9d
@ -1034,6 +1034,56 @@ CONFIG["CHAT_TEMPLATES"] = {}
|
||||
-- }
|
||||
-- }
|
||||
|
||||
-- An example chat template which preselects tools and data sources:
|
||||
-- Both are optional and independent of each other. Leaving a field out is not the same as
|
||||
-- leaving it empty:
|
||||
--
|
||||
-- ToolIds omitted -> the chat starts with the tools set as its default
|
||||
-- ToolIds = {} -> the chat starts with no tools at all
|
||||
-- DataSourceOptions omitted -> the chat starts with the data source defaults
|
||||
-- DataSourceOptions = { ... } -> the chat starts with exactly what this table says
|
||||
--
|
||||
-- Both are a preselection, not a limit: users change either of them in the chat as usual.
|
||||
-- CONFIG["CHAT_TEMPLATES"][#CONFIG["CHAT_TEMPLATES"]+1] = {
|
||||
-- ["Id"] = "00000000-0000-0000-0000-000000000002",
|
||||
-- ["Name"] = "Intranet Research",
|
||||
-- ["SystemPrompt"] = "You are <Company Name>'s research assistant. Answer from our own documents and say where each answer comes from.",
|
||||
-- ["AllowProfileUsage"] = true,
|
||||
--
|
||||
-- -- Optional: the tools a chat with this template starts with, by tool ID.
|
||||
-- -- A tool ID unknown to the installation is ignored, and so is a tool your
|
||||
-- -- organization switched off. A tool has to meet the confidence requirements of the
|
||||
-- -- provider in use, so it may stay unavailable even though this template names it.
|
||||
-- -- Tool IDs include: web_search, read_web_page
|
||||
-- ["ToolIds"] = {
|
||||
-- "read_web_page",
|
||||
-- },
|
||||
--
|
||||
-- -- Optional: the data source options a chat with this template starts with.
|
||||
-- -- Every field inside is optional as well. DisableDataSources defaults to false here,
|
||||
-- -- because writing this table at all says that the template wants data sources; the
|
||||
-- -- other three default to false and an empty list.
|
||||
-- ["DataSourceOptions"] = {
|
||||
-- -- Set to true to start the chat with data sources switched off.
|
||||
-- ["DisableDataSources"] = false,
|
||||
--
|
||||
-- -- Let an agent choose the fitting data sources for each question. When true,
|
||||
-- -- PreselectedDataSourceIds is not used.
|
||||
-- ["AutomaticDataSourceSelection"] = false,
|
||||
--
|
||||
-- -- Let an agent check whether the retrieved data fits the question.
|
||||
-- ["AutomaticValidation"] = true,
|
||||
--
|
||||
-- -- Must contain IDs from CONFIG["DATA_SOURCES"] or user-configured data sources.
|
||||
-- -- IDs from another configuration of your organization work as well: they are
|
||||
-- -- resolved against every known data source, not only against the ones defined
|
||||
-- -- here. IDs that resolve to nothing are ignored.
|
||||
-- ["PreselectedDataSourceIds"] = {
|
||||
-- "00000000-0000-0000-0000-000000000000",
|
||||
-- },
|
||||
-- },
|
||||
-- }
|
||||
|
||||
-- Introduction texts shown as expansion panels on the welcome page:
|
||||
CONFIG["INTRODUCTIONS"] = {}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
|
||||
using SharedTools;
|
||||
@ -26,6 +27,29 @@ public record ChatTemplate(
|
||||
public ChatTemplate() : this(0, Guid.Empty.ToString(), string.Empty, string.Empty, string.Empty, [], [], false)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The tools this template preselects for a chat started with it.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Null means the template says nothing about tools, so the chat starts with the tools chosen
|
||||
/// as its default in the app settings. An empty set is the opposite statement: this template
|
||||
/// wants no tools at all, whatever that default says.<br/><br/>
|
||||
/// A preselection, not a limit: the user changes the selection in the chat as usual, and a
|
||||
/// tool still has to meet the confidence requirements of the provider in use.
|
||||
/// </remarks>
|
||||
public HashSet<string>? ToolIds { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// The data source options a chat started with this template begins with.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Null means the template says nothing, so the chat starts with the data source defaults from
|
||||
/// the app settings. Anything else is the template's own answer, and it carries more than a
|
||||
/// list of sources: whether data sources are used at all, whether an agent picks them, and
|
||||
/// whether the retrieved data is validated.
|
||||
/// </remarks>
|
||||
public DataSourceOptions? DataSourceOptions { get; init; }
|
||||
|
||||
private static string TB(string fallbackEN) => I18N.I.T(fallbackEN, typeof(ChatTemplate).Namespace, nameof(ChatTemplate));
|
||||
|
||||
@ -41,6 +65,8 @@ public record ChatTemplate(
|
||||
ExampleConversation = [],
|
||||
FileAttachments = [],
|
||||
AllowProfileUsage = true,
|
||||
ToolIds = null,
|
||||
DataSourceOptions = null,
|
||||
EnterpriseConfigurationPluginId = Guid.Empty,
|
||||
IsEnterpriseConfiguration = false,
|
||||
};
|
||||
@ -121,6 +147,8 @@ public record ChatTemplate(
|
||||
ExampleConversation = ParseExampleConversation(idx, table),
|
||||
FileAttachments = fileAttachments,
|
||||
AllowProfileUsage = allowProfileUsage,
|
||||
ToolIds = ParseToolIds(idx, table),
|
||||
DataSourceOptions = ParseDataSourceOptions(idx, table),
|
||||
IsEnterpriseConfiguration = true,
|
||||
EnterpriseConfigurationPluginId = configPluginId,
|
||||
};
|
||||
@ -175,6 +203,89 @@ public record ChatTemplate(
|
||||
return exampleConversation;
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// A missing list and an empty one mean different things here, so an empty one must not fall
|
||||
/// back to null: the template then states that it wants no tools. The assistant plugins reject
|
||||
/// an empty list instead, because there it carries no meaning at all.
|
||||
/// </remarks>
|
||||
private static HashSet<string>? ParseToolIds(int idx, LuaTable table)
|
||||
{
|
||||
if (!table.TryGetValue("ToolIds", out var toolIdsValue) || !toolIdsValue.TryRead<LuaTable>(out var toolIdsTable))
|
||||
return null;
|
||||
|
||||
var toolIds = new HashSet<string>(StringComparer.Ordinal);
|
||||
var numToolIds = toolIdsTable.ArrayLength;
|
||||
for (var toolNum = 1; toolNum <= numToolIds; toolNum++)
|
||||
{
|
||||
if (!toolIdsTable[toolNum].TryRead<string>(out var toolId) || string.IsNullOrWhiteSpace(toolId))
|
||||
{
|
||||
LOGGER.LogWarning("The ToolIds entry {ToolNum} in chat template {IdxChatTemplate} is not a valid tool ID and will be ignored.", toolNum, idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
toolIds.Add(toolId.Trim());
|
||||
}
|
||||
|
||||
return toolIds;
|
||||
}
|
||||
|
||||
private static DataSourceOptions? ParseDataSourceOptions(int idx, LuaTable table)
|
||||
{
|
||||
if (!table.TryGetValue("DataSourceOptions", out var optionsValue) || !optionsValue.TryRead<LuaTable>(out var optionsTable))
|
||||
return null;
|
||||
|
||||
//
|
||||
// Writing this table at all is already the statement that the template wants data sources,
|
||||
// hence the switch starts enabled here. Everywhere else in the app, data sources start
|
||||
// switched off.
|
||||
//
|
||||
var disableDataSources = false;
|
||||
if (optionsTable.TryGetValue("DisableDataSources", out var disableValue) && disableValue.TryRead<bool>(out var disable))
|
||||
disableDataSources = disable;
|
||||
|
||||
var automaticSelection = false;
|
||||
if (optionsTable.TryGetValue("AutomaticDataSourceSelection", out var automaticSelectionValue) && automaticSelectionValue.TryRead<bool>(out var automaticSelectionFlag))
|
||||
automaticSelection = automaticSelectionFlag;
|
||||
|
||||
var automaticValidation = false;
|
||||
if (optionsTable.TryGetValue("AutomaticValidation", out var automaticValidationValue) && automaticValidationValue.TryRead<bool>(out var automaticValidationFlag))
|
||||
automaticValidation = automaticValidationFlag;
|
||||
|
||||
return new DataSourceOptions
|
||||
{
|
||||
DisableDataSources = disableDataSources,
|
||||
AutomaticDataSourceSelection = automaticSelection,
|
||||
AutomaticValidation = automaticValidation,
|
||||
PreselectedDataSourceIds = ParsePreselectedDataSourceIds(idx, optionsTable),
|
||||
};
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// The IDs stay strings instead of being parsed as GUIDs: a data source of another
|
||||
/// configuration may carry an ID which is none, and rejecting it here would make it
|
||||
/// unreferenceable for no gain.
|
||||
/// </remarks>
|
||||
private static List<string> ParsePreselectedDataSourceIds(int idx, LuaTable optionsTable)
|
||||
{
|
||||
var dataSourceIds = new List<string>();
|
||||
if (!optionsTable.TryGetValue("PreselectedDataSourceIds", out var idsValue) || !idsValue.TryRead<LuaTable>(out var idsTable))
|
||||
return dataSourceIds;
|
||||
|
||||
var numIds = idsTable.ArrayLength;
|
||||
for (var idNum = 1; idNum <= numIds; idNum++)
|
||||
{
|
||||
if (!idsTable[idNum].TryRead<string>(out var dataSourceId) || string.IsNullOrWhiteSpace(dataSourceId))
|
||||
{
|
||||
LOGGER.LogWarning("The PreselectedDataSourceIds entry {IdNum} in chat template {IdxChatTemplate} is not a valid data source ID and will be ignored.", idNum, idx);
|
||||
continue;
|
||||
}
|
||||
|
||||
dataSourceIds.Add(dataSourceId.Trim());
|
||||
}
|
||||
|
||||
return dataSourceIds;
|
||||
}
|
||||
|
||||
private static List<FileAttachment> ParseFileAttachments(int idx, LuaTable table, string pluginPath)
|
||||
{
|
||||
var fileAttachments = new List<FileAttachment>();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user