Skip to content

Commit 32e300a

Browse files
committed
feat: ✨ some refactoring in the agents
1 parent f1e8a87 commit 32e300a

36 files changed

Lines changed: 939 additions & 373 deletions

Directory.Packages.props

Lines changed: 115 additions & 114 deletions
Large diffs are not rendered by default.

gen-ai-app-samples.sln

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Recommendation", "src\Servi
5757
EndProject
5858
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reviews", "src\Services\Reviews\Reviews.csproj", "{AC102A54-FBB1-4BD6-90B4-CE62D5F4E328}"
5959
EndProject
60+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "UI", "UI", "{407B9EA3-0148-4611-AFD5-D92E7C10DE51}"
61+
EndProject
62+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp", "src\UI\ConsoleApp\ConsoleApp.csproj", "{2D4DADFB-AA8E-4664-BA9B-E9FE40874E48}"
63+
EndProject
6064
Global
6165
GlobalSection(SolutionConfigurationPlatforms) = preSolution
6266
Debug|Any CPU = Debug|Any CPU
@@ -83,6 +87,8 @@ Global
8387
{510C732A-FD95-4DE4-8187-76A7AD012633} = {14C757F9-E1E3-429C-AF7E-E14F28E6F852}
8488
{B9F571EB-1AF4-4343-B763-5DE23EE8FC28} = {14C757F9-E1E3-429C-AF7E-E14F28E6F852}
8589
{AC102A54-FBB1-4BD6-90B4-CE62D5F4E328} = {14C757F9-E1E3-429C-AF7E-E14F28E6F852}
90+
{407B9EA3-0148-4611-AFD5-D92E7C10DE51} = {5DF8C01D-D181-498E-97DE-3535FFD4FFB5}
91+
{2D4DADFB-AA8E-4664-BA9B-E9FE40874E48} = {407B9EA3-0148-4611-AFD5-D92E7C10DE51}
8692
EndGlobalSection
8793
GlobalSection(ProjectConfigurationPlatforms) = postSolution
8894
{15C0604F-9107-44C1-9CDB-B6C407084C52}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -125,5 +131,9 @@ Global
125131
{AC102A54-FBB1-4BD6-90B4-CE62D5F4E328}.Debug|Any CPU.Build.0 = Debug|Any CPU
126132
{AC102A54-FBB1-4BD6-90B4-CE62D5F4E328}.Release|Any CPU.ActiveCfg = Release|Any CPU
127133
{AC102A54-FBB1-4BD6-90B4-CE62D5F4E328}.Release|Any CPU.Build.0 = Release|Any CPU
134+
{2D4DADFB-AA8E-4664-BA9B-E9FE40874E48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
135+
{2D4DADFB-AA8E-4664-BA9B-E9FE40874E48}.Debug|Any CPU.Build.0 = Debug|Any CPU
136+
{2D4DADFB-AA8E-4664-BA9B-E9FE40874E48}.Release|Any CPU.ActiveCfg = Release|Any CPU
137+
{2D4DADFB-AA8E-4664-BA9B-E9FE40874E48}.Release|Any CPU.Build.0 = Release|Any CPU
128138
EndGlobalSection
129139
EndGlobal

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"sdk": {
3-
"version": "9.0.303",
3+
"version": "9.0.305",
44
"rollForward": "latestFeature",
55
"allowPrerelease": true
66
}

src/BuildingBlocks/AI/A2A/A2AClientExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ string agentPath
3636
// https://github.com/microsoft/semantic-kernel/blob/main/dotnet/src/Agents/A2A/A2AAgent.cs#L178
3737
builder.Services.AddHttpClient(agentName, client => client.BaseAddress = agentUri);
3838

39+
// use external service a2a based on http protocol, not json/rpc
3940
builder.Services.AddKeyedSingleton<A2AAgent>(
4041
agentName,
4142
(sp, _) =>
@@ -62,7 +63,7 @@ private static async Task<A2AAgent> CreateAgentAsync(HttpClient httpClient, Uri
6263
ArgumentNullException.ThrowIfNull(agentHostUri);
6364

6465
var client = new A2AClient(agentHostUri, httpClient);
65-
// resolve `agent card` from a2a discovery endpoint `.well-known/agent-card.json`
66+
// resolve `agent card` from a2a http discovery endpoint `.well-known/agent-card.json` in the external service
6667
var cardResolver = new A2ACardResolver(
6768
baseUrl: agentHostUri,
6869
httpClient: httpClient,

src/BuildingBlocks/AI/MCP/DependencyInjectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,7 @@ public static void AddStdioMcpClient(
195195
WorkingDirectory = workingDirectory,
196196
};
197197

198+
// use JSON-RPC 2.0 over stdio
198199
StdioClientTransport stdioTransport = new(stdioOptions, loggerFactory);
199200

200201
McpClient mcpClient = McpClient

src/BuildingBlocks/AI/SemanticKernel/DependencyInjectionExtensions.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ namespace BuildingBlocks.AI.SemanticKernel;
1818

1919
public static class DependencyInjectionExtensions
2020
{
21-
private const string ActivitySourceName = "Microsoft.SemanticKernel*";
22-
2321
public static IHostApplicationBuilder AddSemanticKernel(this IHostApplicationBuilder builder)
2422
{
2523
var options = builder.Configuration.BindOptions<SemanticKernelOptions>();
@@ -147,10 +145,12 @@ private static void AddOpenTelemetry(IHostApplicationBuilder builder)
147145
// https://learn.microsoft.com/en-us/semantic-kernel/concepts/enterprise-readiness/observability/telemetry-with-aspire-dashboard?tabs=Powershell&pivots=programming-language-csharp
148146
AppContext.SetSwitch("Microsoft.SemanticKernel.Experimental.GenAI.EnableOTelDiagnosticsSensitive", true);
149147

148+
var activitySourceName = "Microsoft.SemanticKernel*";
149+
150150
builder
151151
.Services.AddOpenTelemetry()
152-
.WithTracing(x => x.AddSource(ActivitySourceName))
153-
.WithMetrics(x => x.AddMeter(ActivitySourceName));
152+
.WithTracing(x => x.AddSource(activitySourceName))
153+
.WithMetrics(x => x.AddMeter(activitySourceName));
154154

155155
builder
156156
.Services.AddOpenTelemetry()

src/BuildingBlocks/AI/SemanticKernel/SemanticKernelExecutionSettings.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ public static PromptExecutionSettings GetProviderExecutionSettings(SemanticKerne
5353

5454
return new OllamaPromptExecutionSettings
5555
{
56+
FunctionChoiceBehavior = FunctionChoiceBehavior.Auto(
57+
options: new FunctionChoiceBehaviorOptions { RetainArgumentTypes = true }
58+
),
5659
Temperature = semanticKernelOptions.Temperature,
5760
ExtensionData = ollamaMergedExtensionData,
5861
};

src/BuildingBlocks/AI/SemanticKernel/SemanticKernelOptions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ public class SemanticKernelOptions
1616
public ProviderType EmbeddingProviderType { get; set; } = ProviderType.Ollama;
1717
public float Temperature { get; set; } = 0.8f;
1818
public double? SearchThreshold { get; set; }
19+
public int MaximumInvocationCount { get; set; }
1920

2021
public Dictionary<string, object> ChatExtensionData { get; set; } = new();
2122
}

src/BuildingBlocks/BuildingBlocks.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
<PackageReference Include="Microsoft.AspNetCore.OpenApi"/>
1717
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" />
1818
<PackageReference Include="Scalar.AspNetCore"/>
19+
<PackageReference Include="Spectre.Console" />
1920
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI"/>
2021
<PackageReference Include="System.Net.Http.Json" />
2122
<PackageReference Include="System.Text.Json" />

src/BuildingBlocks/VectorDB/SearchServices/SemanticSearch.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
using Microsoft.Extensions.AI;
1111
using Microsoft.Extensions.Options;
1212
using Microsoft.Extensions.VectorData;
13+
using Microsoft.SemanticKernel;
1314
using Microsoft.SemanticKernel.ChatCompletion;
1415

1516
namespace BuildingBlocks.VectorDB.SearchServices;
@@ -18,14 +19,15 @@ public sealed class SemanticSearch(
1819
IChatCompletionService chatCompletionService,
1920
IEmbeddingGenerator<string, Embedding<float>> embeddingGenerator,
2021
VectorStore vectorStore,
22+
Kernel kernel,
2123
IOptions<SemanticKernelOptions> semanticKernelOptions
2224
) : ISemanticSearch
2325
{
2426
private readonly SemanticKernelOptions _semanticKernelOptions = semanticKernelOptions.Value;
2527

2628
private const string InitPrompt =
2729
@"
28-
You are an intelligent, friendly e-commerce assistant designed to help shoppers understand their search results.
30+
You are an intelligent, friendly GenAI-Eshop assistant designed to help users understand their search results.
2931
3032
Follow these guidelines in every response:
3133
- Always respond in a warm, professional, and conversational tone.
@@ -58,19 +60,20 @@ public async Task<VectorSearchResult<TEntity>> HybridSearchAsync<TVectorEntity,
5860

5961
var collection = vectorStore.GetCollection<Guid, TVectorEntity>(typeof(TVectorEntity).Name.Underscore());
6062
await collection.EnsureCollectionExistsAsync(cancellationToken);
61-
var vectorCollection = (IKeywordHybridSearchable<TVectorEntity>)collection;
6263

6364
// https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/hybrid-search?pivots=programming-language-csharp#top-and-skip
6465
var options = new HybridSearchOptions<TVectorEntity>
6566
{
6667
VectorProperty = r => r.Vector,
68+
// field to search on the full-text search column with `IsFullTextIndexed=true` attribute
6769
AdditionalProperty = fullTextSearchFiled ?? (r => r.Description),
6870
Skip = skip,
6971
IncludeVectors = false,
7072
// https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/vector-search?pivots=programming-language-csharp#filter
7173
Filter = filter,
7274
};
7375

76+
var vectorCollection = (IKeywordHybridSearchable<TVectorEntity>)collection;
7477
// https://learn.microsoft.com/en-us/semantic-kernel/concepts/vector-store-connectors/hybrid-search?pivots=programming-language-csharp
7578
// keywords will use to search on full-text search column with `IsFullTextIndexed=true` attribute
7679
var searchResults = vectorCollection.HybridSearchAsync(
@@ -146,7 +149,8 @@ public async Task<VectorSearchResult<TEntity>> HybridSearchAsync<TVectorEntity,
146149
var aiResponse = await chatCompletionService.GetChatMessageContentAsync(
147150
chatHistory: history,
148151
// https://ollama.com/blog/thinking
149-
executionSettings: SemanticKernelExecutionSettings.GetDefaultSettings(_semanticKernelOptions),
152+
executionSettings: SemanticKernelExecutionSettings.GetProviderExecutionSettings(_semanticKernelOptions),
153+
kernel: kernel,
150154
cancellationToken: cancellationToken
151155
);
152156

@@ -173,9 +177,6 @@ public async Task<VectorSearchResult<TEntity>> SemanticSearchAsync<TVectorEntity
173177
where TVectorEntity : VectorEntityBase
174178
where TEntity : Entity
175179
{
176-
// https://learn.microsoft.com/en-us/semantic-kernel/concepts/ai-services/embedding-generation/?tabs=csharp-Ollama&pivots=programming-language-csharp#using-text-embedding-generation-services
177-
var vector = await embeddingGenerator.GenerateVectorAsync(searchTerm, cancellationToken: cancellationToken);
178-
179180
var collection = vectorStore.GetCollection<Guid, TVectorEntity>(typeof(TVectorEntity).Name.Underscore());
180181
await collection.EnsureCollectionExistsAsync(cancellationToken);
181182

@@ -188,6 +189,8 @@ public async Task<VectorSearchResult<TEntity>> SemanticSearchAsync<TVectorEntity
188189
Filter = filter,
189190
};
190191

192+
// https://learn.microsoft.com/en-us/semantic-kernel/concepts/ai-services/embedding-generation/?tabs=csharp-Ollama&pivots=programming-language-csharp#using-text-embedding-generation-services
193+
var vector = await embeddingGenerator.GenerateVectorAsync(searchTerm, cancellationToken: cancellationToken);
191194
var searchResults = collection.SearchAsync(
192195
searchValue: vector,
193196
top: take,
@@ -265,7 +268,8 @@ Make the response sound natural and helpful to the user.
265268
// https://ollama.com/blog/thinking
266269
// - in ollama cli we can `ollama run qwen3:0.6b --think=false` to turn off thinking
267270
// - in ollama api with passing `think=false` as parameter
268-
executionSettings: SemanticKernelExecutionSettings.GetDefaultSettings(_semanticKernelOptions),
271+
executionSettings: SemanticKernelExecutionSettings.GetProviderExecutionSettings(_semanticKernelOptions),
272+
kernel: kernel,
269273
cancellationToken: cancellationToken
270274
);
271275

0 commit comments

Comments
 (0)