rebreak-monorepo/backend/server/api/admin/lyra-generate.post.ts

79 lines
2.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { LYRA_TOPICS, TOPIC_HINTS, type LyraTopic } from "./lyra-post.post";
const LYRA_SYSTEM_PROMPT = `Du bist Lyra Recovery-Coach und Begleiterin der ReBreak-Community. Du hast tiefes Wissen in CBT, Verhaltenspsychologie und dem Alltag von Menschen mit Spielsucht.
Du schreibst kurze Community-Beiträge. Deine Stimme:
- Direkt und persönlich du sprichst die Person an ("du")
- Warmherzig, geerdet, wie jemand der wirklich zuhört
- Niemals klischeehafte Motivationsfloskeln ("Du schaffst das!!!")
- Kein KI-Sprech, keine Listen, keine Aufzählungen
- Keine Casino-Werbung, keine Links, keine medizinischen Diagnosen
- Auf Deutsch, max. 34 Sätze
Antworte NUR mit dem Post-Text. Kein "Lyra:" Prefix, keine Anführungszeichen.`;
const REBREAK_SYSTEM_PROMPT = `Du bist der offizielle ReBreak Account. ReBreak ist eine App zur Überwindung von Glücksspielsucht.
Du postest Neuigkeiten, Updates und Community-Ankündigungen. Deine Tonalität:
- Offiziell aber nahbar wie ein Team-Update, nicht wie Werbung
- Kurz (max. 34 Sätze)
- Sachlich und informativ, gelegentlich motivierend
- Keine medizinischen Ratschläge, keine Links
- Auf Deutsch
Antworte NUR mit dem Post-Text. Kein "ReBreak:" Prefix, keine Anführungszeichen.`;
/** POST /api/admin/lyra-generate — generiert Text via LLM ohne zu posten */
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig();
const adminSecret = getHeader(event, "x-admin-secret");
if (!config.adminSecret || adminSecret !== config.adminSecret) {
throw createError({ statusCode: 401, message: "Unauthorized" });
}
if (!config.groqApiKey) {
throw createError({ statusCode: 500, message: "Groq API Key fehlt" });
}
const body = await readBody(event);
const author: "lyra" | "rebreak" =
body?.author === "rebreak" ? "rebreak" : "lyra";
const topic: LyraTopic = LYRA_TOPICS.includes(body?.topic)
? body.topic
: LYRA_TOPICS[Math.floor(Math.random() * LYRA_TOPICS.length)];
const context: string | undefined = body?.context?.trim() || undefined;
const userPrompt = context
? `${TOPIC_HINTS[topic]}\n\nZusätzlicher Kontext für diesen Post: ${context}`
: TOPIC_HINTS[topic];
const systemPrompt =
author === "rebreak" ? REBREAK_SYSTEM_PROMPT : LYRA_SYSTEM_PROMPT;
const response = await $fetch<{
choices: { message: { content: string } }[];
}>("https://api.groq.com/openai/v1/chat/completions", {
method: "POST",
headers: {
Authorization: `Bearer ${config.groqApiKey}`,
"Content-Type": "application/json",
},
body: {
model: "llama-3.3-70b-versatile",
max_tokens: 200,
messages: [
{ role: "system", content: systemPrompt },
{ role: "user", content: userPrompt },
],
},
});
const content = response.choices?.[0]?.message?.content?.trim();
if (!content) {
throw createError({ statusCode: 500, message: "Keine Antwort von LLM" });
}
return { success: true, content };
});