Space07 / app.py
Hakim18's picture
Upload 10 files
6fd7d0c verified
Raw
History Blame Contribute Delete
5.4 kB
import os, random
import torch
import pandas as pd
from flask import Flask, render_template, request, jsonify
from sentence_transformers import SentenceTransformer, util
import gradio as gr
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
app = Flask(
__name__,
template_folder=os.path.join(BASE_DIR, "templates"),
static_folder=os.path.join(BASE_DIR, "static")
)
CSV_DATA = "dataset_2026.csv"
EMB_FILE = "embeddings_questions.pt"
TOP_K_RECOMMANDATIONS = 5
print("🔄 Chargement du modèle...")
try:
model = SentenceTransformer(
"OrdalieTech/Solon-embeddings-mini-beta-1.1",
device="cpu",
trust_remote_code=True
)
print("✓ Modèle principal (Solon) chargé")
except Exception as e:
print(f"⚠️ Échec du modèle principal (probablement dû à la version Hugging Face Hub): {e}")
print("🔄 Chargement du modèle de secours (paraphrase-multilingual)...")
model = SentenceTransformer(
"paraphrase-multilingual-MiniLM-L12-v2",
device="cpu"
)
print("✓ Modèle de secours chargé avec succès !")
df_cache = None
def load_data():
global df_cache
if df_cache is None:
try:
# We enforce reading the Latin-1 CSV using ';' as sep.
df_cache = pd.read_csv(CSV_DATA, sep=";", encoding="latin-1")
df_cache.columns = df_cache.columns.str.strip()
except:
# Fallback if somehow it's utf-8 with comma
df_cache = pd.read_csv(CSV_DATA, sep=None, engine='python', encoding="utf-8")
df_cache.columns = df_cache.columns.str.strip()
return df_cache
def load_or_create_embeddings(df):
if os.path.exists(EMB_FILE):
emb = torch.load(EMB_FILE, map_location="cpu")
if emb.shape[0] == len(df) and emb.shape[1] == model.get_sentence_embedding_dimension():
return emb
print("⚠️ Dimensions embeddings incorrectes, recréation...")
print("🔨 Création embeddings...")
questions = df["Question"].astype(str).tolist()
emb = model.encode(
questions,
convert_to_tensor=True,
normalize_embeddings=True
)
torch.save(emb, EMB_FILE)
return emb
def enrich_message(base):
return random.choice([
f"Bonne question 🙂\n\n{base}",
f"Voici la réponse détaillée :\n\n{base}",
f"Voici ce que j'ai trouvé :\n\n{base}",
base
])
def process_question(question):
df = load_data()
emb_base = load_or_create_embeddings(df)
emb_q = model.encode(question, convert_to_tensor=True, normalize_embeddings=True)
scores = util.pytorch_cos_sim(emb_q, emb_base)[0]
best_idx = torch.argmax(scores).item()
confidence = int(scores[best_idx].item() * 100)
if confidence < 40:
recs = df["Question"].sample(min(TOP_K_RECOMMANDATIONS, len(df))).tolist()
return {
"response": "Je ne suis pas sûr",
"confidence": confidence,
"matched": "—",
"intent": "Inconnu",
"recs": recs,
"service": None,
"lat": None,
"lon": None
}
row = df.iloc[best_idx]
service_val = str(row["Service"]).strip() if pd.notna(row["Service"]) else None
if service_val and service_val.lower() in ['nan', 'none', 'null', '']: service_val = None
link_val = str(row["ServiceLink"]).strip() if pd.notna(row["ServiceLink"]) else None
if link_val and link_val.lower() in ['nan', 'none', 'null', '']: link_val = None
try:
raw_lat = str(row["Latitude"]).replace(',', '.')
raw_lon = str(row["Longitude"]).replace(',', '.')
lat_val = float(raw_lat)
lon_val = float(raw_lon)
except Exception:
lat_val = None
lon_val = None
return {
"response": enrich_message(row["Response"]),
"confidence": confidence,
"matched": row["Question"],
"intent": row["Intent"],
"recs": [],
"service": service_val,
"link": link_val,
"lat": lat_val,
"lon": lon_val
}
@app.route("/")
def index():
return render_template("index.html")
@app.route("/ask", methods=["POST"])
def ask():
return jsonify(process_question(request.json.get("question", "")))
@app.route("/api/services", methods=["GET"])
def get_services():
df = load_data()
valid_df = df.dropna(subset=["Service", "Latitude", "Longitude"])
services = []
seen = set()
for _, row in valid_df.iterrows():
try:
name = str(row["Service"]).strip()
lat = float(str(row["Latitude"]).replace(',', '.'))
lon = float(str(row["Longitude"]).replace(',', '.'))
if name and name not in seen:
services.append({"service": name, "lat": lat, "lon": lon})
seen.add(name)
except Exception:
pass
return jsonify({"status": "success", "services": services})
# ==============================
# HUGGING FACE SPACES (GRADIO)
# ==============================
def gradio_chat(message, history):
return process_question(message)["response"]
iface = gr.ChatInterface(
fn=gradio_chat,
title="AskLaQ Assistant"
)
if __name__ == "__main__":
print("🚀 Serveur Flask lancé sur http://127.0.0.1:7860")
app.run(host="0.0.0.0", port=7860, debug=True, use_reloader=False)