aidn commited on
Commit
82ed216
Β·
verified Β·
1 Parent(s): 0149312

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +121 -1
app.py CHANGED
@@ -70,6 +70,27 @@ Rules:
70
  - verdict is one precise sentence in German, max 12 words. Acknowledge substance if present.
71
  - ALL string values must be valid JSON strings."""
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
  # ── HF Dataset Persistenz ──────────────────────────────────────────────────────
75
 
@@ -194,7 +215,7 @@ def _render_leaderboard() -> str:
194
  def entry_html(e, rank, side="worst"):
195
  pct = e["pct"]
196
  if side == "best":
197
- color = "#1A5C34" if pct < 40 else "#27AE60" if pct < 70 else "#E67E22"
198
  else:
199
  color = "#C0392B" if pct >= 70 else "#E67E22" if pct >= 50 else "#D4AC0D" if pct >= 30 else "#27AE60"
200
  medal = ["πŸ₯‡","πŸ₯ˆ","πŸ₯‰"] [rank] if rank < 3 else f"{rank+1}."
@@ -371,6 +392,26 @@ def get_bingo(text):
371
  return (f"<p style='color:#c00;font-size:.85rem;padding:8px;'>Analyse fehlgeschlagen: {last_err}</p>",
372
  _render_leaderboard())
373
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
 
375
  def _render_bingo(data):
376
  metrics = data.get("metrics", [])
@@ -424,6 +465,15 @@ def _render_bingo(data):
424
  font-size:.88rem;color:#444;font-style:italic;line-height:1.6;">
425
  πŸ’¬ <strong style="font-style:normal;">Urteil:</strong> {verdict}
426
  </div>
 
 
 
 
 
 
 
 
 
427
  </div>"""
428
 
429
 
@@ -572,6 +622,60 @@ with gr.Blocks(title="LinkedIn Translator") as demo:
572
  markdown_out = gr.Markdown(value="*Noch kein Ergebnis - bitte zuerst ΓΌbersetzen.*", visible=True)
573
  bingo_out = gr.HTML(value="", visible=False)
574
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
575
  with gr.Row():
576
  with gr.Column():
577
  lb_out = gr.HTML(value=_render_leaderboard())
@@ -632,4 +736,20 @@ with gr.Blocks(title="LinkedIn Translator") as demo:
632
  outputs=[lb_out]
633
  )
634
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
635
  demo.launch(css=CSS)
 
70
  - verdict is one precise sentence in German, max 12 words. Acknowledge substance if present.
71
  - ALL string values must be valid JSON strings."""
72
 
73
+ PROMPT_AI_TUNING = """Du bist ein LinkedIn-Post-Optimizer. Du bekommst einen LinkedIn-Post und Tuning-Parameter. Deine Aufgabe: Den Post gezielt verbessern basierend auf diesen Parametern.
74
+
75
+ TUNING PARAMETER:
76
+ - Ton (0=Business Pro/sachlich/professionell, 100=Dynamisch/bold/provokant)
77
+ - Substanz (0=Storytelling/persΓΆnlich/narrativ, 100=Fakten/Daten/konkrete Insights)
78
+ - LΓ€nge (0=sehr kurz max 3 AbsΓ€tze, 100=ausfΓΌhrlich mit Struktur)
79
+ - Zielgruppe: {zielgruppe}
80
+ - Call to Action Ziel: {cta}
81
+
82
+ REGELN:
83
+ - Behalte die Kernaussage des Original-Posts
84
+ - Optimiere GEZIELT fΓΌr die gewΓ€hlten Parameter
85
+ - Kein generisches LinkedIn-Bingo - echte Verbesserung
86
+ - Wenn Ton=Business Pro: klar, direkt, keine Emojis-Überladung
87
+ - Wenn Ton=Dynamisch: mutig, Meinung, provokante ErΓΆffnung
88
+ - Wenn CTA=Kommentare: endet mit echter Diskussionsfrage
89
+ - Wenn CTA=Website: natΓΌrlicher Verweis auf konkreten Mehrwert
90
+ - Wenn CTA=Reichweite: Hook in Zeile 1, Struktur für Übersichtlichkeit
91
+
92
+ Antworte NUR mit dem verbesserten Post. Kein Vorwort, keine ErklΓ€rung."""
93
+
94
 
95
  # ── HF Dataset Persistenz ──────────────────────────────────────────────────────
96
 
 
215
  def entry_html(e, rank, side="worst"):
216
  pct = e["pct"]
217
  if side == "best":
218
+ color = "#1A5C34" if pct < 15 else "#27AE60" if pct < 70 else "#E67E22"
219
  else:
220
  color = "#C0392B" if pct >= 70 else "#E67E22" if pct >= 50 else "#D4AC0D" if pct >= 30 else "#27AE60"
221
  medal = ["πŸ₯‡","πŸ₯ˆ","πŸ₯‰"] [rank] if rank < 3 else f"{rank+1}."
 
392
  return (f"<p style='color:#c00;font-size:.85rem;padding:8px;'>Analyse fehlgeschlagen: {last_err}</p>",
393
  _render_leaderboard())
394
 
395
+ def generate_tuned_post(original_text, ton, substanz, laenge, zielgruppe, cta):
396
+ if not original_text.strip() or not HF_TOKEN:
397
+ return "Bitte zuerst einen Post analysieren."
398
+
399
+ prompt = PROMPT_AI_TUNING.format(zielgruppe=zielgruppe, cta=cta)
400
+ user_msg = f"""ORIGINAL POST:
401
+ {original_text}
402
+
403
+ TUNING:
404
+ - Ton: {ton}/100 (0=Business Pro, 100=Dynamisch & Bold)
405
+ - Substanz: {substanz}/100 (0=Storytelling, 100=Fakten & Insights)
406
+ - LΓ€nge: {laenge}/100 (0=Kurz, 100=AusfΓΌhrlich)
407
+ - Zielgruppe: {zielgruppe}
408
+ - Call to Action: {cta}"""
409
+
410
+ try:
411
+ return _call_llm(prompt, user_msg, max_tokens=800)
412
+ except Exception as e:
413
+ return f"Fehler: {e}"
414
+
415
 
416
  def _render_bingo(data):
417
  metrics = data.get("metrics", [])
 
465
  font-size:.88rem;color:#444;font-style:italic;line-height:1.6;">
466
  πŸ’¬ <strong style="font-style:normal;">Urteil:</strong> {verdict}
467
  </div>
468
+ <div style="margin-top:14px;display:flex;justify-content:flex-end;">
469
+ <button onclick="
470
+ var panel = document.getElementById('tuning_toggle_btn');
471
+ if(panel) panel.click();
472
+ " style="background:#004182;color:#fff;border:none;border-radius:22px;
473
+ padding:8px 20px;font-size:.82rem;font-weight:700;cursor:pointer;">
474
+ ✨ AI Tuning
475
+ </button>
476
+ </div>
477
  </div>"""
