From a8ffe2557e9b30d2cb91cb8c8f693e6071e979ec Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 14 Nov 2024 08:21:27 -0800 Subject: [PATCH 1/2] Update EmbeddingGeneratorBuilder APIs to match new ChatClientBuilder pattern --- .../ChatCompletion/ChatClientBuilder.cs | 4 +- ...lientBuilderServiceCollectionExtensions.cs | 4 +- .../Embeddings/EmbeddingGeneratorBuilder.cs | 38 +++++---- ...ratorBuilderServiceCollectionExtensions.cs | 78 +++++++++++++------ ...AzureAIInferenceEmbeddingGeneratorTests.cs | 4 +- .../EmbeddingGeneratorIntegrationTests.cs | 8 +- .../OllamaEmbeddingGeneratorTests.cs | 4 +- .../OpenAIEmbeddingGeneratorTests.cs | 8 +- ...ConfigureOptionsEmbeddingGeneratorTests.cs | 7 +- ...istributedCachingEmbeddingGeneratorTest.cs | 4 +- .../EmbeddingGeneratorBuilderTests.cs | 38 +++++---- .../LoggingEmbeddingGeneratorTests.cs | 4 +- 12 files changed, 121 insertions(+), 80 deletions(-) diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilder.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilder.cs index abbf4776d51..dc902c8407a 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilder.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilder.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.AI; /// A builder for creating pipelines of . public sealed class ChatClientBuilder { - private Func _innerClientFactory; + private readonly Func _innerClientFactory; /// The registered client factory instances. private List>? _clientFactories; @@ -30,7 +30,7 @@ public ChatClientBuilder(Func innerClientFactory) _innerClientFactory = Throw.IfNull(innerClientFactory); } - /// Returns an that represents the entire pipeline. Calls to this instance will pass through each of the pipeline stages in turn. + /// Builds an that represents the entire pipeline. Calls to this instance will pass through each of the pipeline stages in turn. /// /// The that should provide services to the instances. /// If null, an empty will be used. diff --git a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilderServiceCollectionExtensions.cs b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilderServiceCollectionExtensions.cs index a057a507f24..c3d8ab88edb 100644 --- a/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilderServiceCollectionExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.AI/ChatCompletion/ChatClientBuilderServiceCollectionExtensions.cs @@ -37,7 +37,7 @@ public static ChatClientBuilder AddChatClient( return builder; } - /// Registers a singleton in the . + /// Registers a keyed singleton in the . /// The to which the client should be added. /// The key with which to associate the client. /// The inner that represents the underlying backend. @@ -49,7 +49,7 @@ public static ChatClientBuilder AddKeyedChatClient( IChatClient innerClient) => AddKeyedChatClient(serviceCollection, serviceKey, _ => innerClient); - /// Registers a singleton in the . + /// Registers a keyed singleton in the . /// The to which the client should be added. /// The key with which to associate the client. /// A callback that produces the inner that represents the underlying backend. diff --git a/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilder.cs b/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilder.cs index 96c4c92d4a9..7983ca495bf 100644 --- a/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilder.cs +++ b/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilder.cs @@ -13,39 +13,45 @@ namespace Microsoft.Extensions.AI; public sealed class EmbeddingGeneratorBuilder where TEmbedding : Embedding { + private readonly Func> _innerGeneratorFactory; + /// The registered client factory instances. private List, IEmbeddingGenerator>>? _generatorFactories; /// Initializes a new instance of the class. - /// The service provider to use for dependency injection. - public EmbeddingGeneratorBuilder(IServiceProvider? services = null) + /// The inner that represents the underlying backend. + public EmbeddingGeneratorBuilder(IEmbeddingGenerator innerGenerator) { - Services = services ?? EmptyServiceProvider.Instance; + _ = Throw.IfNull(innerGenerator); + _innerGeneratorFactory = _ => innerGenerator; } - /// Gets the associated with the builder instance. - public IServiceProvider Services { get; } + /// Initializes a new instance of the class. + /// A callback that produces the inner that represents the underlying backend. + public EmbeddingGeneratorBuilder(Func> innerGeneratorFactory) + { + _innerGeneratorFactory = Throw.IfNull(innerGeneratorFactory); + } /// - /// Builds an instance of using the specified inner generator. + /// Builds an that represents the entire pipeline. Calls to this instance will pass through each of the pipeline stages in turn. /// - /// The inner generator to use. - /// An instance of . - /// - /// If there are any factories registered with this builder, is used as a seed to - /// the last factory, and the result of each factory delegate is passed to the previously registered factory. - /// The final result is then returned from this call. - /// - public IEmbeddingGenerator Use(IEmbeddingGenerator innerGenerator) + /// + /// The that should provide services to the instances. + /// If null, an empty will be used. + /// + /// An instance of that represents the entire pipeline. + public IEmbeddingGenerator Build(IServiceProvider? services = null) { - var embeddingGenerator = Throw.IfNull(innerGenerator); + services ??= EmptyServiceProvider.Instance; + var embeddingGenerator = _innerGeneratorFactory(services); // To match intuitive expectations, apply the factories in reverse order, so that the first factory added is the outermost. if (_generatorFactories is not null) { for (var i = _generatorFactories.Count - 1; i >= 0; i--) { - embeddingGenerator = _generatorFactories[i](Services, embeddingGenerator) ?? + embeddingGenerator = _generatorFactories[i](services, embeddingGenerator) ?? throw new InvalidOperationException( $"The {nameof(IEmbeddingGenerator)} entry at index {i} returned null. " + $"Ensure that the callbacks passed to {nameof(Use)} return non-null {nameof(IEmbeddingGenerator)} instances."); diff --git a/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilderServiceCollectionExtensions.cs b/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilderServiceCollectionExtensions.cs index 4f2eddf6b1b..1c57fb08215 100644 --- a/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilderServiceCollectionExtensions.cs +++ b/src/Libraries/Microsoft.Extensions.AI/Embeddings/EmbeddingGeneratorBuilderServiceCollectionExtensions.cs @@ -10,44 +10,74 @@ namespace Microsoft.Extensions.DependencyInjection; /// Provides extension methods for registering with a . public static class EmbeddingGeneratorBuilderServiceCollectionExtensions { - /// Adds a embedding generator to the . + /// Registers a singleton embedding generator in the . /// The type from which embeddings will be generated. /// The type of embeddings to generate. - /// The to which the generator should be added. - /// The factory to use to construct the instance. - /// The collection. - /// The generator is registered as a scoped service. - public static IServiceCollection AddEmbeddingGenerator( - this IServiceCollection services, - Func, IEmbeddingGenerator> generatorFactory) + /// The to which the generator should be added. + /// The inner that represents the underlying backend. + /// An that can be used to build a pipeline around the inner generator. + /// The generator is registered as a singleton service. + public static EmbeddingGeneratorBuilder AddEmbeddingGenerator( + this IServiceCollection serviceCollection, + IEmbeddingGenerator innerGenerator) + where TEmbedding : Embedding + => AddEmbeddingGenerator(serviceCollection, _ => innerGenerator); + + /// Registers a singleton embedding generator in the . + /// The type from which embeddings will be generated. + /// The type of embeddings to generate. + /// The to which the generator should be added. + /// A callback that produces the inner that represents the underlying backend. + /// An that can be used to build a pipeline around the inner generator. + /// The generator is registered as a singleton service. + public static EmbeddingGeneratorBuilder AddEmbeddingGenerator( + this IServiceCollection serviceCollection, + Func> innerGeneratorFactory) where TEmbedding : Embedding { - _ = Throw.IfNull(services); - _ = Throw.IfNull(generatorFactory); + _ = Throw.IfNull(serviceCollection); + _ = Throw.IfNull(innerGeneratorFactory); - return services.AddScoped(services => - generatorFactory(new EmbeddingGeneratorBuilder(services))); + var builder = new EmbeddingGeneratorBuilder(innerGeneratorFactory); + _ = serviceCollection.AddSingleton(builder.Build); + return builder; } - /// Adds an embedding generator to the . + /// Registers a keyed singleton embedding generator in the . + /// The type from which embeddings will be generated. + /// The type of embeddings to generate. + /// The to which the generator should be added. + /// The key with which to associated the generator. + /// The inner that represents the underlying backend. + /// An that can be used to build a pipeline around the inner generator. + /// The generator is registered as a singleton service. + public static EmbeddingGeneratorBuilder AddKeyedEmbeddingGenerator( + this IServiceCollection serviceCollection, + object serviceKey, + IEmbeddingGenerator innerGenerator) + where TEmbedding : Embedding + => AddKeyedEmbeddingGenerator(serviceCollection, serviceKey, _ => innerGenerator); + + /// Registers a keyed singleton embedding generator in the . /// The type from which embeddings will be generated. /// The type of embeddings to generate. - /// The to which the service should be added. + /// The to which the generator should be added. /// The key with which to associated the generator. - /// The factory to use to construct the instance. - /// The collection. - /// The generator is registered as a scoped service. - public static IServiceCollection AddKeyedEmbeddingGenerator( - this IServiceCollection services, + /// A callback that produces the inner that represents the underlying backend. + /// An that can be used to build a pipeline around the inner generator. + /// The generator is registered as a singleton service. + public static EmbeddingGeneratorBuilder AddKeyedEmbeddingGenerator( + this IServiceCollection serviceCollection, object serviceKey, - Func, IEmbeddingGenerator> generatorFactory) + Func> innerGeneratorFactory) where TEmbedding : Embedding { - _ = Throw.IfNull(services); + _ = Throw.IfNull(serviceCollection); _ = Throw.IfNull(serviceKey); - _ = Throw.IfNull(generatorFactory); + _ = Throw.IfNull(innerGeneratorFactory); - return services.AddKeyedScoped(serviceKey, (services, _) => - generatorFactory(new EmbeddingGeneratorBuilder(services))); + var builder = new EmbeddingGeneratorBuilder(innerGeneratorFactory); + _ = serviceCollection.AddKeyedSingleton(serviceKey, (services, _) => builder.Build(services)); + return builder; } } diff --git a/test/Libraries/Microsoft.Extensions.AI.AzureAIInference.Tests/AzureAIInferenceEmbeddingGeneratorTests.cs b/test/Libraries/Microsoft.Extensions.AI.AzureAIInference.Tests/AzureAIInferenceEmbeddingGeneratorTests.cs index abd5f609ed2..843766515b2 100644 --- a/test/Libraries/Microsoft.Extensions.AI.AzureAIInference.Tests/AzureAIInferenceEmbeddingGeneratorTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.AzureAIInference.Tests/AzureAIInferenceEmbeddingGeneratorTests.cs @@ -63,10 +63,10 @@ public void GetService_SuccessfullyReturnsUnderlyingClient() Assert.Same(embeddingGenerator, embeddingGenerator.GetService>>()); Assert.Same(client, embeddingGenerator.GetService()); - using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>() + using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>(embeddingGenerator) .UseOpenTelemetry() .UseDistributedCache(new MemoryDistributedCache(Options.Options.Create(new MemoryDistributedCacheOptions()))) - .Use(embeddingGenerator); + .Build(); Assert.NotNull(pipeline.GetService>>()); Assert.NotNull(pipeline.GetService>>()); diff --git a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs index 70eb6a31283..7ba3878385b 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Integration.Tests/EmbeddingGeneratorIntegrationTests.cs @@ -81,10 +81,10 @@ public virtual async Task Caching_SameOutputsForSameInput() { SkipIfNotEnabled(); - using var generator = new EmbeddingGeneratorBuilder>() + using var generator = new EmbeddingGeneratorBuilder>(CreateEmbeddingGenerator()!) .UseDistributedCache(new MemoryDistributedCache(Options.Options.Create(new MemoryDistributedCacheOptions()))) .UseCallCounting() - .Use(CreateEmbeddingGenerator()!); + .Build(); string input = "Red, White, and Blue"; var embedding1 = await generator.GenerateEmbeddingAsync(input); @@ -110,9 +110,9 @@ public virtual async Task OpenTelemetry_CanEmitTracesAndMetrics() .AddInMemoryExporter(activities) .Build(); - var embeddingGenerator = new EmbeddingGeneratorBuilder>() + var embeddingGenerator = new EmbeddingGeneratorBuilder>(CreateEmbeddingGenerator()!) .UseOpenTelemetry(sourceName: sourceName) - .Use(CreateEmbeddingGenerator()!); + .Build(); _ = await embeddingGenerator.GenerateEmbeddingAsync("Hello, world!"); diff --git a/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaEmbeddingGeneratorTests.cs b/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaEmbeddingGeneratorTests.cs index 541aab244fe..6dd8b82d986 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaEmbeddingGeneratorTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Ollama.Tests/OllamaEmbeddingGeneratorTests.cs @@ -29,10 +29,10 @@ public void GetService_SuccessfullyReturnsUnderlyingClient() Assert.Same(generator, generator.GetService()); Assert.Same(generator, generator.GetService>>()); - using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>() + using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>(generator) .UseOpenTelemetry() .UseDistributedCache(new MemoryDistributedCache(Options.Options.Create(new MemoryDistributedCacheOptions()))) - .Use(generator); + .Build(); Assert.NotNull(pipeline.GetService>>()); Assert.NotNull(pipeline.GetService>>()); diff --git a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIEmbeddingGeneratorTests.cs b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIEmbeddingGeneratorTests.cs index 50b64fc9196..37a45f93441 100644 --- a/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIEmbeddingGeneratorTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.OpenAI.Tests/OpenAIEmbeddingGeneratorTests.cs @@ -78,10 +78,10 @@ public void GetService_OpenAIClient_SuccessfullyReturnsUnderlyingClient() Assert.NotNull(embeddingGenerator.GetService()); - using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>() + using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>(embeddingGenerator) .UseOpenTelemetry() .UseDistributedCache(new MemoryDistributedCache(Options.Options.Create(new MemoryDistributedCacheOptions()))) - .Use(embeddingGenerator); + .Build(); Assert.NotNull(pipeline.GetService>>()); Assert.NotNull(pipeline.GetService>>()); @@ -100,10 +100,10 @@ public void GetService_EmbeddingClient_SuccessfullyReturnsUnderlyingClient() Assert.Same(embeddingGenerator, embeddingGenerator.GetService>>()); Assert.Same(openAIClient, embeddingGenerator.GetService()); - using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>() + using IEmbeddingGenerator> pipeline = new EmbeddingGeneratorBuilder>(embeddingGenerator) .UseOpenTelemetry() .UseDistributedCache(new MemoryDistributedCache(Options.Options.Create(new MemoryDistributedCacheOptions()))) - .Use(embeddingGenerator); + .Build(); Assert.NotNull(pipeline.GetService>>()); Assert.NotNull(pipeline.GetService>>()); diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/ConfigureOptionsEmbeddingGeneratorTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/ConfigureOptionsEmbeddingGeneratorTests.cs index 70674646bd1..ecb96c993ea 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/ConfigureOptionsEmbeddingGeneratorTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/ConfigureOptionsEmbeddingGeneratorTests.cs @@ -20,7 +20,8 @@ public void ConfigureOptionsEmbeddingGenerator_InvalidArgs_Throws() [Fact] public void ConfigureOptions_InvalidArgs_Throws() { - var builder = new EmbeddingGeneratorBuilder>(); + using var innerGenerator = new TestEmbeddingGenerator(); + var builder = new EmbeddingGeneratorBuilder>(innerGenerator); Assert.Throws("configure", () => builder.ConfigureOptions(null!)); } @@ -44,7 +45,7 @@ public async Task ConfigureOptions_ReturnedInstancePassedToNextClient(bool nullP } }; - using var generator = new EmbeddingGeneratorBuilder>() + using var generator = new EmbeddingGeneratorBuilder>(innerGenerator) .ConfigureOptions(options => { Assert.NotSame(providedOptions, options); @@ -59,7 +60,7 @@ public async Task ConfigureOptions_ReturnedInstancePassedToNextClient(bool nullP returnedOptions = options; }) - .Use(innerGenerator); + .Build(); var embeddings = await generator.GenerateAsync([], providedOptions, cts.Token); Assert.Same(expectedEmbeddings, embeddings); diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs index f9356ef45c9..55cc206ebfc 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/DistributedCachingEmbeddingGeneratorTest.cs @@ -321,12 +321,12 @@ public async Task CanResolveIDistributedCacheFromDI() return Task.FromResult>>([_expectedEmbedding]); }, }; - using var outer = new EmbeddingGeneratorBuilder>(services) + using var outer = new EmbeddingGeneratorBuilder>(testGenerator) .UseDistributedCache(configure: instance => { instance.JsonSerializerOptions = TestJsonSerializerContext.Default.Options; }) - .Use(testGenerator); + .Build(services); // Act: Make a request that should populate the cache Assert.Empty(_storage.Keys); diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/EmbeddingGeneratorBuilderTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/EmbeddingGeneratorBuilderTests.cs index 357168c3b65..b25044992e8 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/EmbeddingGeneratorBuilderTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/EmbeddingGeneratorBuilderTests.cs @@ -13,32 +13,37 @@ public class EmbeddingGeneratorBuilderTests public void PassesServiceProviderToFactories() { var expectedServiceProvider = new ServiceCollection().BuildServiceProvider(); - using var expectedResult = new TestEmbeddingGenerator(); - var builder = new EmbeddingGeneratorBuilder>(expectedServiceProvider); + using var expectedOuterGenerator = new TestEmbeddingGenerator(); + using var expectedInnerGenerator = new TestEmbeddingGenerator(); - builder.Use((serviceProvider, innerClient) => + var builder = new EmbeddingGeneratorBuilder>(services => { - Assert.Same(expectedServiceProvider, serviceProvider); - return expectedResult; + Assert.Same(expectedServiceProvider, services); + return expectedInnerGenerator; }); - using var innerGenerator = new TestEmbeddingGenerator(); - Assert.Equal(expectedResult, builder.Use(innerGenerator)); + builder.Use((services, innerClient) => + { + Assert.Same(expectedServiceProvider, services); + return expectedOuterGenerator; + }); + + Assert.Equal(expectedOuterGenerator, builder.Build(expectedServiceProvider)); } [Fact] public void BuildsPipelineInOrderAdded() { // Arrange - using var expectedInnerService = new TestEmbeddingGenerator(); - var builder = new EmbeddingGeneratorBuilder>(); + using var expectedInnerGenerator = new TestEmbeddingGenerator(); + var builder = new EmbeddingGeneratorBuilder>(expectedInnerGenerator); builder.Use(next => new InnerServiceCapturingEmbeddingGenerator("First", next)); builder.Use(next => new InnerServiceCapturingEmbeddingGenerator("Second", next)); builder.Use(next => new InnerServiceCapturingEmbeddingGenerator("Third", next)); // Act - var first = (InnerServiceCapturingEmbeddingGenerator)builder.Use(expectedInnerService); + var first = (InnerServiceCapturingEmbeddingGenerator)builder.Build(); // Assert Assert.Equal("First", first.Name); @@ -46,29 +51,28 @@ public void BuildsPipelineInOrderAdded() Assert.Equal("Second", second.Name); var third = (InnerServiceCapturingEmbeddingGenerator)second.InnerGenerator; Assert.Equal("Third", third.Name); - Assert.Same(expectedInnerService, third.InnerGenerator); + Assert.Same(expectedInnerGenerator, third.InnerGenerator); } [Fact] public void DoesNotAcceptNullInnerService() { - Assert.Throws(() => new EmbeddingGeneratorBuilder>().Use((IEmbeddingGenerator>)null!)); + Assert.Throws(() => new EmbeddingGeneratorBuilder>((IEmbeddingGenerator>)null!)); } [Fact] public void DoesNotAcceptNullFactories() { - var builder = new EmbeddingGeneratorBuilder>(); - Assert.Throws(() => builder.Use((Func>, IEmbeddingGenerator>>)null!)); - Assert.Throws(() => builder.Use((Func>, IEmbeddingGenerator>>)null!)); + Assert.Throws(() => new EmbeddingGeneratorBuilder>((Func>>)null!)); } [Fact] public void DoesNotAllowFactoriesToReturnNull() { - var builder = new EmbeddingGeneratorBuilder>(); + using var innerGenerator = new TestEmbeddingGenerator(); + var builder = new EmbeddingGeneratorBuilder>(innerGenerator); builder.Use(_ => null!); - var ex = Assert.Throws(() => builder.Use(new TestEmbeddingGenerator())); + var ex = Assert.Throws(() => builder.Build()); Assert.Contains("entry at index 0", ex.Message); } diff --git a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/LoggingEmbeddingGeneratorTests.cs b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/LoggingEmbeddingGeneratorTests.cs index 5cd6267eb74..b8a342e5f73 100644 --- a/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/LoggingEmbeddingGeneratorTests.cs +++ b/test/Libraries/Microsoft.Extensions.AI.Tests/Embeddings/LoggingEmbeddingGeneratorTests.cs @@ -39,9 +39,9 @@ public async Task CompleteAsync_LogsStartAndCompletion(LogLevel level) }, }; - using IEmbeddingGenerator> generator = new EmbeddingGeneratorBuilder>(services) + using IEmbeddingGenerator> generator = new EmbeddingGeneratorBuilder>(innerGenerator) .UseLogging() - .Use(innerGenerator); + .Build(services); await generator.GenerateEmbeddingAsync("Blue whale"); From f7d9ece06bd6172a968b1ec38b96192942552720 Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Thu, 14 Nov 2024 08:28:12 -0800 Subject: [PATCH 2/2] Update READMEs --- .../Microsoft.Extensions.AI.Abstractions/README.md | 5 +++-- src/Libraries/Microsoft.Extensions.AI.Ollama/README.md | 7 +++---- src/Libraries/Microsoft.Extensions.AI.OpenAI/README.md | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Libraries/Microsoft.Extensions.AI.Abstractions/README.md b/src/Libraries/Microsoft.Extensions.AI.Abstractions/README.md index f02a0eff4a6..e13709cd932 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Abstractions/README.md +++ b/src/Libraries/Microsoft.Extensions.AI.Abstractions/README.md @@ -432,10 +432,11 @@ var tracerProvider = OpenTelemetry.Sdk.CreateTracerProviderBuilder() // Explore changing the order of the intermediate "Use" calls to see that impact // that has on what gets cached, traced, etc. -IEmbeddingGenerator> generator = new EmbeddingGeneratorBuilder>() +var generator = new EmbeddingGeneratorBuilder>( + new SampleEmbeddingGenerator(new Uri("http://coolsite.ai"), "my-custom-model")) .UseDistributedCache(new MemoryDistributedCache(Options.Create(new MemoryDistributedCacheOptions()))) .UseOpenTelemetry(sourceName) - .Use(new SampleEmbeddingGenerator(new Uri("http://coolsite.ai"), "my-custom-model")); + .Build(); var embeddings = await generator.GenerateAsync( [ diff --git a/src/Libraries/Microsoft.Extensions.AI.Ollama/README.md b/src/Libraries/Microsoft.Extensions.AI.Ollama/README.md index 1eae652e7c8..e468965b9a8 100644 --- a/src/Libraries/Microsoft.Extensions.AI.Ollama/README.md +++ b/src/Libraries/Microsoft.Extensions.AI.Ollama/README.md @@ -210,9 +210,9 @@ IDistributedCache cache = new MemoryDistributedCache(Options.Create(new MemoryDi IEmbeddingGenerator> ollamaGenerator = new OllamaEmbeddingGenerator(new Uri("http://localhost:11434/"), "all-minilm"); -IEmbeddingGenerator> generator = new EmbeddingGeneratorBuilder>() +IEmbeddingGenerator> generator = new EmbeddingGeneratorBuilder>(ollamaGenerator) .UseDistributedCache(cache) - .Use(ollamaGenerator); + .Build(); foreach (var prompt in new[] { "What is AI?", "What is .NET?", "What is AI?" }) { @@ -256,8 +256,7 @@ var builder = WebApplication.CreateBuilder(args); builder.Services.AddChatClient( new OllamaChatClient(new Uri("http://localhost:11434/"), "llama3.1")); -builder.Services.AddEmbeddingGenerator>(g => - g.Use(new OllamaEmbeddingGenerator(endpoint, "all-minilm"))); +builder.Services.AddEmbeddingGenerator(new OllamaEmbeddingGenerator(endpoint, "all-minilm")); var app = builder.Build(); diff --git a/src/Libraries/Microsoft.Extensions.AI.OpenAI/README.md b/src/Libraries/Microsoft.Extensions.AI.OpenAI/README.md index fa0e2956e86..dacafd33a7f 100644 --- a/src/Libraries/Microsoft.Extensions.AI.OpenAI/README.md +++ b/src/Libraries/Microsoft.Extensions.AI.OpenAI/README.md @@ -233,9 +233,9 @@ IEmbeddingGenerator> openAIGenerator = new OpenAIClient(Environment.GetEnvironmentVariable("OPENAI_API_KEY")) .AsEmbeddingGenerator("text-embedding-3-small"); -IEmbeddingGenerator> generator = new EmbeddingGeneratorBuilder>() +IEmbeddingGenerator> generator = new EmbeddingGeneratorBuilder>(openAIGenerator) .UseDistributedCache(cache) - .Use(openAIGenerator); + .Build(); foreach (var prompt in new[] { "What is AI?", "What is .NET?", "What is AI?" }) { @@ -284,8 +284,8 @@ builder.Services.AddSingleton(new OpenAIClient(builder.Configuration["OPENAI_API builder.Services.AddChatClient(services => services.GetRequiredService().AsChatClient("gpt-4o-mini")); -builder.Services.AddEmbeddingGenerator>(g => - g.Use(g.Services.GetRequiredService().AsEmbeddingGenerator("text-embedding-3-small"))); +builder.Services.AddEmbeddingGenerator(services => + services.GetRequiredService().AsEmbeddingGenerator("text-embedding-3-small")); var app = builder.Build();