Open-Source Libraries
Rag.NET is built on a small set of open-source libraries. This page lists each dependency, where it is used, and why it was chosen over the alternatives.
ZeroAlloc ecosystem
All ZeroAlloc packages are authored and maintained by the same team as Rag.NET. They are zero-allocation, source-generator-driven libraries that keep the core pipeline free of reflection and boxing at runtime.
ZeroAlloc.Inject
Used in: Rag.NET (core)
Property injection for singleton pipeline behaviors. Annotate a property with [Inject] and the source generator wires it to the DI container at build time — no reflection, no constructor parameter lists that grow with every new dependency.
[Singleton]
public sealed class EmbeddingBehavior : IIngestionBehavior
{
[Inject] public IEmbeddingGenerator<string, Embedding<float>> EmbeddingGenerator { get; set; } = null!;
[Inject(Required = false)] public ILogger<EmbeddingBehavior>? Logger { get; set; }
...
}
Why not constructor injection? Behavior classes are singletons assembled by a pipeline builder. Optional services (loggers, feature-specific clients) would require nullable constructor parameters for every behavior. Property injection with Required = false expresses optionality at the declaration site without cluttering constructors.
ZeroAlloc.Pipeline
Used in: Rag.NET (core)
Source-generates the behavior-chain plumbing for IIngestionBehavior and IRetrievalBehavior. Each behavior receives a next delegate and decides whether to call it, short-circuit, or modify the context before passing it on — identical to ASP.NET Core middleware.
Why not a hand-rolled chain? The generator emits the PipelineIngestor and PipelineRetriever coordinator classes from a simple ordered list of behavior types. Adding or reordering a behavior requires changing one line in the builder, not updating wiring code.
ZeroAlloc.Results
Used in: Rag.NET (core), Rag.NET.Mediator
Result<T> (success/failure) and Result<T, E> (typed error) discriminated unions. Used for all internal LLM calls, vector store operations, and the public IRagPipeline API.
var result = await pipeline.IngestAsync(stream, metadata);
if (result.IsSuccess)
Console.WriteLine($"Stored {result.Value.ChunksStored} chunks");
else
Console.WriteLine($"Failed: {result.Error}");
Why not exceptions? Expected failures (LLM parse errors, malformed JSON, ingestion validation) should not unwind call stacks. Result<T> forces callers to handle both paths at the call site without try/catch blocks.
ZeroAlloc.Specification
Used in: Rag.NET (core)
ISpecification<T> interface and source-generated implementations. Used for post-retrieval filtering — HasTagSpec, DocumentIdSpec, and MinScoreSpec are composed at runtime from RetrievalOptions.Filter and applied in FilterBehavior.
var filter = new HasTagSpec("language", "csharp")
.And(new MinScoreSpec(0.7));
var results = await pipeline.RetrieveAsync("async patterns", new RetrievalOptions
{
Filter = filter
});
Why not LINQ predicates? ISpecification<T> exposes both IsSatisfiedBy(T) for in-process filtering and ToExpression() for potential push-down to a query engine. Specifications are also composable, testable in isolation, and named — HasTagSpec("language", "csharp") is more readable than an anonymous lambda.
ZeroAlloc.Validation
Used in: Rag.NET (core)
Declarative validation attributes for options and model classes. Applied to DocumentMetadata, ChunkingOptions, RetrievalOptions, and the ingestion pipeline to surface configuration errors early with descriptive messages.
Why not FluentValidation? ZeroAlloc.Validation is a source generator with zero runtime allocations. For a pipeline library where options objects are constructed on every call, avoiding heap pressure on the validation path matters.
ZeroAlloc.Mediator
Used in: Rag.NET.Mediator
Source-generated CQRS mediator. IngestCommand, RetrieveQuery, and DeleteCommand are dispatched through IMediator without reflection-based handler discovery.
Why not MediatR? MediatR uses reflection at dispatch time. ZeroAlloc.Mediator generates direct handler dispatch at build time — no dictionary lookups, no boxing. For applications that already depend on ZeroAlloc.Mediator for CQRS, this package adds Rag.NET pipeline operations as first-class mediator requests with no additional runtime overhead.
ZeroAlloc.ValueObjects
Used in: Rag.NET (core) — DocumentId
Source-generates Equals, GetHashCode, ==, !=, and ToString for partial class and partial struct types annotated with [ValueObject]. [EqualityMember] opts specific properties in when the default (all public properties) is not appropriate.
[ValueObject]
public sealed partial class DocumentId
{
[EqualityMember]
public string Value => _value; // backing field stays private
...
}
Why not record? DocumentId needs a custom JSON converter, custom implicit/explicit operators, and a ToString() that returns the bare value (not "DocumentId { Value = ... }"). Using record would add EqualityContract, Deconstruct, and with to the public API — none of which are appropriate for a typed identifier. [ValueObject] generates only what is needed.
Third-party libraries
AngleSharp
Used in: Rag.NET.Parsers.Html
HTML parsing and DOM traversal for HtmlDocumentParser. Produces a typed DOM from raw HTML so the parser can walk headings, extract text, strip navigation/footer elements, and convert anchor hrefs to inline text.
Why not HtmlAgilityPack? AngleSharp implements the WHATWG HTML5 parsing spec (the same spec browsers use). It handles malformed HTML consistently and provides a CSS selector API (QuerySelectorAll) that makes structural traversal straightforward.
DocumentFormat.OpenXml
Used in: Rag.NET.Parsers.Office
Microsoft's official Open XML SDK for reading .docx, .xlsx, and .pptx files without requiring Office to be installed. Used to extract text, heading levels, and page/sheet structure from Office documents.
PdfPig
Used in: Rag.NET.Parsers.Pdf
Pure .NET PDF text extraction. Reads PDF content streams to extract text with position information, enabling page-number tracking in DocumentSection.
Why not iTextSharp / PdfSharp? PdfPig is MIT-licensed, dependency-free, and actively maintained. It produces reliable text extraction with word/line bounding boxes that can be used for layout-aware chunking.
Npgsql + Pgvector
Used in: Rag.NET.VectorStores.PgVector
Npgsql is the standard .NET PostgreSQL driver. Pgvector adds pgvector extension support — the Vector type, distance operator bindings, and index hints. Together they power PgVectorStore.
Qdrant.Client
Used in: Rag.NET.VectorStores.Qdrant
Official gRPC client for Qdrant vector database. Used by QdrantVectorStore for upsert, search, and delete operations against a Qdrant collection.
Azure.Search.Documents
Used in: Rag.NET.VectorStores.AzureAISearch
Official Azure SDK client for Azure AI Search (formerly Cognitive Search). Used by AzureAISearchVectorStore for index management, document upload, vector search, and native hybrid search (BM25 + vector via SemanticSearch).
Octokit
Used in: Rag.NET.DataProviders.GitHub
Official GitHub API client for .NET. Used by the GitHub data provider to list repository contents and fetch file blobs for ingestion.
ModelContextProtocol
Used in: Rag.NET.Mcp
Official .NET SDK for the Model Context Protocol (MCP). Used to expose Rag.NET ingest, retrieve, and delete operations as MCP tools that can be called from any MCP-compatible client (Claude Desktop, VS Code Copilot, etc.).