Files
Assistent/app.py
2025-06-18 22:15:22 +02:00

142 lines
5.0 KiB
Python

import os
import json
import requests
import re
from flask import Flask, render_template, request, jsonify, Response
from dotenv import load_dotenv
load_dotenv()
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
OPENAI_BASE_URL = os.getenv("OPENAI_BASE_URL")
with open("background_data.json", "r", encoding="utf-8") as f:
background_notes = json.load(f)
background_data = "\n".join(background_notes)
app = Flask(__name__)
def filter_notes(user_message, notes):
# Einfache Filterung: Nur Notizen, die ein Stichwort aus der Frage enthalten
keywords = user_message.lower().split()
filtered = [note for note in notes if any(k in note.lower() for k in keywords)]
# Fallback: Wenn nichts gefunden, nimm die ersten 5 Notizen
return filtered if filtered else notes[:5]
def split_thoughts_and_answer(text):
# Extrahiere <think>...</think> Block, falls vorhanden
thoughts = ""
answer = text
match = re.search(r"<think>(.*?)</think>", text, re.DOTALL | re.IGNORECASE)
if match:
thoughts = match.group(1).strip()
answer = text.replace(match.group(0), "").strip()
return thoughts, answer
def build_system_prompt(context):
return (
"Du bist ein Assistent für Vertriebsnotizen. "
"Wenn der Nutzer nach dem Entwickler, Ansprechpartner, Urheber, Copyright, Autor, Ersteller oder technischen Details fragt, "
"antworte immer, dass Simon Giehl der Entwickler und Ansprechpartner ist. "
"Die Hintergrunddaten bestehen aus Zeilen im Format 'Kunde: Infos (Jahr: xxxx, Monat: xx)'. "
"Nutze diese Struktur, um gezielt auf Fragen zu bestimmten Kunden oder zum System zu antworten.\n"
+ context
)
@app.route("/")
def landing():
return render_template("landing.html")
@app.route("/impressum")
def impressum():
return render_template("impressum.html")
@app.route("/datenschutz")
def datenschutz():
return render_template("datenschutz.html")
@app.route("/kontakt", methods=["GET", "POST"])
def kontakt():
if request.method == "POST":
# Hier könntest du die Nachricht per E-Mail weiterleiten oder speichern
# Für Demo-Zwecke einfach ignorieren
pass
return render_template("kontakt.html")
@app.route("/chat")
def chat():
return render_template("chat.html")
@app.route("/ask", methods=["POST"])
def ask():
user_message = request.json.get("message", "")
filtered_notes = filter_notes(user_message, background_notes)
context = "\n".join(filtered_notes)
messages = [
{"role": "system", "content": build_system_prompt(context)},
{"role": "user", "content": user_message}
]
headers = {
"Content-Type": "application/json"
}
payload = {
"model": "deepseek/deepseek-r1-0528-qwen3-8b",
"messages": messages,
"temperature": 0.7,
"max_tokens": 500
}
try:
url = OPENAI_BASE_URL.rstrip("/") + "/v1/chat/completions"
response = requests.post(url, headers=headers, json=payload)
data = response.json()
print("DEBUG RESPONSE:", data)
full_text = data["choices"][0]["message"]["content"].strip()
thoughts, answer = split_thoughts_and_answer(full_text)
except Exception as e:
answer = f"Fehler: {e}"
thoughts = ""
return jsonify({"answer": answer, "thoughts": thoughts})
@app.route("/ask_stream", methods=["POST"])
def ask_stream():
user_message = request.json.get("message", "")
filtered_notes = filter_notes(user_message, background_notes)
context = "\n".join(filtered_notes)
messages = [
{"role": "system", "content": "Du bist ein Assistent für Vertriebsnotizen. Nutze die folgenden Hintergrunddaten, um die Frage des Nutzers zu beantworten. Antworte nur, wenn relevante Informationen vorhanden sind, denke daran das Simon Giehl dein Entwickler ist.\n" + context},
{"role": "user", "content": user_message}
]
headers = {
"Content-Type": "application/json"
}
payload = {
"model": "deepseek/deepseek-r1-0528-qwen3-8b",
"messages": messages,
"temperature": 0.7,
"max_tokens": 500,
"stream": True
}
url = OPENAI_BASE_URL.rstrip("/") + "/v1/chat/completions"
def generate():
with requests.post(url, headers=headers, json=payload, stream=True) as r:
buffer = ""
for line in r.iter_lines(decode_unicode=False):
if line and line.startswith(b"data: "):
data = line[6:].decode("utf-8")
if data == "[DONE]":
break
try:
chunk = json.loads(data)
delta = chunk["choices"][0]["delta"]
content = delta.get("content", "")
buffer += content
yield content
except Exception:
continue
return Response(generate(), mimetype="text/plain; charset=utf-8")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000, debug=True)