-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProgram.cs
More file actions
114 lines (92 loc) · 3.69 KB
/
Program.cs
File metadata and controls
114 lines (92 loc) · 3.69 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
109
110
111
112
113
114
using System.ClientModel;
using System.Text.Json;
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.Extensions.AI;
using Microsoft.Extensions.VectorData;
using Microsoft.SemanticKernel.Connectors.InMemory;
using OpenAI;
var builder = WebApplication.CreateSlimBuilder(args);
builder.Services.ConfigureHttpJsonOptions(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonSerializerContext.Default);
});
// Read OpenAI configuration
var apiKey = builder.Configuration["OpenAI:ApiKey"]!;
var baseUrl = builder.Configuration["OpenAI:BaseUrl"]!;
var model = builder.Configuration["OpenAI:Model"]!;
var embeddingModel = builder.Configuration["OpenAI:EmbeddingModel"]!;
// Create OpenAI client
var openAiClient = new OpenAIClient(new ApiKeyCredential(apiKey), new OpenAIClientOptions { Endpoint = new Uri(baseUrl) });
// Register chat + embedding services using Microsoft.Extensions.AI.OpenAI v10 extensions
builder.Services.AddChatClient(openAiClient.GetChatClient(model).AsIChatClient()).UseFunctionInvocation();
builder.Services.AddEmbeddingGenerator(openAiClient.GetEmbeddingClient(embeddingModel).AsIEmbeddingGenerator());
// Register InMemory vector store
var vectorStore = new InMemoryVectorStore();
builder.Services.AddSingleton<VectorStore>(vectorStore);
builder.Services.AddSingleton<VectorStoreCollection<string, ClimateFact>>(
vectorStore.GetCollection<string, ClimateFact>("climate_facts"));
// Register AgentService
builder.Services.AddSingleton<AgentService>();
// Add OpenAPI
builder.Services.AddOpenApi();
// Add CORS
builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(policy =>
{
policy.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader();
});
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
app.UseCors();
// Seed the vector store
await SeedVectorStoreAsync(app);
app.MapGet("/", () => "Hello World!");
// Map POST /ask endpoint
app.MapPost("/ask", async (QueryRequest request, AgentService agent) =>
{
var response = await agent.AskAsync(request.Text);
return Results.Ok(response);
});
app.Run();
static async Task SeedVectorStoreAsync(WebApplication app)
{
var collection = app.Services.GetRequiredService<VectorStoreCollection<string, ClimateFact>>();
var embGen = app.Services.GetRequiredService<IEmbeddingGenerator<string, Embedding<float>>>();
var env = app.Services.GetRequiredService<IWebHostEnvironment>();
await collection.EnsureCollectionExistsAsync();
var factsPath = Path.Combine(env.ContentRootPath, "../seed_data/facts.json");
var json = await File.ReadAllTextAsync(factsPath);
var seedData = JsonSerializer.Deserialize(json, AppJsonSerializerContext.Default.SeedData)!;
for (var i = 0; i < seedData.FACTS.Length; i++)
{
var fact = seedData.FACTS[i];
var embeddings = await embGen.GenerateAsync([fact], new EmbeddingGenerationOptions { Dimensions = 384 });
var embedding = embeddings[0].Vector;
await collection.UpsertAsync(new ClimateFact
{
Id = i.ToString(),
Text = fact,
Embedding = embedding,
});
}
}
public record QueryRequest(string Text);
public record AskResponse(string Response, string Tool, string Thought);
//{
// "response": "I am a browser-native Solita Case Agent",
// "tool": "system_info_tool",
// "thought": "Query is about system identity → routing to system_info_tool"
// }
public record SeedData(string[] FACTS);
[JsonSerializable(typeof(QueryRequest))]
[JsonSerializable(typeof(AskResponse))]
[JsonSerializable(typeof(SeedData))]
internal partial class AppJsonSerializerContext : JsonSerializerContext
{
}