feat: enhance OpenAI provider with web research context

This commit is contained in:
Christopher Mayor
2026-04-24 14:33:50 -07:00
parent 3a448a5063
commit 71ef567d0d

View File

@@ -5,6 +5,7 @@ import type {
DimensionResult, DimensionResult,
ItemResearch, ItemResearch,
} from "../types"; } from "../types";
import type { SearchResult } from "./tavily";
const client = new OpenAI({ const client = new OpenAI({
apiKey: process.env.OPENAI_API_KEY, apiKey: process.env.OPENAI_API_KEY,
@@ -140,3 +141,75 @@ Provide a comprehensive comparison with scores, pros/cons, and a recommendation.
`Failed to generate comparison after ${MAX_RETRIES} attempts: ${lastError?.message}` `Failed to generate comparison after ${MAX_RETRIES} attempts: ${lastError?.message}`
); );
} }
export async function generateComparisonWithResearch(
request: ComparisonRequest,
searchResults: Record<string, SearchResult[]>
): Promise<ComparisonResult> {
const allResults = Object.values(searchResults).flat();
if (allResults.length === 0) {
return generateComparison(request);
}
let researchContext = "Web research data:\n\n";
for (const [itemName, results] of Object.entries(searchResults)) {
if (results.length === 0) continue;
researchContext += `=== ${itemName} ===\n`;
for (const r of results) {
researchContext += `- ${r.title}: ${r.content}\n Source: ${r.url}\n`;
}
researchContext += "\n";
}
const userPrompt = `Compare the following items: ${request.items.join(", ")}
${request.query ? `Focus: ${request.query}` : ""}
${request.dimensions?.length ? `Specific dimensions to include: ${request.dimensions.join(", ")}` : ""}
${researchContext}
Use the web research data above to provide factual, data-driven insights. Reference specific data points in your analysis. Provide a comprehensive comparison with scores, pros/cons, and a recommendation.`;
let lastError: Error | null = null;
for (let attempt = 1; attempt <= MAX_RETRIES; attempt++) {
try {
const response = await client.chat.completions.create({
model: "gpt-4o-mini",
messages: [
{ role: "system", content: SYSTEM_PROMPT },
{
role: "system",
content:
"You have access to real web search results. Use them to ground your comparison in factual data. Cite specific findings from the research when scoring and analyzing items.",
},
{ role: "user", content: userPrompt },
],
response_format: { type: "json_object" },
temperature: 0.3,
});
const content = response.choices[0]?.message?.content;
if (!content) {
throw new Error("Empty response from OpenAI");
}
const parsed: unknown = JSON.parse(content);
if (!validateComparisonResult(parsed)) {
throw new Error("Invalid comparison result structure from OpenAI");
}
return parsed;
} catch (error) {
lastError = error instanceof Error ? error : new Error(String(error));
if (attempt < MAX_RETRIES) {
await sleep(RETRY_DELAY_MS * attempt);
}
}
}
throw new Error(
`Failed to generate comparison with research after ${MAX_RETRIES} attempts: ${lastError?.message}`
);
}