Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -11,33 +11,33 @@ LEADERBOARD_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "lea
|
|
| 11 |
|
| 12 |
# ── System Prompts ─────────────────────────────────────────────────────────────
|
| 13 |
|
| 14 |
-
PROMPT_TO_LINKEDIN = """Du bist ein LinkedIn-Influencer-Generator. Deine einzige Aufgabe ist es, banale,
|
| 15 |
|
| 16 |
Regeln:
|
| 17 |
- Alles ist eine "Journey", ein "Gamechanger" oder eine "powerful lesson"
|
| 18 |
- Nutze mindestens 3 Emojis strategisch
|
| 19 |
-
-
|
| 20 |
-
-
|
| 21 |
- Endet mit einer rhetorischen Frage an die Community
|
| 22 |
-
- Benutze dramatische
|
| 23 |
- Alles ist ausnahmslos positiv, auch wenn das Original negativ ist
|
| 24 |
- Hashtags am Ende sind Pflicht (mindestens 5)
|
| 25 |
-
- Klingt wie jemand, der gerade ein Buch
|
| 26 |
-
- Formatiere mit Markdown: Eroeffnungssatz als ##
|
| 27 |
|
| 28 |
-
Antworte NUR mit dem LinkedIn-Post in Markdown. Kein Vorwort, keine
|
| 29 |
|
| 30 |
PROMPT_FROM_LINKEDIN = """Du bist ein gnadenloser semantischer Reduzierer. Du hasst Floskeln. Deine Aufgabe: LinkedIn-Texte auf das absolute, brutalste Minimum eindampfen.
|
| 31 |
|
| 32 |
Regeln:
|
| 33 |
- EIN Satz. Nicht zwei. Einer.
|
| 34 |
-
-
|
| 35 |
- Null Emotion, null Wertung, null Kontext der niemanden interessiert
|
| 36 |
-
- Streiche alles was keine neue Information
|
| 37 |
- Wenn der gesamte Post nur bedeutet "Ich hab heute Kaffee getrunken" schreib genau das
|
| 38 |
- Maximal 15 Woerter
|
| 39 |
|
| 40 |
-
Antworte NUR mit diesem einen Satz. Kein Vorwort, keine
|
| 41 |
|
| 42 |
PROMPT_BINGO = """You are a precise, fair but sarcastic LinkedIn post analyst. Your job is to measure actual corporate nonsense - not just LinkedIn formatting habits.
|
| 43 |
|
|
@@ -50,15 +50,15 @@ CRITICAL: You must distinguish between FORM and SUBSTANCE.
|
|
| 50 |
Rate on these 5 metrics (score 1-10, where 10 = maximum LinkedIn nonsense):
|
| 51 |
|
| 52 |
1. label="Buzzword-Dichte": Are the buzzwords empty filler, or do they refer to real, specific concepts? Real tools and methodologies (e.g. MLflow, LiteLLM, RAG, specific frameworks) are NOT buzzwords. Empty buzzwords: "synergy", "impact", "journey", "game-changer" used without context.
|
| 53 |
-
2. label="
|
| 54 |
-
3. label="
|
| 55 |
4. label="Hashtag-Overload": Score LOW for 1-6 relevant hashtags. Score HIGH for 10+ hashtags or hashtags irrelevant to the content.
|
| 56 |
5. label="Sinnlosigkeits-Index": Could someone learn something concrete from this post? A post with real takeaways, named tools, or specific problems solved scores LOW. Pure inspiration porn scores HIGH.
|
| 57 |
|
| 58 |
Reply ONLY with a single valid JSON object. No markdown fences, no backticks, no preamble. Raw JSON only.
|
| 59 |
|
| 60 |
Use exactly this structure:
|
| 61 |
-
{"metrics":[{"label":"Buzzword-Dichte","score":3,"comment":"kurz sarkastisch"},{"label":"
|
| 62 |
|
| 63 |
Rules:
|
| 64 |
- score is an integer 1-10. Be calibrated: most posts will not score 8-10 on every metric. Reserve 9-10 for truly egregious cases.
|
|
@@ -98,7 +98,7 @@ def _add_to_lb(post_text: str, total: int, max_score: int, verdict: str):
|
|
| 98 |
def _render_leaderboard() -> str:
|
| 99 |
entries = _load_lb()
|
| 100 |
if not entries:
|
| 101 |
-
return "<p style='color:#888;font-size:.85rem;text-align:center;padding:20px;'>Noch keine
|
| 102 |
|
| 103 |
sorted_asc = sorted(entries, key=lambda x: x["pct"])
|
| 104 |
sorted_desc = sorted(entries, key=lambda x: x["pct"], reverse=True)
|
|
@@ -139,7 +139,7 @@ def _render_leaderboard() -> str:
|
|
| 139 |
<span style="font-weight:700;font-size:.95rem;color:#004182;
|
| 140 |
text-transform:uppercase;letter-spacing:.5px;">Leaderboard</span>
|
| 141 |
<span style="margin-left:auto;font-size:.78rem;color:#888;">
|
| 142 |
-
{total_count}
|
| 143 |
</span>
|
| 144 |
</div>
|
| 145 |
<div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;">
|
|
@@ -153,7 +153,7 @@ def _render_leaderboard() -> str:
|
|
| 153 |
<div>
|
| 154 |
<div style="font-size:.76rem;font-weight:700;text-transform:uppercase;
|
| 155 |
letter-spacing:.5px;color:#C0392B;margin-bottom:10px;">
|
| 156 |
-
💩 Reinster LinkedIn-Nonsense (
|
| 157 |
</div>
|
| 158 |
{worst_html}
|
| 159 |
</div>
|
|
@@ -208,7 +208,7 @@ def _extract_json(raw: str) -> dict:
|
|
| 208 |
|
| 209 |
|
| 210 |
def get_bingo(text: str):
|
| 211 |
-
"""Gibt (bingo_html, leaderboard_html)
|
| 212 |
if not text.strip() or not HF_TOKEN:
|
| 213 |
return "", _render_leaderboard()
|
| 214 |
last_err = None
|
|
@@ -238,8 +238,8 @@ def _render_bingo(data):
|
|
| 238 |
|
| 239 |
ICONS = {
|
| 240 |
"Buzzword-Dichte": "🗣️",
|
| 241 |
-
"
|
| 242 |
-
"
|
| 243 |
"Hashtag-Overload": "#️⃣",
|
| 244 |
"Sinnlosigkeits-Index": "🌀",
|
| 245 |
}
|
|
@@ -413,12 +413,12 @@ with gr.Blocks(title="LinkedIn Translator", css=CSS) as demo:
|
|
| 413 |
with gr.Column(scale=5):
|
| 414 |
input_box = gr.Textbox(
|
| 415 |
label="✍️ Normale Aussage",
|
| 416 |
-
placeholder="z.B. 'Ich hab heute meinen Kaffee
|
| 417 |
lines=10,
|
| 418 |
)
|
| 419 |
with gr.Column(scale=1, min_width=120):
|
| 420 |
gr.HTML("<div style='height:40px'></div>")
|
| 421 |
-
translate_btn = gr.Button("
|
| 422 |
gr.HTML("<div style='height:12px'></div>")
|
| 423 |
swap_btn = gr.Button("🔄 → LinkedIn", variant="secondary", size="sm")
|
| 424 |
with gr.Column(scale=5):
|
|
@@ -433,7 +433,7 @@ with gr.Blocks(title="LinkedIn Translator", css=CSS) as demo:
|
|
| 433 |
with gr.Row():
|
| 434 |
with gr.Column():
|
| 435 |
markdown_out = gr.Markdown(
|
| 436 |
-
value="*Noch kein Ergebnis - bitte zuerst
|
| 437 |
visible=True,
|
| 438 |
)
|
| 439 |
bingo_out = gr.HTML(value="", visible=False)
|
|
@@ -448,7 +448,7 @@ with gr.Blocks(title="LinkedIn Translator", css=CSS) as demo:
|
|
| 448 |
<div style="background:#FFF4CE;border:1px solid #F9C642;border-left:4px solid #F9C642;
|
| 449 |
border-radius:6px;padding:10px 14px;font-size:.85rem;color:#7A5800;margin-top:8px;">
|
| 450 |
<strong>Kein HF_TOKEN gefunden.</strong>
|
| 451 |
-
Unter <em>Settings → Variables and secrets</em> als <code>HF_TOKEN</code>
|
| 452 |
</div>
|
| 453 |
""")
|
| 454 |
|
|
|
|
| 11 |
|
| 12 |
# ── System Prompts ─────────────────────────────────────────────────────────────
|
| 13 |
|
| 14 |
+
PROMPT_TO_LINKEDIN = """Du bist ein LinkedIn-Influencer-Generator. Deine einzige Aufgabe ist es, banale, alltägliche Aussagen in absurd ausschweifende, klischeebeladene LinkedIn-Posts zu verwandeln.
|
| 15 |
|
| 16 |
Regeln:
|
| 17 |
- Alles ist eine "Journey", ein "Gamechanger" oder eine "powerful lesson"
|
| 18 |
- Nutze mindestens 3 Emojis strategisch
|
| 19 |
+
- Erwähne "Growth", "Mindset", "Passion" oder "Impact" wo immer moeglich
|
| 20 |
+
- Füge eine persoenliche Anekdote hinzu, die niemand braucht
|
| 21 |
- Endet mit einer rhetorischen Frage an die Community
|
| 22 |
+
- Benutze dramatische Zeilenumbrüche für Effekt
|
| 23 |
- Alles ist ausnahmslos positiv, auch wenn das Original negativ ist
|
| 24 |
- Hashtags am Ende sind Pflicht (mindestens 5)
|
| 25 |
+
- Klingt wie jemand, der gerade ein Buch über sich selbst schreiben würde
|
| 26 |
+
- Formatiere mit Markdown: Eroeffnungssatz als ## überschrift, Schlüsselbegriffe wie **Gamechanger**, **Growth**, **Mindset**, **Journey** fett hervorheben, Abschnitte mit Leerzeilen trennen
|
| 27 |
|
| 28 |
+
Antworte NUR mit dem LinkedIn-Post in Markdown. Kein Vorwort, keine Erklärung."""
|
| 29 |
|
| 30 |
PROMPT_FROM_LINKEDIN = """Du bist ein gnadenloser semantischer Reduzierer. Du hasst Floskeln. Deine Aufgabe: LinkedIn-Texte auf das absolute, brutalste Minimum eindampfen.
|
| 31 |
|
| 32 |
Regeln:
|
| 33 |
- EIN Satz. Nicht zwei. Einer.
|
| 34 |
+
- Kürze bis es wehtut. Dann nochmal kürzen.
|
| 35 |
- Null Emotion, null Wertung, null Kontext der niemanden interessiert
|
| 36 |
+
- Streiche alles was keine neue Information trägt
|
| 37 |
- Wenn der gesamte Post nur bedeutet "Ich hab heute Kaffee getrunken" schreib genau das
|
| 38 |
- Maximal 15 Woerter
|
| 39 |
|
| 40 |
+
Antworte NUR mit diesem einen Satz. Kein Vorwort, keine Erklärung."""
|
| 41 |
|
| 42 |
PROMPT_BINGO = """You are a precise, fair but sarcastic LinkedIn post analyst. Your job is to measure actual corporate nonsense - not just LinkedIn formatting habits.
|
| 43 |
|
|
|
|
| 50 |
Rate on these 5 metrics (score 1-10, where 10 = maximum LinkedIn nonsense):
|
| 51 |
|
| 52 |
1. label="Buzzword-Dichte": Are the buzzwords empty filler, or do they refer to real, specific concepts? Real tools and methodologies (e.g. MLflow, LiteLLM, RAG, specific frameworks) are NOT buzzwords. Empty buzzwords: "synergy", "impact", "journey", "game-changer" used without context.
|
| 53 |
+
2. label="Länge vs. Inhalt": Is the length justified by actual information density? A long post with dense technical content scores LOW. A long post that repeats one obvious idea scores HIGH.
|
| 54 |
+
3. label="Selbstbeweihräuche": Is the post primarily about ego ("look how great we are") or about sharing knowledge? Score HIGH only if the author is the hero, not the content.
|
| 55 |
4. label="Hashtag-Overload": Score LOW for 1-6 relevant hashtags. Score HIGH for 10+ hashtags or hashtags irrelevant to the content.
|
| 56 |
5. label="Sinnlosigkeits-Index": Could someone learn something concrete from this post? A post with real takeaways, named tools, or specific problems solved scores LOW. Pure inspiration porn scores HIGH.
|
| 57 |
|
| 58 |
Reply ONLY with a single valid JSON object. No markdown fences, no backticks, no preamble. Raw JSON only.
|
| 59 |
|
| 60 |
Use exactly this structure:
|
| 61 |
+
{"metrics":[{"label":"Buzzword-Dichte","score":3,"comment":"kurz sarkastisch"},{"label":"Länge vs. Inhalt","score":4,"comment":"kurz sarkastisch"},{"label":"Selbstbeweihräuche","score":2,"comment":"kurz sarkastisch"},{"label":"Hashtag-Overload","score":5,"comment":"kurz sarkastisch"},{"label":"Sinnlosigkeits-Index","score":3,"comment":"kurz sarkastisch"}],"verdict":"Ein präzises Urteil auf Deutsch."}
|
| 62 |
|
| 63 |
Rules:
|
| 64 |
- score is an integer 1-10. Be calibrated: most posts will not score 8-10 on every metric. Reserve 9-10 for truly egregious cases.
|
|
|
|
| 98 |
def _render_leaderboard() -> str:
|
| 99 |
entries = _load_lb()
|
| 100 |
if not entries:
|
| 101 |
+
return "<p style='color:#888;font-size:.85rem;text-align:center;padding:20px;'>Noch keine Einträge. Analysiere einen LinkedIn-Post um zu starten.</p>"
|
| 102 |
|
| 103 |
sorted_asc = sorted(entries, key=lambda x: x["pct"])
|
| 104 |
sorted_desc = sorted(entries, key=lambda x: x["pct"], reverse=True)
|
|
|
|
| 139 |
<span style="font-weight:700;font-size:.95rem;color:#004182;
|
| 140 |
text-transform:uppercase;letter-spacing:.5px;">Leaderboard</span>
|
| 141 |
<span style="margin-left:auto;font-size:.78rem;color:#888;">
|
| 142 |
+
{total_count} Einträge · Ø {avg_pct}% Nonsense
|
| 143 |
</span>
|
| 144 |
</div>
|
| 145 |
<div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;">
|
|
|
|
| 153 |
<div>
|
| 154 |
<div style="font-size:.76rem;font-weight:700;text-transform:uppercase;
|
| 155 |
letter-spacing:.5px;color:#C0392B;margin-bottom:10px;">
|
| 156 |
+
💩 Reinster LinkedIn-Nonsense (höchster Score)
|
| 157 |
</div>
|
| 158 |
{worst_html}
|
| 159 |
</div>
|
|
|
|
| 208 |
|
| 209 |
|
| 210 |
def get_bingo(text: str):
|
| 211 |
+
"""Gibt (bingo_html, leaderboard_html) zurück."""
|
| 212 |
if not text.strip() or not HF_TOKEN:
|
| 213 |
return "", _render_leaderboard()
|
| 214 |
last_err = None
|
|
|
|
| 238 |
|
| 239 |
ICONS = {
|
| 240 |
"Buzzword-Dichte": "🗣️",
|
| 241 |
+
"Länge vs. Inhalt": "📏",
|
| 242 |
+
"Selbstbeweihräuche": "🪞",
|
| 243 |
"Hashtag-Overload": "#️⃣",
|
| 244 |
"Sinnlosigkeits-Index": "🌀",
|
| 245 |
}
|
|
|
|
| 413 |
with gr.Column(scale=5):
|
| 414 |
input_box = gr.Textbox(
|
| 415 |
label="✍️ Normale Aussage",
|
| 416 |
+
placeholder="z.B. 'Ich hab heute meinen Kaffee verschüttet.'",
|
| 417 |
lines=10,
|
| 418 |
)
|
| 419 |
with gr.Column(scale=1, min_width=120):
|
| 420 |
gr.HTML("<div style='height:40px'></div>")
|
| 421 |
+
translate_btn = gr.Button("übersetzen", variant="primary", size="lg")
|
| 422 |
gr.HTML("<div style='height:12px'></div>")
|
| 423 |
swap_btn = gr.Button("🔄 → LinkedIn", variant="secondary", size="sm")
|
| 424 |
with gr.Column(scale=5):
|
|
|
|
| 433 |
with gr.Row():
|
| 434 |
with gr.Column():
|
| 435 |
markdown_out = gr.Markdown(
|
| 436 |
+
value="*Noch kein Ergebnis - bitte zuerst übersetzen.*",
|
| 437 |
visible=True,
|
| 438 |
)
|
| 439 |
bingo_out = gr.HTML(value="", visible=False)
|
|
|
|
| 448 |
<div style="background:#FFF4CE;border:1px solid #F9C642;border-left:4px solid #F9C642;
|
| 449 |
border-radius:6px;padding:10px 14px;font-size:.85rem;color:#7A5800;margin-top:8px;">
|
| 450 |
<strong>Kein HF_TOKEN gefunden.</strong>
|
| 451 |
+
Unter <em>Settings → Variables and secrets</em> als <code>HF_TOKEN</code> hinzufügen.
|
| 452 |
</div>
|
| 453 |
""")
|
| 454 |
|