Added embedding information

This commit is contained in:
Thorsten Sommer 2024-12-25 22:50:04 +01:00
parent 07df50bbb7
commit 75b11ff1a3
Signed by: tsommer
GPG Key ID: 371BBA77A02C0108
6 changed files with 373 additions and 0 deletions

View File

@ -146,6 +146,57 @@
}
</MudSelect>
<MudText Typo="Typo.h4" Class="mt-6 mb-3">
Embedding settings
</MudText>
<MudText Typo="Typo.body1" Class="mb-2">
You will likely use one or more embedding methods to encode the meaning of your data into a typically high-dimensional vector
space. In this case, you will use a vector database to store and search these vectors (called embeddings). However, you don't
have to use embedding methods. When your retrieval method works without any embedding, you can ignore this section. An example: You
store files on a file server, and your retrieval method works exclusively with file names in the file system, so you don't
need embeddings.
</MudText>
<MudText Typo="Typo.body1" Class="mb-3">
You can specify more than one embedding method. This can be useful when you want to use different embeddings for different queries
or data types. For example, one embedding for texts, another for images, and a third for videos, etc.
</MudText>
<MudTable Items="@this.embeddings" Hover="@true" Class="border-dashed border rounded-lg">
<ColGroup>
<col/>
<col style="width: 34em;"/>
<col style="width: 34em;"/>
</ColGroup>
<HeaderContent>
<MudTh>Name</MudTh>
<MudTh>Type</MudTh>
<MudTh Style="text-align: left;">Actions</MudTh>
</HeaderContent>
<RowTemplate>
<MudTd>@context.EmbeddingName</MudTd>
<MudTd>@context.EmbeddingType</MudTd>
<MudTd Style="text-align: left;">
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditEmbedding(context)">
Edit
</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteEmbedding(context)">
Delete
</MudButton>
</MudTd>
</RowTemplate>
</MudTable>
@if(this.embeddings.Count == 0)
{
<MudText Typo="Typo.h6" Class="mt-3">No embeddings configured yet.</MudText>
}
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddEmbedding">
Add Embedding
</MudButton>
<MudText Typo="Typo.h4" Class="mt-6 mb-1">
Data retrieval settings
</MudText>

View File

