Skip to content

Commit 5dbd800

Browse files
Merge pull request Azure#74 from Azure/assistants-bot-scripts
Assistants bot scripts
2 parents ee9206f + 1770cec commit 5dbd800

7 files changed

Lines changed: 123 additions & 29 deletions

File tree

gen-ai/Assistants/bot-in-a-box/azure.yaml

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ services:
1010
language: dotnet
1111
hooks:
1212
postdeploy:
13-
shell: sh
14-
run: ./scripts/createAssistant.sh
15-
interactive: true
16-
continueOnError: false
13+
windows:
14+
shell: pwsh
15+
run: ./scripts/createAssistant.ps1
16+
interactive: true
17+
continueOnError: false
18+
posix:
19+
shell: sh
20+
run: ./scripts/createAssistant.sh
21+
interactive: true
22+
continueOnError: false

gen-ai/Assistants/bot-in-a-box/scripts/createAssistant.ps1

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,33 +9,39 @@ foreach ($line in (& azd env get-values)) {
99

1010
$AOAI_API_KEY=az cognitiveservices account keys list -n $env:AOAI_NAME -g $env:AZURE_RESOURCE_GROUP_NAME --query key1 -o tsv
1111
$AOAI_ASSISTANT_NAME="assistant_in_a_box"
12-
$ASSISTANT_ID=((curl "$env:AOAI_API_ENDPOINT/openai/assistants?api-version=2024-02-15-preview" -H "api-key: $AOAI_API_KEY" | ConvertFrom-Json).data | Where-Object name -eq $AOAI_ASSISTANT_NAME).id
13-
if ( "$ASSISTANT_ID" == "null" )
14-
{ASSISTANT_ID=""}
12+
$ASSISTANT_ID=((curl "${env:AOAI_API_ENDPOINT}openai/assistants`?api-version=2024-02-15-preview" -H "api-key: $AOAI_API_KEY" | ConvertFrom-Json).data | Where-Object name -eq $AOAI_ASSISTANT_NAME).id
13+
14+
if ( $ASSISTANT_ID -eq $null )
15+
{
16+
$ASSISTANT_ID=""
17+
echo "empty"
18+
}
1519
else
16-
{ASSISTANT_ID=/$ASSISTANT_ID}
20+
{
21+
$ASSISTANT_ID="/$ASSISTANT_ID"
22+
echo "not empty"
23+
}
24+
25+
$TOOLS="{}"
26+
Get-ChildItem "./src/Tools" -Filter *.json |
27+
Foreach-Object {
28+
$content = Get-Content $_.FullName
29+
$TOOLS = "$TOOLS,$content"
30+
}
1731

1832
echo "{
1933
`"name`":`"${AOAI_ASSISTANT_NAME}`",
2034
`"model`":`"gpt-4`",
2135
`"instructions`":`"`",
2236
`"tools`":[
23-
$(Get-ChildItem "./src/Tools" -Filter *.json |
24-
Foreach-Object {
25-
$content = Get-Content $_.FullName
26-
echo $content","
27-
})
28-
{}
37+
$TOOLS
2938
],
3039
`"file_ids`":[],
3140
`"metadata`":{}
32-
}" > tmp.json
33-
curl "$env:AOAI_API_ENDPOINT/openai/assistants$ASSISTANT_ID?api-version=2024-02-15-preview" \
34-
-H "api-key: $AOAI_API_KEY" \
35-
-H 'content-type: application/json' \
36-
-d @tmp.json
41+
}" | Out-File tmp.json
42+
curl "${env:AOAI_API_ENDPOINT}openai/assistants$ASSISTANT_ID`?api-version=2024-02-15-preview" -H "api-key: $AOAI_API_KEY" -H 'content-type: application/json' -d '@tmp.json'
3743
rm tmp.json
3844

39-
$ASSISTANT_ID=((curl "$env:AOAI_API_ENDPOINT/openai/assistants?api-version=2024-02-15-preview" -H "api-key: $AOAI_API_KEY" | ConvertFrom-Json).data | Where-Object name -eq $AOAI_ASSISTANT_NAME).id
45+
$ASSISTANT_ID=((curl "${env:AOAI_API_ENDPOINT}openai/assistants`?api-version=2024-02-15-preview" -H "api-key: $AOAI_API_KEY" | ConvertFrom-Json).data | Where-Object name -eq $AOAI_ASSISTANT_NAME).id
4046

