NLP & RAG Tutorial
{: .no_toc }
Build powerful text processing and retrieval-augmented generation systems. {: .fs-6 .fw-300 }
Table of contents
{: .no_toc .text-delta }
- TOC {:toc}
Overview
AiDotNet provides 50+ RAG components for building intelligent document systems:
- Embeddings: Sentence Transformers, custom models
- Vector Stores: In-memory, FAISS, distributed
- Retrievers: Dense, sparse, hybrid
- Rerankers: Cross-encoder, ColBERT
Text Embeddings
Generate Embeddings
using AiDotNet.RetrievalAugmentedGeneration;
// Create embedding model
var embedder = new SentenceTransformerEmbeddings<float>(
model: "all-MiniLM-L6-v2");
// Single text
var embedding = embedder.Encode("Hello, world!");
Console.WriteLine($"Embedding dimension: {embedding.Length}"); // 384
// Batch encoding
var texts = new[] { "First document", "Second document" };
var embeddings = embedder.EncodeBatch(texts);
Similarity Search
// Compute cosine similarity
float similarity = embedder.ComputeSimilarity(
"machine learning",
"deep learning");
Console.WriteLine($"Similarity: {similarity:F3}"); // ~0.85
Vector Stores
In-Memory Store
var vectorStore = new InMemoryVectorStore<float>(
dimension: 384);
// Add documents
var docs = new[]
{
new Document { Id = "1", Text = "First document about AI" },
new Document { Id = "2", Text = "Second document about ML" }
};
await vectorStore.AddAsync(docs, embedder);
// Search
var results = await vectorStore.SearchAsync(
query: "artificial intelligence",
embedder: embedder,
topK: 5);
FAISS Store (For Large Datasets)
var faissStore = new FAISSVectorStore<float>(
dimension: 384,
indexType: FAISSIndexType.IVFFlat,
nlist: 100);
// Index millions of documents
await faissStore.AddAsync(documents, embedder);
// Fast search
var results = await faissStore.SearchAsync(query, embedder, topK: 10);
Retrieval-Augmented Generation (RAG)
Basic RAG Pipeline
using AiDotNet.RetrievalAugmentedGeneration;
// Build RAG pipeline
var rag = new RAGPipeline<float>()
.WithEmbeddings(new SentenceTransformerEmbeddings<float>())
.WithVectorStore(new InMemoryVectorStore<float>())
.WithRetriever(new DenseRetriever<float>(topK: 5))
.Build();
// Index documents
var documents = new[]
{
"AiDotNet is a .NET machine learning framework.",
"It supports 100+ neural network architectures.",
"GPU acceleration is available via CUDA."
};
await rag.IndexDocumentsAsync(documents);
// Query
var response = await rag.QueryAsync("What is AiDotNet?");
Console.WriteLine(response.Answer);
Console.WriteLine($"Sources: {string.Join(", ", response.SourceDocuments)}");
Advanced RAG with Reranking
var advancedRag = new RAGPipeline<float>()
.WithEmbeddings(new SentenceTransformerEmbeddings<float>("all-mpnet-base-v2"))
.WithVectorStore(new FAISSVectorStore<float>(768))
.WithRetriever(new HybridRetriever<float>(
denseWeight: 0.7f,
sparseWeight: 0.3f,
topK: 20))
.WithReranker(new CrossEncoderReranker<float>(
model: "cross-encoder/ms-marco-MiniLM-L-6-v2",
topK: 5))
.WithChunker(new RecursiveChunker(
chunkSize: 512,
chunkOverlap: 50))
.Build();
GraphRAG
Enhance RAG with knowledge graphs:
using AiDotNet.RetrievalAugmentedGeneration.Graph;
var graphRag = new GraphRAGPipeline<float>()
.WithEmbeddings(new SentenceTransformerEmbeddings<float>())
.WithKnowledgeGraph(new InMemoryKnowledgeGraph<float>())
.WithEntityExtractor(new NEREntityExtractor<float>())
.WithRelationExtractor(new RelationExtractor<float>())
.Build();
// Index with entity extraction
await graphRag.IndexDocumentsAsync(documents);
// Query with graph traversal
var response = await graphRag.QueryAsync(
"How are AI and machine learning related?");
Text Classification
using AiDotNet.Classification;
var texts = new[]
{
"This movie was amazing!",
"Terrible waste of time.",
"Pretty good overall."
};
var labels = new[] { 1, 0, 1 }; // positive/negative
var result = await new AiModelBuilder<float, string, int>()
.ConfigureModel(new TextClassifier<float>(
backbone: "distilbert-base-uncased",
numClasses: 2))
.ConfigureTokenizer(new BertTokenizer())
.BuildAsync(texts, labels);
// Use result.Predict() directly (facade pattern)
var prediction = result.Predict("Great film!");
Named Entity Recognition
using AiDotNet.NLP;
var ner = new NamedEntityRecognizer<float>("bert-base-NER");
var text = "Apple Inc. was founded by Steve Jobs in California.";
var entities = ner.Extract(text);
foreach (var entity in entities)
{
Console.WriteLine($"{entity.Text} [{entity.Label}]");
// Apple Inc. [ORG]
// Steve Jobs [PERSON]
// California [LOCATION]
}
Document Chunking
Strategies
// Fixed size chunks
var fixedChunker = new FixedSizeChunker(
chunkSize: 512,
overlap: 50);
// Sentence-based
var sentenceChunker = new SentenceChunker(
maxSentencesPerChunk: 5);
// Recursive (respects document structure)
var recursiveChunker = new RecursiveChunker(
chunkSize: 512,
separators: ["\n\n", "\n", ". ", " "]);
// Semantic (groups similar content)
var semanticChunker = new SemanticChunker<float>(
embedder: embedder,
similarityThreshold: 0.7f);
Best Practices
Embedding Selection
| Model | Dimension | Speed | Quality |
|---|---|---|---|
| all-MiniLM-L6-v2 | 384 | ⚡⚡⚡ | ⭐⭐⭐ |
| all-mpnet-base-v2 | 768 | ⚡⚡ | ⭐⭐⭐⭐ |
| e5-large-v2 | 1024 | ⚡ | ⭐⭐⭐⭐⭐ |
RAG Tips
- Chunk size matters: Too small loses context, too large adds noise
- Use reranking: Significantly improves retrieval quality
- Hybrid retrieval: Combine dense + sparse for best results
- Metadata filtering: Filter by date, source, type before retrieval
- Evaluate systematically: Use RAGAS or similar frameworks