review_zammad_unknown.py 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/usr/bin/env python3
  2. import json
  3. import sqlite3
  4. import subprocess
  5. DB = "data/zammad_analysis.sqlite3"
  6. MODEL = "qwen3:8b"
  7. SYSTEM = """Du analysierst historische Zammad-Artikel eines Kundenservice-Systems.
  8. Entscheide ausschließlich zwischen:
  9. AGENT_RESPONSE = individuell formulierte fachliche Antwort eines Mitarbeiters
  10. AUTOMATION = automatisch erzeugte System-/Ticketnachricht
  11. Eine fachliche Antwort kann auch von Zammad als System/email geführt werden.
  12. Antworte ausschließlich als JSON:
  13. {
  14. "role": "AGENT_RESPONSE|AUTOMATION",
  15. "confidence": 0.0,
  16. "reason": "kurze Begründung"
  17. }
  18. """
  19. db = sqlite3.connect(DB)
  20. rows = db.execute("""
  21. SELECT id, ticket_id, subject, clean_body
  22. FROM articles
  23. WHERE content_role = 'UNKNOWN_REVIEW'
  24. ORDER BY id
  25. """).fetchall()
  26. print("=" * 72)
  27. print("QWEN – UNKNOWN REVIEW")
  28. print("=" * 72)
  29. print(f"Fälle: {len(rows)}")
  30. print(f"Modell: {MODEL}")
  31. print()
  32. for article_id, ticket_id, subject, body in rows:
  33. prompt = f"""{SYSTEM}
  34. Betreff:
  35. {subject or ""}
  36. Artikel:
  37. {body or ""}
  38. """
  39. result = subprocess.run(
  40. [
  41. "ollama",
  42. "run",
  43. MODEL,
  44. prompt,
  45. ],
  46. capture_output=True,
  47. text=True,
  48. timeout=300,
  49. )
  50. output = result.stdout.strip()
  51. # JSON aus möglichem Markdown-Codeblock extrahieren
  52. if "{" in output and "}" in output:
  53. output = output[
  54. output.find("{"):
  55. output.rfind("}") + 1
  56. ]
  57. try:
  58. data = json.loads(output)
  59. role = data.get("role")
  60. confidence = float(
  61. data.get("confidence", 0)
  62. )
  63. reason = data.get("reason", "")
  64. if role not in (
  65. "AGENT_RESPONSE",
  66. "AUTOMATION",
  67. ):
  68. raise ValueError(
  69. f"Ungültige Rolle: {role}"
  70. )
  71. except Exception as exc:
  72. print(
  73. f"Ticket #{ticket_id}: "
  74. f"JSON-Fehler: {exc}"
  75. )
  76. print(output[:500])
  77. continue
  78. db.execute("""
  79. UPDATE articles
  80. SET content_role = ?,
  81. classification_score = ?,
  82. classification_reason = ?
  83. WHERE id = ?
  84. """, (
  85. role,
  86. confidence,
  87. "QWEN: " + reason,
  88. article_id,
  89. ))
  90. db.commit()
  91. print(
  92. f"Ticket #{ticket_id}: "
  93. f"{role:16} "
  94. f"{confidence:.2f} "
  95. f"{reason}"
  96. )
  97. db.close()