-
Notifications
You must be signed in to change notification settings - Fork 2k
Expand file tree
/
Copy pathComputerUseUtil.cs
More file actions
93 lines (79 loc) · 3.06 KB
/
Copy pathComputerUseUtil.cs
File metadata and controls
93 lines (79 loc) · 3.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright (c) Microsoft. All rights reserved.
using Microsoft.Extensions.AI;
using OpenAI.Responses;
namespace Demo.ComputerUse;
/// <summary>
/// Enum for tracking the state of the simulated web search flow.
/// </summary>
internal enum SearchState
{
Initial, // Browser search page
Typed, // Text entered in search box
PressedEnter // Enter key pressed, transitioning to results
}
internal static class ComputerUseUtil
{
internal static async Task<Dictionary<string, string>> UploadScreenshotAssetsAsync(IHostedFileClient fileClient)
{
string assetsDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets");
(string key, string fileName)[] files =
[
("browser_search", "cua_browser_search.jpg"),
("search_typed", "cua_search_typed.jpg"),
("search_results", "cua_search_results.jpg")
];
Dictionary<string, string> screenshots = [];
foreach (var (key, fileName) in files)
{
HostedFileContent result = await fileClient.UploadAsync(
Path.Combine(assetsDir, fileName), new HostedFileClientOptions() { Purpose = "assistants" });
screenshots[key] = result.FileId;
}
return screenshots;
}
internal static async Task EnsureDeleteScreenshotAssetsAsync(IHostedFileClient fileClient, Dictionary<string, string> screenshots)
{
foreach (var (_, fileId) in screenshots)
{
try
{
await fileClient.DeleteAsync(fileId);
}
catch
{
}
}
}
/// <summary>
/// Simulates executing a computer action by advancing the state
/// and returning the screenshot file ID for the new state.
/// </summary>
internal static async Task<(SearchState State, string FileId)> GetScreenshotAsync(
ComputerCallAction action,
SearchState currentState,
Dictionary<string, string> screenshots)
{
if (action.Kind == ComputerCallActionKind.Wait)
{
await Task.Delay(TimeSpan.FromSeconds(5));
}
SearchState nextState = action.Kind switch
{
ComputerCallActionKind.Click when currentState == SearchState.Typed => SearchState.PressedEnter,
ComputerCallActionKind.Type when action.TypeText is not null => SearchState.Typed,
ComputerCallActionKind.KeyPress when IsEnterKey(action) => SearchState.PressedEnter,
_ => currentState
};
string imageKey = nextState switch
{
SearchState.PressedEnter => "search_results",
SearchState.Typed => "search_typed",
_ => "browser_search"
};
return (nextState, screenshots[imageKey]);
}
private static bool IsEnterKey(ComputerCallAction action) =>
action.KeyPressKeyCodes is not null &&
(action.KeyPressKeyCodes.Contains("Return", StringComparer.OrdinalIgnoreCase) ||
action.KeyPressKeyCodes.Contains("Enter", StringComparer.OrdinalIgnoreCase));
}