Files
Atlas/lib/ai-service.ts
2025-11-12 20:21:32 +01:00

226 lines
7.1 KiB
TypeScript

import OpenAI from 'openai';
const openai = new OpenAI({
apiKey: process.env.OPENAI_API_KEY || '',
});
interface ParsedBookingData {
customerName: string;
customerEmail: string;
customerPhone: string;
customerAddress?: string;
customerCity?: string;
customerZip?: string;
companyName?: string;
invoiceType: 'PRIVATE' | 'BUSINESS';
eventDate: string;
eventAddress: string;
eventCity: string;
eventZip: string;
eventLocation?: string;
setupTimeStart: string;
setupTimeLatest?: string;
photoboxModel?: 'VINTAGE_SMILE' | 'VINTAGE_PHOTOS' | 'NOSTALGIE' | 'MAGIC_MIRROR';
specialRequests?: string;
}
export class AIService {
async parseBookingEmail(emailContent: string, subject: string): Promise<{
parsed: ParsedBookingData;
responseDraft: string;
confidence: number;
}> {
const prompt = `Du bist ein KI-Assistent für ein Fotobox-Vermietungsunternehmen.
Analysiere die folgende E-Mail-Anfrage und extrahiere alle relevanten Buchungsinformationen.
E-Mail-Betreff: ${subject}
E-Mail-Inhalt:
${emailContent}
Extrahiere folgende Informationen (falls vorhanden):
- Kundenname
- E-Mail-Adresse
- Telefonnummer
- Adresse (Straße, PLZ, Stadt)
- Firmenname (falls Geschäftskunde)
- Event-Datum (Format: YYYY-MM-DD)
- Event-Uhrzeit (wann soll die Fotobox aufgebaut sein?)
- Event-Adresse (Straße, PLZ, Stadt)
- Event-Location-Name
- Gewünschtes Fotobox-Modell
- Besondere Wünsche
Antworte im folgenden JSON-Format:
{
"customerData": {
"name": "string",
"email": "string",
"phone": "string",
"address": "string",
"city": "string",
"zip": "string",
"companyName": "string oder null",
"invoiceType": "PRIVATE" oder "BUSINESS"
},
"eventData": {
"date": "YYYY-MM-DD",
"time": "HH:MM",
"address": "string",
"city": "string",
"zip": "string",
"locationName": "string",
"photoboxModel": "VINTAGE_SMILE" | "VINTAGE_PHOTOS" | "NOSTALGIE" | "MAGIC_MIRROR" oder null,
"specialRequests": "string"
},
"confidence": 0.0 bis 1.0 (wie sicher bist du bei der Extraktion?)
}`;
try {
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: 'Du bist ein Experte für die Analyse von Buchungsanfragen. Antworte immer nur mit validem JSON.',
},
{
role: 'user',
content: prompt,
},
],
response_format: { type: 'json_object' },
temperature: 0.3,
});
const result = JSON.parse(completion.choices[0].message.content || '{}');
const parsed: ParsedBookingData = {
customerName: result.customerData.name,
customerEmail: result.customerData.email,
customerPhone: result.customerData.phone,
customerAddress: result.customerData.address,
customerCity: result.customerData.city,
customerZip: result.customerData.zip,
companyName: result.customerData.companyName,
invoiceType: result.customerData.invoiceType,
eventDate: `${result.eventData.date}T${result.eventData.time || '00:00'}:00.000Z`,
eventAddress: result.eventData.address,
eventCity: result.eventData.city,
eventZip: result.eventData.zip,
eventLocation: result.eventData.locationName,
setupTimeStart: `${result.eventData.date}T${result.eventData.time || '00:00'}:00.000Z`,
photoboxModel: result.eventData.photoboxModel,
specialRequests: result.eventData.specialRequests,
};
const responseDraft = await this.generateResponseDraft(parsed, emailContent);
return {
parsed,
responseDraft,
confidence: result.confidence,
};
} catch (error) {
console.error('AI Email Parsing Error:', error);
throw new Error('KI-Analyse fehlgeschlagen');
}
}
async generateResponseDraft(bookingData: ParsedBookingData, originalEmail: string): Promise<string> {
const prompt = `Du bist Kundenservice-Mitarbeiter bei "Save the Moment" - einem Premium-Fotobox-Vermietungsservice.
Erstelle eine professionelle, freundliche Antwort-E-Mail für diese Buchungsanfrage:
Kundendaten:
- Name: ${bookingData.customerName}
- Event-Datum: ${new Date(bookingData.eventDate).toLocaleDateString('de-DE')}
- Event-Ort: ${bookingData.eventCity}
${bookingData.specialRequests ? `- Besondere Wünsche: ${bookingData.specialRequests}` : ''}
Die E-Mail soll:
1. Freundlich und professionell sein
2. Die Anfrage bestätigen
3. Die wichtigsten Details zusammenfassen
4. Erwähnen, dass ein Angebot und Mietvertrag im Anhang sind
5. Nächste Schritte erklären (Vertrag digital unterschreiben)
6. Kontaktdaten für Rückfragen nennen
Schreibe die E-Mail auf Deutsch, ohne Betreff-Zeile (nur Body).`;
try {
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: 'Du bist ein freundlicher, professioneller Kundenservice-Mitarbeiter.',
},
{
role: 'user',
content: prompt,
},
],
temperature: 0.7,
max_tokens: 500,
});
return completion.choices[0].message.content || '';
} catch (error) {
console.error('AI Response Generation Error:', error);
return `Sehr geehrte/r ${bookingData.customerName},
vielen Dank für Ihre Anfrage für den ${new Date(bookingData.eventDate).toLocaleDateString('de-DE')} in ${bookingData.eventCity}.
Wir haben Ihre Anfrage erhalten und freuen uns, Ihnen unser Angebot sowie den Mietvertrag im Anhang zu senden.
Bitte prüfen Sie die Unterlagen und unterschreiben Sie den Vertrag digital über den Link im Anhang.
Bei Fragen stehen wir Ihnen gerne zur Verfügung.
Mit freundlichen Grüßen
Ihr Save the Moment Team`;
}
}
async improveContractText(standardContract: string, bookingData: any): Promise<string> {
const prompt = `Personalisiere den folgenden Standard-Mietvertrag mit den spezifischen Buchungsdaten:
STANDARD-VERTRAG:
${standardContract}
BUCHUNGSDATEN:
- Kunde: ${bookingData.customerName}
- Event-Datum: ${new Date(bookingData.eventDate).toLocaleDateString('de-DE')}
- Event-Ort: ${bookingData.eventAddress}, ${bookingData.eventZip} ${bookingData.eventCity}
- Aufbauzeit: ${new Date(bookingData.setupTimeStart).toLocaleTimeString('de-DE')}
Füge die Daten in die Platzhalter ein und passe die Formulierungen an. Der Vertrag soll rechtlich bindend bleiben.`;
try {
const completion = await openai.chat.completions.create({
model: 'gpt-4-turbo-preview',
messages: [
{
role: 'system',
content: 'Du bist ein Experte für Vertragsformulierungen. Achte auf korrekte Rechtschreibung und Grammatik.',
},
{
role: 'user',
content: prompt,
},
],
temperature: 0.2,
max_tokens: 2000,
});
return completion.choices[0].message.content || standardContract;
} catch (error) {
console.error('AI Contract Generation Error:', error);
return standardContract;
}
}
}
export const aiService = new AIService();