Spaces:
Sleeping
Sleeping
| // LLM client — Ollama (default), Anthropic, or any OpenAI-compatible endpoint | |
| // Configure via env: | |
| // LLM_PROVIDER=ollama|anthropic|openai (default: ollama) | |
| // LLM_BASE_URL=http://localhost:11434 (default for ollama) | |
| // LLM_MODEL=llama3 (default) | |
| // LLM_API_KEY=... (required for anthropic/openai) | |
| const PROVIDER = process.env.LLM_PROVIDER || 'ollama' | |
| const MODEL = process.env.LLM_MODEL || 'llama3' | |
| const API_KEY = process.env.LLM_API_KEY | |
| const BASE_URL = process.env.LLM_BASE_URL || 'http://localhost:11434' | |
| export async function chat(messages) { | |
| if (PROVIDER === 'anthropic') return anthropic(messages) | |
| if (PROVIDER === 'openai') return openaiCompat(messages, BASE_URL || 'https://api.openai.com/v1') | |
| return ollama(messages) | |
| } | |
| async function ollama(messages) { | |
| const r = await fetch(`${BASE_URL}/api/chat`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ model: MODEL, messages, stream: false }), | |
| }) | |
| if (!r.ok) throw new Error(`Ollama ${r.status}: ${await r.text()}`) | |
| const data = await r.json() | |
| return data.message.content | |
| } | |
| async function anthropic(messages) { | |
| // Separate system message — Anthropic requires it at top level | |
| const system = messages.find(m => m.role === 'system')?.content | |
| const rest = messages.filter(m => m.role !== 'system') | |
| const r = await fetch('https://api.anthropic.com/v1/messages', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| 'x-api-key': API_KEY, | |
| 'anthropic-version': '2023-06-01', | |
| }, | |
| body: JSON.stringify({ | |
| model: MODEL || 'claude-sonnet-4-6', | |
| max_tokens: 2048, | |
| ...(system && { system }), | |
| messages: rest, | |
| }), | |
| }) | |
| if (!r.ok) throw new Error(`Anthropic ${r.status}: ${await r.text()}`) | |
| const data = await r.json() | |
| return data.content[0].text | |
| } | |
| async function openaiCompat(messages, base) { | |
| const r = await fetch(`${base}/chat/completions`, { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| ...(API_KEY && { Authorization: `Bearer ${API_KEY}` }), | |
| }, | |
| body: JSON.stringify({ model: MODEL, messages, stream: false }), | |
| }) | |
| if (!r.ok) throw new Error(`LLM ${r.status}: ${await r.text()}`) | |
| const data = await r.json() | |
| return data.choices[0].message.content | |
| } | |