KI-Chat: reichhaltigerer Kontext (Stellenbeschreibung, Korrespondenz, Profil)
Der Assistent kannte nur Firma/Stelle/Status/Notizen und konnte daher keine firmenspezifischen Fragen beantworten. gatherChatContext lädt jetzt pro Bewerbung: Ort, interne Notizen, Stellenbeschreibung (bzw. verknüpftes Jobangebot), Kontakt/Ansprechpartner und die E-Mail-Korrespondenz (Betreffe). Zusätzlich wird der Lebenslauf des Bewerbers injiziert, damit Antworten auf "was für mich wichtig" zugeschnitten werden können. Relevante Bewerbungen = Termin-Bewerbungen + 12 jüngste (gebunden im Token-Budget). Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+30
-15
@@ -99,8 +99,9 @@ async function streamChat({ system, messages, onToken, temperature = 0.6, signal
|
||||
|
||||
// Build the German system prompt that grounds the assistant in the user's
|
||||
// application data. `context` is gathered by the server from SQLite:
|
||||
// { settings, applications, recentEmails, upcomingTermine }
|
||||
// Each entry is already trimmed to the fields the prompt needs.
|
||||
// { heute, settings, applications, upcomingTermine }
|
||||
// Each application entry carries firma/stelle/status, notes, the (trimmed)
|
||||
// job description, contact, and the recent e-mail correspondence subjects.
|
||||
function buildContextPrompt(ctx) {
|
||||
const name = (ctx && ctx.settings && ctx.settings.name) || 'der Bewerber';
|
||||
const heute = (ctx && ctx.heute) || '';
|
||||
@@ -112,7 +113,9 @@ function buildContextPrompt(ctx) {
|
||||
'Antworte natürlich, knapp und auf Deutsch im lateinischen Alphabet. ' +
|
||||
'Erfinde KEINE Fakten (keine erfundenen Termine, Zahlen, Zusagen, Firmen). ' +
|
||||
'Wenn eine Angabe nötig ist, die du nicht weißt, setze einen klar erkennbaren ' +
|
||||
'Platzhalter in eckigen Klammern. Verwende nur den einfachen Bindestrich "-".'
|
||||
'Platzhalter in eckigen Klammern. Verwende nur den einfachen Bindestrich "-". ' +
|
||||
'Fasse Stellenbeschreibungen verständlich zusammen, statt sie wörtlich ' +
|
||||
'wiederzugeben, und beziehe sie auf das Profil des Bewerbers.'
|
||||
);
|
||||
if (heute) {
|
||||
parts.push('# Heute\n' + 'Heutiges Datum: ' + heute + '. ' +
|
||||
@@ -122,34 +125,46 @@ function buildContextPrompt(ctx) {
|
||||
'bzw. UTC+2 während der Sommerzeit).');
|
||||
}
|
||||
|
||||
if (ctx && ctx.profil) {
|
||||
parts.push('# Dein Profil (Lebenslauf)\n' + ctx.profil +
|
||||
'\nNutze dies, um Antworten auf den Bewerber zuzuschneiden: Wenn der Nutzer ' +
|
||||
'nach einer Firma fragt, hebe hervor, welche Anforderungen der Stelle zu ' +
|
||||
'seinem Profil passen und wo Lücken bestehen.');
|
||||
}
|
||||
|
||||
const apps = (ctx && ctx.applications) || [];
|
||||
if (apps.length) {
|
||||
parts.push('# Bewerbungen (jüngste zuerst)');
|
||||
for (const a of apps) {
|
||||
const lines = [
|
||||
`• ${a.firma || '?'} – ${a.stelle || '?'} (Status: ${a.status || '—'}, Datum: ${a.datum || '—'})`,
|
||||
`• [Bewerbung ${a.id}] ${a.firma || '?'} – ${a.stelle || '?'} ` +
|
||||
`(Status: ${a.status || '—'}, Datum: ${a.datum || '—'}${a.ort ? `, Ort: ${a.ort}` : ''})`,
|
||||
];
|
||||
if (a.kontakt || a.ansprechpartner) {
|
||||
lines.push(` Kontakt: ${[a.ansprechpartner, a.kontakt].filter(Boolean).join(', ')}`);
|
||||
}
|
||||
if (a.quelle_url) lines.push(` Quelle: ${a.quelle_url}`);
|
||||
if (a.notizen) lines.push(` Notizen: ${a.notizen}`);
|
||||
if (a.interne_notizen) lines.push(` Interne Notizen: ${a.interne_notizen}`);
|
||||
if (a.stellenbeschreibung) lines.push(` Stellenbeschreibung: ${a.stellenbeschreibung}`);
|
||||
const kor = a.korrespondenz || [];
|
||||
if (kor.length) {
|
||||
lines.push(' Korrespondenz (neueste zuerst):');
|
||||
for (const e of kor) {
|
||||
const tag = e.direction === 'out' ? 'gesendet' : 'eingegangen';
|
||||
lines.push(` - ${tag}: ${e.subject || '(kein Betreff)'}${e.from ? ` — von ${e.from}` : ''}`);
|
||||
}
|
||||
}
|
||||
parts.push(lines.join('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
const emails = (ctx && ctx.recentEmails) || [];
|
||||
if (emails.length) {
|
||||
parts.push('# Letzte eingegangene E-Mails');
|
||||
for (const e of emails) {
|
||||
parts.push(
|
||||
`• ${e.subject || '(kein Betreff)'} — von ${e.from || '?'} (${e.bewerbung || '?'})`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const termine = (ctx && ctx.upcomingTermine) || [];
|
||||
if (termine.length) {
|
||||
parts.push('# Kommende Termine');
|
||||
for (const t of termine) {
|
||||
parts.push(
|
||||
`• ${t.titel} — ${t.start}${t.bewerbung ? ` (${t.bewerbung})` : ''}`
|
||||
`• ${t.titel} — ${t.start}${t.bewerbung ? ` (Bewerbung ${t.bewerbung_id || '?'}, ${t.bewerbung})` : ''}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user