Files
rfp_response_automation/files/modules/admin/routes.py
2026-02-18 20:34:33 -03:00

160 lines
3.9 KiB
Python

from flask import Blueprint, render_template, request, jsonify, redirect, flash
from modules.core.security import requires_admin_auth
from modules.core.audit import audit_log
import threading
from modules.core.audit import audit_log
from oci_genai_llm_graphrag_rerank_rfp import (
search_chunks_for_invalidation,
revoke_chunk_by_hash,
get_chunk_metadata,
add_manual_knowledge_entry,
reload_all
)
admin_bp = Blueprint("admin", __name__)
# =========================
# ADMIN HOME (invalidate UI)
# =========================
@admin_bp.route("/")
@requires_admin_auth
def admin_home():
return render_template("admin_menu.html")
@admin_bp.route("/invalidate")
@requires_admin_auth
def invalidate_page():
return render_template(
"invalidate.html",
results=[],
statement=""
)
# =========================
# SEARCH CHUNKS
# =========================
@admin_bp.route("/search", methods=["POST"])
@requires_admin_auth
def search_for_invalidation():
statement = request.form["statement"]
docs = search_chunks_for_invalidation(statement)
hashes = [d.metadata.get("chunk_hash") for d in docs if d.metadata.get("chunk_hash")]
meta = get_chunk_metadata(hashes)
results = []
for d in docs:
h = d.metadata.get("chunk_hash")
m = meta.get(h, {})
results.append({
"chunk_hash": h,
"source": d.metadata.get("source"),
"text": d.page_content,
"origin": m.get("origin"),
"status": m.get("status")
})
return render_template(
"invalidate.html",
statement=statement,
results=results
)
# =========================
# REVOKE
# =========================
@admin_bp.route("/revoke", methods=["POST"])
@requires_admin_auth
def revoke_chunk_ui():
data = request.get_json()
chunk_hash = str(data["chunk_hash"])
reason = str(data.get("reason", "Manual revoke"))
audit_log("INVALIDATE", f"chunk_hash={chunk_hash}")
print("chunk_hash", chunk_hash)
print("reason", reason)
revoke_chunk_by_hash(chunk_hash, reason)
return {"status": "ok", "chunk_hash": chunk_hash}
# =========================
# ADD MANUAL KNOWLEDGE
# =========================
@admin_bp.route("/add-knowledge", methods=["POST"])
@requires_admin_auth
def add_manual_knowledge():
data = request.get_json(force=True)
chunk_hash = add_manual_knowledge_entry(
text=data["text"],
author="ADMIN",
reason=data.get("reason"),
source="MANUAL_INPUT",
origin="MANUAL",
also_update_graph=True
)
audit_log("ADD_KNOWLEDGE", f"chunk_hash={chunk_hash}")
return jsonify({
"status": "OK",
"chunk_hash": chunk_hash
})
# =========================
# UPDATE CHUNK
# =========================
@admin_bp.route("/update-chunk", methods=["POST"])
@requires_admin_auth
def update_chunk():
data = request.get_json() or {}
chunk_hash = str(data.get("chunk_hash", "")).strip()
text = str(data.get("text", "")).strip()
print("chunk_hash", chunk_hash)
print("text", text)
if not chunk_hash:
return {"status": "error", "message": "missing hash"}, 400
reason = str(data.get("reason", "Manual change"))
revoke_chunk_by_hash(chunk_hash, reason=reason)
chunk_hash = add_manual_knowledge_entry(
text=text,
author="ADMIN",
reason=reason,
source="MANUAL_INPUT",
origin="MANUAL",
also_update_graph=True
)
audit_log("UPDATE CHUNK", f"chunk_hash={chunk_hash}")
return jsonify({
"status": "OK",
"chunk_hash": chunk_hash
})
@admin_bp.route("/reboot", methods=["POST"])
@requires_admin_auth
def reboot_service():
# roda em background pra não travar request
threading.Thread(target=reload_all, daemon=True).start()
return jsonify({
"status": "ok",
"message": "Knowledge reload started"
})