diff --git a/CS/DashboardAIAssistant.csproj b/CS/DashboardAIAssistant.csproj index 7f933ca..b90087f 100644 --- a/CS/DashboardAIAssistant.csproj +++ b/CS/DashboardAIAssistant.csproj @@ -22,8 +22,8 @@ - - + + diff --git a/CS/Services/AIAssistantCreator.cs b/CS/Services/AIAssistantCreator.cs index a426aa5..202cded 100644 --- a/CS/Services/AIAssistantCreator.cs +++ b/CS/Services/AIAssistantCreator.cs @@ -20,28 +20,24 @@ public AIAssistantCreator(OpenAIClient client, string deployment) { this.deployment = deployment; } - public async Task<(string assistantId, string threadId)> CreateAssistantAsync(Stream data, string fileName, string instructions, bool useFileSearchTool = true, CancellationToken ct = default) { + public async Task<(string assistantId, string threadId)> CreateAssistantAndThreadAsync(Stream data, string fileName, string instructions, CancellationToken ct = default) { data.Position = 0; ClientResult fileResponse = await fileClient.UploadFileAsync(data, fileName, FileUploadPurpose.Assistants, ct); OpenAIFile file = fileResponse.Value; var resources = new ToolResources() { - CodeInterpreter = new CodeInterpreterToolResources(), - FileSearch = useFileSearchTool ? new FileSearchToolResources() : null + CodeInterpreter = new CodeInterpreterToolResources() }; - resources.FileSearch?.NewVectorStores.Add(new VectorStoreCreationHelper([file.Id])); resources.CodeInterpreter.FileIds.Add(file.Id); AssistantCreationOptions assistantCreationOptions = new AssistantCreationOptions() { Name = Guid.NewGuid().ToString(), Instructions = instructions, - ToolResources = resources + ToolResources = resources, + Tools = { new CodeInterpreterToolDefinition() } }; - assistantCreationOptions.Tools.Add(new CodeInterpreterToolDefinition()); - if (useFileSearchTool) { - assistantCreationOptions.Tools.Add(new FileSearchToolDefinition()); - } + ClientResult assistantResponse = await assistantClient.CreateAssistantAsync(deployment, assistantCreationOptions, ct); ClientResult threadResponse = await assistantClient.CreateThreadAsync(cancellationToken: ct); diff --git a/CS/Services/AIAssistantProvider.cs b/CS/Services/AIAssistantProvider.cs index a0e84e4..bd126da 100644 --- a/CS/Services/AIAssistantProvider.cs +++ b/CS/Services/AIAssistantProvider.cs @@ -21,7 +21,7 @@ public async Task CreateAssistant(Stream fileContent, string prompt) { Guard.ArgumentIsNotNullOrEmpty(prompt, nameof(prompt)); string assistantName = Guid.NewGuid().ToString(); - (string assistantId, string threadId) = await assistantCreator.CreateAssistantAsync(fileContent, $"{assistantName}.xlsx", prompt, false); + (string assistantId, string threadId) = await assistantCreator.CreateAssistantAndThreadAsync(fileContent, $"{assistantName}.xlsx", prompt); IAIAssistant assistant = await assistantFactory.GetAssistant(assistantId, threadId); await assistant.InitializeAsync(); diff --git a/CS/Services/IAIAssistantProvider.cs b/CS/Services/IAIAssistantProvider.cs index 7e4d339..6625709 100644 --- a/CS/Services/IAIAssistantProvider.cs +++ b/CS/Services/IAIAssistantProvider.cs @@ -5,7 +5,7 @@ namespace DashboardAIAssistant.Services { public interface IAIAssistantProvider { Task CreateAssistant(Stream fileContent, string prompt); - IAIAssistant GetAssistant(string assistantId); - void DisposeAssistant(string assistantId); + IAIAssistant GetAssistant(string assistantName); + void DisposeAssistant(string assistantName); } } diff --git a/CS/wwwroot/js/aiChatCustomItem.js b/CS/wwwroot/js/aiChatCustomItem.js index 4734934..9148f3e 100644 --- a/CS/wwwroot/js/aiChatCustomItem.js +++ b/CS/wwwroot/js/aiChatCustomItem.js @@ -143,11 +143,16 @@ let AIChatCustomItem = (function() { }; normalizeAIResponse(text) { - text = text.replace(/【\d+:\d+†[^\】]+】/g, ""); - let html = marked.parse(text); - if (/

\.\s*<\/p>\s*$/.test(html)) - html = html.replace(/

\.\s*<\/p>\s*$/, "") - return html; + if (text) { + text = text.replace(/【\d+:\d+†[^\】]+】/g, ""); + let html = marked.parse(text); + if (/

\.\s*<\/p>\s*$/.test(html)) + html = html.replace(/

\.\s*<\/p>\s*$/, "") + return html; + } + else { + return "Please try again later." + } } renderAssistantMessage(instance, message) { diff --git a/README.md b/README.md index 334bbae..cbd5c0d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -![](https://img.shields.io/endpoint?url=https://codecentral.devexpress.com/api/v1/VersionRange/938296554/25.1.2%2B) [![](https://img.shields.io/badge/Open_in_DevExpress_Support_Center-FF7200?style=flat-square&logo=DevExpress&logoColor=white)](https://supportcenter.devexpress.com/ticket/details/T1279614) [![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183) [![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives) @@ -14,8 +13,14 @@ The AI Assistant reviews and analyzes all data displayed in the dashboard to ans **Please note that AI Assistant initialization takes time. The assistant is ready for interaction once Microsoft Azure scans the source document on the server side.** -> [!Important] -> We use version **9.4.3-preview.1.25230.7** of the _Microsoft.Extensions.AI.*_ libraries in our source code. We do not guarantee compatibility or correct operation with higher versions. +> [!Note] +> We use the following versions of the `Microsoft.Extensions.AI.*` libraries in our source code: +> +> - Microsoft.Extensions.AI.Abstractions: **9.5.0** +> - Microsoft.Extensions.AI: **9.5.0** +> - Microsoft.Extensions.AI.OpenAI: **9.5.0-preview.1.25265.7** +> +> We do not guarantee compatibility or correct operation with higher versions. ## Implementation Details @@ -81,13 +86,20 @@ public interface IAIAssistantProvider { } ``` -You can review and tailor AI assistant instructions in the following file: [AssistantHelper.cs](./CS/Services/AssistantHelper.cs) +The `AIAssistantCreator.CreateAssistantAndThreadAsync` method uploads a file to OpenAI, configures tool resources, creates an assistant with specified instructions and tools, initializes a new thread, and returns the assistant and thread IDs. The generated assistant and thread IDs are then passed to the `IAIAssistantFactory.GetAssistant` method, which returns an `IAIAssistant` instance. The created instance is added to the application's assistant collection and is referenced by its unique name. + +For information on OpenAI Assistants, refer to the following documents: +- [OpenAI Assistants API overview](https://platform.openai.com/docs/assistants/overview) +- [Azure OpenAI: OpenAI Assistants client library for .NET](https://learn.microsoft.com/en-us/dotnet/api/overview/azure/ai.openai.assistants-readme?view=azure-dotnet-preview) +- [OpenAI .NET API library](https://github.com/openai/openai-dotnet) + +You can review and tailor AI assistant instructions in the following file: [AssistantHelper.cs](./CS/Services/AssistantHelper.cs). Files to Review: -- [AIAssistantProvider.cs](./CS/Services/AIAssistantProvider.cs) - [IAIAssistantProvider.cs](./CS/Services/IAIAssistantProvider.cs) -- [AssistantHelper.cs](./CS/Services/AssistantHelper.cs) - +- [AIAssistantProvider.cs](./CS/Services/AIAssistantProvider.cs) +- [AIAssistantProvider.cs](./CS/Services/AIAssistantProvider.cs) +- [AIAssistantCreator.cs](./CS/Services/AIAssistantCreator.cs) ### Create an AI Assistant Custom Item @@ -197,6 +209,7 @@ async onMessageEntered(e) { - [IAIAssistantProvider.cs](./CS/Services/IAIAssistantProvider.cs) - [AIChatController.cs](./CS/Controllers/AIChatController.cs) - [AssistantHelper.cs](./CS/Services/AssistantHelper.cs) +- [AIAssistantCreator.cs](./CS/Services/AIAssistantCreator.cs) ## Documentation