Files
0pt/app/api/ai/parse/route.ts
T

60 lines
3.0 KiB
TypeScript

import { NextRequest, NextResponse } from "next/server";
import { engineFetch } from "@/lib/engine";
// POST /api/ai/parse (docs/04) — natural-language need -> prefilled order config.
// Uses the engine's LLM when available; otherwise a transparent keyword heuristic.
const MARKETS: [RegExp, string][] = [
[/sverige|svensk|\bse\b/i, "SE"], [/norge|norsk|\bno\b/i, "NO"], [/danmark|dansk|\bdk\b/i, "DK"],
[/finland|finsk|\bfi\b/i, "FI"], [/tyskland|\bde\b/i, "DE"], [/storbritannien|\buk\b|\bgb\b/i, "GB"],
];
const SERVICE: [RegExp, string][] = [
[/skrap|scrap/i, "scraping"], [/mappa|matcha|match|koppla/i, "mapping"],
[/normaliser|städ|dedup|tvätta/i, "normalization"], [/konsolider|crm|erp|hubspot|salesforce|dynamics|pipedrive|fivecrm/i, "consolidation"],
[/dokument|ocr|pdf|scann/i, "documents"], [/berik|enrich/i, "enrichment"],
[/\bicp\b|leads?|målgrupp|beslutsfattare/i, "icp"], [/\bml\b|modell|scoring|prognos|kluster/i, "ml"],
[/\bbi\b|dashboard|analys|marknadsanalys/i, "bi"], [/flöde|feed|övervak|freshness/i, "feeds"],
];
const FIELDS: [RegExp, string][] = [
[/e-?post|email|mejl|kontakt|telefon/i, "contact"], [/omsättning|finans|bokslut|resultat|nyckeltal/i, "financials"],
[/lei|cross-?border/i, "lei"], [/huvudman|ubo|ägar/i, "ubo"], [/intent|köpsignal|signal/i, "intent"],
];
const DEST: [RegExp, string][] = [
[/hubspot/i, "HubSpot"], [/salesforce/i, "Salesforce"], [/dynamics/i, "Microsoft Dynamics"],
[/pipedrive/i, "Pipedrive"], [/fivecrm/i, "FiveCRM"], [/sheets/i, "Google Sheets"],
];
export async function POST(req: NextRequest) {
const parsed = await req.json().catch(() => ({ text: "" }));
const body = parsed && typeof parsed === "object" ? parsed : { text: "" };
const { text } = body as { text?: string };
if (!text) return NextResponse.json({ error: { code: "bad_request", message: "text krävs" } }, { status: 400 });
const eng = await engineFetch("/ai/parse", { method: "POST", body: JSON.stringify({ text }) });
if (eng && eng.ok) return NextResponse.json(await eng.json());
const pick = (table: [RegExp, string][]) => table.filter(([re]) => re.test(text)).map(([, v]) => v);
const markets = [...new Set(pick(MARKETS))];
const service = pick(SERVICE)[0] ?? "data";
const fields = [...new Set(pick(FIELDS))];
const destination = pick(DEST)[0] ?? null;
const volMatch = text.replace(/\s/g, "").match(/(\d{3,})/);
const volume = volMatch ? Math.min(1_000_000, parseInt(volMatch[1], 10)) : 5000;
return NextResponse.json({
config: {
service_type: service,
markets: markets.length ? markets : ["SE"],
type: "Bolag",
fieldIds: fields.length ? fields : ["lei"],
enrichmentIds: [],
volume,
frequency: service === "feeds" || service === "enrichment" ? "Veckovis" : "Engångs",
confidence: 92,
destination,
description: text,
},
rationale: `Tolkat som ${service}${markets.length ? ` · ${markets.join(", ")}` : ""}${destination ? ` · ${destination}` : ""}. Justera fritt.`,
heuristic: true,
});
}