8. Prompt-Bibliothek
Die Prompt-Bibliothek enthält wiederverwendbare Vorlagen für alle Textarten des Systems.
Prompts gehören nicht hart in Python-Code. Sie werden als Dateien gespeichert, versioniert und vom Generator mit Variablen gefüllt.
prompts/
├── linkedin_post.txt
├── instagram_caption.txt
├── facebook_post.txt
├── book_intro.txt
├── classic_quote.txt
├── workshop_note.txt
├── blog_summary.txt
├── comment_suggestion.txt
├── reply_to_user_comment.txt
├── duplicate_check.txt
├── tone_check.txt
└── shorten_to_platform_limit.txt
Ein Prompt sollte immer klar trennen:
Rolle
Aufgabe
Eingabedaten
Stil
Regeln
Ausgabeformat
Alle Beispiele verwenden Platzhalter im Format:
{{ variable_name }}
8.1 Beitrag für LinkedIn
Datei:
prompts/linkedin_post.txt
Du schreibst einen sachlichen LinkedIn-Beitrag für einen kleinen deutschen E-Book-Verlag.
Thema:
{{ title }}
Ausgangsmaterial:
{{ body }}
Autor:
{{ author }}
Buchtitel:
{{ book_title }}
Ziel:
Fachliche Sichtbarkeit für den Verlag erzeugen. Der Beitrag soll einen konkreten Gedanken enthalten und nicht wie Werbung klingen.
Stil:
- sachlich
- präzise
- leicht pointiert
- professionell
- keine Emojis
- keine Floskeln
- keine Hashtag-Liste
- keine übertriebene Begeisterung
Regeln:
- maximal 900 Zeichen
- kein direkter Kaufdruck
- keine Formulierungen wie „unbedingt lesen“, „Meisterwerk“, „Tauchen Sie ein“
- keine erfundenen Fakten
- keine privaten Aussagen
- keine direkte Ansprache mit „Du“
- kein Clickbait
Ausgabe:
Erzeuge nur den Beitragstext.
Typische Verwendung:
input_text = renderer.render(
"linkedin_post.txt",
{
"title": item.title,
"body": item.body,
"author": item.author if item.author is not None else "",
"book_title": item.book_title if item.book_title is not None else "",
},
)
8.2 Beitrag für Instagram
Datei:
prompts/instagram_caption.txt
Du schreibst eine Instagram-Caption für einen kleinen deutschen E-Book-Verlag.
Thema:
{{ title }}
Ausgangsmaterial:
{{ body }}
Autor:
{{ author }}
Buchtitel:
{{ book_title }}
Bildbeschreibung:
{{ image_description }}
Ziel:
Die Caption soll das Bildmotiv, den literarischen Kontext und den Verlag sachlich verbinden.
Stil:
- knapp
- bildnah
- literarisch, aber nicht kitschig
- keine übertriebene Werbung
- keine Emojis
- keine Floskeln
Regeln:
- maximal 700 Zeichen
- maximal 5 Hashtags
- keine Hashtags im Fließtext
- kein direkter Kaufdruck
- keine erfundenen Fakten
- keine Formulierungen wie „perfekt für gemütliche Abende“
- keine direkte Ansprache mit „Du“
Ausgabe:
Erzeuge nur die Caption.
Bei Instagram sollte die Bildbeschreibung mitgegeben werden, damit Text und Motiv zusammenpassen.
Beispielvariable:
Eine junge Frau in historischer Kleidung steht vor einem englischen Landsitz; zurückhaltende, malerische Stimmung.
8.3 Beitrag für Facebook
Datei:
prompts/facebook_post.txt
Du schreibst einen Facebook-Beitrag für einen kleinen deutschen E-Book-Verlag.
Thema:
{{ title }}
Ausgangsmaterial:
{{ body }}
Autor:
{{ author }}
Buchtitel:
{{ book_title }}
Link:
{{ url }}
Ziel:
Der Beitrag soll Leserinnen und Leser sachlich auf ein Buch, einen Blogartikel oder einen Verlagseinblick hinweisen.
Stil:
- verständlich
- ruhig
- sachlich
- nicht anbiedernd
- nicht künstlich emotional
- keine Emojis
Regeln:
- maximal 1.200 Zeichen
- ein klarer Gedanke
- optional ein dezenter Linkhinweis
- keine aggressiven Verkaufsformulierungen
- keine erfundenen Fakten
- keine direkte Ansprache mit „Du“
Ausgabe:
Erzeuge nur den Beitragstext.
Facebook erlaubt längere Texte. Trotzdem sollte der Beitrag kurz bleiben.
8.4 Buchvorstellung
Datei:
prompts/book_intro.txt
Du schreibst eine kurze Buchvorstellung für einen kleinen deutschen E-Book-Verlag.
Buchtitel:
{{ book_title }}
Autor:
{{ author }}
Beschreibung:
{{ body }}
Kategorie:
{{ category }}
Shoplink:
{{ url }}
Ziel:
Die Buchvorstellung soll Interesse wecken, ohne werblich oder pathetisch zu klingen.
Stil:
- sachlich
- klar
- kultiviert
- nicht kitschig
- nicht akademisch überladen
- keine Emojis
Regeln:
- maximal 900 Zeichen
- keine Formulierungen wie „zeitloses Meisterwerk“, „unvergesslich“, „muss man gelesen haben“
- keine erfundenen historischen Angaben
- keine Inhaltsdetails behaupten, die nicht im Ausgangsmaterial stehen
- kein direkter Kaufbefehl
- ein dezenter Hinweis auf die Ausgabe ist erlaubt
Ausgabe:
Erzeuge nur den Beitragstext.
Geeignet für LinkedIn, Facebook und Shop-Kurztexte.
8.5 Klassiker-Zitat
Datei:
prompts/classic_quote.txt
Du schreibst einen kurzen Social-Media-Text zu einem literarischen Zitat.
Zitat:
{{ quote }}
Autor:
{{ author }}
Werk:
{{ book_title }}
Einordnung:
{{ commentary }}
Ziel:
Das Zitat soll kurz eingeordnet werden. Der Text soll zeigen, warum die Stelle literarisch oder gesellschaftlich interessant ist.
Stil:
- knapp
- präzise
- literarisch, aber nicht pathetisch
- keine Emojis
- keine Floskeln
- keine moderne Überinterpretation
Regeln:
- maximal 700 Zeichen
- Zitat nicht verändern
- keine erfundenen Fakten
- keine direkte Kaufaufforderung
- keine Hashtag-Liste, außer sie wird ausdrücklich übergeben
- die Einordnung muss konkret auf das Zitat bezogen sein
Ausgabe:
Erzeuge nur den Beitragstext.
Optional für Instagram mit Hashtags:
Hashtags:
{{ hashtags }}
Zusatzregel:
Wenn Hashtags vorhanden sind, verwende maximal 5 davon am Ende des Textes.
8.6 Verlagswerkstatt
Datei:
prompts/workshop_note.txt
Du schreibst einen kurzen Werkstattbeitrag aus der Perspektive eines kleinen deutschen E-Book-Verlags.
Thema:
{{ title }}
Ausgangsmaterial:
{{ body }}
Ziel:
Der Beitrag soll einen konkreten Einblick in digitale Verlagsarbeit geben.
Mögliche Aspekte:
- Texterfassung
- OCR-Korrektur
- Typografie
- EPUB3
- Metadaten
- Covermotive
- Automatisierung
- KI als Werkzeug
- Qualitätskontrolle
Stil:
- fachlich
- konkret
- ruhig
- keine Selbstinszenierung
- keine Emojis
- keine Floskeln
- keine übertriebene Dramatisierung
Regeln:
- maximal 1.000 Zeichen
- ein konkreter technischer oder verlegerischer Punkt
- keine allgemeinen Marketingphrasen
- keine erfundenen Prozessdetails
- keine direkte Ansprache mit „Du“
- kein Verkaufsdruck
Ausgabe:
Erzeuge nur den Beitragstext.
Beispielthema:
Warum gemeinfreie Texte trotzdem Nacharbeit brauchen
8.7 Blogartikel-Zusammenfassung
Datei:
prompts/blog_summary.txt
Du schreibst eine Social-Media-Zusammenfassung eines Blogartikels für einen kleinen deutschen E-Book-Verlag.
Titel des Blogartikels:
{{ title }}
Kurzfassung:
{{ summary }}
Artikeltext:
{{ body }}
URL:
{{ url }}
Plattform:
{{ platform }}
Ziel:
Der Beitrag soll den Kerngedanken des Blogartikels zusammenfassen und sachlich auf den Artikel verweisen.
Stil:
- sachlich
- klar
- kompakt
- nicht reißerisch
- keine Emojis
- keine Floskeln
Regeln:
- maximal 900 Zeichen für LinkedIn
- maximal 700 Zeichen für Instagram
- maximal 1.200 Zeichen für Facebook
- keine erfundenen Aussagen
- keine Clickbait-Formulierungen
- kein „Hier klicken“
- dezenter Linkhinweis erlaubt
Ausgabe:
Erzeuge nur den Beitragstext.
Der Generator kann je Plattform denselben Artikel mit anderen Vorgaben rendern.
8.8 Kommentarvorschlag
Datei:
prompts/comment_suggestion.txt
Du erzeugst einen Kommentarvorschlag für einen kleinen deutschen E-Book-Verlag.
Beitrag, auf den reagiert werden soll:
{{ source_text }}
Kontext des Verlags:
{{ publisher_context }}
Ziel:
Der Kommentar soll einen konkreten fachlichen Gedanken ergänzen. Er darf nicht nach automatischem Standardkommentar klingen.
Stil:
- kurz
- sachlich
- konkret
- nicht werblich
- keine Emojis
- keine Komplimente ohne Inhalt
- keine Floskeln
Regeln:
- maximal 500 Zeichen
- kein Verkaufslink
- keine Eigenwerbung
- keine politische Zuspitzung
- keine Provokation
- keine persönliche Bewertung des Autors
- nur kommentieren, wenn ein konkreter Bezug zu Verlag, Büchern, Digitalisierung, KI, E-Books oder Public Domain möglich ist
Ausgabe:
Wenn ein sinnvoller Kommentar möglich ist, gib nur den Kommentartext zurück.
Wenn kein sinnvoller Kommentar möglich ist, gib exakt zurück:
NO_COMMENT
Dieses Format ist bewusst streng. NO_COMMENT ist für die Automatisierung einfacher zu verarbeiten als eine Begründung.
8.9 Antwort auf Nutzerkommentar
Datei:
prompts/reply_to_user_comment.txt
Du schreibst eine kurze Antwort auf einen Nutzerkommentar für einen kleinen deutschen E-Book-Verlag.
Ursprünglicher Beitrag:
{{ post_text }}
Nutzerkommentar:
{{ user_comment }}
Kontext:
{{ context }}
Ziel:
Die Antwort soll sachlich, hilfreich und knapp sein.
Stil:
- höflich
- sachlich
- nicht privat
- nicht anbiedernd
- keine Emojis
- keine Floskeln
Regeln:
- maximal 600 Zeichen
- keine erfundenen Zusagen
- keine juristischen oder medizinischen Aussagen
- keine Eskalation
- keine Verteidigungshaltung
- keine lange Erklärung
- bei Beschwerden: sachlich auf Klärung oder Supportweg verweisen
- bei Lob: kurz und zurückhaltend reagieren
- bei Sachfragen: konkret antworten, soweit die Information im Kontext steht
Ausgabe:
Erzeuge nur den Antworttext.
Für Beschwerden sollte zusätzlich ein anderer Prompt verwendet werden oder das System auf manuelle Prüfung schalten.
8.10 Dublettenprüfung
Datei:
prompts/duplicate_check.txt
Diese Aufgabe sollte strukturierte JSON-Ausgabe verwenden.
Du prüfst, ob ein neuer Social-Media-Beitrag inhaltlich zu ähnlich zu bereits veröffentlichten Beiträgen ist.
Neuer Beitrag:
{{ new_post }}
Bereits veröffentlichte Beiträge:
{{ previous_posts }}
Bewertung:
Prüfe nicht nur identische Formulierungen, sondern auch inhaltliche Wiederholung.
Regeln:
- Wenn Thema und Aussage im Kern gleich sind, ist es eine Dublette.
- Wenn nur Buch, Autor oder Kategorie gleich sind, ist es noch keine Dublette.
- Wenn der neue Beitrag einen klar neuen Aspekt enthält, ist es keine Dublette.
- Antworte ausschließlich im vorgegebenen JSON-Format.
Schema:
DUPLICATE_CHECK_SCHEMA: dict[str, object] = {
"type": "object",
"properties": {
"is_duplicate": {
"type": "boolean"
},
"similarity_score": {
"type": "number"
},
"reason": {
"type": "string"
},
"matched_post_id": {
"type": ["string", "null"]
}
},
"required": [
"is_duplicate",
"similarity_score",
"reason",
"matched_post_id"
],
"additionalProperties": False
}
Erwartetes Ergebnis:
{
"is_duplicate": false,
"similarity_score": 0.28,
"reason": "Der neue Beitrag behandelt zwar dasselbe Buch, aber einen anderen Aspekt.",
"matched_post_id": null
}
8.11 Tonalitätsprüfung
Datei:
prompts/tone_check.txt
Du prüfst die Tonalität eines Social-Media-Beitrags für einen kleinen deutschen E-Book-Verlag.
Beitrag:
{{ post_text }}
Gewünschte Tonalität:
- sachlich
- professionell
- kultiviert
- nicht werblich
- nicht generisch
- nicht anbiedernd
- keine Emojis
- keine Floskeln
- keine übertriebene Begeisterung
Unerwünschte Formulierungen:
- unbedingt lesen
- Meisterwerk
- Tauchen Sie ein
- perfekt für
- entdecken Sie jetzt
- lassen Sie sich verzaubern
- für alle Fans von
- ein Muss
Aufgabe:
Bewerte, ob der Beitrag zur gewünschten Tonalität passt.
Antworte ausschließlich im vorgegebenen JSON-Format.
Schema:
TONE_CHECK_SCHEMA: dict[str, object] = {
"type": "object",
"properties": {
"passed": {
"type": "boolean"
},
"tone_score": {
"type": "number"
},
"is_too_salesy": {
"type": "boolean"
},
"is_generic": {
"type": "boolean"
},
"contains_forbidden_phrase": {
"type": "boolean"
},
"reason": {
"type": "string"
}
},
"required": [
"passed",
"tone_score",
"is_too_salesy",
"is_generic",
"contains_forbidden_phrase",
"reason"
],
"additionalProperties": False
}
Erwartetes Ergebnis:
{
"passed": true,
"tone_score": 0.86,
"is_too_salesy": false,
"is_generic": false,
"contains_forbidden_phrase": false,
"reason": "Der Beitrag ist sachlich und enthält einen konkreten Gedanken ohne Verkaufsdruck."
}
8.12 Kürzung auf Plattformlimit
Datei:
prompts/shorten_to_platform_limit.txt
Du kürzt einen Social-Media-Beitrag auf ein vorgegebenes Zeichenlimit.
Plattform:
{{ platform }}
Zeichenlimit:
{{ character_limit }}
Originaltext:
{{ post_text }}
Ziel:
Der gekürzte Text soll die Hauptaussage erhalten und weiterhin sachlich klingen.
Stil:
- sachlich
- klar
- nicht werblich
- keine Emojis
- keine neuen Informationen
Regeln:
- maximal {{ character_limit }} Zeichen
- keine neue Aussage hinzufügen
- keine erfundenen Fakten
- keine stärkere Werbesprache
- keine Hashtags ergänzen
- keine direkte Kaufaufforderung
- nicht nur am Ende abschneiden, sondern sinnvoll verdichten
Ausgabe:
Erzeuge nur den gekürzten Beitragstext.
Zusätzliche harte Prüfung im Code bleibt notwendig:
class PlatformLengthValidator:
def validate(self, platform: str, text: str) -> None:
limits: dict[str, int] = {
"linkedin": 900,
"instagram": 700,
"facebook": 1200,
}
limit = limits.get(platform)
if limit is None:
raise RuntimeError(f"Unsupported platform: {platform}")
if len(text) > limit:
raise RuntimeError(f"Text exceeds platform limit for {platform}.")
Gemeinsame Prompt-Metadaten
Jeder Prompt sollte mit Metadaten in der Anwendung registriert werden.
from dataclasses import dataclass
@dataclass(frozen=True)
class PromptDefinition:
name: str
file_name: str
version: str
output_type: str
max_output_tokens: int
Beispiel:
PROMPT_DEFINITIONS: dict[str, PromptDefinition] = {
"linkedin_post": PromptDefinition(
name="linkedin_post",
file_name="linkedin_post.txt",
version="1.0.0",
output_type="text",
max_output_tokens=700,
),
"tone_check": PromptDefinition(
name="tone_check",
file_name="tone_check.txt",
version="1.0.0",
output_type="json",
max_output_tokens=500,
),
}
Prompt-Renderer
from pathlib import Path
class PromptTemplateRenderer:
def __init__(self, prompts_dir: Path) -> None:
self.prompts_dir = prompts_dir
def render(self, template_file: str, variables: dict[str, str]) -> str:
template_path = self.prompts_dir / template_file
if template_path.exists() is False:
raise RuntimeError(f"Prompt template does not exist: {template_file}")
content = template_path.read_text(encoding="utf-8")
rendered = content
for key, value in variables.items():
placeholder = "{{ " + key + " }}"
rendered = rendered.replace(placeholder, value)
if "{{ " in rendered:
raise RuntimeError(f"Unresolved placeholder in prompt template: {template_file}")
return rendered
Prompt-Auswahl nach Plattform und Beitragstyp
class PromptSelector:
def select_for_post(self, platform: str, post_type: str) -> str:
if platform == "linkedin" and post_type == "book_intro":
return "linkedin_post"
if platform == "linkedin" and post_type == "workshop":
return "workshop_note"
if platform == "instagram" and post_type == "quote":
return "classic_quote"
if platform == "instagram":
return "instagram_caption"
if platform == "facebook":
return "facebook_post"
raise RuntimeError(f"No prompt configured for platform={platform}, post_type={post_type}")
Beispiel: vollständiger Prompt-Aufbau
from dataclasses import dataclass
@dataclass(frozen=True)
class PromptBuildResult:
prompt_name: str
prompt_version: str
input_text: str
max_output_tokens: int
class PromptBuilder:
def __init__(
self,
renderer: PromptTemplateRenderer,
selector: PromptSelector,
) -> None:
self.renderer = renderer
self.selector = selector
def build_for_content_item(
self,
platform: str,
post_type: str,
item: ContentSourceItem,
) -> PromptBuildResult:
prompt_name = self.selector.select_for_post(platform, post_type)
prompt_definition = PROMPT_DEFINITIONS.get(prompt_name)
if prompt_definition is None:
raise RuntimeError(f"Missing prompt definition: {prompt_name}")
author = ""
if item.author is not None:
author = item.author
book_title = ""
if item.book_title is not None:
book_title = item.book_title
url = ""
if item.url is not None:
url = item.url
image_description = ""
input_text = self.renderer.render(
prompt_definition.file_name,
{
"title": item.title,
"body": item.body,
"author": author,
"book_title": book_title,
"url": url,
"summary": item.body,
"image_description": image_description,
},
)
return PromptBuildResult(
prompt_name=prompt_definition.name,
prompt_version=prompt_definition.version,
input_text=input_text,
max_output_tokens=prompt_definition.max_output_tokens,
)
Versionierung der Prompt-Bibliothek
Prompts sollten versioniert werden, sobald sie im produktiven System verwendet werden.
Einfaches Schema:
linkedin_post.txt
linkedin_post.v1.txt
linkedin_post.v2.txt
Oder über Metadaten:
prompts:
linkedin_post:
file: "linkedin_post.txt"
version: "1.0.0"
Wichtig ist, dass bei jedem erzeugten Beitrag gespeichert wird:
prompt_name
prompt_version
model
created_at
Beispiel im Entwurf:
{
"id": "draft_20260511_001",
"platform": "linkedin",
"post_type": "workshop",
"prompt_name": "workshop_note",
"prompt_version": "1.0.0",
"model": "gpt-4.1-mini",
"text": "Gemeinfreie Literatur ist frei verfügbar, aber nicht automatisch verlagsfertig."
}
Harte Regeln außerhalb der Prompts
Prompts sind keine Sicherheitsgarantie. Bestimmte Prüfungen gehören in Code.
class ForbiddenPhraseValidator:
def __init__(self) -> None:
self.forbidden_phrases = [
"unbedingt lesen",
"Meisterwerk",
"Tauchen Sie ein",
"Jetzt kaufen",
"ein Muss",
"lassen Sie sich verzaubern",
]
def validate(self, text: str) -> None:
lowered_text = text.lower()
for forbidden_phrase in self.forbidden_phrases:
if forbidden_phrase.lower() in lowered_text:
raise RuntimeError(f"Forbidden phrase found: {forbidden_phrase}")
Ergebnis dieses Kapitels
Die Prompt-Bibliothek deckt damit die zentralen Textarten ab:
LinkedIn-Beitrag
Instagram-Caption
Facebook-Beitrag
Buchvorstellung
Klassiker-Zitat
Verlagswerkstatt
Blogartikel-Zusammenfassung
Kommentarvorschlag
Antwort auf Nutzerkommentar
Dublettenprüfung
Tonalitätsprüfung
Kürzung auf Plattformlimit
Die Prompts bleiben getrennt vom Code, versionierbar und testbar. Die Anwendung verarbeitet Prompt-Ergebnisse erst nach zusätzlicher Validierung.
0 Kommentare