feat: enhance OpenAI provider with web research context
This commit is contained in:
@@ -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}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user