Skip to content

Commit 17afd30

Browse files
committed
feat: add LiteLLM as AI gateway provider
1 parent d62124b commit 17afd30

3 files changed

Lines changed: 58 additions & 0 deletions

File tree

packages/api/ai/config.mts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ export async function getModel(): Promise<LanguageModel> {
5757
});
5858
return openrouter.chat(model);
5959

60+
case 'litellm':
61+
const litellm = createOpenAI({
62+
apiKey: config.customApiKey || 'sk-1234',
63+
baseURL: aiBaseUrl || 'http://localhost:4000/v1',
64+
});
65+
return litellm.chat(model);
66+
6067
case 'custom':
6168
if (typeof aiBaseUrl !== 'string') {
6269
throw new Error('Local AI base URL is not set');

packages/shared/src/ai.mts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const AiProvider = {
44
XAI: 'Xai',
55
Gemini: 'Gemini',
66
OpenRouter: 'openrouter',
7+
LiteLLM: 'litellm',
78
Custom: 'custom',
89
} as const;
910

@@ -16,6 +17,7 @@ export const defaultModels: Record<AiProviderType, string> = {
1617
[AiProvider.XAI]: 'grok-beta',
1718
[AiProvider.Gemini]: 'gemini-1.5-pro-latest',
1819
[AiProvider.OpenRouter]: 'anthropic/claude-3-opus-20240229',
20+
[AiProvider.LiteLLM]: 'gpt-4o-mini',
1921
} as const;
2022

2123
export function isValidProvider(provider: string): provider is AiProviderType {

packages/web/src/routes/settings.tsx

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,16 @@ function AiInfoBanner() {
176176
</div>
177177
);
178178

179+
case 'litellm':
180+
return (
181+
<div className="flex items-center gap-10 bg-sb-yellow-20 text-sb-yellow-80 rounded-sm text-sm font-medium px-3 py-2">
182+
<p>LiteLLM proxy URL required</p>
183+
<a href="https://docs.litellm.ai/docs/simple_proxy" target="_blank" className="underline">
184+
LiteLLM docs
185+
</a>
186+
</div>
187+
);
188+
179189
case 'custom':
180190
return (
181191
<div className="flex items-center gap-10 bg-sb-yellow-20 text-sb-yellow-80 rounded-sm text-sm font-medium px-3 py-2">
@@ -332,6 +342,7 @@ export function AiSettings({ saveButtonLabel }: AiSettingsProps) {
332342
<SelectItem value="Xai">Xai</SelectItem>
333343
<SelectItem value="Gemini">Gemini</SelectItem>
334344
<SelectItem value="openrouter">openrouter</SelectItem>
345+
<SelectItem value="litellm">litellm</SelectItem>
335346
<SelectItem value="custom">custom</SelectItem>
336347
</SelectContent>
337348
</Select>
@@ -448,6 +459,44 @@ export function AiSettings({ saveButtonLabel }: AiSettingsProps) {
448459
</div>
449460
)}
450461

462+
{aiProvider === 'litellm' && (
463+
<div>
464+
<p className="opacity-70 text-sm mb-4">
465+
LiteLLM is an AI gateway that routes to 100+ LLM providers through a single proxy.
466+
Enter your proxy URL and API key below. Use LiteLLM model IDs like
467+
&quot;anthropic/claude-3-5-sonnet&quot; or &quot;openai/gpt-4o&quot;.
468+
</p>
469+
<div className="flex flex-col gap-2">
470+
<div className="flex gap-2">
471+
<Input
472+
name="baseUrl"
473+
placeholder="http://localhost:4000/v1"
474+
value={baseUrl}
475+
onChange={(e) => setBaseUrl(e.target.value)}
476+
/>
477+
<Input
478+
name="customApiKey"
479+
placeholder="LiteLLM API key"
480+
type="password"
481+
value={customApiKey}
482+
onChange={(e) => setCustomApiKey(e.target.value)}
483+
/>
484+
</div>
485+
<div className="flex justify-end">
486+
<Button
487+
className="px-5"
488+
onClick={() =>
489+
updateConfigContext({ aiBaseUrl: baseUrl, customApiKey, aiModel: model })
490+
}
491+
disabled={!customModelSaveEnabled}
492+
>
493+
{saveButtonLabel ?? 'Save'}
494+
</Button>
495+
</div>
496+
</div>
497+
</div>
498+
)}
499+
451500
{aiProvider === 'custom' && (
452501
<div>
453502
<p className="opacity-70 text-sm mb-4">

0 commit comments

Comments
 (0)