|
import streamlit as st |
|
from google import genai |
|
import logging |
|
import sys |
|
from pathlib import Path |
|
from typing import Generator |
|
|
|
|
|
logging.basicConfig( |
|
level=logging.DEBUG, |
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', |
|
handlers=[ |
|
logging.StreamHandler(sys.stdout), |
|
logging.FileHandler(Path('app.log')) |
|
] |
|
) |
|
logger = logging.getLogger(__name__) |
|
|
|
class GeminiClient: |
|
"""Classe pour gérer les interactions avec l'API Gemini""" |
|
def __init__(self, api_key: str): |
|
self.client = None |
|
self.init_client(api_key) |
|
|
|
def init_client(self, api_key: str) -> None: |
|
"""Initialise le client Gemini""" |
|
try: |
|
self.client = genai.Client( |
|
api_key=api_key, |
|
http_options={'api_version': 'v1alpha'} |
|
) |
|
except Exception as e: |
|
logger.error(f"Erreur d'initialisation du client Gemini: {e}") |
|
raise RuntimeError(f"Impossible d'initialiser le client Gemini: {e}") |
|
|
|
def get_response(self, question: str, model_name: str) -> Generator: |
|
"""Obtient une réponse de Gemini""" |
|
if not self.client: |
|
raise RuntimeError("Client Gemini non initialisé") |
|
|
|
try: |
|
response = self.client.models.generate_content_stream( |
|
model=model_name, |
|
config={'thinking_config': {'include_thoughts': True}}, |
|
contents=[question] |
|
) |
|
return response |
|
except Exception as e: |
|
logger.error(f"Erreur lors de la génération de la réponse: {e}") |
|
raise |
|
|
|
def stream_response(container, response: Generator) -> None: |
|
"""Gère le streaming de la réponse""" |
|
thinking_placeholder = None |
|
answer_placeholder = None |
|
thinking_text = "" |
|
answer_text = "" |
|
mode = 'starting' |
|
|
|
try: |
|
for chunk in response: |
|
if hasattr(chunk, 'candidates') and chunk.candidates: |
|
content = chunk.candidates[0].content |
|
|
|
if hasattr(content, 'parts'): |
|
for part in content.parts: |
|
has_thought = hasattr(part, 'thought') and part.thought |
|
text = getattr(part, 'text', '') |
|
|
|
if not text: |
|
continue |
|
|
|
if has_thought: |
|
if mode != "thinking": |
|
if thinking_placeholder is None: |
|
with container.expander("Voir le raisonnement", expanded=False): |
|
thinking_placeholder = st.empty() |
|
mode = "thinking" |
|
thinking_text += text |
|
thinking_placeholder.markdown(thinking_text) |
|
else: |
|
if mode != "answering": |
|
if answer_placeholder is None: |
|
answer_placeholder = container.empty() |
|
container.subheader("~•") |
|
mode = "answering" |
|
answer_text += text |
|
answer_placeholder.markdown(answer_text) |
|
|
|
except Exception as e: |
|
logger.error(f"Erreur dans le streaming de la réponse: {e}") |
|
if not answer_text and not thinking_text: |
|
container.error("Une erreur est survenue lors de l'analyse. Veuillez réessayer.") |
|
raise |
|
finally: |
|
if not answer_text and not thinking_text: |
|
container.warning("Aucune réponse n'a pu être générée. Veuillez réessayer.") |
|
|
|
def main(): |
|
st.set_page_config( |
|
page_title="Mariam M1", |
|
page_icon="💭", |
|
layout="wide", |
|
initial_sidebar_state="collapsed" |
|
) |
|
|
|
st.title("Mariam M-0") |
|
|
|
|
|
try: |
|
api_key = st.secrets["GEMINI_API_KEY"] |
|
except Exception as e: |
|
logger.error(f"Erreur dans la récupération des secrets: {e}") |
|
st.error("Erreur: Impossible d'accéder aux secrets de l'application.") |
|
return |
|
|
|
|
|
try: |
|
gemini_client = GeminiClient(api_key) |
|
except Exception as e: |
|
st.error(f"Erreur lors de l'initialisation du client Gemini: {e}") |
|
return |
|
|
|
|
|
question = st.text_area( |
|
"Posez votre question", |
|
height=100, |
|
help="Entrez votre question ici" |
|
) |
|
|
|
if question: |
|
model_name = "gemini-2.0-flash-thinking-exp-01-21" |
|
|
|
if st.button("Obtenir une réponse", type="primary"): |
|
response_container = st.container() |
|
|
|
with st.spinner("Génération de la réponse en cours..."): |
|
try: |
|
print(question) |
|
response = gemini_client.get_response(question, model_name) |
|
stream_response(response_container, response) |
|
except Exception as e: |
|
logger.error(f"Erreur lors de la génération: {e}", exc_info=True) |
|
st.error("Une erreur est survenue. Veuillez réessayer.") |
|
|
|
if __name__ == "__main__": |
|
main() |