478
 
479
 
 
622
  markdown_out = gr.Markdown(value="*Noch kein Ergebnis - bitte zuerst ΓΌbersetzen.*", visible=True)
623
  bingo_out = gr.HTML(value="", visible=False)
624
 
625
+ # ── AI Tuning Panel ──────────────────────────────────────────────────────
626
+ with gr.Row():
627
+ with gr.Column():
628
+ tuning_panel = gr.Column(visible=False)
629
+ tuning_toggle_btn = gr.Button("toggle", elem_id="tuning_toggle_btn", visible=False)
630
+ with tuning_panel:
631
+ gr.HTML("""
632
+ <div style="background:#fff;border:1px solid #E0DFDC;border-radius:12px;
633
+ padding:22px 26px;margin-top:4px;box-shadow:0 2px 12px rgba(0,0,0,.07);">
634
+ <div style="display:flex;align-items:center;gap:10px;margin-bottom:20px;">
635
+ <span style="font-size:1.3rem;">✨</span>
636
+ <span style="font-weight:700;font-size:.95rem;color:#004182;
637
+ text-transform:uppercase;letter-spacing:.5px;">AI Post Tuning</span>
638
+ </div>
639
+ </div>
640
+ """)
641
+ with gr.Row():
642
+ with gr.Column(scale=1):
643
+ slider_ton = gr.Slider(
644
+ minimum=0, maximum=100, value=50, step=1,
645
+ label="πŸŽ™οΈ Ton",
646
+ info="Business Pro ◀──▢ Dynamisch & Bold"
647
+ )
648
+ slider_substanz = gr.Slider(
649
+ minimum=0, maximum=100, value=50, step=1,
650
+ label="🧠 Substanz",
651
+ info="Storytelling ◀──▢ Fakten & Insights"
652
+ )
653
+ slider_laenge = gr.Slider(
654
+ minimum=0, maximum=100, value=40, step=1,
655
+ label="πŸ“ LΓ€nge",
656
+ info="Kurz & Knackig ◀──▢ AusfΓΌhrlich"
657
+ )
658
+ with gr.Column(scale=1):
659
+ dd_zielgruppe = gr.Dropdown(
660
+ choices=["Fachpublikum", "FΓΌhrungskrΓ€fte", "Breites Netzwerk", "Potenzielle Kunden"],
661
+ value="Breites Netzwerk",
662
+ label="🎯 Zielgruppe"
663
+ )
664
+ dd_cta = gr.Dropdown(
665
+ choices=["Reichweite & Likes", "Kommentare & Dialog", "Reposts", "Website-Conversion", "DMs"],
666
+ value="Kommentare & Dialog",
667
+ label="⚑ Call to Action"
668
+ )
669
+ tuning_btn = gr.Button("✨ Post optimieren", variant="primary")
670
+
671
+ tuning_out = gr.Textbox(
672
+ label="πŸ’‘ Optimierter Post",
673
+ lines=10,
674
+ interactive=True,
675
+ placeholder="Der optimierte Post erscheint hier..."
676
+ )
677
+
678
+
679
  with gr.Row():
680
  with gr.Column():
681
  lb_out = gr.HTML(value=_render_leaderboard())
 
736
  outputs=[lb_out]
737
  )
738
 
739
+ # Tuning panel toggle
740
+ def toggle_tuning(current_text):
741
+ return gr.update(visible=True)
742
+
743
+ tuning_toggle_btn.click(
744
+ fn=toggle_tuning,
745
+ inputs=[input_box],
746
+ outputs=[tuning_panel]
747
+ )
748
+
749
+ # Post optimieren
750
+ tuning_btn.click(
751
+ fn=generate_tuned_post,
752
+ inputs=[input_box, slider_ton, slider_substanz, slider_laenge, dd_zielgruppe, dd_cta],
753
+ outputs=[tuning_out]
754
+ )
755
  demo.launch(css=CSS)