A .NET 10 file-based program demonstrating a complete Retrieval-Augmented Generation (RAG) pipeline using Microsoft Extensions for AI and Data Ingestion.
This project showcases how to build an end-to-end data ingestion pipeline that:
- Reads Policy documents from a directory
- Enriches content with AI-generated image descriptions
- Chunks text using semantic similarity
- Generates AI summaries for each chunk
- Stores embeddings in a SQLite vector database
- Enables semantic search and question answering
- Document Reading: Processes Markdown files using the Markdig reader
- AI-Powered Enrichment: Generates alternative text for images using GPT-4.1
- Semantic Chunking: Intelligently splits documents using embedding-based semantic similarity
- Summary Generation: Creates AI summaries for each chunk
- Vector Storage: SQLite-based vector database for efficient similarity search
- Interactive Q&A: Query the ingested documents using natural language
Click the "Open in GitHub Codespaces" badge to open this project in a pre-configured development environment with all dependencies installed.
-
Prerequisites:
- .NET 10 SDK
- GitHub Personal Access Token (for accessing GitHub Models)
-
Set the GitHub Token Environment Variable:
$env:GITHUB_TOKEN = "your_github_token_here"
-
Add Your Documents: Place Markdown files in the
./datadirectory. A sample primer is already included.
dotnet run DataIngestion.csNote: As a file-based program, this application doesn't require a project file. Dependencies are specified directly in the source file using
#:packagedirectives and are automatically resolved at runtime.
The application will:
- Process all
.mdfiles in the./datadirectory - Display processing status for each document
- Enter interactive mode for querying
After ingestion completes, enter questions at the prompt:
Enter your question (or 'exit' to quit): How do I prepare data for RAG?
Searching...
Score: 0.39424318075180054
Content: ### Example C# Extraction Snippet
## 4.2 Transformation
Normalize, clean, or convert content into a structured form suitable for retrieval or embedding.
Common steps:...
Type exit to quit the application.
Markdown Files → Document Reader → Image Enricher → Semantic Chunker → Summary Enricher → Vector Store
- MarkdownReader: Parses Markdown documents
- ImageAlternativeTextEnricher: Adds AI-generated descriptions for images
- SemanticSimilarityChunker: Splits text into token chunks using semantic boundaries
- SummaryEnricher: Generates summaries for each chunk
- VectorStoreWriter: Stores chunks with embeddings in SQLite
- Chat Model:
gpt-4.1(via GitHub Models) - Embedding Model:
text-embedding-3-small(1536 dimensions) - Tokenizer: Tiktoken (GPT-4 encoding)
DataIngestion/
├── .devcontainer/ # Dev Container configuration
│ └── devcontainer.json
├── DataIngestion.cs # Main file-based program with embedded dependencies
├── data/ # Input documents directory
│ └── Data-Ingestion-Primer.md
└── vectors.db # Generated SQLite vector database (created at runtime)
Dependencies are declared using #:package directives at the top of DataIngestion.cs:
#:package Microsoft.Extensions.AI.OpenAI@10.0.1-preview.1.25571.5
#:package Microsoft.Extensions.DataIngestion@10.0.1-preview.1.25571.5
#:package Microsoft.Extensions.DataIngestion.Markdig@10.0.1-preview.1.25571.5
#:package Microsoft.Extensions.Logging.Console@10.0.0
#:package Microsoft.ML.Tokenizers.Data.Cl100kBase@2.0.0
#:package Microsoft.SemanticKernel.Connectors.SqliteVec@1.67.1-preview- MaxTokensPerChunk: 2000 tokens
- OverlapTokens: 0 (no overlap between chunks)
- Top K: 3 (returns top 3 most relevant chunks)
- Database:
vectors.db(SQLite) - Collection:
data - Embedding Dimensions: 1536
IngestionChunkerOptions chunkerOptions = new(TiktokenTokenizer.CreateForModel("gpt-4"))
{
MaxTokensPerChunk = 1000, // Smaller chunks
OverlapTokens = 100 // Add overlap
};await foreach (var result in collection.SearchAsync(searchValue, top: 5))Replace MarkdownReader with another document reader implementation.
This is a sample project for educational purposes.
Issue: GITHUB_TOKEN not found
- Solution: Ensure the environment variable is set in your current PowerShell session
Issue: Database locked errors
- Solution: The SQLite connection uses
Pooling=falseto prevent this. Ensure only one instance is running.
Issue: Model not found
- Solution: Verify your GitHub token has access to GitHub Models