41-
az webapp config appsettings set -g $AZURE_RESOURCE_GROUP_NAME -n $APP_NAME --settings AOAI_ASSISTANT_ID=$ASSISTANT_ID APP_URL=$APP_HOSTNAME
47+
az webapp config appsettings set -g $env:AZURE_RESOURCE_GROUP_NAME -n $env:APP_NAME --settings AOAI_ASSISTANT_ID=$ASSISTANT_ID APP_URL=$env:APP_HOSTNAME

gen-ai/Assistants/bot-in-a-box/src/AssistantBot.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project Sdk="Microsoft.NET.Sdk.Web">
22
<PropertyGroup>
3-
<TargetFramework>net8.0</TargetFramework>
3+
<TargetFramework>net7.0</TargetFramework>
44
<LangVersion>latest</LangVersion>
55
<UserSecretsId>73c2a03b-aae7-4833-b3a8-c01744ad2b7e</UserSecretsId>
66
</PropertyGroup>

gen-ai/Assistants/bot-in-a-box/src/Bots/AssistantBot.cs

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
using HtmlAgilityPack;
1919
using Services;
2020
using Models;
21+
using System.IO;
2122

2223

2324
namespace Microsoft.BotBuilderSamples
@@ -77,13 +78,23 @@ public override async Task<List<string>> ProcessMessage(ConversationData convers
7778
// await turnContext.SendActivityAsync($"Thread found: {conversationData.ThreadId}");
7879
}
7980

81+
// Process any attachments
82+
83+
if (!turnContext.Activity.Attachments.IsNullOrEmpty())
84+
foreach (Bot.Schema.Attachment attachment in turnContext.Activity.Attachments)
85+
await IngestAttachment(conversationData, turnContext, attachment);
86+
87+
if (turnContext.Activity.Text.IsNullOrEmpty())
88+
return new List<string>() {"1"};
89+
90+
// Process keywords
8091
if (turnContext.Activity.Text.ToLower() == "clear")
8192
{
8293
var thread = await _aoaiClient.DeleteThread(conversationData.ThreadId);
8394
conversationData.ThreadId = null;
8495
conversationData.History.Clear();
8596
conversationData.Attachments.Clear();
86-
return new List<string> { $"Thread {thread.Id} deleted." };
97+
return new List<string>() { $"Thread {thread.Id} deleted." };
8798
}
8899

89100
// Add user message to thread
@@ -113,7 +124,8 @@ public override async Task<List<string>> ProcessMessage(ConversationData convers
113124
System.Threading.Thread.Sleep(10000);
114125
run = await _aoaiClient.GetThreadRun(conversationData.ThreadId, run.Id);
115126
}
116-
if (run.Status == "failed") {
127+
if (run.Status == "failed")
128+
{
117129
await turnContext.SendActivityAsync("Something went wrong when running the assistant.");
118130
}
119131

@@ -134,7 +146,7 @@ public override async Task<List<string>> ProcessMessage(ConversationData convers
134146
if (messages[i].Content[j].Type == "image_file")
135147
{
136148
responses.Add($"Image (ID: {messages[i].Content[j].ImageFile.FileId})");
137-
List<object> images = [new { type = "Image", url = $"{_appUrl}/openai/files/{messages[i].Content[j].ImageFile.FileId}/content" }];
149+
List<object> images = new() { new { type = "Image", url = $"{_appUrl}/openai/files/{messages[i].Content[j].ImageFile.FileId}/content" } };
138150
object adaptiveCardJson = new
139151
{
140152
type = "AdaptiveCard",
@@ -153,5 +165,22 @@ public override async Task<List<string>> ProcessMessage(ConversationData convers
153165
}
154166
return responses;
155167
}
168+
169+
170+
private async Task IngestAttachment(ConversationData conversationData, ITurnContext<IMessageActivity> turnContext, Bot.Schema.Attachment attachment)
171+
{
172+
Uri fileUri = new Uri(attachment.ContentUrl);
173+
var httpClient = new HttpClient();
174+
var stream = await httpClient.GetStreamAsync(fileUri);
175+
var file = await _aoaiClient.UploadFile(stream, attachment.Name);
176+
await _aoaiClient.SendMessage(conversationData.ThreadId, new MessageInput()
177+
{
178+
Role = "user",
179+
Content = "(File uploaded)",
180+
FileIds = new List<string>() {file.Id}
181+
});
182+
stream.Dispose();
183+
await turnContext.SendActivityAsync($"File {attachment.Name} uploaded successfully!");
184+
}
156185
}
157186
}

gen-ai/Assistants/bot-in-a-box/src/Models/AOAIModels.cs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public class MessageInput
2929

3030
[JsonPropertyName("content")]
3131
public string Content { get; set; } = null;
32+
33+
[JsonPropertyName("file_ids")]
34+
public List<string> FileIds { get; set; } = new();
3235
}
3336
public class MessageContentText {
3437
[JsonPropertyName("value")]
@@ -44,6 +47,12 @@ public class MessageContent {
4447
public ImageFile ImageFile { get; set; }
4548
}
4649

50+
public class File {
51+
[JsonPropertyName("id")]
52+
public string Id { get; set; }
53+
}
54+
55+
4756
public class ImageFile {
4857
[JsonPropertyName("file_id")]
4958
public string FileId { get; set; }
@@ -55,7 +64,10 @@ public class Message
5564
public string Role { get; set; }
5665

5766
[JsonPropertyName("content")]
58-
public List<MessageContent> Content { get; set; }
67+
public List<MessageContent> Content { get; set; } = null;
68+
69+
[JsonPropertyName("file_ids")]
70+
public List<string> FileIds { get; set; }
5971
}
6072

6173
public class ThreadRunInput

gen-ai/Assistants/bot-in-a-box/src/Services/AOAIClient.cs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.IO;
34
using System.Net.Http;
45
using System.Text;
56
using System.Text.Json;
67
using System.Threading.Tasks;
8+
using Microsoft.Azure.Cosmos.Core;
79
using Models;
810

911
namespace Services
@@ -57,13 +59,24 @@ public async Task<List<Message>> ListThreadMessages(string threadId)
5759
var result = await JsonRequest<AOAIResponse<Message>>($"/threads/{threadId}/messages", HttpMethod.Get);
5860
return result.Data;
5961
}
62+
public async Task<Models.File> UploadFile(Stream file, string fileName)
63+
{
64+
MultipartFormDataContent form = new MultipartFormDataContent
65+
{
66+
{ new StringContent("assistants"), "purpose" },
67+
{ new StreamContent(file), "file", fileName }
68+
};
69+
var result = await JsonRequest<Models.File>($"/files", HttpMethod.Post, form);
70+
return result;
71+
}
6072
public async Task<HttpResponseMessage> GetFile(string fileId)
6173
{
6274
var result = await SendRequest($"/files/{fileId}/content", HttpMethod.Get);
6375
return result;
6476
}
6577

