Aktualizovat sk1/backend/app.py
This commit is contained in:
parent
71e32912cd
commit
55dc649360
@ -1,172 +1,170 @@
|
|||||||
|
from flask import Flask, request, jsonify, Response, send_from_directory
|
||||||
from flask import Flask, request, jsonify, Response, send_from_directory
|
from flask_cors import CORS
|
||||||
from flask_cors import CORS
|
from flask_caching import Cache
|
||||||
from flask_caching import Cache
|
import json
|
||||||
import json
|
import os
|
||||||
import os
|
import hashlib
|
||||||
import hashlib
|
import re
|
||||||
import re
|
import psycopg2
|
||||||
import psycopg2
|
from datetime import datetime
|
||||||
from datetime import datetime
|
import pytz
|
||||||
import pytz
|
import torch
|
||||||
import torch
|
from transformers import AutoModelForSequenceClassification, AutoTokenizer
|
||||||
from transformers import AutoModelForSequenceClassification, AutoTokenizer
|
|
||||||
|
app = Flask(__name__)
|
||||||
app = Flask(__name__)
|
CORS(app)
|
||||||
CORS(app)
|
app.config['CACHE_TYPE'] = 'SimpleCache'
|
||||||
app.config['CACHE_TYPE'] = 'SimpleCache'
|
cache = Cache(app)
|
||||||
cache = Cache(app)
|
|
||||||
|
# Database connection
|
||||||
# Database connection
|
DATABASE_URL = os.environ.get('DATABASE_URL')
|
||||||
DATABASE_URL = os.environ.get('DATABASE_URL')
|
conn = psycopg2.connect(DATABASE_URL)
|
||||||
conn = psycopg2.connect(DATABASE_URL)
|
cursor = conn.cursor()
|
||||||
cursor = conn.cursor()
|
|
||||||
|
# Initialize DB
|
||||||
# Initialize DB
|
cursor.execute('''
|
||||||
cursor.execute('''
|
CREATE TABLE IF NOT EXISTS history (
|
||||||
CREATE TABLE IF NOT EXISTS history (
|
id SERIAL PRIMARY KEY,
|
||||||
id SERIAL PRIMARY KEY,
|
text TEXT NOT NULL,
|
||||||
text TEXT NOT NULL,
|
prediction TEXT NOT NULL,
|
||||||
prediction TEXT NOT NULL,
|
timestamp TIMESTAMP NOT NULL
|
||||||
timestamp TIMESTAMP NOT NULL
|
)
|
||||||
)
|
''')
|
||||||
''')
|
conn.commit()
|
||||||
conn.commit()
|
|
||||||
|
model_path = "tetianamohorian/hate_speech_model"
|
||||||
model_path = "tetianamohorian/hate_speech_model"
|
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
||||||
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
||||||
model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
model.eval()
|
||||||
model.eval()
|
|
||||||
|
HISTORY_FILE = "history.json"
|
||||||
HISTORY_FILE = "history.json"
|
|
||||||
|
def generate_text_hash(text):
|
||||||
def generate_text_hash(text):
|
return hashlib.md5(text.encode('utf-8')).hexdigest()
|
||||||
return hashlib.md5(text.encode('utf-8')).hexdigest()
|
|
||||||
|
def get_current_time():
|
||||||
def get_current_time():
|
tz = pytz.timezone('Europe/Bratislava')
|
||||||
tz = pytz.timezone('Europe/Bratislava')
|
return datetime.now(tz)
|
||||||
return datetime.now(tz)
|
|
||||||
|
def sync_history_file():
|
||||||
def sync_history_file():
|
# Synchronizácia history.json so všetkými záznamami z databázy
|
||||||
# Synchronizácia history.json so všetkými záznamami z databázy
|
cursor.execute("SELECT text, prediction, timestamp FROM history ORDER BY timestamp DESC")
|
||||||
cursor.execute("SELECT text, prediction, timestamp FROM history ORDER BY timestamp DESC")
|
rows = cursor.fetchall()
|
||||||
rows = cursor.fetchall()
|
history = [
|
||||||
history = [
|
{
|
||||||
{
|
"text": r[0],
|
||||||
"text": r[0],
|
"prediction": r[1],
|
||||||
"prediction": r[1],
|
"timestamp": r[2].strftime("%d.%m.%Y %H:%M:%S")
|
||||||
"timestamp": r[2].strftime("%d.%m.%Y %H:%M:%S")
|
} for r in rows
|
||||||
} for r in rows
|
]
|
||||||
]
|
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
|
||||||
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
|
json.dump(history, f, ensure_ascii=False, indent=2)
|
||||||
json.dump(history, f, ensure_ascii=False, indent=2)
|
|
||||||
|
def save_to_history(text, prediction_label):
|
||||||
def save_to_history(text, prediction_label):
|
timestamp = get_current_time()
|
||||||
timestamp = get_current_time()
|
try:
|
||||||
try:
|
cursor.execute(
|
||||||
# Проверка на дубликат
|
"SELECT 1 FROM history WHERE text = %s AND prediction = %s",
|
||||||
cursor.execute(
|
(text, prediction_label)
|
||||||
"SELECT 1 FROM history WHERE text = %s AND prediction = %s",
|
)
|
||||||
(text, prediction_label)
|
if cursor.fetchone() is None:
|
||||||
)
|
cursor.execute(
|
||||||
if cursor.fetchone() is None:
|
"INSERT INTO history (text, prediction, timestamp) VALUES (%s, %s, %s)",
|
||||||
cursor.execute(
|
(text, prediction_label, timestamp)
|
||||||
"INSERT INTO history (text, prediction, timestamp) VALUES (%s, %s, %s)",
|
)
|
||||||
(text, prediction_label, timestamp)
|
conn.commit()
|
||||||
)
|
sync_history_file()
|
||||||
conn.commit()
|
except Exception as e:
|
||||||
sync_history_file()
|
print("Nepodarilo sa uložiť do databázy alebo prepísať history.json:", e)
|
||||||
except Exception as e:
|
|
||||||
print("Nepodarilo sa uložiť do databázy alebo prepísať history.json:", e)
|
@app.route("/")
|
||||||
|
def serve_frontend():
|
||||||
@app.route("/")
|
return send_from_directory("static", "index.html")
|
||||||
def serve_frontend():
|
|
||||||
return send_from_directory("static", "index.html")
|
@app.route("/<path:path>")
|
||||||
|
def serve_static_files(path):
|
||||||
@app.route("/<path:path>")
|
return send_from_directory("static", path)
|
||||||
def serve_static_files(path):
|
|
||||||
return send_from_directory("static", path)
|
@app.route("/api/predict", methods=["POST"])
|
||||||
|
def predict():
|
||||||
@app.route("/api/predict", methods=["POST"])
|
try:
|
||||||
def predict():
|
data = request.json
|
||||||
try:
|
text = data.get("text", "")
|
||||||
data = request.json
|
|
||||||
text = data.get("text", "")
|
if not text:
|
||||||
|
return jsonify({"error": "Text nesmie byť prázdny."}), 400
|
||||||
if not text:
|
if len(text) > 512:
|
||||||
return jsonify({"error": "Text nesmie byť prázdny."}), 400
|
return jsonify({"error": "Text je príliš dlhý. Maximálne 512 znakov."}), 400
|
||||||
if len(text) > 512:
|
if re.search(r"[а-яА-ЯёЁ]", text):
|
||||||
return jsonify({"error": "Text je príliš dlhý. Maximálne 512 znakov."}), 400
|
return jsonify({"error": "Text nesmie obsahovať azbuku (cyriliku)."}), 400
|
||||||
if re.search(r"[а-яА-ЯёЁ]", text):
|
|
||||||
return jsonify({"error": "Text nesmie obsahovať azbuku (cyriliku)."}), 400
|
text_hash = generate_text_hash(text)
|
||||||
|
cached_result = cache.get(text_hash)
|
||||||
text_hash = generate_text_hash(text)
|
if cached_result:
|
||||||
cached_result = cache.get(text_hash)
|
save_to_history(text, cached_result)
|
||||||
if cached_result:
|
return jsonify({"prediction": cached_result}), 200
|
||||||
save_to_history(text, cached_result)
|
|
||||||
return jsonify({"prediction": cached_result}), 200
|
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
|
||||||
|
|
||||||
inputs = tokenizer(text, return_tensors="pt", truncation=True, padding=True)
|
with torch.no_grad():
|
||||||
|
outputs = model(**inputs)
|
||||||
with torch.no_grad():
|
predictions = torch.argmax(outputs.logits, dim=1).item()
|
||||||
outputs = model(**inputs)
|
|
||||||
predictions = torch.argmax(outputs.logits, dim=1).item()
|
prediction_label = "Pravdepodobne toxický" if predictions == 1 else "Neutrálny text"
|
||||||
|
cache.set(text_hash, prediction_label)
|
||||||
prediction_label = "Pravdepodobne toxický" if predictions == 1 else "Neutrálny text"
|
|
||||||
cache.set(text_hash, prediction_label)
|
save_to_history(text, prediction_label)
|
||||||
|
|
||||||
save_to_history(text, prediction_label)
|
return jsonify({"prediction": prediction_label}), 200
|
||||||
|
|
||||||
return jsonify({"prediction": prediction_label}), 200
|
except Exception as e:
|
||||||
|
return jsonify({"error": str(e)}), 500
|
||||||
except Exception as e:
|
|
||||||
return jsonify({"error": str(e)}), 500
|
@app.route("/api/history", methods=["GET"])
|
||||||
|
def get_history():
|
||||||
@app.route("/api/history", methods=["GET"])
|
try:
|
||||||
def get_history():
|
with open(HISTORY_FILE, "r", encoding="utf-8") as f:
|
||||||
try:
|
content = json.load(f)
|
||||||
with open(HISTORY_FILE, "r", encoding="utf-8") as f:
|
return Response(
|
||||||
content = json.load(f)
|
json.dumps(content, ensure_ascii=False, indent=2),
|
||||||
return Response(
|
mimetype="application/json"
|
||||||
json.dumps(content, ensure_ascii=False, indent=2),
|
)
|
||||||
mimetype="application/json"
|
except Exception as e:
|
||||||
)
|
return jsonify({"error": str(e)}), 500
|
||||||
except Exception as e:
|
|
||||||
return jsonify({"error": str(e)}), 500
|
@app.route("/api/history/reset", methods=["POST"])
|
||||||
|
def reset_history():
|
||||||
@app.route("/api/history/reset", methods=["POST"])
|
try:
|
||||||
def reset_history():
|
cursor.execute("DELETE FROM history")
|
||||||
try:
|
conn.commit()
|
||||||
cursor.execute("DELETE FROM history")
|
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
|
||||||
conn.commit()
|
json.dump([], f, ensure_ascii=False, indent=2)
|
||||||
with open(HISTORY_FILE, "w", encoding="utf-8") as f:
|
return jsonify({"message": "História bola úspešne vymazaná."}), 200
|
||||||
json.dump([], f, ensure_ascii=False, indent=2)
|
except Exception as e:
|
||||||
return jsonify({"message": "História bola úspešne vymazaná."}), 200
|
return jsonify({"error": str(e)}), 500
|
||||||
except Exception as e:
|
|
||||||
return jsonify({"error": str(e)}), 500
|
@app.route("/api/history/db", methods=["GET"])
|
||||||
|
def get_history_from_db():
|
||||||
@app.route("/api/history/db", methods=["GET"])
|
try:
|
||||||
def get_history_from_db():
|
cursor.execute("SELECT text, prediction, timestamp FROM history ORDER BY timestamp DESC")
|
||||||
try:
|
rows = cursor.fetchall()
|
||||||
cursor.execute("SELECT text, prediction, timestamp FROM history ORDER BY timestamp DESC")
|
history = [
|
||||||
rows = cursor.fetchall()
|
{
|
||||||
history = [
|
"text": r[0],
|
||||||
{
|
"prediction": r[1],
|
||||||
"text": r[0],
|
"timestamp": r[2].strftime("%d.%m.%Y %H:%M:%S")
|
||||||
"prediction": r[1],
|
} for r in rows
|
||||||
"timestamp": r[2].strftime("%d.%m.%Y %H:%M:%S")
|
]
|
||||||
} for r in rows
|
return Response(
|
||||||
]
|
json.dumps(history, ensure_ascii=False, indent=2),
|
||||||
return Response(
|
mimetype="application/json"
|
||||||
json.dumps(history, ensure_ascii=False, indent=2),
|
)
|
||||||
mimetype="application/json"
|
except Exception as e:
|
||||||
)
|
return jsonify({"error": str(e)}), 500
|
||||||
except Exception as e:
|
|
||||||
return jsonify({"error": str(e)}), 500
|
print("✅ Flask is starting...")
|
||||||
|
sync_history_file()
|
||||||
print("✅ Flask is starting...")
|
|
||||||
sync_history_file()
|
if __name__ == "__main__":
|
||||||
|
port = int(os.environ.get("PORT", 8080))
|
||||||
if __name__ == "__main__":
|
app.run(host="0.0.0.0", port=port)
|
||||||
port = int(os.environ.get("PORT", 8080))
|
|
||||||
app.run(host="0.0.0.0", port=port)
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user