Skip to content

Integrate data sources into any chat #282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
7587775
Prepared changelog
SommerEngineering Feb 10, 2025
a7efd75
Updated README.md
SommerEngineering Feb 10, 2025
7642bfa
Renamed PopoverTriggerMode
SommerEngineering Feb 10, 2025
a695e3c
Allow TextInfoLines to color its content
SommerEngineering Feb 10, 2025
ea671a1
Add support for customizable right margin in the ProfileSelection com…
SommerEngineering Feb 10, 2025
e85a75a
Added an option to all data sources to select a local security policy
SommerEngineering Feb 10, 2025
01e8b09
Fixed data source editing; the security policy was not loaded
SommerEngineering Feb 10, 2025
32819d3
Added a program logger
SommerEngineering Feb 11, 2025
57af208
Added a handler for unobserved task exceptions
SommerEngineering Feb 11, 2025
1900cd2
Added exception handling
SommerEngineering Feb 11, 2025
129484e
Improved confidence card for small spaces
SommerEngineering Feb 11, 2025
9e965b3
Refactored UpdateService to relocate StopAsync method for improved co…
SommerEngineering Feb 12, 2025
feb7e9e
Added documentation
SommerEngineering Feb 12, 2025
03ac9af
Moved Rust service into the service namespace
SommerEngineering Feb 13, 2025
e78e74f
Added a data source service
SommerEngineering Feb 13, 2025
b10a397
Added documentation
SommerEngineering Feb 14, 2025
947b1f2
Added handling for default providers
SommerEngineering Feb 14, 2025
05e1c66
Refactored data service to handle different provider types
SommerEngineering Feb 14, 2025
63113ca
Integrate data sources per chat thread & store them with the chat
SommerEngineering Feb 14, 2025
5ee7f2f
Propagate the data service to the common mid-level AI generation code…
SommerEngineering Feb 14, 2025
762b4ba
Implemented the final data source filter step just before eventually …
SommerEngineering Feb 14, 2025
a999f47
Fixed naming
SommerEngineering Feb 15, 2025
3567a42
Added documentation
SommerEngineering Feb 15, 2025
96b6148
Removed data source flag (was moved inside the data options)
SommerEngineering Feb 15, 2025
3414286
Added an option to preselect data sources and options for new chats
SommerEngineering Feb 15, 2025
f95348e
Added a data source selection component
SommerEngineering Feb 15, 2025
9fdc78a
Integrate the data source selection into the chat component
SommerEngineering Feb 15, 2025
c6ab1b1
Check if data sources are enabled
SommerEngineering Feb 15, 2025
45cf77c
Fixed an issue when typing the next prompt & data source options wher…
SommerEngineering Feb 15, 2025
c135568
Fixed a bug when loading an old chat first & the data selection compo…
SommerEngineering Feb 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ Things we are currently working on:
- [ ] App: Implement the continuous process of vectorizing data
- [x] ~~App: Define a common retrieval context interface for the integration of RAG processes in chats (PR [#281](https://github.com/MindWorkAI/AI-Studio/pull/281))~~
- [ ] App: Define a common augmentation interface for the integration of RAG processes in chats
- [ ] App: Integrate data sources in chats
- [x] ~~App: Integrate data sources in chats (PR [#282](https://github.com/MindWorkAI/AI-Studio/pull/282))~~


- Since September 2024: Experiments have been started on how we can work on long texts with AI Studio. Let's say you want to write a fantasy novel or create a complex project proposal and use LLM for support. The initial experiments were promising, but not yet satisfactory. We are testing further approaches until a satisfactory solution is found. The current state of our experiment is available as an experimental preview feature through your app configuration. Related PR: ~~[#167](https://github.com/MindWorkAI/AI-Studio/pull/167), [#226](https://github.com/MindWorkAI/AI-Studio/pull/226)~~.
Expand Down
7 changes: 5 additions & 2 deletions app/MindWork AI Studio/Agents/AgentBase.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using AIStudio.Chat;
using AIStudio.Provider;
using AIStudio.Settings;
using AIStudio.Tools.Services;

// ReSharper disable MemberCanBePrivate.Global

namespace AIStudio.Agents;

public abstract class AgentBase(ILogger<AgentBase> logger, SettingsManager settingsManager, ThreadSafeRandom rng) : IAgent
public abstract class AgentBase(ILogger<AgentBase> logger, SettingsManager settingsManager, DataSourceService dataSourceService, ThreadSafeRandom rng) : IAgent
{
protected DataSourceService DataSourceService { get; init; } = dataSourceService;

protected SettingsManager SettingsManager { get; init; } = settingsManager;

protected ThreadSafeRandom RNG { get; init; } = rng;
Expand Down Expand Up @@ -107,6 +110,6 @@ protected async Task AddAIResponseAsync(ChatThread thread, DateTimeOffset time)
// Use the selected provider to get the AI response.
// By awaiting this line, we wait for the entire
// content to be streamed.
await aiText.CreateFromProviderAsync(providerSettings.CreateProvider(this.Logger), this.SettingsManager, providerSettings.Model, this.lastUserPrompt, thread);
await aiText.CreateFromProviderAsync(providerSettings.CreateProvider(this.Logger), this.SettingsManager, this.DataSourceService, providerSettings.Model, this.lastUserPrompt, thread);
}
}
3 changes: 2 additions & 1 deletion app/MindWork AI Studio/Agents/AgentTextContentCleaner.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using AIStudio.Chat;
using AIStudio.Settings;
using AIStudio.Tools.Services;

namespace AIStudio.Agents;

public sealed class AgentTextContentCleaner(ILogger<AgentBase> logger, SettingsManager settingsManager, ThreadSafeRandom rng) : AgentBase(logger, settingsManager, rng)
public sealed class AgentTextContentCleaner(ILogger<AgentBase> logger, SettingsManager settingsManager, DataSourceService dataSourceService, ThreadSafeRandom rng) : AgentBase(logger, settingsManager, dataSourceService, rng)
{
private static readonly ContentBlock EMPTY_BLOCK = new()
{
Expand Down
2 changes: 1 addition & 1 deletion app/MindWork AI Studio/Assistants/AssistantBase.razor
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@

@if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)
{
<ConfidenceInfo Mode="ConfidenceInfoMode.BUTTON" LLMProvider="@this.providerSettings.UsedLLMProvider"/>
<ConfidenceInfo Mode="PopoverTriggerMode.BUTTON" LLMProvider="@this.providerSettings.UsedLLMProvider"/>
}

@if (this.AllowProfiles && this.ShowProfileSelection)
Expand Down
7 changes: 5 additions & 2 deletions app/MindWork AI Studio/Assistants/AssistantBase.razor.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using AIStudio.Chat;
using AIStudio.Provider;
using AIStudio.Settings;
using AIStudio.Tools.Services;

using Microsoft.AspNetCore.Components;

using MudBlazor.Utilities;

using RustService = AIStudio.Tools.RustService;
using Timer = System.Timers.Timer;

namespace AIStudio.Assistants;
Expand All @@ -28,6 +28,9 @@ public abstract partial class AssistantBase : ComponentBase, IMessageBusReceiver
[Inject]
protected RustService RustService { get; init; } = null!;

[Inject]
protected DataSourceService DataSourceService { get; init; } = null!;

[Inject]
protected NavigationManager NavigationManager { get; init; } = null!;

Expand Down Expand Up @@ -290,7 +293,7 @@ protected async Task<string> AddAIResponseAsync(DateTimeOffset time, bool hideCo
// Use the selected provider to get the AI response.
// By awaiting this line, we wait for the entire
// content to be streamed.
await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.SettingsManager, this.providerSettings.Model, this.lastUserPrompt, this.chatThread);
await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(this.Logger), this.SettingsManager, this.DataSourceService, this.providerSettings.Model, this.lastUserPrompt, this.chatThread);

this.isProcessing = false;
this.StateHasChanged();
Expand Down
6 changes: 6 additions & 0 deletions app/MindWork AI Studio/Chat/ChatThread.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using AIStudio.Settings;
using AIStudio.Settings.DataModel;

namespace AIStudio.Chat;

Expand Down Expand Up @@ -27,6 +28,11 @@ public sealed record ChatThread
/// </summary>
public string SelectedProfile { get; set; } = string.Empty;

/// <summary>
/// The data source options for this chat thread.
/// </summary>
public DataSourceOptions DataSourceOptions { get; set; } = new();

/// <summary>
/// The name of the chat thread. Usually generated by an AI model or manually edited by the user.
/// </summary>
Expand Down
3 changes: 1 addition & 2 deletions app/MindWork AI Studio/Chat/ContentBlockComponent.razor.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
using AIStudio.Settings;
using AIStudio.Tools.Services;

using Microsoft.AspNetCore.Components;

using RustService = AIStudio.Tools.RustService;

namespace AIStudio.Chat;

/// <summary>
Expand Down
3 changes: 2 additions & 1 deletion app/MindWork AI Studio/Chat/ContentImage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using AIStudio.Provider;
using AIStudio.Settings;
using AIStudio.Tools.Services;

namespace AIStudio.Chat;

Expand Down Expand Up @@ -29,7 +30,7 @@ public sealed class ContentImage : IContent
public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask;

/// <inheritdoc />
public Task CreateFromProviderAsync(IProvider provider, SettingsManager settings, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default)
public Task CreateFromProviderAsync(IProvider provider, SettingsManager settings, DataSourceService dataSourceService, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default)
{
throw new NotImplementedException();
}
Expand Down
41 changes: 31 additions & 10 deletions app/MindWork AI Studio/Chat/ContentText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using AIStudio.Provider;
using AIStudio.Settings;
using AIStudio.Tools.Services;

namespace AIStudio.Chat;

Expand Down Expand Up @@ -35,23 +36,43 @@ public sealed class ContentText : IContent
public Func<Task> StreamingEvent { get; set; } = () => Task.CompletedTask;

/// <inheritdoc />
public async Task CreateFromProviderAsync(IProvider provider, SettingsManager settings, Model chatModel, IContent? lastPrompt, ChatThread? chatThread, CancellationToken token = default)
public async Task CreateFromProviderAsync(IProvider provider, SettingsManager settings, DataSourceService dataSourceService, Model chatModel, IContent? lastPrompt, ChatThread? chatThread, CancellationToken token = default)
{
if(chatThread is null)
return;

//
// Check if the user wants to bind any data sources to the chat:
//

//
// Trigger the retrieval part of the (R)AG process:
//

//
// Perform the augmentation of the R(A)G process:
//

if (chatThread.DataSourceOptions.IsEnabled())
{
//
// When the user wants to bind data sources to the chat, we
// have to check if the data sources are available for the
// selected provider. Also, we have to check if any ERI
// data sources changed its security requirements.
//
List<IDataSource> preselectedDataSources = chatThread.DataSourceOptions.PreselectedDataSourceIds.Select(id => settings.ConfigurationData.DataSources.FirstOrDefault(ds => ds.Id == id)).Where(ds => ds is not null).ToList()!;
var dataSources = await dataSourceService.GetDataSources(provider, preselectedDataSources);
var selectedDataSources = dataSources.SelectedDataSources;

//
// Should the AI select the data sources?
//
if (chatThread.DataSourceOptions.AutomaticDataSourceSelection)
{
// TODO: Start agent based on allowed data sources.
}

//
// Trigger the retrieval part of the (R)AG process:
//

//
// Perform the augmentation of the R(A)G process:
//
}

// Store the last time we got a response. We use this later
// to determine whether we should notify the UI about the
// new content or not. Depends on the energy saving mode
Expand Down
3 changes: 2 additions & 1 deletion app/MindWork AI Studio/Chat/IContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using AIStudio.Provider;
using AIStudio.Settings;
using AIStudio.Tools.Services;

namespace AIStudio.Chat;

Expand Down Expand Up @@ -42,5 +43,5 @@ public interface IContent
/// <summary>
/// Uses the provider to create the content.
/// </summary>
public Task CreateFromProviderAsync(IProvider provider, SettingsManager settings, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default);
public Task CreateFromProviderAsync(IProvider provider, SettingsManager settings, DataSourceService dataSourceService, Model chatModel, IContent? lastPrompt, ChatThread? chatChatThread, CancellationToken token = default);
}
7 changes: 6 additions & 1 deletion app/MindWork AI Studio/Components/ChatComponent.razor
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@

@if (this.SettingsManager.ConfigurationData.LLMProviders.ShowProviderConfidence)
{
<ConfidenceInfo Mode="ConfidenceInfoMode.ICON" LLMProvider="@this.Provider.UsedLLMProvider"/>
<ConfidenceInfo Mode="PopoverTriggerMode.ICON" LLMProvider="@this.Provider.UsedLLMProvider"/>
}

@if (this.isStreaming && this.cancellationTokenSource is not null)
Expand All @@ -108,6 +108,11 @@
}

<ProfileSelection CurrentProfile="@this.currentProfile" CurrentProfileChanged="@this.ProfileWasChanged"/>

@if (PreviewFeatures.PRE_RAG_2024.IsEnabled(this.SettingsManager))
{
<DataSourceSelection @ref="@this.dataSourceSelectionComponent" PopoverTriggerMode="PopoverTriggerMode.BUTTON" PopoverButtonClasses="ma-3" LLMProvider="@this.Provider" DataSourceOptions="@this.GetCurrentDataSourceOptions()" DataSourceOptionsChanged="@(async options => await this.SetCurrentDataSourceOptions(options))"/>
}
</MudToolBar>
</FooterContent>
</InnerScrolling>
Loading