Skip to main content

Embeddings

Embedding providers turn text into numeric vectors. The vector is what a vector store indexes, what cosine similarity measures, and what hybrid search combines with BM25.

LogicGrid.Memory serves three providers — local (Ollama) OpenAI Client and OpenAI compatible hosted-API servers (vLLM, TEI, Gemini).

dotnet add package LogicGrid.Memory

EmbeddingClientBase contract

public abstract class EmbeddingClientBase
{
public abstract string ModelName { get; }
public abstract int Dimensions { get; }

public abstract Task<float[]> EmbedAsync(
string text, CancellationToken ct = default);

// Override for providers with native batching (OpenAI, vLLM, TEI).
// Default implementation calls EmbedAsync in a loop.
public virtual Task<float[][]> EmbedBatchAsync(
IList<string> texts, CancellationToken ct = default);
}

Dimensions is sometimes 0 until the first call (Ollama discovers it from the response); pass the known dimension count to the constructor when you have it to avoid that round-trip.

OllamaEmbeddingClient

public OllamaEmbeddingClient(
string baseUrl = "http://localhost:11434",
string defaultModel = "nomic-embed-text",
int dimensions = 0) // 0 = discover on first call

Common used models

ModelDimensionsWhen to use
nomic-embed-text (default)768General-purpose, balanced quality/size.
mxbai-embed-large1024Higher quality, slightly slower.
bge-m31024Multilingual.

How to use it

var embedder = new OllamaEmbeddingClient(defaultModel: "nomic-embed-text");
var vec = await embedder.EmbedAsync("Hybrid search combines dense and sparse retrieval.");
Console.WriteLine($"Dimensions: {embedder.Dimensions}"); // 768

OpenAiEmbeddingClient

public OpenAiEmbeddingClient(
string apiKey,
string defaultModel = "text-embedding-3-small",
int dimensions = 1536)

The OpenAI API. text-embedding-3-small is the cheap default; text-embedding-3-large is the higher-quality option.

How to use it

var embedder = new OpenAiEmbeddingClient(
apiKey: Environment.GetEnvironmentVariable("OPENAI_API_KEY")!,
defaultModel: "text-embedding-3-small");

OpenAiCompatibleEmbeddingClient

public OpenAiCompatibleEmbeddingClient(
string baseUrl,
string defaultModel,
int dimensions = 0,
string? apiKey = null)

Anything that exposes the OpenAI Embeddings API at /v1/embeddings: vLLM, TEI (HuggingFace Text Embeddings Inference), LM Studio, Gemini via its OpenAI-compatible endpoint.

// vLLM serving an embedding model locally
var vllm = new OpenAiCompatibleEmbeddingClient(
baseUrl: "http://localhost:8000",
defaultModel: "BAAI/bge-large-en-v1.5",
dimensions: 1024);

// TEI
var tei = new OpenAiCompatibleEmbeddingClient(
baseUrl: "http://localhost:3000",
defaultModel: "BAAI/bge-base-en-v1.5",
dimensions: 768);

Batch embedding

EmbedBatchAsync is significantly cheaper per item — every provider batches under the hood. The RAG pipeline uses it automatically when ingesting documents.

var vectors = await embedder.EmbedBatchAsync(new[]
{
"First chunk.",
"Second chunk.",
"Third chunk.",
});

Where next