Docfile commited on
Commit
0c9dced
·
verified ·
1 Parent(s): f6602fb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +129 -90
app.py CHANGED
@@ -5,11 +5,10 @@ from dotenv import load_dotenv
5
  import http.client
6
  import json
7
  import shutil
 
8
 
9
  # Charger les variables d'environnement
10
  load_dotenv()
11
-
12
- # Configurer la clé API
13
  genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
14
 
15
  # Paramètres de sécurité
@@ -20,25 +19,21 @@ safety_settings = [
20
  {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
21
  ]
22
 
23
- # Instructions système pour Mariam (inchangées pour brièveté, mais peuvent être affinées)
24
  ss = """
25
  # Prompt System pour Mariam, IA conçu par youssouf
26
  [...]
27
  """
28
 
29
- # Initialisation du modèle
30
  model = genai.GenerativeModel('gemini-2.0-flash-exp', tools='code_execution',
31
  safety_settings=safety_settings,
32
  system_instruction=ss)
33
 
34
- # Fonction de recherche web
35
  def perform_web_search(query):
36
  conn = http.client.HTTPSConnection("google.serper.dev")
37
  payload = json.dumps({"q": query})
38
- headers = {
39
- 'X-API-KEY': '9b90a274d9e704ff5b21c0367f9ae1161779b573',
40
- 'Content-Type': 'application/json'
41
- }
42
  try:
43
  conn.request("POST", "/search", payload, headers)
44
  res = conn.getresponse()
@@ -50,7 +45,6 @@ def perform_web_search(query):
50
  finally:
51
  conn.close()
52
 
53
- # Formater les résultats de recherche
54
  def format_search_results(data):
55
  if not data:
56
  return "Aucun résultat trouvé"
@@ -62,17 +56,9 @@ def format_search_results(data):
62
  result += "### Résultats principaux:\n"
63
  for item in data['organic'][:3]:
64
  result += f"- **{item['title']}**\n {item['snippet']}\n [Lien]({item['link']})\n\n"
65
- if 'peopleAlsoAsk' in data:
66
- result += "### Questions fréquentes:\n"
67
- for item in data['peopleAlsoAsk'][:2]:
68
- result += f"- **{item['question']}**\n {item['snippet']}\n\n"
69
  return result
70
 
71
- # Convertir les rôles pour Streamlit
72
- def role_to_streamlit(role):
73
- return "assistant" if role == "model" else role
74
-
75
- # Initialiser l'état de la session
76
  if "chat" not in st.session_state:
77
  st.session_state.chat = model.start_chat(history=[])
78
  if "web_search" not in st.session_state:
@@ -85,83 +71,136 @@ def clear_chat_history():
85
  st.session_state.chat = model.start_chat(history=[])
86
  st.session_state.messages = []
87
 
88
- # Créer un dossier temporaire
89
- os.makedirs("temp", exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
- # Titre de l’application
92
  st.title("Mariam AI")
93
 
94
- # Section des paramètres dans la barre latérale
95
- with st.sidebar:
96
- st.header("Paramètres")
97
  st.session_state.web_search = st.toggle("Activer la recherche web", value=st.session_state.web_search,
98
- help="Permet d’enrichir les réponses avec des informations du web.")
99
- if st.button("Effacer l’historique", on_click=clear_chat_history):
 
100
  st.success("Historique effacé.")
101
 
102
- # Section de téléchargement de fichiers
103
- with st.sidebar:
104
- st.header("Téléchargement de fichiers")
105
  st.info("Types acceptés : jpg, jpeg, png, pdf, txt")
106
  uploaded_file = st.file_uploader("Choisir un fichier", type=['jpg', 'jpeg', 'png', 'pdf', 'txt'])
107
 
108
- # Section de conversation
109
- st.header("Conversation")
110
- chat_container = st.container()
111
-
112
- # Afficher les messages
113
- with chat_container:
114
- for message in st.session_state.messages:
115
- with st.chat_message(message["role"]):
116
- st.markdown(message["content"])
117
-
118
- # Champ de saisie multiligne
119
- user_input = st.text_area("Votre message", height=100)
120
-
121
- # Bouton pour envoyer
122
- if st.button("Envoyer"):
123
- if user_input:
124
- # Ajouter le message de l’utilisateur
125
- st.session_state.messages.append({"role": "user", "content": user_input})
126
-
127
- # Traiter le fichier téléchargé
128
- uploaded_gemini_file = None
129
- if uploaded_file:
130
- file_ext = uploaded_file.name.split('.')[-1].lower()
131
- accepted_types = ['jpg', 'jpeg', 'png', 'pdf', 'txt']
132
- if file_ext in accepted_types:
133
- with open(os.path.join("temp", uploaded_file.name), "wb") as f:
134
- f.write(uploaded_file.getbuffer())
135
- try:
136
- uploaded_gemini_file = genai.upload_file(os.path.join("temp", uploaded_file.name))
137
- except Exception as e:
138
- st.error(f"Erreur lors de l’upload du fichier : {e}")
139
- else:
140
- st.error("Type de fichier non accepté. Utilisez jpg, jpeg, png, pdf ou txt.")
141
-
142
- # Recherche web si activée
143
- web_results = None
144
- if st.session_state.web_search:
145
- with st.spinner("Recherche web en cours..."):
146
- web_results = perform_web_search(user_input)
147
- if web_results:
148
- formatted_results = format_search_results(web_results)
149
- user_input = f"{user_input}\n\nVoici les résultats de la recherche web. Analyse-les et donne-moi une réponse complète :\n\n{formatted_results}"
150
-
151
- # Envoyer à Gemini
152
- try:
153
- if uploaded_gemini_file:
154
- response = st.session_state.chat.send_message([uploaded_gemini_file, "\n\n", user_input])
155
- else:
156
- response = st.session_state.chat.send_message(user_input)
157
- st.session_state.messages.append({"role": "assistant", "content": response.text})
158
- with chat_container:
159
- with st.chat_message("assistant"):
160
- st.markdown(response.text)
161
- except Exception as e:
162
- st.error(f"Erreur lors de l’envoi : {e}")
163
-
164
- # Nettoyer les fichiers temporaires
165
- if uploaded_file:
166
- shutil.rmtree("temp", ignore_errors=True)
167
- os.makedirs("temp", exist_ok=True)
 
 
 
 
 
 
 
 
 
 
 
 
5
  import http.client
6
  import json
7
  import shutil
8
+ import streamlit.components.v1 as components
9
 
10
  # Charger les variables d'environnement
11
  load_dotenv()
 
 
12
  genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
13
 
14
  # Paramètres de sécurité
 
19
  {"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
20
  ]
21
 
22
+ # Instructions système (inchangées pour brièveté)
23
  ss = """
24
  # Prompt System pour Mariam, IA conçu par youssouf
25
  [...]
26
  """
27
 
 
28
  model = genai.GenerativeModel('gemini-2.0-flash-exp', tools='code_execution',
29
  safety_settings=safety_settings,
30
  system_instruction=ss)
31
 
32
+ # Fonctions de recherche web (inchangées)
33
  def perform_web_search(query):
34
  conn = http.client.HTTPSConnection("google.serper.dev")
35
  payload = json.dumps({"q": query})
36
+ headers = {'X-API-KEY': '9b90a274d9e704ff5b21c0367f9ae1161779b573', 'Content-Type': 'application/json'}
 
 
 
37
  try:
38
  conn.request("POST", "/search", payload, headers)
39
  res = conn.getresponse()
 
45
  finally:
46
  conn.close()
47
 
 
48
  def format_search_results(data):
49
  if not data:
50
  return "Aucun résultat trouvé"
 
56
  result += "### Résultats principaux:\n"
57
  for item in data['organic'][:3]:
58
  result += f"- **{item['title']}**\n {item['snippet']}\n [Lien]({item['link']})\n\n"
 
 
 
 
59
  return result
60
 
61
+ # Initialisation de l’état
 
 
 
 
62
  if "chat" not in st.session_state:
63
  st.session_state.chat = model.start_chat(history=[])
64
  if "web_search" not in st.session_state:
 
71
  st.session_state.chat = model.start_chat(history=[])
72
  st.session_state.messages = []
73
 
74
+ # CSS personnalisé pour mobile
75
+ st.markdown("""
76
+ <style>
77
+ .chat-container {
78
+ height: 60vh;
79
+ overflow-y: auto;
80
+ padding: 10px;
81
+ background-color: #f9f9f9;
82
+ border-radius: 10px;
83
+ }
84
+ .user-message {
85
+ background-color: #007bff;
86
+ color: white;
87
+ padding: 10px;
88
+ border-radius: 10px;
89
+ margin: 5px 0;
90
+ max-width: 80%;
91
+ align-self: flex-end;
92
+ }
93
+ .assistant-message {
94
+ background-color: #e9ecef;
95
+ color: black;
96
+ padding: 10px;
97
+ border-radius: 10px;
98
+ margin: 5px 0;
99
+ max-width: 80%;
100
+ }
101
+ .input-container {
102
+ position: fixed;
103
+ bottom: 0;
104
+ width: 100%;
105
+ padding: 10px;
106
+ background-color: white;
107
+ box-shadow: 0 -2px 5px rgba(0,0,0,0.1);
108
+ }
109
+ @media (max-width: 600px) {
110
+ .chat-container {
111
+ height: 70vh;
112
+ }
113
+ .stTextArea textarea {
114
+ height: 80px !important;
115
+ }
116
+ }
117
+ </style>
118
+ """, unsafe_allow_html=True)
119
 
120
+ # Titre
121
  st.title("Mariam AI")
122
 
123
+ # Section des paramètres (expansible)
124
+ with st.expander("Paramètres"):
 
125
  st.session_state.web_search = st.toggle("Activer la recherche web", value=st.session_state.web_search,
126
+ help="Permet des réponses enrichies avec des données du web.")
127
+ if st.button("Effacer l’historique"):
128
+ clear_chat_history()
129
  st.success("Historique effacé.")
130
 
131
+ # Section de téléchargement
132
+ with st.expander("Télécharger un fichier"):
 
133
  st.info("Types acceptés : jpg, jpeg, png, pdf, txt")
134
  uploaded_file = st.file_uploader("Choisir un fichier", type=['jpg', 'jpeg', 'png', 'pdf', 'txt'])
135
 
136
+ # Zone de conversation
137
+ st.markdown('<div class="chat-container">', unsafe_allow_html=True)
138
+ for message in st.session_state.messages:
139
+ if message["role"] == "user":
140
+ st.markdown(f'<div class="user-message">{message["content"]}</div>', unsafe_allow_html=True)
141
+ else:
142
+ st.markdown(f'<div class="assistant-message">{message["content"]}</div>', unsafe_allow_html=True)
143
+ st.markdown('</div>', unsafe_allow_html=True)
144
+
145
+ # JavaScript pour défiler automatiquement
146
+ components.html("""
147
+ <script>
148
+ const chatContainer = document.querySelector('.chat-container');
149
+ chatContainer.scrollTop = chatContainer.scrollHeight;
150
+ </script>
151
+ """)
152
+
153
+ # Zone de saisie
154
+ st.markdown('<div class="input-container">', unsafe_allow_html=True)
155
+ user_input = st.text_area("Votre message", height=80, key="input")
156
+ col1, col2 = st.columns([3, 1])
157
+ with col1:
158
+ pass
159
+ with col2:
160
+ send_button = st.button("Envoyer")
161
+ st.markdown('</div>', unsafe_allow_html=True)
162
+
163
+ # Traitement de l’entrée utilisateur
164
+ if send_button and user_input:
165
+ st.session_state.messages.append({"role": "user", "content": user_input})
166
+
167
+ # Traitement du fichier
168
+ uploaded_gemini_file = None
169
+ if uploaded_file:
170
+ file_ext = uploaded_file.name.split('.')[-1].lower()
171
+ if file_ext in ['jpg', 'jpeg', 'png', 'pdf', 'txt']:
172
+ with open(os.path.join("temp", uploaded_file.name), "wb") as f:
173
+ f.write(uploaded_file.getbuffer())
174
+ try:
175
+ uploaded_gemini_file = genai.upload_file(os.path.join("temp", uploaded_file.name))
176
+ except Exception as e:
177
+ st.error(f"Erreur lors de l’upload : {e}")
178
+ else:
179
+ st.error("Type de fichier non accepté.")
180
+
181
+ # Recherche web
182
+ web_results = None
183
+ if st.session_state.web_search:
184
+ with st.spinner("Recherche web en cours..."):
185
+ web_results = perform_web_search(user_input)
186
+ if web_results:
187
+ formatted_results = format_search_results(web_results)
188
+ user_input = f"{user_input}\n\nRésultats de recherche :\n{formatted_results}\nAnalyse ces informations et réponds-moi."
189
+
190
+ # Réponse de Mariam
191
+ try:
192
+ if uploaded_gemini_file:
193
+ response = st.session_state.chat.send_message([uploaded_gemini_file, "\n\n", user_input])
194
+ else:
195
+ response = st.session_state.chat.send_message(user_input)
196
+ st.session_state.messages.append({"role": "assistant", "content": response.text})
197
+ except Exception as e:
198
+ st.error(f"Erreur : {e}")
199
+
200
+ # Nettoyage
201
+ if uploaded_file:
202
+ shutil.rmtree("temp", ignore_errors=True)
203
+ os.makedirs("temp", exist_ok=True)
204
+
205
+ # Rafraîchir la page pour afficher la réponse
206
+ st.rerun()