@ -1,7 +1,10 @@
using AIStudio.Chat;
using AIStudio.Dialogs;
using Microsoft.AspNetCore.Components;
using DialogOptions = AIStudio.Dialogs.DialogOptions;
namespace AIStudio.Assistants.ERI;
public partial class AssistantERI : AssistantBaseCore
@ -9,6 +12,9 @@ public partial class AssistantERI : AssistantBaseCore
[Inject]
private HttpClient HttpClient { get; set; } = null!;
[Inject]
private IDialogService DialogService { get; init; } = null!;
public override Tools.Components Component => Tools.Components.ERI_ASSISTANT;
protected override string Title => "ERI Server";
@ -56,6 +62,7 @@ public partial class AssistantERI : AssistantBaseCore
this.authDescription = string.Empty;
this.selectedOperatingSystem = OperatingSystem.NONE;
this.allowedLLMProviders = AllowedLLMProviders.NONE;
this.embeddings = new();
this.retrievalDescription = string.Empty;
this.additionalLibraries = string.Empty;
}
@ -83,6 +90,7 @@ public partial class AssistantERI : AssistantBaseCore
this.authDescription = this.SettingsManager.ConfigurationData.ERI.PreselectedAuthDescription;
this.selectedOperatingSystem = this.SettingsManager.ConfigurationData.ERI.PreselectedOperatingSystem;
this.allowedLLMProviders = this.SettingsManager.ConfigurationData.ERI.PreselectedAllowedLLMProviders;
this.embeddings = this.SettingsManager.ConfigurationData.ERI.EmbeddingInfos;
this.retrievalDescription = this.SettingsManager.ConfigurationData.ERI.PreselectedRetrievalDescription;
this.additionalLibraries = this.SettingsManager.ConfigurationData.ERI.PreselectedAdditionalLibraries;
return true;
@ -115,6 +123,7 @@ public partial class AssistantERI : AssistantBaseCore
this.SettingsManager.ConfigurationData.ERI.PreselectedAuthDescription = this.authDescription;
this.SettingsManager.ConfigurationData.ERI.PreselectedOperatingSystem = this.selectedOperatingSystem;
this.SettingsManager.ConfigurationData.ERI.PreselectedAllowedLLMProviders = this.allowedLLMProviders;
this.SettingsManager.ConfigurationData.ERI.EmbeddingInfos = this.embeddings;
this.SettingsManager.ConfigurationData.ERI.PreselectedRetrievalDescription = this.retrievalDescription;
this.SettingsManager.ConfigurationData.ERI.PreselectedAdditionalLibraries = this.additionalLibraries;
await this.SettingsManager.StoreSettings();
@ -135,6 +144,7 @@ public partial class AssistantERI : AssistantBaseCore
private string authDescription = string.Empty;
private OperatingSystem selectedOperatingSystem = OperatingSystem.NONE;
private AllowedLLMProviders allowedLLMProviders = AllowedLLMProviders.NONE;
private List<EmbeddingInfo> embeddings = new();
private string retrievalDescription = string.Empty;
private string additionalLibraries = string.Empty;
@ -389,6 +399,62 @@ public partial class AssistantERI : AssistantBaseCore
return true;
}
}
private async Task AddEmbedding()
{
var dialogParameters = new DialogParameters<EmbeddingMethodDialog>
{
{ x => x.IsEditing, false },
};
var dialogReference = await this.DialogService.ShowAsync<EmbeddingMethodDialog>("Add Embedding", dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
var addedEmbedding = (EmbeddingInfo)dialogResult.Data!;
this.embeddings.Add(addedEmbedding);
await this.AutoSave();
}
private async Task EditEmbedding(EmbeddingInfo embeddingInfo)
{
var dialogParameters = new DialogParameters<EmbeddingMethodDialog>
{
{ x => x.DataEmbeddingName, embeddingInfo.EmbeddingName },
{ x => x.DataEmbeddingType, embeddingInfo.EmbeddingType },
{ x => x.DataDescription, embeddingInfo.Description },
{ x => x.DataUsedWhen, embeddingInfo.UsedWhen },
{ x => x.DataLink, embeddingInfo.Link },
{ x => x.IsEditing, true },
};
var dialogReference = await this.DialogService.ShowAsync<EmbeddingMethodDialog>("Edit Embedding", dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
var editedEmbedding = (EmbeddingInfo)dialogResult.Data!;
this.embeddings[this.embeddings.IndexOf(embeddingInfo)] = editedEmbedding;
await this.AutoSave();
}
private async Task DeleteEmbedding(EmbeddingInfo embeddingInfo)
{
var dialogParameters = new DialogParameters
{
{ "Message", $"Are you sure you want to delete the embedding '{embeddingInfo.EmbeddingName}'?" },
};
var dialogReference = await this.DialogService.ShowAsync<ConfirmDialog>("Delete Embedding", dialogParameters, DialogOptions.FULLSCREEN);
var dialogResult = await dialogReference.Result;
if (dialogResult is null || dialogResult.Canceled)
return;
this.embeddings.Remove(embeddingInfo);
await this.AutoSave();
}
private async Task GenerateServer()
{

View File

@ -0,0 +1,19 @@
namespace AIStudio.Assistants.ERI;
/// <summary>
/// Represents information about the used embedding for a data source.
/// </summary>
/// <param name="EmbeddingType">What kind of embedding is used. For example, "Transformer Embedding," "Contextual Word
/// Embedding," "Graph Embedding," etc.</param>
/// <param name="EmbeddingName">Name the embedding used. This can be a library, a framework, or the name of the used
/// algorithm.</param>
/// <param name="Description">A short description of the embedding. Describe what the embedding is doing.</param>
/// <param name="UsedWhen">Describe when the embedding is used. For example, when the user prompt contains certain
/// keywords, or anytime?</param>
/// <param name="Link">A link to the embedding's documentation or the source code. Might be null.</param>
public readonly record struct EmbeddingInfo(
string EmbeddingType,
string EmbeddingName,
string Description,
string UsedWhen,
string? Link);

View File

@ -0,0 +1,103 @@
<MudDialog>
<DialogContent>
<MudForm @ref="@this.form" @bind-IsValid="@this.dataIsValid" @bind-Errors="@this.dataIssues">
@* ReSharper disable once CSharpWarnings::CS8974 *@
<MudTextField
T="string"
@bind-Text="@this.DataEmbeddingName"
Label="Embedding Name"
HelperText="The name of the embedding method."
Class="mb-3"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Label"
AdornmentColor="Color.Info"
Validation="@this.ValidateName"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
/>
@* ReSharper disable once CSharpWarnings::CS8974 *@
<MudTextField
T="string"
@bind-Text="@this.DataEmbeddingType"
Label="Embedding Type"
HelperText="What kind of embedding is used. For example, Transformer Embedding, Contextual Word Embedding, Graph Embedding, etc."
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Extension"
AdornmentColor="Color.Info"
Validation="@this.ValidateType"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
/>
<MudList T="@string" Class="mb-3">
<MudListItem Icon="@Icons.Material.Filled.Link" Href="https://en.wikipedia.org/wiki/Word_embedding" Target="_blank" Text="See Wikipedia for more information about word embeddings"/>
<MudListItem Icon="@Icons.Material.Filled.Link" Href="https://en.wikipedia.org/wiki/Knowledge_graph_embedding" Target="_blank" Text="See Wikipedia for more information about knowledge graph embeddings"/>
</MudList>
@* ReSharper disable once CSharpWarnings::CS8974 *@
<MudTextField
T="string"
@bind-Text="@this.DataDescription"
Label="Embedding Description"
HelperText="A short description of the embedding method."
Lines="3"
AutoGrow="@true"
MaxLines="6"
Immediate="@true"
Variant="Variant.Outlined"
Class="mb-3"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Extension"
AdornmentColor="Color.Info"
Validation="@this.ValidateDescription"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
/>
@* ReSharper disable once CSharpWarnings::CS8974 *@
<MudTextField
T="string"
@bind-Text="@this.DataUsedWhen"
Label="Used when"
HelperText="When is this embedding used? When you define multiple embeddings, it is helpful to know when to use which one."
Lines="3"
AutoGrow="@true"
MaxLines="6"
Immediate="@true"
Variant="Variant.Outlined"
Class="mb-3"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Assessment"
AdornmentColor="Color.Info"
Validation="@this.ValidateUsedWhen"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
/>
@* ReSharper disable once CSharpWarnings::CS8974 *@
<MudTextField
T="string"
@bind-Text="@this.DataLink"
Label="Embedding Link"
HelperText="A link to the embedding, e.g., to the model, the source code, the paper, it's Wikipedia page, etc."
Class="mb-3"
Adornment="Adornment.Start"
AdornmentIcon="@Icons.Material.Filled.Link"
AdornmentColor="Color.Info"
UserAttributes="@SPELLCHECK_ATTRIBUTES"
/>
</MudForm>
<Issues IssuesData="@this.dataIssues"/>
</DialogContent>
<DialogActions>
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">Cancel</MudButton>
<MudButton OnClick="@this.Store" Variant="Variant.Filled" Color="Color.Primary">
@if(this.IsEditing)
{
@:Update
}
else
{
@:Add
}
</MudButton>
</DialogActions>
</MudDialog>

View File

@ -0,0 +1,129 @@
using AIStudio.Assistants.ERI;
using AIStudio.Settings;
using Microsoft.AspNetCore.Components;
namespace AIStudio.Dialogs;
public partial class EmbeddingMethodDialog : ComponentBase
{
[CascadingParameter]
private MudDialogInstance MudDialog { get; set; } = null!;
/// <summary>
/// The user chosen embedding name.
/// </summary>
[Parameter]
public string DataEmbeddingName { get; set; } = string.Empty;
/// <summary>
/// The user chosen embedding type.
/// </summary>
[Parameter]
public string DataEmbeddingType { get; set; } = string.Empty;
/// <summary>
/// The embedding description.
/// </summary>
[Parameter]
public string DataDescription { get; set; } = string.Empty;
/// <summary>
/// When is the embedding used?
/// </summary>
[Parameter]
public string DataUsedWhen { get; set; } = string.Empty;
/// <summary>
/// A link to the embedding documentation or the source code. Might be null, which means no link is provided.
/// </summary>
[Parameter]
public string? DataLink { get; set; }
/// <summary>
/// Should the dialog be in editing mode?
/// </summary>
[Parameter]
public bool IsEditing { get; init; }
[Inject]
private SettingsManager SettingsManager { get; init; } = null!;
private static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
private bool dataIsValid;
private string[] dataIssues = [];
// We get the form reference from Blazor code to validate it manually:
private MudForm form = null!;
private EmbeddingInfo CreateEmbeddingInfo() => new(this.DataEmbeddingType, this.DataEmbeddingName, this.DataDescription, this.DataUsedWhen, this.DataLink);
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
// Configure the spellchecking for the instance name input:
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
await base.OnInitializedAsync();
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
// Reset the validation when not editing and on the first render.
// We don't want to show validation errors when the user opens the dialog.
if(!this.IsEditing && firstRender)
this.form.ResetValidation();
await base.OnAfterRenderAsync(firstRender);
}
#endregion
private string? ValidateName(string name)
{
if (string.IsNullOrWhiteSpace(name))
return "The embedding name must not be empty. Please name the embedding.";
return null;
}
private string? ValidateType(string type)
{
if (string.IsNullOrWhiteSpace(type))
return "The embedding type must not be empty. Please specify the embedding type.";
return null;
}
private string? ValidateDescription(string description)
{
if (string.IsNullOrWhiteSpace(description))
return "The description must not be empty. Please describe the embedding method.";
return null;
}
private string? ValidateUsedWhen(string usedWhen)
{
if (string.IsNullOrWhiteSpace(usedWhen))
return "Please describe when the embedding is used. Might be anytime or when certain keywords are present, etc.";
return null;
}
private async Task Store()
{
await this.form.Validate();
// When the data is not valid, we don't store it:
if (!this.dataIsValid)
return;
var embeddingInfo = this.CreateEmbeddingInfo();
this.MudDialog.Close(DialogResult.Ok(embeddingInfo));
}
private void Cancel() => this.MudDialog.Cancel();
}

View File

@ -87,6 +87,11 @@ public sealed class DataERI
/// </summary>
public AllowedLLMProviders PreselectedAllowedLLMProviders { get; set; } = AllowedLLMProviders.NONE;
/// <summary>
/// Do you want to predefine any embedding information?
/// </summary>
public List<EmbeddingInfo> EmbeddingInfos { get; set; } = new();
/// <summary>
/// Do you want to preselect a retrieval description?
/// </summary>