Skip to content

Commit 6114c21

Browse files
feature(models): added vllm provider (#2103)
* Add vLLM self-hosted provider * updated vllm to have pull parity with openai, dynamically fetch models --------- Co-authored-by: MagellaX <[email protected]>
1 parent d1f0d21 commit 6114c21

File tree

14 files changed

+775
-9
lines changed

14 files changed

+775
-9
lines changed

apps/sim/app/(landing)/components/integrations/integrations.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const modelProviderIcons = [
1313
{ icon: Icons.OllamaIcon, label: 'Ollama' },
1414
{ icon: Icons.DeepseekIcon, label: 'Deepseek' },
1515
{ icon: Icons.ElevenLabsIcon, label: 'ElevenLabs' },
16+
{ icon: Icons.VllmIcon, label: 'vLLM' },
1617
]
1718

1819
const communicationIcons = [
@@ -88,7 +89,6 @@ interface TickerRowProps {
8889
}
8990

9091
function TickerRow({ direction, offset, showOdd, icons }: TickerRowProps) {
91-
// Create multiple copies of the icons array for seamless looping
9292
const extendedIcons = [...icons, ...icons, ...icons, ...icons]
9393

9494
return (

apps/sim/app/.env.example

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ INTERNAL_API_SECRET=your_internal_api_secret # Use `openssl rand -hex 32` to gen
2020
# If left commented out, emails will be logged to console instead
2121

2222
# Local AI Models (Optional)
23-
# OLLAMA_URL=http://localhost:11434 # URL for local Ollama server - uncomment if using local models
23+
# OLLAMA_URL=http://localhost:11434 # URL for local Ollama server - uncomment if using local models
24+
# VLLM_BASE_URL=http://localhost:8000 # Base URL for your self-hosted vLLM (OpenAI-compatible)
25+
# VLLM_API_KEY= # Optional bearer token if your vLLM instance requires auth
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { type NextRequest, NextResponse } from 'next/server'
2+
import { env } from '@/lib/env'
3+
import { createLogger } from '@/lib/logs/console/logger'
4+
5+
const logger = createLogger('VLLMModelsAPI')
6+
7+
/**
8+
* Get available vLLM models
9+
*/
10+
export async function GET(request: NextRequest) {
11+
const baseUrl = (env.VLLM_BASE_URL || '').replace(/\/$/, '')
12+
13+
if (!baseUrl) {
14+
logger.info('VLLM_BASE_URL not configured')
15+
return NextResponse.json({ models: [] })
16+
}
17+
18+
try {
19+
logger.info('Fetching vLLM models', {
20+
baseUrl,
21+
})
22+
23+
const response = await fetch(`${baseUrl}/v1/models`, {
24+
headers: {
25+
'Content-Type': 'application/json',
26+
},
27+
next: { revalidate: 60 },
28+
})
29+
30+
if (!response.ok) {
31+
logger.warn('vLLM service is not available', {
32+
status: response.status,
33+
statusText: response.statusText,
34+
})
35+
return NextResponse.json({ models: [] })
36+
}
37+
38+
const data = (await response.json()) as { data: Array<{ id: string }> }
39+
const models = data.data.map((model) => `vllm/${model.id}`)
40+
41+
logger.info('Successfully fetched vLLM models', {
42+
count: models.length,
43+
models,
44+
})
45+
46+
return NextResponse.json({ models })
47+
} catch (error) {
48+
logger.error('Failed to fetch vLLM models', {
49+
error: error instanceof Error ? error.message : 'Unknown error',
50+
baseUrl,
51+
})
52+
53+
// Return empty array instead of error to avoid breaking the UI
54+
return NextResponse.json({ models: [] })
55+
}
56+
}

apps/sim/app/workspace/[workspaceId]/providers/provider-models-loader.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@
33
import { useEffect } from 'react'
44
import { createLogger } from '@/lib/logs/console/logger'
55
import { useProviderModels } from '@/hooks/queries/providers'
6-
import { updateOllamaProviderModels, updateOpenRouterProviderModels } from '@/providers/utils'
6+
import {
7+
updateOllamaProviderModels,
8+
updateOpenRouterProviderModels,
9+
updateVLLMProviderModels,
10+
} from '@/providers/utils'
711
import { useProvidersStore } from '@/stores/providers/store'
812
import type { ProviderName } from '@/stores/providers/types'
913

@@ -24,6 +28,8 @@ function useSyncProvider(provider: ProviderName) {
2428
try {
2529
if (provider === 'ollama') {
2630
updateOllamaProviderModels(data)
31+
} else if (provider === 'vllm') {
32+
updateVLLMProviderModels(data)
2733
} else if (provider === 'openrouter') {
2834
void updateOpenRouterProviderModels(data)
2935
}
@@ -44,6 +50,7 @@ function useSyncProvider(provider: ProviderName) {
4450
export function ProviderModelsLoader() {
4551
useSyncProvider('base')
4652
useSyncProvider('ollama')
53+
useSyncProvider('vllm')
4754
useSyncProvider('openrouter')
4855
return null
4956
}

apps/sim/blocks/blocks/agent.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ const getCurrentOllamaModels = () => {
1818
return useProvidersStore.getState().providers.ollama.models
1919
}
2020

21+
const getCurrentVLLMModels = () => {
22+
return useProvidersStore.getState().providers.vllm.models
23+
}
24+
2125
import { useProvidersStore } from '@/stores/providers/store'
2226
import type { ToolResponse } from '@/tools/types'
2327

@@ -90,8 +94,11 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
9094
const providersState = useProvidersStore.getState()
9195
const baseModels = providersState.providers.base.models
9296
const ollamaModels = providersState.providers.ollama.models
97+
const vllmModels = providersState.providers.vllm.models
9398
const openrouterModels = providersState.providers.openrouter.models
94-
const allModels = Array.from(new Set([...baseModels, ...ollamaModels, ...openrouterModels]))
99+
const allModels = Array.from(
100+
new Set([...baseModels, ...ollamaModels, ...vllmModels, ...openrouterModels])
101+
)
95102

96103
return allModels.map((model) => {
97104
const icon = getProviderIcon(model)
@@ -172,7 +179,7 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
172179
password: true,
173180
connectionDroppable: false,
174181
required: true,
175-
// Hide API key for hosted models and Ollama models
182+
// Hide API key for hosted models, Ollama models, and vLLM models
176183
condition: isHosted
177184
? {
178185
field: 'model',
@@ -181,8 +188,8 @@ export const AgentBlock: BlockConfig<AgentResponse> = {
181188
}
182189
: () => ({
183190
field: 'model',
184-
value: getCurrentOllamaModels(),
185-
not: true, // Show for all models EXCEPT Ollama models
191+
value: [...getCurrentOllamaModels(), ...getCurrentVLLMModels()],
192+
not: true, // Show for all models EXCEPT Ollama and vLLM models
186193
}),
187194
},
188195
{

apps/sim/components/icons.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4150,3 +4150,13 @@ export function VideoIcon(props: SVGProps<SVGSVGElement>) {
41504150
</svg>
41514151
)
41524152
}
4153+
4154+
export function VllmIcon(props: SVGProps<SVGSVGElement>) {
4155+
return (
4156+
<svg {...props} fill='currentColor' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'>
4157+
<title>vLLM</title>
4158+
<path d='M0 4.973h9.324V23L0 4.973z' fill='#FDB515' />
4159+
<path d='M13.986 4.351L22.378 0l-6.216 23H9.324l4.662-18.649z' fill='#30A2FF' />
4160+
</svg>
4161+
)
4162+
}

apps/sim/hooks/queries/providers.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const logger = createLogger('ProviderModelsQuery')
77
const providerEndpoints: Record<ProviderName, string> = {
88
base: '/api/providers/base/models',
99
ollama: '/api/providers/ollama/models',
10+
vllm: '/api/providers/vllm/models',
1011
openrouter: '/api/providers/openrouter/models',
1112
}
1213

apps/sim/lib/env.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ export const env = createEnv({
7777
ANTHROPIC_API_KEY_2: z.string().min(1).optional(), // Additional Anthropic API key for load balancing
7878
ANTHROPIC_API_KEY_3: z.string().min(1).optional(), // Additional Anthropic API key for load balancing
7979
OLLAMA_URL: z.string().url().optional(), // Ollama local LLM server URL
80+
VLLM_BASE_URL: z.string().url().optional(), // vLLM self-hosted base URL (OpenAI-compatible)
81+
VLLM_API_KEY: z.string().optional(), // Optional bearer token for vLLM
8082
ELEVENLABS_API_KEY: z.string().min(1).optional(), // ElevenLabs API key for text-to-speech in deployed chat
8183
SERPER_API_KEY: z.string().min(1).optional(), // Serper API key for online search
8284
EXA_API_KEY: z.string().min(1).optional(), // Exa AI API key for enhanced online search

apps/sim/providers/models.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
OllamaIcon,
2020
OpenAIIcon,
2121
OpenRouterIcon,
22+
VllmIcon,
2223
xAIIcon,
2324
} from '@/components/icons'
2425

@@ -82,6 +83,19 @@ export const PROVIDER_DEFINITIONS: Record<string, ProviderDefinition> = {
8283
contextInformationAvailable: false,
8384
models: [],
8485
},
86+
vllm: {
87+
id: 'vllm',
88+
name: 'vLLM',
89+
icon: VllmIcon,
90+
description: 'Self-hosted vLLM with an OpenAI-compatible API',
91+
defaultModel: 'vllm/generic',
92+
modelPatterns: [/^vllm\//],
93+
capabilities: {
94+
temperature: { min: 0, max: 2 },
95+
toolUsageControl: true,
96+
},
97+
models: [],
98+
},
8599
openai: {
86100
id: 'openai',
87101
name: 'OpenAI',
@@ -1366,6 +1380,21 @@ export function updateOllamaModels(models: string[]): void {
13661380
}))
13671381
}
13681382

1383+
/**
1384+
* Update vLLM models dynamically
1385+
*/
1386+
export function updateVLLMModels(models: string[]): void {
1387+
PROVIDER_DEFINITIONS.vllm.models = models.map((modelId) => ({
1388+
id: modelId,
1389+
pricing: {
1390+
input: 0,
1391+
output: 0,
1392+
updatedAt: new Date().toISOString().split('T')[0],
1393+
},
1394+
capabilities: {},
1395+
}))
1396+
}
1397+
13691398
/**
13701399
* Update OpenRouter models dynamically
13711400
*/

apps/sim/providers/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export type ProviderId =
1212
| 'mistral'
1313
| 'ollama'
1414
| 'openrouter'
15+
| 'vllm'
1516

1617
/**
1718
* Model pricing information per million tokens

0 commit comments

Comments
 (0)