feat: support OpenRouter/custom LLM providers via env vars
Add LLM_API_KEY, LLM_BASE_URL, LLM_MODEL env vars so any OpenAI-compatible API (OpenRouter, etc.) can be used as the LLM backend without code changes.
This commit is contained in:
@@ -13,9 +13,9 @@ export interface Provider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function getActiveProvider(): Provider {
|
export function getActiveProvider(): Provider {
|
||||||
|
const hasOpenAI = !!process.env.OPENAI_API_KEY || !!process.env.LLM_API_KEY;
|
||||||
const hasTavily = !!process.env.TAVILY_API_KEY;
|
const hasTavily = !!process.env.TAVILY_API_KEY;
|
||||||
const hasPerplexity = !!process.env.PERPLEXITY_API_KEY;
|
const hasPerplexity = !!process.env.PERPLEXITY_API_KEY;
|
||||||
const hasOpenAI = !!process.env.OPENAI_API_KEY;
|
|
||||||
|
|
||||||
if (hasTavily && hasPerplexity) {
|
if (hasTavily && hasPerplexity) {
|
||||||
console.log("[llm] Using provider: Tavily search + Perplexity synthesis");
|
console.log("[llm] Using provider: Tavily search + Perplexity synthesis");
|
||||||
|
|||||||
@@ -8,10 +8,16 @@ import type {
|
|||||||
import type { SearchResult } from "./tavily";
|
import type { SearchResult } from "./tavily";
|
||||||
|
|
||||||
let _client: OpenAI | null = null;
|
let _client: OpenAI | null = null;
|
||||||
|
const MODEL = process.env.LLM_MODEL || "gpt-4o-mini";
|
||||||
|
|
||||||
function getClient(): OpenAI {
|
function getClient(): OpenAI {
|
||||||
if (!_client) {
|
if (!_client) {
|
||||||
_client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
|
const baseURL = process.env.LLM_BASE_URL || undefined;
|
||||||
|
const apiKey = process.env.OPENAI_API_KEY || process.env.LLM_API_KEY;
|
||||||
|
if (!apiKey) {
|
||||||
|
throw new Error("No API key configured. Set OPENAI_API_KEY or LLM_API_KEY.");
|
||||||
|
}
|
||||||
|
_client = new OpenAI({ apiKey, baseURL });
|
||||||
}
|
}
|
||||||
return _client;
|
return _client;
|
||||||
}
|
}
|
||||||
@@ -112,7 +118,7 @@ Provide a comprehensive comparison with scores, pros/cons, and a recommendation.
|
|||||||
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
||||||
try {
|
try {
|
||||||
const response = await getClient().chat.completions.create({
|
const response = await getClient().chat.completions.create({
|
||||||
model: "gpt-4o-mini",
|
model: MODEL,
|
||||||
messages: [
|
messages: [
|
||||||
{ role: "system", content: SYSTEM_PROMPT },
|
{ role: "system", content: SYSTEM_PROMPT },
|
||||||
{ role: "user", content: userPrompt },
|
{ role: "user", content: userPrompt },
|
||||||
@@ -179,7 +185,7 @@ Use the web research data above to provide factual, data-driven insights. Refere
|
|||||||
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
|
||||||
try {
|
try {
|
||||||
const response = await getClient().chat.completions.create({
|
const response = await getClient().chat.completions.create({
|
||||||
model: "gpt-4o-mini",
|
model: MODEL,
|
||||||
messages: [
|
messages: [
|
||||||
{ role: "system", content: SYSTEM_PROMPT },
|
{ role: "system", content: SYSTEM_PROMPT },
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user