-
Notifications
You must be signed in to change notification settings - Fork 88
Expand file tree
/
Copy pathProgram.cs
More file actions
109 lines (92 loc) · 4.72 KB
/
Program.cs
File metadata and controls
109 lines (92 loc) · 4.72 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
using System;
using System.ComponentModel;
using System.ClientModel;
using OpenAI;
using Microsoft.Extensions.AI;
using Microsoft.Agents.AI;
using Microsoft.Agents.AI.Workflows;
using DotNetEnv;
// Load environment variables
Env.Load("../../../../.env");
var github_endpoint = Environment.GetEnvironmentVariable("GITHUB_ENDPOINT") ?? throw new InvalidOperationException("GITHUB_ENDPOINT is not set.");
var github_model_id = "gpt-4o";
var github_token = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? throw new InvalidOperationException("GITHUB_TOKEN is not set.");
var imgPath = "../../imgs/home.png";
// Configure OpenAI client
var openAIOptions = new OpenAIClientOptions()
{
Endpoint = new Uri(github_endpoint)
};
var openAIClient = new OpenAIClient(new ApiKeyCredential(github_token), openAIOptions);
// Define agent names and instructions
const string SalesAgentName = "Sales-Agent";
const string SalesAgentInstructions = "You are my furniture sales consultant, you can find different furniture elements from the pictures and give me a purchase suggestion";
const string PriceAgentName = "Price-Agent";
const string PriceAgentInstructions = @"You are a furniture pricing specialist and budget consultant. Your responsibilities include:
1. Analyze furniture items and provide realistic price ranges based on quality, brand, and market standards
2. Break down pricing by individual furniture pieces
3. Provide budget-friendly alternatives and premium options
4. Consider different price tiers (budget, mid-range, premium)
5. Include estimated total costs for room setups
6. Suggest where to find the best deals and shopping recommendations
7. Factor in additional costs like delivery, assembly, and accessories
8. Provide seasonal pricing insights and best times to buy
Always format your response with clear price breakdowns and explanations for the pricing rationale.";
const string QuoteAgentName = "Quote-Agent";
const string QuoteAgentInstructions = @"You are a assistant that create a quote for furniture purchase.
1. Create a well-structured quote document that includes:
2. A title page with the document title, date, and client name
3. An introduction summarizing the purpose of the document
4. A summary section with total estimated costs and recommendations
5. Use clear headings, bullet points, and tables for easy readability
6. All quotes are presented in markdown form";
// Read image bytes
async Task<byte[]> OpenImageBytesAsync(string path)
{
return await File.ReadAllBytesAsync(path);
}
var imageBytes = await OpenImageBytesAsync(imgPath);
// Create AI agents
AIAgent salesagent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
name: SalesAgentName, instructions: SalesAgentInstructions);
AIAgent priceagent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
name: PriceAgentName, instructions: PriceAgentInstructions);
AIAgent quoteagent = openAIClient.GetChatClient(github_model_id).AsIChatClient().AsAIAgent(
name: QuoteAgentName, instructions: QuoteAgentInstructions);
// Build sequential workflow
var workflow = new WorkflowBuilder(salesagent)
.AddEdge(salesagent, priceagent)
.AddEdge(priceagent, quoteagent)
.Build();
// Create user message with image
ChatMessage userMessage = new ChatMessage(ChatRole.User, [
new DataContent(imageBytes, "image/png"),
new TextContent("Please find the relevant furniture according to the image and give the corresponding price for each piece of furniture.Finally Output generates a quotation")
]);
// Execute workflow
StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, userMessage);
// Process streaming results
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
string id = "";
string messageData = "";
await foreach (WorkflowEvent evt in run.WatchStreamAsync().ConfigureAwait(false))
{
if (evt is AgentResponseUpdateEvent executorComplete)
{
messageData += executorComplete.Data;
Console.WriteLine($"{executorComplete.ExecutorId}: {executorComplete.Data}");
}
}
Console.WriteLine(messageData);
// Mermaid
Console.WriteLine("\nMermaid string: \n=======");
var mermaid = workflow.ToMermaidString();
Console.WriteLine(mermaid);
Console.WriteLine("=======");
// DOT - Save to file instead of stdout to avoid pipe issues
var dotString = workflow.ToDotString();
var dotFilePath = "workflow.dot";
File.WriteAllText(dotFilePath, dotString);
Console.WriteLine($"\nDOT graph saved to: {dotFilePath}");
Console.WriteLine("To generate image: dot -Tsvg workflow.dot -o workflow.svg");
Console.WriteLine(" dot -Tpng workflow.dot -o workflow.png");