diff --git a/src/lib/llm/providers/index.ts b/src/lib/llm/providers/index.ts new file mode 100644 index 0000000..0d46526 --- /dev/null +++ b/src/lib/llm/providers/index.ts @@ -0,0 +1,63 @@ +import type { ComparisonRequest, ComparisonResult } from "../types"; +import type { SearchResult } from "./tavily"; +import { generateComparisonWithResearch, generateComparison } from "./openai"; +import { synthesizeResearch } from "./perplexity"; + +export interface Provider { + name: string; + hasSearch: boolean; + synthesize: ( + request: ComparisonRequest, + searchResults: Record + ) => Promise; +} + +export function getActiveProvider(): Provider { + const hasTavily = !!process.env.TAVILY_API_KEY; + const hasPerplexity = !!process.env.PERPLEXITY_API_KEY; + const hasOpenAI = !!process.env.OPENAI_API_KEY; + + if (hasTavily && hasPerplexity) { + console.log("[llm] Using provider: Tavily search + Perplexity synthesis"); + return { + name: "Tavily + Perplexity", + hasSearch: true, + synthesize: synthesizeResearch, + }; + } + + if (hasTavily && hasOpenAI) { + console.log("[llm] Using provider: Tavily search + OpenAI synthesis"); + return { + name: "Tavily + OpenAI", + hasSearch: true, + synthesize: generateComparisonWithResearch, + }; + } + + if (hasOpenAI) { + console.log("[llm] Using provider: OpenAI only (no web search)"); + return { + name: "OpenAI", + hasSearch: false, + synthesize: async (request) => generateComparison(request), + }; + } + + console.warn( + "[llm] No API keys configured. Research will fail at synthesis." + ); + return { + name: "None", + hasSearch: false, + synthesize: async () => { + throw new Error( + "No LLM provider configured. Set OPENAI_API_KEY, TAVILY_API_KEY, or PERPLEXITY_API_KEY." + ); + }, + }; +} + +export { searchItem, type SearchResult } from "./tavily"; +export { generateComparison, generateComparisonWithResearch } from "./openai"; +export { synthesizeResearch } from "./perplexity";