Aspire issue link
No response (not previously discussed in dotnet/aspire)
Overview
vLLM is a popular, OpenAI-compatible inference server for running open-weight models on your own
GPU. An Aspire app host has no first-class way to run one today. You drop down to a raw container
resource and hand-write the image, the port, the GPU runtime args, a readiness health check, and
then the OpenAI client wiring on the consuming side. Every app repeats that setup, and the first run
has a few sharp edges: the health check has to gate on the model actually loading, and the OpenAI
client needs the /v1 path plus a non-empty API key even though vLLM ignores the key.
The Community Toolkit already covers this shape for Ollama. vLLM is the natural companion for
GPU-served models, higher throughput, and larger context windows, so I'd like to add it as a
matching pair of packages:
CommunityToolkit.Aspire.Hosting.VLLM (hosting). AddVLLM("vllm") adds the
vllm/vllm-openai container with an HTTP endpoint (container port 8000) and a /health check
that reports healthy only once the model is loaded, so WaitFor dependents block until the server
can actually answer. WithGPUSupport() adds --gpus all for NVIDIA or switches to the ROCm image
with the right device mounts for AMD. WithDataVolume() persists the Hugging Face cache across
restarts, WithModel(...) and WithServedModelName(...) choose and name the model, and
WithHuggingFaceToken(...) wires a secret parameter for gated models.
CommunityToolkit.Aspire.VLLM (client). AddVLLMClient("vllm").AddChatClient() reads the
hosting resource's connection string and registers an IChatClient (through
Microsoft.Extensions.AI) pointed at the server. It appends /v1, supplies the placeholder API
key the OpenAI client requires, targets the served model name, and registers a matching /health
check plus OpenTelemetry. Because the surface is Microsoft.Extensions.AI, the same app code keeps
working against any OpenAI-compatible endpoint later.
The two mirror CommunityToolkit.Aspire.Hosting.Ollama and CommunityToolkit.Aspire.OllamaSharp:
add the server in the app host, reference it from a project, and consume it as an IChatClient.
Usage example
Add the server in the app host and gate a project on it:
// AppHost.cs
var builder = DistributedApplication.CreateBuilder(args);
var vllm = builder.AddVLLM("vllm")
.WithGPUSupport() // NVIDIA by default; VLLMGpuVendor.AMD for ROCm
.WithDataVolume() // persist the Hugging Face cache
.WithModel("Qwen/Qwen3-8B");
builder.AddProject<Projects.Web>("web")
.WithReference(vllm) // injects the connection string
.WaitFor(vllm); // blocks until the model is serving
builder.Build().Run();
Consume it as an IChatClient in the referencing project:
// Web Program.cs
builder.AddVLLMClient("vllm", settings => settings.Model = "Qwen/Qwen3-8B")
.AddChatClient()
.UseFunctionInvocation();
Additional context
Both packages already exist, build, and run. I built them for
magenticbrain-vllm-aspire, a local
RAG app, and shaped them from the start to match this repo's conventions so they can move here with
little change.
Proven running. This is not a sketch. The same two packages run
microsoft/MagenticBrain, a 14B model quantized to
4-bit, on a single 16 GB laptop GPU (RTX 3080), under Aspire, behind the aichatweb RAG template,
with tool-calling. I verified the full client path against a live GPU server: the placeholder key,
the /v1 suffix, and the served model name all work, and the app returns grounded answers with
citations.
What's already there (links to main):
Why a dedicated client and not just AddOpenAIClient? vLLM is OpenAI-compatible, so a reviewer
may reasonably ask. The client adds three vLLM-specific things on top of the generic OpenAI client:
it pairs with the hosting resource over the connection string and appends /v1 (the hosting
resource emits the base URL without it, so a raw OpenAI client 404s until you fix it up by hand); it
fills in vLLM-correct defaults (the placeholder API key and the served model name); and it adds
vLLM's /health readiness check. If you'd prefer, the same behavior could ship as a defaults layer
over AddOpenAIClient rather than a standalone package. Happy to go either way.
Alternatives. Today you write AddContainer("vllm/vllm-openai", ...) by hand and pair it with
AddOpenAIClient, reproducing the GPU args, the readiness health check, and the /v1 and API-key
fix-ups in every app. That works, but it is the boilerplate an integration should own.
Relationship to Ollama. This complements the existing Ollama integration rather than replacing
it. Ollama is the easy CPU/GGUF path; vLLM is the GPU-first, high-throughput, OpenAI-native path for
larger models and longer context. Many apps will want vLLM for chat and Ollama for embeddings.
A few choices for maintainers. I'm flexible on all of these:
- Acronym casing:
VLLM (matches the product) vs Vllm (matches .NET acronym casing), for both
type names and AddVLLM/AddVllm.
- The
VLLMGpuVendor enum name (Ollama uses an unprefixed GpuVendor; I prefixed it to avoid a
clash if both integrations are referenced from the same app host).
- Client shape:
AddVLLMClient(name).AddChatClient() (leaves room for .AddEmbeddingGenerator(),
since vLLM can serve embedding models too) vs a single-call AddVLLMChatClient(name).
- One combined proposal vs separate hosting and client issues, whichever you track better.
I'll sign the .NET Foundation CLA and can open the companion docs PR to aspire.dev. I'd love to
bring this in.
Help us help you
Yes, I'd like to be assigned to work on this item
Aspire issue link
No response (not previously discussed in dotnet/aspire)
Overview
vLLM is a popular, OpenAI-compatible inference server for running open-weight models on your own
GPU. An Aspire app host has no first-class way to run one today. You drop down to a raw container
resource and hand-write the image, the port, the GPU runtime args, a readiness health check, and
then the OpenAI client wiring on the consuming side. Every app repeats that setup, and the first run
has a few sharp edges: the health check has to gate on the model actually loading, and the OpenAI
client needs the
/v1path plus a non-empty API key even though vLLM ignores the key.The Community Toolkit already covers this shape for Ollama. vLLM is the natural companion for
GPU-served models, higher throughput, and larger context windows, so I'd like to add it as a
matching pair of packages:
CommunityToolkit.Aspire.Hosting.VLLM(hosting).AddVLLM("vllm")adds thevllm/vllm-openaicontainer with an HTTP endpoint (container port 8000) and a/healthcheckthat reports healthy only once the model is loaded, so
WaitFordependents block until the servercan actually answer.
WithGPUSupport()adds--gpus allfor NVIDIA or switches to the ROCm imagewith the right device mounts for AMD.
WithDataVolume()persists the Hugging Face cache acrossrestarts,
WithModel(...)andWithServedModelName(...)choose and name the model, andWithHuggingFaceToken(...)wires a secret parameter for gated models.CommunityToolkit.Aspire.VLLM(client).AddVLLMClient("vllm").AddChatClient()reads thehosting resource's connection string and registers an
IChatClient(throughMicrosoft.Extensions.AI) pointed at the server. It appends/v1, supplies the placeholder APIkey the OpenAI client requires, targets the served model name, and registers a matching
/healthcheck plus OpenTelemetry. Because the surface is
Microsoft.Extensions.AI, the same app code keepsworking against any OpenAI-compatible endpoint later.
The two mirror
CommunityToolkit.Aspire.Hosting.OllamaandCommunityToolkit.Aspire.OllamaSharp:add the server in the app host, reference it from a project, and consume it as an
IChatClient.Usage example
Add the server in the app host and gate a project on it:
Consume it as an
IChatClientin the referencing project:Additional context
Both packages already exist, build, and run. I built them for
magenticbrain-vllm-aspire, a localRAG app, and shaped them from the start to match this repo's conventions so they can move here with
little change.
Proven running. This is not a sketch. The same two packages run
microsoft/MagenticBrain, a 14B model quantized to4-bit, on a single 16 GB laptop GPU (RTX 3080), under Aspire, behind the
aichatwebRAG template,with tool-calling. I verified the full client path against a live GPU server: the placeholder key,
the
/v1suffix, and the served model name all work, and the app returns grounded answers withcitations.
What's already there (links to
main):src/CommunityToolkit.Aspire.Hosting.VLLM(namespace
Aspire.Hosting, theAddVLLMsurface,VLLMResource : ContainerResource, IResourceWithConnectionString, IResourceWithEndpoints).src/CommunityToolkit.Aspire.VLLM(extensions in
Microsoft.Extensions.Hosting, per the client-integration convention).examples/vllm.docs/create-integration.md:docs/upstream-vllm-integration.md.Why a dedicated client and not just
AddOpenAIClient? vLLM is OpenAI-compatible, so a reviewermay reasonably ask. The client adds three vLLM-specific things on top of the generic OpenAI client:
it pairs with the hosting resource over the connection string and appends
/v1(the hostingresource emits the base URL without it, so a raw OpenAI client 404s until you fix it up by hand); it
fills in vLLM-correct defaults (the placeholder API key and the served model name); and it adds
vLLM's
/healthreadiness check. If you'd prefer, the same behavior could ship as a defaults layerover
AddOpenAIClientrather than a standalone package. Happy to go either way.Alternatives. Today you write
AddContainer("vllm/vllm-openai", ...)by hand and pair it withAddOpenAIClient, reproducing the GPU args, the readiness health check, and the/v1and API-keyfix-ups in every app. That works, but it is the boilerplate an integration should own.
Relationship to Ollama. This complements the existing Ollama integration rather than replacing
it. Ollama is the easy CPU/GGUF path; vLLM is the GPU-first, high-throughput, OpenAI-native path for
larger models and longer context. Many apps will want vLLM for chat and Ollama for embeddings.
A few choices for maintainers. I'm flexible on all of these:
VLLM(matches the product) vsVllm(matches .NET acronym casing), for bothtype names and
AddVLLM/AddVllm.VLLMGpuVendorenum name (Ollama uses an unprefixedGpuVendor; I prefixed it to avoid aclash if both integrations are referenced from the same app host).
AddVLLMClient(name).AddChatClient()(leaves room for.AddEmbeddingGenerator(),since vLLM can serve embedding models too) vs a single-call
AddVLLMChatClient(name).I'll sign the .NET Foundation CLA and can open the companion docs PR to
aspire.dev. I'd love tobring this in.
Help us help you
Yes, I'd like to be assigned to work on this item