import streamlit as st
import os
from chromadb import Client as ChromaClient
from chroma_storage import ChromaStorage
from retrieval import Retriever
from langchain_groq import ChatGroq
from generation import RAGGenerator
from langchain_community.vectorstores import Chroma
from langchain_huggingface import HuggingFaceEmbeddings
from constant import categorie
from dotenv import load_dotenv
import chromadb
from Reranker import Reranker
chromadb.api.client.SharedSystemClient.clear_system_cache()
load_dotenv()
import os
CHROMA_DIR = "src/chroma_db"
COLLECTION_NAME = "my_collection"
st.markdown("""
""", unsafe_allow_html=True)
# --- En-tête bleu avec logo et titre ---
st.markdown(f'''
''', unsafe_allow_html=True)
#if "categories" not in st.session_state:
# st.session_state.categories = categorie
if "messages" not in st.session_state:
st.session_state.messages = []
if "step" not in st.session_state:
st.session_state.step = 0
if "selected_category" not in st.session_state:
st.session_state.selected_category = None
# --- Affichage du chat uniquement après sélection ---
#sel = st.session_state.selected_category
# Ajouter le message initial du bot à l'étape 1
if st.session_state.step == 0:
st.session_state.messages.append({
"role": "assistant",
"content": "I am your assistant, Ominimo"
})
# save_conversation_to_mongo(st.session_state.messages)
st.session_state.step = 1
st.rerun()
# ─────────────────────────────────────────────────────────────────────────────
# 2) INITIALISATION UNIQUE (cache via session_state)
# ─────────────────────────────────────────────────────────────────────────────
if "initialized" not in st.session_state:
st.session_state.initialized = True
retriever = Retriever(
chroma_dir=CHROMA_DIR,
collection_name=COLLECTION_NAME
)
llm = ChatGroq(
model="meta-llama/llama-4-scout-17b-16e-instruct",
temperature=0,
max_tokens=None,
timeout=None,
max_retries=2,
)
generator = RAGGenerator()
reranker = Reranker(model=llm)
st.session_state.retriever = retriever
st.session_state.generator = generator
st.session_state.reranker = reranker
# st.session_state.categories = categorie
# ─────────────────────────────────────────────────────────────────────────────
# 3) UI & État de chat
# ─────────────────────────────────────────────────────────────────────────────
query = st.chat_input("chat_query")
#if "last_rerank" in st.session_state:
# st.code(f"Rerank result: {st.session_state.last_rerank}")
# Si l'utilisateur a saisi une requête
if query:
# Si on est en phase de clarification
if "qa_pairs" in st.session_state and "clarif_idx" in st.session_state:
idx = st.session_state.clarif_idx
st.session_state.messages.append({"role": "user", "content": query})
# save_conversation_to_mongo(st.session_state.messages)
st.session_state.qa_pairs[idx]["response"] = query
st.session_state.clarif_idx += 1
else:
# Requête initiale normale
st.session_state.messages.append({"role": "user", "content": query})
# save_conversation_to_mongo(st.session_state.messages)
try:
# 1. Récupération des documents initiaux
# with st.spinner():
docs = st.session_state.retriever.retrieve(query)
passages = [(doc_tuple[0].page_content, doc_tuple[1]) for doc_tuple in docs]
# st.code(passages)
# 2. Reranking des documents pour améliorer la pertinence
if docs:
rerank_result = st.session_state.reranker.rerank(query, passages)
# Affichage du résultat brut pour debug
# st.code(f"Rerank raw result: {rerank_result}")
if rerank_result is not None:
st.session_state.last_rerank = rerank_result.model_dump()
# Filtrage et réorganisation des documents selon le reranking
if rerank_result.top_indexes:
reranked_docs = [docs[i] for i in rerank_result.top_indexes if i < len(docs)]
docs = reranked_docs
else:
st.session_state.messages.append({
"role": "assistant",
"content": rerank_result.message or "Aucun document pertinent trouvé. Veuillez reformuler votre question."
})
# Si le reranker a échoué
# Si le reranker a échoué
else:
pass
# 3. Génération de la réponse avec les documents reranked
if docs: # Vérifier que nous avons des documents avant de continuer
qa_pairs, solution, lang = st.session_state.generator.retrieve_qa(
query=query,
docs_scores=docs
)
st.session_state.qa_pairs = qa_pairs
st.session_state.solution = solution
st.session_state.lang = lang
else:
# Aucun document disponible
st.session_state.messages.append({
"role": "assistant",
"content": "Aucun document pertinent trouvé pour votre requête. Pouvez-vous la reformuler ?"
})
except ValueError as e:
st.session_state.messages.append({
"role": "assistant",
"content": str(e)
})
# save_conversation_to_mongo(st.session_state.messages)
except Exception as e:
st.error(f"❌ Erreur : {e}")
# ───────────────────────────────────────────────
# Gestion des clarifications
# ───────────────────────────────────────────────
if "qa_pairs" in st.session_state:
if "clarif_shown" not in st.session_state:
questions_text = "\n".join([
f"{i+1}. {pair['question']}" for i, pair in enumerate(st.session_state.qa_pairs)
])
st.session_state.messages.append({
"role": "assistant",
"content": questions_text
})
# save_conversation_to_mongo(st.session_state.messages)
st.session_state.clarif_shown = True
if "clarif_idx" not in st.session_state:
st.session_state.clarif_idx = 0
# Lorsque toutes les clarifications sont remplies, générer la réponse finale
if st.session_state.clarif_idx >= len(st.session_state.qa_pairs):
final = st.session_state.generator.generate_answer(
st.session_state.messages,
st.session_state.solution,
st.session_state.lang
)
if not final.strip() or "sorry" in final.lower():
st.session_state.messages.append({
"role": "assistant",
"content": "I'm sorry, I cannot answer this request. It is beyond my capabilities or not related to car insurance."
})
else:
st.session_state.messages.append({"role": "assistant", "content": final})
for key in ["qa_pairs", "solution", "lang", "clarif_idx", "clarif_shown"]:
st.session_state.pop(key, None)
for key in ["qa_pairs", "solution", "lang", "clarif_idx", "clarif_shown"]:
st.session_state.pop(key, None)
st.markdown('', unsafe_allow_html=True)
for msg in st.session_state.messages:
if not msg.get("content"):
continue
if msg["role"] == "assistant":
st.markdown(f'''
{msg["content"]}
''', unsafe_allow_html=True)
else:
st.markdown(f'''
{msg["content"]}
''', unsafe_allow_html=True)
st.markdown('
', unsafe_allow_html=True)