Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Интерфейс 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.