-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
108 lines (93 loc) · 3.55 KB
/
Copy pathProgram.cs
File metadata and controls
108 lines (93 loc) · 3.55 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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
using Microsoft.Agents.AI.Workflows;
using MongoDB.AgentFramework;
WorkflowRetrievalOptions command = WorkflowRetrievalOptions.Parse(args);
WorkflowRetrievalSettings settings = WorkflowRetrievalSettings.Load();
var providerOptions = new MongoDBRAGProviderOptions
{
SearchMode = MongoDBSearchMode.FullText,
SearchIndexName = settings.SearchIndexName,
SearchTextFieldNames = ["text"],
TopK = 3,
MandatoryFilter = MongoDBRAGFilter.Equal("tenant_id", settings.TenantId),
};
await using var provider = new MongoDBRAGProvider(
settings.ConnectionString,
settings.DatabaseName,
settings.CollectionName,
providerOptions);
async ValueTask<string> RetrieveAsync(string query, CancellationToken cancellationToken)
{
IReadOnlyList<MongoDBRAGResult> results = await provider.SearchAsync(query, cancellationToken);
if (results.Count == 0)
{
throw new InvalidOperationException(
"No authorized knowledge matched the workflow query. Preload tenant-scoped Search documents before " +
"running this sample.");
}
return string.Join(
Environment.NewLine + Environment.NewLine,
results.Select(static result => $"[{result.SourceName ?? result.Id}] {result.Text}"));
}
ExecutorBinding retrievalStep =
((Func<string, CancellationToken, ValueTask<string>>)RetrieveAsync)
.BindAsExecutor(id: "mongodb-retrieval-step", threadsafe: true);
Workflow workflow = new WorkflowBuilder(retrievalStep)
.WithName("workflow-retrieval")
.WithDescription("Deterministic direct MongoDB retrieval inside a workflow step.")
.WithOutputFrom(retrievalStep)
.Build(validateOrphans: true);
if (command.ValidateOnly)
{
Console.WriteLine("Validated workflow retrieval configuration.");
return;
}
await provider.ValidateSearchIndexAsync();
await using Run run = await InProcessExecution.RunAsync(
workflow,
settings.QueryText,
sessionId: "workflow-retrieval-sample");
string output = run.OutgoingEvents
.OfType<WorkflowOutputEvent>()
.Select(static workflowEvent => workflowEvent.As<string>())
.FirstOrDefault(static value => !string.IsNullOrWhiteSpace(value))
?? throw new InvalidOperationException("The workflow completed without yielding a retrieval result.");
Console.WriteLine(output);
internal sealed record WorkflowRetrievalOptions(bool ValidateOnly)
{
public static WorkflowRetrievalOptions Parse(string[] args)
{
if (args.Length == 0)
{
return new(false);
}
if (args.Length == 1 && string.Equals(args[0], "--validate-only", StringComparison.Ordinal))
{
return new(true);
}
throw new ArgumentException("Usage: dotnet run --project ... -- [--validate-only]");
}
}
internal sealed record WorkflowRetrievalSettings(
string ConnectionString,
string DatabaseName,
string CollectionName,
string SearchIndexName,
string TenantId,
string QueryText)
{
public static WorkflowRetrievalSettings Load() =>
new(
Required("MONGODB_URI"),
Required("MONGODB_DATABASE"),
Required("MONGODB_RAG_COLLECTION"),
Required("MONGODB_RAG_SEARCH_INDEX"),
Required("MONGODB_RAG_TENANT"),
"How is tenant access enforced?");
private static string Required(string name)
{
string? value = Environment.GetEnvironmentVariable(name)?.Trim();
return !string.IsNullOrWhiteSpace(value)
? value
: throw new InvalidOperationException($"Set {name} before running workflow retrieval.");
}
}