66-
private async Task<HttpResponseMessage> SendRequest(string path, HttpMethod method, StringContent body = null) {
78+
private async Task<HttpResponseMessage> SendRequest(string path, HttpMethod method, StringContent body = null)
79+
{
6780
var url = "/openai" + path + "?api-version=2024-02-15-preview";
6881

6982
var request = new HttpRequestMessage(method, url)
@@ -76,7 +89,7 @@ private async Task<HttpResponseMessage> SendRequest(string path, HttpMethod meth
7689
};
7790
return await _httpClient.SendAsync(request, default);
7891
}
79-
92+
8093

8194
private async Task<T> JsonRequest<T>(string path, HttpMethod method, StringContent body = null)
8295
{
@@ -89,6 +102,34 @@ private async Task<T> JsonRequest<T>(string path, HttpMethod method, StringConte
89102
return content;
90103
}
91104

105+
private async Task<HttpResponseMessage> SendRequest(string path, HttpMethod method, MultipartFormDataContent body)
106+
{
107+
var url = "/openai" + path + "?api-version=2024-02-15-preview";
108+
109+
var request = new HttpRequestMessage(method, url)
110+
{
111+
Headers =
112+
{
113+
{ "api-key", _accessKey },
114+
},
115+
Content = body
116+
};
117+
return await _httpClient.SendAsync(request, default);
118+
}
119+
120+
121+
private async Task<T> JsonRequest<T>(string path, HttpMethod method, MultipartFormDataContent body)
122+
{
123+
var response = await SendRequest(path, method, body);
124+
125+
var responseContent = await response.Content.ReadAsStringAsync();
126+
if (!response.IsSuccessStatusCode)
127+
throw new Exception(responseContent);
128+
129+
var content = JsonSerializer.Deserialize<T>(responseContent);
130+
return content;
131+
}
132+
92133

93134
}
94135
}

gen-ai/Assistants/bot-in-a-box/src/Tools/_Tools.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public async Task<ToolOutputData> RunRequestedTools(ThreadRun run)
3535
{
3636
var method = typeof(Tools).GetMethod(toolcall.Function.Name);
3737
var arguments = JsonSerializer.Deserialize<Dictionary<string, object>>(toolcall.Function.Arguments);
38-
string output = await (Task<string>)method.Invoke(this, [arguments]);
38+
string output = await (Task<string>)method.Invoke(this, new object[]{arguments});
3939
var toolOutput = new ToolOutput
4040
{
4141
ToolCallId = toolcall.Id,

0 commit comments

Comments
 (0)