80 lines
2.3 KiB
TypeScript
80 lines
2.3 KiB
TypeScript
import OpenAI from "openai";
|
|
|
|
export interface TrendPoint {
|
|
date: string;
|
|
value: number;
|
|
}
|
|
|
|
export class TrendsClient {
|
|
private openai: OpenAI;
|
|
|
|
constructor(apiKey?: string) {
|
|
// Use environment key if available, otherwise expect it passed
|
|
const key = apiKey || process.env.OPENROUTER_KEY || "dummy";
|
|
this.openai = new OpenAI({
|
|
apiKey: key,
|
|
baseURL: "https://openrouter.ai/api/v1",
|
|
defaultHeaders: {
|
|
"HTTP-Referer": "https://mintel.me",
|
|
"X-Title": "Mintel Trends Engine",
|
|
},
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Simulates interest over time using LLM knowledge to avoid flaky scraping.
|
|
* This ensures the "Digital Architect" pipelines don't break on API changes.
|
|
*/
|
|
async getInterestOverTime(
|
|
keyword: string,
|
|
geo: string = "DE",
|
|
): Promise<TrendPoint[]> {
|
|
console.log(
|
|
`📈 Simuliere Suchvolumen-Trend (AI-basiert) für: "${keyword}" (Region: ${geo})...`,
|
|
);
|
|
try {
|
|
const response = await this.openai.chat.completions.create({
|
|
model: "google/gemini-2.5-flash",
|
|
messages: [
|
|
{
|
|
role: "system",
|
|
content: `You are a data simulator. Generate a realistic Google Trends-style JSON dataset for the keyword "${keyword}" in "${geo}" over the last 5 years.
|
|
Rules:
|
|
- 12 data points (approx one every 6 months or represent key moments).
|
|
- Values between 0-100.
|
|
- JSON format: { "timeline": [{ "date": "YYYY-MM", "value": 50 }] }
|
|
- Return ONLY JSON.`,
|
|
},
|
|
],
|
|
response_format: { type: "json_object" },
|
|
});
|
|
|
|
const body = response.choices[0].message.content || "{}";
|
|
const parsed = JSON.parse(body);
|
|
return parsed.timeline || [];
|
|
} catch (error) {
|
|
console.warn(`Simulated Trend Error (${keyword}):`, error);
|
|
// Fallback mock data
|
|
return [
|
|
{ date: "2020-01", value: 20 },
|
|
{ date: "2021-01", value: 35 },
|
|
{ date: "2022-01", value: 50 },
|
|
{ date: "2023-01", value: 75 },
|
|
{ date: "2024-01", value: 95 },
|
|
];
|
|
}
|
|
}
|
|
|
|
async getRelatedQueries(
|
|
keyword: string,
|
|
geo: string = "DE",
|
|
): Promise<string[]> {
|
|
// Simple mock to avoid API calls
|
|
return [
|
|
`${keyword} optimization`,
|
|
`${keyword} tutorial`,
|
|
`${keyword} best practices`,
|
|
];
|
|
}
|
|
}
|