Prototype: AI models as small NuGet packages with on-demand fetch, cache, and verify
C#
1
35 commits
updated Sep 3, 2026
What if AI models shipped like NuGet packages — small metadata packages that fetch, cache, and verify large model binaries on demand?
AI models are large. A typical embedding model is 80–300 MB; LLMs run into the gigabytes. Shipping these inside NuGet packages creates real problems:
dotnet restore re-downloads hundreds of MB.nupkg, you can't redirect consumers to a corporate mirror or a local cacheBut .NET developers expect things to just work. dotnet add package SomeModel should give you a working model — no manual downloads, no hunting for URLs, no SHA256 verification by hand.
This prototype explores a different approach: model packages contain only code and metadata (~few KB). The heavy model binary is fetched on first use, cached locally, and verified against a SHA256 hash. Think of it like how NuGet itself works — you don't ship source code in a package, you ship compiled artifacts that restore from feeds.
The key insight: just as nuget.config lets you redirect package sources (nuget.org → corporate feed → local folder), a model-sources.json lets you redirect model sources (HuggingFace → corporate mirror → air-gapped local path) — without changing any application code.
Click the badge above, wait for the container to build, then:
# Run the ONNX track — downloads model from HuggingFace on first run (~86 MB)
dotnet run --project samples/SampleConsumer.Onnx
# Run the .mlnet track — uses a pre-built pipeline
dotnet run --project samples/SampleConsumer.MLNet
# Try other task types
dotnet run --project samples/SampleConsumer.Classification
dotnet run --project samples/SampleConsumer.NER
dotnet run --project samples/SampleConsumer.QA
dotnet run --project samples/SampleConsumer.Reranking
dotnet run --project samples/SampleConsumer.TextGeneration
# Audio samples (require a test.wav file in the consumer directory)
dotnet run --project samples/SampleConsumer.WhisperTiny
dotnet run --project samples/SampleConsumer.SileroVad
dotnet run --project samples/SampleConsumer.AstAudioSet
dotnet run --project samples/SampleConsumer.ClapEmbedding
dotnet run --project samples/SampleConsumer.SpeechT5Tts
# Image samples (require a test image; models downloaded on first run)
dotnet run --project samples/SampleConsumer.ImageClassification
dotnet run --project samples/SampleConsumer.ObjectDetection
dotnet run --project samples/SampleConsumer.ImageSegmentation
dotnet run --project samples/SampleConsumer.DepthEstimation
dotnet run --project samples/SampleConsumer.ImageEmbedding
dotnet run --project samples/SampleConsumer.ZeroShotClassification
dotnet run --project samples/SampleConsumer.ImageCaptioning
dotnet run --project samples/SampleConsumer.VisualQA
dotnet run --project samples/SampleConsumer.SegmentAnything
dotnet run --project samples/SampleConsumer.TextToImage
Prerequisites: .NET 10 SDK
git clone https://github.com/luisquintanilla/model-packages-prototype.git
cd model-packages-prototype
dotnet build
dotnet run --project samples/SampleConsumer.Onnx
Both samples generate text embeddings using all-MiniLM-L6-v2, compute cosine similarities, and display results — proving the full pipeline works end-to-end.
The prototype includes sample model packages and consumers for every major ML/AI inference task:
| Task | Model Package | Consumer | Model |
|---|---|---|---|
| Embedding (ONNX) | SampleModelPackage.Onnx | SampleConsumer.Onnx | all-MiniLM-L6-v2 |
| Embedding (.mlnet) | SampleModelPackage.MLNet | SampleConsumer.MLNet | all-MiniLM-L6-v2 |
| Embedding (BGE) | SampleModelPackage.BgeEmbedding | SampleConsumer.BgeEmbedding | BGE-small-en-v1.5 |
| Embedding (E5) | SampleModelPackage.E5Embedding | SampleConsumer.E5Embedding | E5-small-v2 |
| Embedding (GTE) | SampleModelPackage.GteEmbedding | SampleConsumer.GteEmbedding | GTE-small |
| Classification | SampleModelPackage.Classification | SampleConsumer.Classification | DistilBERT SST-2 |
| Named Entity Recognition | SampleModelPackage.NER | SampleConsumer.NER | BERT-base NER |
| Question Answering | SampleModelPackage.QA | SampleConsumer.QA | MiniLM-Squad2 |
| Reranking | SampleModelPackage.Reranking | SampleConsumer.Reranking | MS MARCO MiniLM |
| Text Generation (local) | SampleModelPackage.TextGeneration | SampleConsumer.TextGeneration | Phi-3-mini |
| Text Generation (MEAI) | — | SampleConsumer.TextGenerationMeai | Any IChatClient provider |
| Audio Embedding (CLAP) | SampleModelPackage.ClapEmbedding | SampleConsumer.ClapEmbedding | CLAP HTSAT-unfused |
| Audio Classification | SampleModelPackage.AstAudioSet | SampleConsumer.AstAudioSet | AST AudioSet |
| Voice Activity Detection | SampleModelPackage.SileroVad | SampleConsumer.SileroVad | Silero VAD v4 |
| Speech-to-Text (Tiny) | SampleModelPackage.WhisperTiny | SampleConsumer.WhisperTiny | Whisper Tiny |
| Speech-to-Text (Base) | SampleModelPackage.WhisperBase | SampleConsumer.WhisperBase | Whisper Base |
| Text-to-Speech | SampleModelPackage.SpeechT5Tts | SampleConsumer.SpeechT5Tts | SpeechT5 TTS |
| Image Classification | SampleModelPackage.ImageClassification | SampleConsumer.ImageClassification | ViT-Base-Patch16-224 |
| Object Detection | SampleModelPackage.ObjectDetection | SampleConsumer.ObjectDetection | YOLOv8s |
| Image Segmentation | SampleModelPackage.ImageSegmentation | SampleConsumer.ImageSegmentation | SegFormer-B0 ADE-512 |
| Depth Estimation | SampleModelPackage.DepthEstimation | SampleConsumer.DepthEstimation | DPT-Hybrid-Midas |
| Image Embedding | SampleModelPackage.ImageEmbedding | SampleConsumer.ImageEmbedding | CLIP ViT-Base-Patch32 |
| Zero-Shot Classification | SampleModelPackage.ZeroShotClassification | SampleConsumer.ZeroShotClassification | CLIP ViT-Base-Patch32 |
| Image Captioning | SampleModelPackage.ImageCaptioning | SampleConsumer.ImageCaptioning | GIT-Base-COCO |
| Visual QA | SampleModelPackage.VisualQA | SampleConsumer.VisualQA | GIT-Base-TextVQA |
| Segment Anything | SampleModelPackage.SegmentAnything | SampleConsumer.SegmentAnything | SAM2-Hiera-Tiny |
| Text-to-Image | SampleModelPackage.TextToImage | SampleConsumer.TextToImage | Stable Diffusion v1.4 |
Each model package embeds a manifest and small assets (vocabs, label maps) while large model binaries are fetched on demand through the Core SDK.
model-packages-prototype/
│
├── src/
│ ├── ModelPackages/ ← Core SDK: fetch, cache, verify (format-agnostic)
│ └── ModelPackages.Tool/ ← CLI tool: prefetch, verify, info, clear-cache
│
├── samples/
│ │ ── Embeddings ──────────────────────────────────────────────────
│ ├── SampleModelPackage.Onnx/ ← MiniLM embedding (raw ONNX from HuggingFace)
│ ├── SampleConsumer.Onnx/ ← Consumer: cosine similarity demo
│ ├── SampleModelPackage.MLNet/ ← MiniLM embedding (pre-built .mlnet pipeline)
│ ├── SampleConsumer.MLNet/ ← Consumer: same API, different packaging
│ ├── SampleModelPackage.BgeEmbedding/ ← BGE-small-en-v1.5 (query prefix baked in)
│ ├── SampleConsumer.BgeEmbedding/ ← Consumer: asymmetric retrieval demo
│ ├── SampleModelPackage.E5Embedding/ ← E5-small-v2 (dual query/passage prefix)
│ ├── SampleConsumer.E5Embedding/ ← Consumer: dual-prefix retrieval demo
│ ├── SampleModelPackage.GteEmbedding/ ← GTE-small (no prefix needed)
│ ├── SampleConsumer.GteEmbedding/ ← Consumer: semantic search demo
│ │ ── Classification ──────────────────────────────────────────────
│ ├── SampleModelPackage.Classification/ ← DistilBERT sentiment analysis
│ ├── SampleConsumer.Classification/ ← Consumer: classify text sentiment
│ │ ── Named Entity Recognition ────────────────────────────────────
│ ├── SampleModelPackage.NER/ ← BERT-base NER (person, org, location)
│ ├── SampleConsumer.NER/ ← Consumer: extract named entities
│ │ ── Question Answering ──────────────────────────────────────────
│ ├── SampleModelPackage.QA/ ← MiniLM-Squad2 extractive QA
│ ├── SampleConsumer.QA/ ← Consumer: answer questions from context
│ │ ── Reranking ───────────────────────────────────────────────────
│ ├── SampleModelPackage.Reranking/ ← MS MARCO MiniLM cross-encoder
│ ├── SampleConsumer.Reranking/ ← Consumer: rerank search results
│ │ ── Text Generation ─────────────────────────────────────────────
│ ├── SampleModelPackage.TextGeneration/ ← Phi-3-mini local ONNX GenAI
│ ├── SampleConsumer.TextGeneration/ ← Consumer: local text generation
│ ├── SampleConsumer.TextGenerationMeai/ ← Consumer: provider-agnostic IChatClient
│ │ ── Audio ────────────────────────────────────────────────────
│ ├── SampleModelPackage.ClapEmbedding/ ← CLAP audio embedding (ONNX)
│ ├── SampleConsumer.ClapEmbedding/ ← Consumer: cosine similarity demo
│ ├── SampleModelPackage.AstAudioSet/ ← AST AudioSet classification (527 labels)
│ ├── SampleConsumer.AstAudioSet/ ← Consumer: classify audio events
│ ├── SampleModelPackage.SileroVad/ ← Silero VAD v4 voice activity detection
│ ├── SampleConsumer.SileroVad/ ← Consumer: detect speech segments
│ ├── SampleModelPackage.WhisperTiny/ ← Whisper Tiny speech-to-text (ONNX)
│ ├── SampleConsumer.WhisperTiny/ ← Consumer: transcribe audio
│ ├── SampleModelPackage.WhisperBase/ ← Whisper Base speech-to-text (ONNX)
│ ├── SampleConsumer.WhisperBase/ ← Consumer: transcribe audio
│ ├── SampleModelPackage.SpeechT5Tts/ ← SpeechT5 text-to-speech (5 ONNX files)
│ ├── SampleConsumer.SpeechT5Tts/ ← Consumer: synthesize speech
│ │ ── Image ────────────────────────────────────────────────────
│ ├── SampleModelPackage.ImageClassification/ ← ViT image classification (ImageNet)
│ ├── SampleConsumer.ImageClassification/ ← Consumer: classify images
│ ├── SampleModelPackage.ObjectDetection/ ← YOLOv8s object detection
│ ├── SampleConsumer.ObjectDetection/ ← Consumer: detect objects in images
│ ├── SampleModelPackage.ImageSegmentation/ ← SegFormer semantic segmentation
│ ├── SampleConsumer.ImageSegmentation/ ← Consumer: segment image pixels
│ ├── SampleModelPackage.DepthEstimation/ ← DPT monocular depth estimation
│ ├── SampleConsumer.DepthEstimation/ ← Consumer: estimate depth maps
│ ├── SampleModelPackage.ImageEmbedding/ ← CLIP image embedding (MEAI)
│ ├── SampleConsumer.ImageEmbedding/ ← Consumer: image similarity
│ ├── SampleModelPackage.ZeroShotClassification/ ← CLIP zero-shot classification
│ ├── SampleConsumer.ZeroShotClassification/ ← Consumer: classify with text labels
│ ├── SampleModelPackage.ImageCaptioning/ ← GIT-Base image captioning (MEAI)
│ ├── SampleConsumer.ImageCaptioning/ ← Consumer: generate captions
│ ├── SampleModelPackage.VisualQA/ ← GIT-Base visual question answering
│ ├── SampleConsumer.VisualQA/ ← Consumer: answer questions about images
│ ├── SampleModelPackage.SegmentAnything/ ← SAM2 segment anything
│ ├── SampleConsumer.SegmentAnything/ ← Consumer: point/box prompted segmentation
│ ├── SampleModelPackage.TextToImage/ ← Stable Diffusion text-to-image
│ └── SampleConsumer.TextToImage/ ← Consumer: generate images from text
│
├── tools/
│ └── PrepareMLNetModel/ ← Helper to build .mlnet from raw ONNX + vocab
│
└── docs/ ← Architecture, design decisions, guides
┌─────────────────────────────────────────────────────────┐
│ Layer 4: Consumer App │
│ dotnet add package SampleModelPackage.Onnx │
│ var gen = await MiniLMModel.CreateEmbeddingGenerator() │
│ var emb = await gen.GenerateAsync(texts) │
├─────────────────────────────────────────────────────────┤
│ Layer 3: Model Package (authored by model publisher) │
│ Embeds: model-manifest.json + vocab.txt │
│ Exposes: MiniLMModel.CreateEmbeddingGeneratorAsync() │
├─────────────────────────────────────────────────────────┤
│ Layer 2: Inference Library (NuGet packages) │
│ MLNet.TextInference.Onnx — embeddings, classification, │
│ NER, QA, reranking via ML.NET + ONNX Runtime │
│ MLNet.AudioInference.Onnx — audio classification, │
│ embedding, VAD, TTS, speech-to-text │
│ MLNet.ImageInference.Onnx — image classification, │
│ detection, segmentation, depth, captioning, VQA │
│ MLNet.ImageGeneration.OnnxGenAI — text-to-image │
│ MLNet.TextGeneration.OnnxGenAI — local text generation │
│ IEmbeddingGenerator, IChatClient (MEAI abstractions) │
├─────────────────────────────────────────────────────────┤
│ Layer 1: Core SDK (ModelPackages) │
│ Resolve source → Check cache → Download → SHA256 verify│
│ Named sources, atomic writes, lock files │
└─────────────────────────────────────────────────────────┘
IEmbeddingGenerator<string, Embedding<float>> (Microsoft.Extensions.AI).| Track 1: Raw ONNX | Track 2: Pre-built .mlnet | |
|---|---|---|
| What's downloaded | Raw .onnx file from HuggingFace | Pre-built .mlnet pipeline zip |
| Pipeline built | On consumer's machine (Fit) | By model author (ahead of time) |
| First-run cost | Download + Fit (~5s) | Download only |
| Flexibility | Consumer can customize pipeline | Fixed pipeline |
| File size | 86 MB (ONNX only) | 79 MB (ONNX + vocab + config in zip) |
The consumer code is nearly identical for both tracks — that's the proof the abstraction works.
nuget.config analogy)Just as nuget.config redirects package feeds, model-sources.json redirects model sources:
{
"sources": {
"company-mirror": {
"type": "mirror",
"endpoint": "https://models.internal.company.com"
}
},
"defaultSource": "company-mirror"
}
Set MODELPACKAGES_SOURCE=company-mirror or drop a model-sources.json next to your .csproj — no code changes needed.
# Pre-download a model (e.g., in CI/CD)
dotnet run --project src/ModelPackages.Tool -- prefetch --manifest path/to/model-manifest.json
# Verify cached model integrity
dotnet run --project src/ModelPackages.Tool -- verify --manifest path/to/model-manifest.json
# Show resolved source and cache path
dotnet run --project src/ModelPackages.Tool -- info --manifest path/to/model-manifest.json
The Core SDK and CLI tool are published to GitHub Packages. Preview builds are published on every push to main.
GitHub Packages requires authentication even for public repos. Create a personal access token with read:packages scope, then:
dotnet nuget add source https://nuget.pkg.github.com/luisquintanilla/index.json \
--name model-packages \
--username YOUR_GITHUB_USERNAME \
--password YOUR_PAT
dotnet add package ModelPackages --prerelease
dotnet tool install -g ModelPackages.Tool --prerelease \
--add-source https://nuget.pkg.github.com/luisquintanilla/index.json
Release .nupkg files are also attached to GitHub Releases. Download and use with a local NuGet source:
dotnet nuget add source /path/to/downloaded/packages --name local
dotnet add package ModelPackages
IEmbeddingGenerator<string, Embedding<float>> and IChatClient abstractionsThis is a prototype / proof of concept exploring the design space. Not production-ready. See the Roadmap for planned improvements.
MIT
C#
100.0%
Prototype: AI models as small NuGet packages with on-demand fetch, cache, and verify
C#
1
35 commits
updated Sep 3, 2026
What if AI models shipped like NuGet packages — small metadata packages that fetch, cache, and verify large model binaries on demand?
AI models are large. A typical embedding model is 80–300 MB; LLMs run into the gigabytes. Shipping these inside NuGet packages creates real problems:
dotnet restore re-downloads hundreds of MB.nupkg, you can't redirect consumers to a corporate mirror or a local cacheBut .NET developers expect things to just work. dotnet add package SomeModel should give you a working model — no manual downloads, no hunting for URLs, no SHA256 verification by hand.
This prototype explores a different approach: model packages contain only code and metadata (~few KB). The heavy model binary is fetched on first use, cached locally, and verified against a SHA256 hash. Think of it like how NuGet itself works — you don't ship source code in a package, you ship compiled artifacts that restore from feeds.
The key insight: just as nuget.config lets you redirect package sources (nuget.org → corporate feed → local folder), a model-sources.json lets you redirect model sources (HuggingFace → corporate mirror → air-gapped local path) — without changing any application code.
Click the badge above, wait for the container to build, then:
# Run the ONNX track — downloads model from HuggingFace on first run (~86 MB)
dotnet run --project samples/SampleConsumer.Onnx
# Run the .mlnet track — uses a pre-built pipeline
dotnet run --project samples/SampleConsumer.MLNet
# Try other task types
dotnet run --project samples/SampleConsumer.Classification
dotnet run --project samples/SampleConsumer.NER
dotnet run --project samples/SampleConsumer.QA
dotnet run --project samples/SampleConsumer.Reranking
dotnet run --project samples/SampleConsumer.TextGeneration
# Audio samples (require a test.wav file in the consumer directory)
dotnet run --project samples/SampleConsumer.WhisperTiny
dotnet run --project samples/SampleConsumer.SileroVad
dotnet run --project samples/SampleConsumer.AstAudioSet
dotnet run --project samples/SampleConsumer.ClapEmbedding
dotnet run --project samples/SampleConsumer.SpeechT5Tts
# Image samples (require a test image; models downloaded on first run)
dotnet run --project samples/SampleConsumer.ImageClassification
dotnet run --project samples/SampleConsumer.ObjectDetection
dotnet run --project samples/SampleConsumer.ImageSegmentation
dotnet run --project samples/SampleConsumer.DepthEstimation
dotnet run --project samples/SampleConsumer.ImageEmbedding
dotnet run --project samples/SampleConsumer.ZeroShotClassification
dotnet run --project samples/SampleConsumer.ImageCaptioning
dotnet run --project samples/SampleConsumer.VisualQA
dotnet run --project samples/SampleConsumer.SegmentAnything
dotnet run --project samples/SampleConsumer.TextToImage
Prerequisites: .NET 10 SDK
git clone https://github.com/luisquintanilla/model-packages-prototype.git
cd model-packages-prototype
dotnet build
dotnet run --project samples/SampleConsumer.Onnx
Both samples generate text embeddings using all-MiniLM-L6-v2, compute cosine similarities, and display results — proving the full pipeline works end-to-end.
The prototype includes sample model packages and consumers for every major ML/AI inference task:
| Task | Model Package | Consumer | Model |
|---|---|---|---|
| Embedding (ONNX) | SampleModelPackage.Onnx | SampleConsumer.Onnx | all-MiniLM-L6-v2 |
| Embedding (.mlnet) | SampleModelPackage.MLNet | SampleConsumer.MLNet | all-MiniLM-L6-v2 |
| Embedding (BGE) | SampleModelPackage.BgeEmbedding | SampleConsumer.BgeEmbedding | BGE-small-en-v1.5 |
| Embedding (E5) | SampleModelPackage.E5Embedding | SampleConsumer.E5Embedding | E5-small-v2 |
| Embedding (GTE) | SampleModelPackage.GteEmbedding | SampleConsumer.GteEmbedding | GTE-small |
| Classification | SampleModelPackage.Classification | SampleConsumer.Classification | DistilBERT SST-2 |
| Named Entity Recognition | SampleModelPackage.NER | SampleConsumer.NER | BERT-base NER |
| Question Answering | SampleModelPackage.QA | SampleConsumer.QA | MiniLM-Squad2 |
| Reranking | SampleModelPackage.Reranking | SampleConsumer.Reranking | MS MARCO MiniLM |
| Text Generation (local) | SampleModelPackage.TextGeneration | SampleConsumer.TextGeneration | Phi-3-mini |
| Text Generation (MEAI) | — | SampleConsumer.TextGenerationMeai | Any IChatClient provider |
| Audio Embedding (CLAP) | SampleModelPackage.ClapEmbedding | SampleConsumer.ClapEmbedding | CLAP HTSAT-unfused |
| Audio Classification | SampleModelPackage.AstAudioSet | SampleConsumer.AstAudioSet | AST AudioSet |
| Voice Activity Detection | SampleModelPackage.SileroVad | SampleConsumer.SileroVad | Silero VAD v4 |
| Speech-to-Text (Tiny) | SampleModelPackage.WhisperTiny | SampleConsumer.WhisperTiny | Whisper Tiny |
| Speech-to-Text (Base) | SampleModelPackage.WhisperBase | SampleConsumer.WhisperBase | Whisper Base |
| Text-to-Speech | SampleModelPackage.SpeechT5Tts | SampleConsumer.SpeechT5Tts | SpeechT5 TTS |
| Image Classification | SampleModelPackage.ImageClassification | SampleConsumer.ImageClassification | ViT-Base-Patch16-224 |
| Object Detection | SampleModelPackage.ObjectDetection | SampleConsumer.ObjectDetection | YOLOv8s |
| Image Segmentation | SampleModelPackage.ImageSegmentation | SampleConsumer.ImageSegmentation | SegFormer-B0 ADE-512 |
| Depth Estimation | SampleModelPackage.DepthEstimation | SampleConsumer.DepthEstimation | DPT-Hybrid-Midas |
| Image Embedding | SampleModelPackage.ImageEmbedding | SampleConsumer.ImageEmbedding | CLIP ViT-Base-Patch32 |
| Zero-Shot Classification | SampleModelPackage.ZeroShotClassification | SampleConsumer.ZeroShotClassification | CLIP ViT-Base-Patch32 |
| Image Captioning | SampleModelPackage.ImageCaptioning | SampleConsumer.ImageCaptioning | GIT-Base-COCO |
| Visual QA | SampleModelPackage.VisualQA | SampleConsumer.VisualQA | GIT-Base-TextVQA |
| Segment Anything | SampleModelPackage.SegmentAnything | SampleConsumer.SegmentAnything | SAM2-Hiera-Tiny |
| Text-to-Image | SampleModelPackage.TextToImage | SampleConsumer.TextToImage | Stable Diffusion v1.4 |
Each model package embeds a manifest and small assets (vocabs, label maps) while large model binaries are fetched on demand through the Core SDK.
model-packages-prototype/
│
├── src/
│ ├── ModelPackages/ ← Core SDK: fetch, cache, verify (format-agnostic)
│ └── ModelPackages.Tool/ ← CLI tool: prefetch, verify, info, clear-cache
│
├── samples/
│ │ ── Embeddings ──────────────────────────────────────────────────
│ ├── SampleModelPackage.Onnx/ ← MiniLM embedding (raw ONNX from HuggingFace)
│ ├── SampleConsumer.Onnx/ ← Consumer: cosine similarity demo
│ ├── SampleModelPackage.MLNet/ ← MiniLM embedding (pre-built .mlnet pipeline)
│ ├── SampleConsumer.MLNet/ ← Consumer: same API, different packaging
│ ├── SampleModelPackage.BgeEmbedding/ ← BGE-small-en-v1.5 (query prefix baked in)
│ ├── SampleConsumer.BgeEmbedding/ ← Consumer: asymmetric retrieval demo
│ ├── SampleModelPackage.E5Embedding/ ← E5-small-v2 (dual query/passage prefix)
│ ├── SampleConsumer.E5Embedding/ ← Consumer: dual-prefix retrieval demo
│ ├── SampleModelPackage.GteEmbedding/ ← GTE-small (no prefix needed)
│ ├── SampleConsumer.GteEmbedding/ ← Consumer: semantic search demo
│ │ ── Classification ──────────────────────────────────────────────
│ ├── SampleModelPackage.Classification/ ← DistilBERT sentiment analysis
│ ├── SampleConsumer.Classification/ ← Consumer: classify text sentiment
│ │ ── Named Entity Recognition ────────────────────────────────────
│ ├── SampleModelPackage.NER/ ← BERT-base NER (person, org, location)
│ ├── SampleConsumer.NER/ ← Consumer: extract named entities
│ │ ── Question Answering ──────────────────────────────────────────
│ ├── SampleModelPackage.QA/ ← MiniLM-Squad2 extractive QA
│ ├── SampleConsumer.QA/ ← Consumer: answer questions from context
│ │ ── Reranking ───────────────────────────────────────────────────
│ ├── SampleModelPackage.Reranking/ ← MS MARCO MiniLM cross-encoder
│ ├── SampleConsumer.Reranking/ ← Consumer: rerank search results
│ │ ── Text Generation ─────────────────────────────────────────────
│ ├── SampleModelPackage.TextGeneration/ ← Phi-3-mini local ONNX GenAI
│ ├── SampleConsumer.TextGeneration/ ← Consumer: local text generation
│ ├── SampleConsumer.TextGenerationMeai/ ← Consumer: provider-agnostic IChatClient
│ │ ── Audio ────────────────────────────────────────────────────
│ ├── SampleModelPackage.ClapEmbedding/ ← CLAP audio embedding (ONNX)
│ ├── SampleConsumer.ClapEmbedding/ ← Consumer: cosine similarity demo
│ ├── SampleModelPackage.AstAudioSet/ ← AST AudioSet classification (527 labels)
│ ├── SampleConsumer.AstAudioSet/ ← Consumer: classify audio events
│ ├── SampleModelPackage.SileroVad/ ← Silero VAD v4 voice activity detection
│ ├── SampleConsumer.SileroVad/ ← Consumer: detect speech segments
│ ├── SampleModelPackage.WhisperTiny/ ← Whisper Tiny speech-to-text (ONNX)
│ ├── SampleConsumer.WhisperTiny/ ← Consumer: transcribe audio
│ ├── SampleModelPackage.WhisperBase/ ← Whisper Base speech-to-text (ONNX)
│ ├── SampleConsumer.WhisperBase/ ← Consumer: transcribe audio
│ ├── SampleModelPackage.SpeechT5Tts/ ← SpeechT5 text-to-speech (5 ONNX files)
│ ├── SampleConsumer.SpeechT5Tts/ ← Consumer: synthesize speech
│ │ ── Image ────────────────────────────────────────────────────
│ ├── SampleModelPackage.ImageClassification/ ← ViT image classification (ImageNet)
│ ├── SampleConsumer.ImageClassification/ ← Consumer: classify images
│ ├── SampleModelPackage.ObjectDetection/ ← YOLOv8s object detection
│ ├── SampleConsumer.ObjectDetection/ ← Consumer: detect objects in images
│ ├── SampleModelPackage.ImageSegmentation/ ← SegFormer semantic segmentation
│ ├── SampleConsumer.ImageSegmentation/ ← Consumer: segment image pixels
│ ├── SampleModelPackage.DepthEstimation/ ← DPT monocular depth estimation
│ ├── SampleConsumer.DepthEstimation/ ← Consumer: estimate depth maps
│ ├── SampleModelPackage.ImageEmbedding/ ← CLIP image embedding (MEAI)
│ ├── SampleConsumer.ImageEmbedding/ ← Consumer: image similarity
│ ├── SampleModelPackage.ZeroShotClassification/ ← CLIP zero-shot classification
│ ├── SampleConsumer.ZeroShotClassification/ ← Consumer: classify with text labels
│ ├── SampleModelPackage.ImageCaptioning/ ← GIT-Base image captioning (MEAI)
│ ├── SampleConsumer.ImageCaptioning/ ← Consumer: generate captions
│ ├── SampleModelPackage.VisualQA/ ← GIT-Base visual question answering
│ ├── SampleConsumer.VisualQA/ ← Consumer: answer questions about images
│ ├── SampleModelPackage.SegmentAnything/ ← SAM2 segment anything
│ ├── SampleConsumer.SegmentAnything/ ← Consumer: point/box prompted segmentation
│ ├── SampleModelPackage.TextToImage/ ← Stable Diffusion text-to-image
│ └── SampleConsumer.TextToImage/ ← Consumer: generate images from text
│
├── tools/
│ └── PrepareMLNetModel/ ← Helper to build .mlnet from raw ONNX + vocab
│
└── docs/ ← Architecture, design decisions, guides
┌─────────────────────────────────────────────────────────┐
│ Layer 4: Consumer App │
│ dotnet add package SampleModelPackage.Onnx │
│ var gen = await MiniLMModel.CreateEmbeddingGenerator() │
│ var emb = await gen.GenerateAsync(texts) │
├─────────────────────────────────────────────────────────┤
│ Layer 3: Model Package (authored by model publisher) │
│ Embeds: model-manifest.json + vocab.txt │
│ Exposes: MiniLMModel.CreateEmbeddingGeneratorAsync() │
├─────────────────────────────────────────────────────────┤
│ Layer 2: Inference Library (NuGet packages) │
│ MLNet.TextInference.Onnx — embeddings, classification, │
│ NER, QA, reranking via ML.NET + ONNX Runtime │
│ MLNet.AudioInference.Onnx — audio classification, │
│ embedding, VAD, TTS, speech-to-text │
│ MLNet.ImageInference.Onnx — image classification, │
│ detection, segmentation, depth, captioning, VQA │
│ MLNet.ImageGeneration.OnnxGenAI — text-to-image │
│ MLNet.TextGeneration.OnnxGenAI — local text generation │
│ IEmbeddingGenerator, IChatClient (MEAI abstractions) │
├─────────────────────────────────────────────────────────┤
│ Layer 1: Core SDK (ModelPackages) │
│ Resolve source → Check cache → Download → SHA256 verify│
│ Named sources, atomic writes, lock files │
└─────────────────────────────────────────────────────────┘
IEmbeddingGenerator<string, Embedding<float>> (Microsoft.Extensions.AI).| Track 1: Raw ONNX | Track 2: Pre-built .mlnet | |
|---|---|---|
| What's downloaded | Raw .onnx file from HuggingFace | Pre-built .mlnet pipeline zip |
| Pipeline built | On consumer's machine (Fit) | By model author (ahead of time) |
| First-run cost | Download + Fit (~5s) | Download only |
| Flexibility | Consumer can customize pipeline | Fixed pipeline |
| File size | 86 MB (ONNX only) | 79 MB (ONNX + vocab + config in zip) |
The consumer code is nearly identical for both tracks — that's the proof the abstraction works.
nuget.config analogy)Just as nuget.config redirects package feeds, model-sources.json redirects model sources:
{
"sources": {
"company-mirror": {
"type": "mirror",
"endpoint": "https://models.internal.company.com"
}
},
"defaultSource": "company-mirror"
}
Set MODELPACKAGES_SOURCE=company-mirror or drop a model-sources.json next to your .csproj — no code changes needed.
# Pre-download a model (e.g., in CI/CD)
dotnet run --project src/ModelPackages.Tool -- prefetch --manifest path/to/model-manifest.json
# Verify cached model integrity
dotnet run --project src/ModelPackages.Tool -- verify --manifest path/to/model-manifest.json
# Show resolved source and cache path
dotnet run --project src/ModelPackages.Tool -- info --manifest path/to/model-manifest.json
The Core SDK and CLI tool are published to GitHub Packages. Preview builds are published on every push to main.
GitHub Packages requires authentication even for public repos. Create a personal access token with read:packages scope, then:
dotnet nuget add source https://nuget.pkg.github.com/luisquintanilla/index.json \
--name model-packages \
--username YOUR_GITHUB_USERNAME \
--password YOUR_PAT
dotnet add package ModelPackages --prerelease
dotnet tool install -g ModelPackages.Tool --prerelease \
--add-source https://nuget.pkg.github.com/luisquintanilla/index.json
Release .nupkg files are also attached to GitHub Releases. Download and use with a local NuGet source:
dotnet nuget add source /path/to/downloaded/packages --name local
dotnet add package ModelPackages
IEmbeddingGenerator<string, Embedding<float>> and IChatClient abstractionsThis is a prototype / proof of concept exploring the design space. Not production-ready. See the Roadmap for planned improvements.
MIT
C#
100.0%