Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować się zalogować lub zmienić katalog.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Interfejs IEmbeddingGenerator<TInput,TEmbedding> reprezentuje ogólny generator osadzonych elementów. W przypadku parametrów typu ogólnego, TInput jest typem wartości wejściowych, które są osadzane, a TEmbedding jest typem wygenerowanego osadzenia, który dziedziczy z klasy Embedding.
Klasa Embedding służy jako klasa bazowa dla osadzeń generowanych przez IEmbeddingGenerator. Jest ona przeznaczona do przechowywania metadanych i danych skojarzonych z osadzaniem i zarządzania nimi. Typy pochodne, takie jak Embedding<T>, zapewniają konkretne dane wektorów osadzania. Na przykład Embedding<float> udostępnia właściwość ReadOnlyMemory<float> Vector { get; }, która umożliwia dostęp do danych osadzania.
Interfejs IEmbeddingGenerator definiuje metodę do asynchronicznego generowania osadzeń dla kolekcji wartości wejściowych, z opcjonalną konfiguracją i obsługą anulowania. Udostępnia również metadane opisujące generator i umożliwia pobieranie mocno typowanych usług, które mogą być udostępniane przez generator lub podstawowe jego usługi.
Tworzenie osadzeń
Podstawowa operacja wykonywana przy użyciu IEmbeddingGenerator<TInput,TEmbedding> to generowanie osadzeń, które jest realizowane za pomocą metody GenerateAsync.
using Microsoft.Extensions.AI;
using OllamaSharp;
IEmbeddingGenerator<string, Embedding<float>> generator =
new OllamaApiClient(new Uri("http://localhost:11434/"), "phi3:mini");
foreach (Embedding<float> embedding in
await generator.GenerateAsync(["What is AI?", "What is .NET?"]))
{
Console.WriteLine(string.Join(", ", embedding.Vector.ToArray()));
}
Istnieją również metody rozszerzenia akceleratora, aby uprościć typowe przypadki, takie jak generowanie wektora osadzania z jednego wejścia.
ReadOnlyMemory<float> vector = await generator.GenerateVectorAsync("What is AI?");
Potoki funkcji
Podobnie jak w przypadku IChatClientimplementacje IEmbeddingGenerator mogą być warstwowe.
Microsoft.Extensions.AI dostarcza delegującą implementację dla IEmbeddingGenerator, która obsługuje buforowanie i telemetrię.
using Microsoft.Extensions.AI;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using OllamaSharp;
using OpenTelemetry.Trace;
// Configure OpenTelemetry exporter
string sourceName = Guid.NewGuid().ToString();
TracerProvider tracerProvider = OpenTelemetry.Sdk.CreateTracerProviderBuilder()
.AddSource(sourceName)
.AddConsoleExporter()
.Build();
// Explore changing the order of the intermediate "Use" calls to see
// what impact that has on what gets cached and traced.
IEmbeddingGenerator<string, Embedding<float>> generator = new EmbeddingGeneratorBuilder<string, Embedding<float>>(
new OllamaApiClient(new Uri("http://localhost:11434/"), "phi3:mini"))
.UseDistributedCache(
new MemoryDistributedCache(
Options.Create(new MemoryDistributedCacheOptions())))
.UseOpenTelemetry(sourceName: sourceName)
.Build();
GeneratedEmbeddings<Embedding<float>> embeddings = await generator.GenerateAsync(
[
"What is AI?",
"What is .NET?",
"What is AI?"
]);
foreach (Embedding<float> embedding in embeddings)
{
Console.WriteLine(string.Join(", ", embedding.Vector.ToArray()));
}
IEmbeddingGenerator umożliwia tworzenie niestandardowego oprogramowania pośredniczącego, które rozszerza funkcjonalność IEmbeddingGenerator. Klasa DelegatingEmbeddingGenerator<TInput,TEmbedding> to implementacja interfejsu IEmbeddingGenerator<TInput, TEmbedding>, który służy jako klasa bazowa do tworzenia generatorów osadzania, które delegują swoje operacje do innego wystąpienia IEmbeddingGenerator<TInput, TEmbedding>. Umożliwia łączenie wielu generatorów w dowolnej kolejności z przekazywaniem wywołań do bazowego generatora. Klasa udostępnia domyślne implementacje metod, takich jak GenerateAsync i Dispose, które przekazują wywołania do wewnętrznego wystąpienia generatora, umożliwiając elastyczne i modułowe generowanie osadzonych elementów.
Poniżej przedstawiono przykładową implementację takiego delegującego generatora osadzania, który ogranicza liczbę żądań generowania osadzania.
using Microsoft.Extensions.AI;
using System.Threading.RateLimiting;
public class RateLimitingEmbeddingGenerator(
IEmbeddingGenerator<string, Embedding<float>> innerGenerator, RateLimiter rateLimiter)
: DelegatingEmbeddingGenerator<string, Embedding<float>>(innerGenerator)
{
public override async Task<GeneratedEmbeddings<Embedding<float>>> GenerateAsync(
IEnumerable<string> values,
EmbeddingGenerationOptions? options = null,
CancellationToken cancellationToken = default)
{
using var lease = await rateLimiter.AcquireAsync(permitCount: 1, cancellationToken)
.ConfigureAwait(false);
if (!lease.IsAcquired)
{
throw new InvalidOperationException("Unable to acquire lease.");
}
return await base.GenerateAsync(values, options, cancellationToken);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
rateLimiter.Dispose();
}
base.Dispose(disposing);
}
}
Można to następnie warstwować wokół dowolnego IEmbeddingGenerator<string, Embedding<float>> , aby ograniczyć szybkość wszystkich operacji generowania osadzania.
using Microsoft.Extensions.AI;
using OllamaSharp;
using System.Threading.RateLimiting;
IEmbeddingGenerator<string, Embedding<float>> generator =
new RateLimitingEmbeddingGenerator(
new OllamaApiClient(new Uri("http://localhost:11434/"), "phi3:mini"),
new ConcurrencyLimiter(new()
{
PermitLimit = 1,
QueueLimit = int.MaxValue
}));
foreach (Embedding<float> embedding in
await generator.GenerateAsync(["What is AI?", "What is .NET?"]))
{
Console.WriteLine(string.Join(", ", embedding.Vector.ToArray()));
}
W ten sposób RateLimitingEmbeddingGenerator może być komponowany z innymi instancjami IEmbeddingGenerator<string, Embedding<float>> w celu zapewnienia funkcjonalności ograniczania szybkości.
Przykład wdrożenia
Większość użytkowników nie musi implementować interfejsu IEmbeddingGenerator . Jeśli jednak jesteś autorem biblioteki, warto zapoznać się z tymi przykładami implementacji.
Poniższy kod pokazuje, jak SampleEmbeddingGenerator klasa implementuje IEmbeddingGenerator<TInput,TEmbedding> interfejs. Ma podstawowy konstruktor, który akceptuje punkt końcowy i identyfikator modelu, który jest używany do identyfikowania generatora. Implementuje również metodę GenerateAsync(IEnumerable<TInput>, EmbeddingGenerationOptions, CancellationToken) generowania osadzeń dla kolekcji wartości wejściowych.
using Microsoft.Extensions.AI;
public sealed class SampleEmbeddingGenerator(
Uri endpoint, string modelId)
: IEmbeddingGenerator<string, Embedding<float>>
{
private readonly EmbeddingGeneratorMetadata _metadata =
new("SampleEmbeddingGenerator", endpoint, modelId);
public async Task<GeneratedEmbeddings<Embedding<float>>> GenerateAsync(
IEnumerable<string> values,
EmbeddingGenerationOptions? options = null,
CancellationToken cancellationToken = default)
{
// Simulate some async operation.
await Task.Delay(100, cancellationToken);
// Create random embeddings.
return [.. from value in values
select new Embedding<float>(
Enumerable.Range(0, 384)
.Select(_ => Random.Shared.NextSingle()).ToArray())];
}
public object? GetService(Type serviceType, object? serviceKey) =>
serviceKey is not null
? null
: serviceType == typeof(EmbeddingGeneratorMetadata)
? _metadata
: serviceType?.IsInstanceOfType(this) is true
? this
: null;
void IDisposable.Dispose() { }
}
Ta przykładowa implementacja generuje tylko losowe wektory osadzania. Aby uzyskać bardziej realistyczne, konkretne wdrożenie, zobacz OpenTelemetryEmbeddingGenerator.cs.