Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Интерфейс IEmbeddingGenerator<TInput,TEmbedding> представляет универсальный генератор эмбеддингов. Для параметров универсального типа TInput — это тип встраиваемых входных значений, а TEmbedding — это тип создаваемого встраивания, который наследует от класса Embedding.
Класс Embedding служит базовым классом для внедрений, созданных IEmbeddingGenerator. Он предназначен для хранения метаданных и данных, связанных с внедрением, и управления ими. Производные типы, такие как Embedding<T>, предоставляют конкретные данные векторов вложения. Например, объект Embedding<float> предоставляет свойство ReadOnlyMemory<float> Vector { get; } для доступа к его встроенным данным.
Интерфейс IEmbeddingGenerator определяет метод асинхронной генерации векторных представлений для коллекции входных значений с поддержкой необязательной конфигурации и возможности отмены. Он также предоставляет метаданные, описывающие генератор, и позволяет получить строго типизированные службы, которые могут быть предоставлены генератором или ее базовыми службами.
Создание встраиваний
Основная операция, выполняемая с IEmbeddingGenerator<TInput,TEmbedding>, — генерация внедрений, которая осуществляется с помощью метода 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()));
}
Методы расширения акселератора также существуют для упрощения распространенных случаев, таких как создание вектора внедрения из одного входного ввода.
ReadOnlyMemory<float> vector = await generator.GenerateVectorAsync("What is AI?");
Конвейеры функциональных возможностей
Как и в случае с IChatClient, реализации IEmbeddingGenerator могут быть многослойными.
Microsoft.Extensions.AI предоставляет делегированную реализацию IEmbeddingGenerator, предназначенную для кэширования и телеметрии.
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 позволяет создавать пользовательские решения на основе промежуточного программного обеспечения, расширяющие функциональные возможности IEmbeddingGenerator. Класс DelegatingEmbeddingGenerator<TInput,TEmbedding> — это реализация интерфейса IEmbeddingGenerator<TInput, TEmbedding>, который служит базовым классом для создания генераторов внедрения, которые делегируют свои операции другому экземпляру IEmbeddingGenerator<TInput, TEmbedding>. Он позволяет связывать несколько генераторов в любом порядке, передавая вызовы через базовый генератор. Класс предоставляет реализации по умолчанию для таких методов, как GenerateAsync и Dispose, которые перенаправляют вызовы к внутреннему экземпляру генератора, обеспечивая гибкую и модульную генерацию вложений.
Ниже приведен пример реализации такого делегированного генератора встраивания, который ограничивает количество запросов на создание встраивания.
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);
}
}
Затем это можно уложить слоями вокруг произвольного IEmbeddingGenerator<string, Embedding<float>> для ограничения скорости выполнения всех операций генерации встраивания.
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()));
}
Таким образом, RateLimitingEmbeddingGenerator можно комбинировать с другими экземплярами IEmbeddingGenerator<string, Embedding<float>>, чтобы обеспечить функциональность ограничения скорости.
Примеры реализации
Большинству пользователей не нужно реализовать IEmbeddingGenerator интерфейс. Тем не менее, если вы автор библиотеки, возможно, полезно ознакомиться с этими примерами реализации.
В следующем коде показано, как SampleEmbeddingGenerator класс реализует IEmbeddingGenerator<TInput,TEmbedding> интерфейс. Он имеет основной конструктор, который принимает конечную точку и идентификатор модели, которые используются для идентификации генератора. Он также реализует метод GenerateAsync(IEnumerable<TInput>, EmbeddingGenerationOptions, CancellationToken) для создания эмбеддингов для коллекции входных значений.
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() { }
}
Эта примерная реализация просто создает случайные векторы внедрения. Более реалистичную и конкретную реализацию можно найти в OpenTelemetryEmbeddingGenerator.cs.