SN_NLP / src /streamlit_app.py
ColinceTatsa's picture
Update src/streamlit_app.py
e39c339 verified
import streamlit as st
import requests
import re
import tempfile
import os
from dotenv import load_dotenv
# Nouveaux imports pour Groq et LangSmith
from groq import Groq
from langsmith import traceable
# Charger les variables d'environnement
load_dotenv()
# --- INTERFACE STREAMLIT ---
st.set_page_config(page_title="nlp", layout="wide")
st.title("SN NATURAL LANGUAGE PROCESSING")
st.subheader('Étudiant MASTER II: TATSA TCHINDA Colince')
# Sidebar logo
try:
image_path = 'src/Keyce.jpg'
st.sidebar.image(image_path, caption="Keyce informatique et intelligence artificielle", use_container_width=True)
except FileNotFoundError:
st.sidebar.warning("Image 'keyce.jpg' non trouvée. Assurez-vous qu'elle est dans le même répertoire que le script.")
# --- GESTION DES CLÉS API (depuis .env) ---
st.session_state["API_TOKEN_HF"] = os.getenv("HUGGINGFACE_API_KEY")
st.session_state["API_TOKEN_GROQ"] = os.getenv("GROQ_API_KEY")
api_token_langsmith = os.getenv("LANGCHAIN_API_KEY")
# Configuration de LangSmith si la clé est fournie
if api_token_langsmith:
st.session_state["LANGSMITH_CONFIGURED"] = True
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_ENDPOINT"] = "https://api.smith.langchain.com"
os.environ["LANGCHAIN_API_KEY"] = api_token_langsmith
os.environ["LANGCHAIN_PROJECT"] = "Mon App Streamlit NLP" # Nom du projet dans LangSmith
st.sidebar.info("Tracing LangSmith activé.")
else:
st.session_state["LANGSMITH_CONFIGURED"] = False
# Désactiver le tracing si aucune clé n'est fournie
if "LANGCHAIN_TRACING_V2" in os.environ:
del os.environ["LANGCHAIN_TRACING_V2"]
# --- INITIALISATION DES CLIENTS ---
headers = {}
if st.session_state.get("API_TOKEN_HF"):
headers = {"Authorization": f"Bearer {st.session_state['API_TOKEN_HF']}"}
# --- FONCTIONS UTILES ---
def nettoyer_reponse(text):
# La fonction de nettoyage n'est plus nécessaire pour Groq, mais on la garde au cas où.
cleaned = re.sub(r"<think>.*?</think>", "", text, flags=re.DOTALL)
return cleaned.strip()
@traceable(name="Groq Llama3 Generator") # Le décorateur @traceable active le suivi LangSmith
def generate_with_groq_llama(prompt, api_key):
"""
Génère du texte en utilisant l'API Groq avec un modèle Llama3 et trace l'appel avec LangSmith.
"""
try:
client_groq = Groq(api_key=api_key)
chat_completion = client_groq.chat.completions.create(
messages=[
{
"role": "user",
"content": prompt,
}
],
model="llama3-8b-8192",
temperature=0.7,
max_tokens=1024,
)
return chat_completion.choices[0].message.content
except Groq.APIConnectionError as e:
st.error(f"Erreur de connexion avec Groq: {e.__cause__}")
return "Impossible de se connecter à l'API Groq. Veuillez vérifier votre connexion réseau."
except Exception as e:
st.error(f"Une erreur inattendue est survenue avec Groq: {e}")
return "Une erreur est survenue lors de la génération de texte."
def transcribe_audio(path, content_type):
request_headers = headers.copy()
if not request_headers.get("Authorization"):
st.error("Veuillez entrer une clé API Hugging Face pour utiliser cette fonctionnalité.")
return "Erreur : clé API Hugging Face manquante."
request_headers["Content-Type"] = content_type
API_URL = "https://api-inference.huggingface.co/models/openai/whisper-large-v2"
# Débogage
st.info(f"Tentative de transcription audio...")
st.info(f"Chemin du fichier audio : {path}")
st.info(f"Type de contenu (Content-Type) : {content_type}")
st.info(f"En-têtes de la requête (partie Authorization masquée) : {{'Authorization': 'Bearer [MASQUÉE]', 'Content-Type': '{content_type}'}}")
if not st.session_state.get("API_TOKEN_HF"):
st.error("DEBUG: La clé API Hugging Face n'est PAS présente dans st.session_state.")
else:
st.success("DEBUG: La clé API Hugging Face est présente dans st.session_state.")
try:
with open(path, "rb") as f:
response = requests.post(API_URL, headers=request_headers, data=f)
response.raise_for_status() # Lève une exception pour les codes d'erreur HTTP
return response.json().get("text", "Erreur: 'text' non trouvé dans la réponse.")
except requests.exceptions.HTTPError as err:
st.error(f"Erreur Whisper Large: {err.response.status_code} - {err.response.text}")
return f"Erreur lors de la transcription (Code: {err.response.status_code}). Vérifiez votre clé API HF et les limites d'utilisation."
except Exception as e:
st.error(f"Une erreur inattendue est survenue lors de la transcription : {str(e)}")
return "Erreur lors de la transcription."
def summarize_text(text):
"""
Génère un résumé de texte en utilisant le modèle Groq Llama3.
"""
if not st.session_state.get("API_TOKEN_GROQ"):
st.error("Veuillez configurer votre clé API Groq dans le fichier .env pour le résumé.")
return "Erreur : clé API Groq manquante."
prompt = f"Résume le texte suivant de manière concise en français :\n\nTexte : '''{text}'''\n\nRésumé :"
summary = generate_with_groq_llama(prompt, st.session_state["API_TOKEN_GROQ"])
return summary
# --- MENU ---
option = st.sidebar.radio(
"Choisissez une fonctionnalité :",
["📝 Générateur de texte", "🎙 Audio vers texte", "🧠 Résumeur de texte"]
)
# --- GÉNÉRATEUR DE TEXTE ---
if option == "📝 Générateur de texte":
st.subheader("📝 Génération de texte (Groq Llama3)")
st.markdown("Utilise le modèle `llama3-8b-8192` via l'API ultra-rapide de Groq.")
if st.session_state.get("LANGSMITH_CONFIGURED"):
st.info("Le suivi avec LangSmith est activé. [Voir le projet](https://smith.langchain.com/)", icon="🔗")
if not st.session_state.get("API_TOKEN_GROQ"):
st.warning("Veuillez entrer une clé API Groq dans votre fichier `.env` pour utiliser le générateur de texte.")
else:
prompt = st.text_area("Entrez votre prompt :", key="prompt", height=150)
if st.button("Générer", key="gen"):
if prompt.strip():
with st.spinner("Génération en cours avec Groq..."):
try:
output = generate_with_groq_llama(prompt, st.session_state["API_TOKEN_GROQ"])
st.success("Texte généré :")
st.write(output)
except Exception as e:
st.error(f"Erreur lors de la génération avec Groq : {e}")
else:
st.warning("Veuillez entrer un prompt.")
# --- AUDIO VERS TEXTE ---
elif option == "🎙 Audio vers texte":
st.subheader("🎧 Transcription automatisée d’un fichier audio (30 sec max)")
if not st.session_state.get("API_TOKEN_HF"):
st.warning("Veuillez entrer une clé API Hugging Face dans votre fichier `.env` pour utiliser cette fonctionnalité.")
else:
audio_file = st.file_uploader("🎵 Chargez un fichier audio", type=["wav", "mp3", "m4a"])
if audio_file is not None:
# Créer un fichier temporaire pour sauvegarder l'audio
with tempfile.NamedTemporaryFile(delete=False, suffix=f'.{audio_file.name.split(".")[-1]}') as tmp_file:
tmp_file.write(audio_file.getvalue())
audio_path = tmp_file.name
st.audio(audio_path)
if st.button("✍️ Transcrire"):
with st.spinner("Transcription en cours..."):
# On passe le type MIME du fichier original à la fonction
transcript = transcribe_audio(audio_path, audio_file.type)
if "Erreur" not in transcript: # Vérifiez si la transcription n'est pas une erreur
st.markdown(f"**Transcription :**")
st.text_area("Résultat", transcript, height=150)
# Nettoyer le fichier temporaire
os.unlink(audio_path)
# --- RÉSUMEUR DE TEXTE ---
elif option == "🧠 Résumeur de texte":
st.subheader("🧠 Résumé de texte (Groq Llama3)")
st.markdown("Utilise le modèle `llama3-8b-8192` pour générer un résumé.")
if not st.session_state.get("API_TOKEN_GROQ"):
st.warning("Veuillez vous assurer qu'une clé API Groq est configurée dans votre fichier .env pour utiliser cette fonctionnalité.")
else:
input_text = st.text_area("Texte à résumer :", height=300)
if st.button("Résumer"):
if input_text.strip():
with st.spinner("Résumé en cours avec Groq..."):
summary = summarize_text(input_text)
st.success("Résumé généré :")
st.write(summary)
else:
st.warning("Veuillez entrer un texte à résumer.")