Skip to content

Commit 3b8a2a2

Browse files
aleks-proprokhorov.alexanderDevExpressExampleBot
authored
Update example according to new AI Assistant reuse API (#3)
* Update example according to new AI Assistant reuse API * README auto update [skip ci] --------- Co-authored-by: prokhorov.alexander <[email protected]> Co-authored-by: DevExpressExampleBot <[email protected]>
1 parent 42cd606 commit 3b8a2a2

File tree

4 files changed

+76
-22
lines changed

4 files changed

+76
-22
lines changed

CS/Program.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,10 @@
5151
new AzureKeyCredential(EnvSettings.AzureOpenAIKey));
5252
var chatClient = azureOpenAIClient.GetChatClient(EnvSettings.DeploymentName).AsIChatClient();
5353

54+
var assistantCreator = new AIAssistantCreator(azureOpenAIClient, EnvSettings.DeploymentName);
55+
5456
builder.Services.AddSingleton(chatClient);
57+
builder.Services.AddSingleton(assistantCreator);
5558
builder.Services.AddSingleton<IAIAssistantProvider, AIAssistantProvider>();
5659
builder.Services.AddDevExpressAI(config =>
5760
{

CS/Services/AIAssistantCreator.cs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using System;
2+
using System.ClientModel;
3+
using System.IO;
4+
using System.Threading;
5+
using System.Threading.Tasks;
6+
using OpenAI;
7+
using OpenAI.Assistants;
8+
using OpenAI.Files;
9+
10+
namespace DashboardAIAssistant.Services {
11+
#pragma warning disable OPENAI001
12+
public class AIAssistantCreator {
13+
readonly AssistantClient assistantClient;
14+
readonly OpenAIFileClient fileClient;
15+
readonly string deployment;
16+
17+
public AIAssistantCreator(OpenAIClient client, string deployment) {
18+
assistantClient = client.GetAssistantClient();
19+
fileClient = client.GetOpenAIFileClient();
20+
this.deployment = deployment;
21+
}
22+
23+
public async Task<(string assistantId, string threadId)> CreateAssistantAsync(Stream data, string fileName, string instructions, bool useFileSearchTool = true, CancellationToken ct = default) {
24+
data.Position = 0;
25+
26+
ClientResult<OpenAIFile> fileResponse = await fileClient.UploadFileAsync(data, fileName, FileUploadPurpose.Assistants, ct);
27+
OpenAIFile file = fileResponse.Value;
28+
29+
var resources = new ToolResources() {
30+
CodeInterpreter = new CodeInterpreterToolResources(),
31+
FileSearch = useFileSearchTool ? new FileSearchToolResources() : null
32+
};
33+
resources.FileSearch?.NewVectorStores.Add(new VectorStoreCreationHelper([file.Id]));
34+
resources.CodeInterpreter.FileIds.Add(file.Id);
35+
36+
AssistantCreationOptions assistantCreationOptions = new AssistantCreationOptions() {
37+
Name = Guid.NewGuid().ToString(),
38+
Instructions = instructions,
39+
ToolResources = resources
40+
};
41+
assistantCreationOptions.Tools.Add(new CodeInterpreterToolDefinition());
42+
if (useFileSearchTool) {
43+
assistantCreationOptions.Tools.Add(new FileSearchToolDefinition());
44+
}
45+
46+
ClientResult<Assistant> assistantResponse = await assistantClient.CreateAssistantAsync(deployment, assistantCreationOptions, ct);
47+
ClientResult<AssistantThread> threadResponse = await assistantClient.CreateThreadAsync(cancellationToken: ct);
48+
49+
return (assistantResponse.Value.Id, threadResponse.Value.Id);
50+
}
51+
}
52+
#pragma warning restore OPENAI001
53+
}

CS/Services/AIAssistantProvider.cs

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,53 +1,52 @@
1-
using DevExpress.AIIntegration.OpenAI.Services;
2-
using DevExpress.AIIntegration.Services.Assistant;
3-
using DevExpress.Utils;
4-
using System;
1+
using System;
52
using System.Collections.Concurrent;
63
using System.IO;
74
using System.Threading.Tasks;
5+
using DevExpress.AIIntegration.Services.Assistant;
6+
using DevExpress.Utils;
87

98
namespace DashboardAIAssistant.Services {
109
public class AIAssistantProvider : IAIAssistantProvider {
1110
private readonly IAIAssistantFactory assistantFactory;
11+
private readonly AIAssistantCreator assistantCreator;
1212
private ConcurrentDictionary<string, IAIAssistant> Assistants { get; set; } = new();
1313

14-
public AIAssistantProvider(IAIAssistantFactory assistantFactory) {
14+
public AIAssistantProvider(IAIAssistantFactory assistantFactory, AIAssistantCreator assistantCreator) {
1515
this.assistantFactory = assistantFactory;
16+
this.assistantCreator = assistantCreator;
1617
}
1718

1819
public async Task<string> CreateAssistant(Stream fileContent, string prompt) {
1920
Guard.ArgumentNotNull(fileContent, nameof(fileContent));
2021
Guard.ArgumentIsNotNullOrEmpty(prompt, nameof(prompt));
21-
22-
string assistantId = Guid.NewGuid().ToString();
2322

24-
IAIAssistant assistant = await assistantFactory.CreateAssistant(assistantId);
25-
Assistants.TryAdd(assistantId, assistant);
23+
string assistantName = Guid.NewGuid().ToString();
24+
(string assistantId, string threadId) = await assistantCreator.CreateAssistantAsync(fileContent, $"{assistantName}.xlsx", prompt, false);
25+
26+
IAIAssistant assistant = await assistantFactory.GetAssistant(assistantId, threadId);
27+
await assistant.InitializeAsync();
2628

27-
await assistant.InitializeAsync(new OpenAIAssistantOptions($"{assistantId}.xlsx", fileContent) {
28-
Instructions = prompt,
29-
UseFileSearchTool = false,
30-
});
29+
Assistants.TryAdd(assistantName, assistant);
3130

32-
return assistantId;
31+
return assistantName;
3332
}
3433

35-
public IAIAssistant GetAssistant(string assistantId) {
36-
Guard.ArgumentIsNotNullOrEmpty(assistantId, nameof(assistantId));
34+
public IAIAssistant GetAssistant(string assistantName) {
35+
Guard.ArgumentIsNotNullOrEmpty(assistantName, nameof(assistantName));
3736

3837
IAIAssistant assistant = null;
3938

40-
if(!Assistants.TryGetValue(assistantId, out assistant)) {
41-
throw new ArgumentException($"Incorrect assistant id: {assistantId}");
39+
if(!Assistants.TryGetValue(assistantName, out assistant)) {
40+
throw new ArgumentException($"Incorrect assistant id: {assistantName}");
4241
}
4342

4443
return assistant;
4544
}
4645

47-
public void DisposeAssistant(string assistantId) {
48-
Guard.ArgumentIsNotNullOrEmpty(assistantId, nameof(assistantId));
46+
public void DisposeAssistant(string assistantName) {
47+
Guard.ArgumentIsNotNullOrEmpty(assistantName, nameof(assistantName));
4948

50-
if(Assistants.TryRemove(assistantId, out IAIAssistant assistant)) {
49+
if(Assistants.TryRemove(assistantName, out IAIAssistant assistant)) {
5150
assistant.Dispose();
5251
}
5352
}

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
<!-- default badges list -->
2-
![](https://img.shields.io/endpoint?url=https://codecentral.devexpress.com/api/v1/VersionRange/938296554/25.1.2%2B)
32
[![](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)
43
[![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183)
54
[![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives)

0 commit comments

Comments
 (0)