Docfile commited on
Commit
2b85178
·
verified ·
1 Parent(s): b9fcf25

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -62
app.py CHANGED
@@ -5,7 +5,7 @@ from PIL import Image
5
  import json
6
  import logging
7
  import re
8
- from typing import Optional, Generator, Any, Tuple
9
  import sys
10
  from pathlib import Path
11
 
@@ -20,16 +20,15 @@ logging.basicConfig(
20
  )
21
  logger = logging.getLogger(__name__)
22
 
23
-
24
  class LatexFormatter:
25
  """Classe améliorée pour le formatage LaTeX"""
26
 
27
  @staticmethod
28
  def cleanup_latex_fractions(text: str) -> str:
29
  """Nettoie et formate correctement les fractions LaTeX"""
30
- # Remplace \frac{x}{y} par \frac{x}{y}
31
  text = re.sub(r'\\frac\{([^}]*)\}\{([^}]*)\}', r'$$\\frac{\1}{\2}$$', text)
32
- # Gère les cas spéciaux comme \left et \right
33
  text = re.sub(r'\\left\(', r'\\left(', text)
34
  text = re.sub(r'\\right\)', r'\\right)', text)
35
  return text
@@ -37,17 +36,30 @@ class LatexFormatter:
37
  @staticmethod
38
  def format_inline_math(text: str) -> str:
39
  """Formate les expressions mathématiques en ligne"""
40
- # Ajoute des espaces autour des expressions inline
41
  text = re.sub(r'(?<!\\)\$([^$]+)(?<!\\)\$', r' $\1$ ', text)
 
 
42
  return text
43
 
44
  @staticmethod
45
  def format_display_math(text: str) -> str:
46
  """Formate les expressions mathématiques en mode display"""
47
- # Ajoute des sauts de ligne autour des expressions display
48
  text = re.sub(r'\$\$(.*?)\$\$', r'\n\n$$\1$$\n\n', text, flags=re.DOTALL)
49
  return text
50
 
 
 
 
 
 
 
 
 
 
 
 
51
  @staticmethod
52
  def enhance_latex_display(text: str) -> str:
53
  """Améliore globalement l'affichage LaTeX"""
@@ -55,25 +67,17 @@ class LatexFormatter:
55
  text = text.replace('\\[', '$$').replace('\\]', '$$')
56
  text = text.replace('\\(', '$').replace('\\)', '$')
57
 
58
- # Nettoyage des fractions
59
  text = LatexFormatter.cleanup_latex_fractions(text)
60
-
61
- # Formatage du mode inline
62
  text = LatexFormatter.format_inline_math(text)
63
-
64
- # Formatage du mode display
65
  text = LatexFormatter.format_display_math(text)
66
 
67
- # Assure que chaque ligne d'équation est bien espacée
68
  text = re.sub(r'(\n\s*\$\$[^$]+\$\$)', r'\n\n\1\n\n', text)
69
 
70
  return text
71
 
72
-
73
-
74
-
75
-
76
-
77
  class GeminiClient:
78
  """Classe pour gérer les interactions avec l'API Gemini"""
79
  def __init__(self, api_key: str):
@@ -102,7 +106,7 @@ class GeminiClient:
102
  config={'thinking_config': {'include_thoughts': True}},
103
  contents=[
104
  image,
105
- prompt + " Si ta réponse contient des expressions mathématiques, utilise la notation LaTeX avec les délimiteurs appropriés ($ pour inline, $$ pour les blocs)."
106
  ]
107
  )
108
  return response
@@ -110,21 +114,11 @@ class GeminiClient:
110
  logger.error(f"Erreur lors de l'analyse de l'image: {e}")
111
  raise
112
 
113
- def format_text_with_latex(text: str) -> str:
114
- """Formate le texte en appliquant les améliorations LaTeX"""
115
- formatter = LatexFormatter()
116
- text = formatter.format_inline_latex(text)
117
- text = formatter.format_block_latex(text)
118
- text = formatter.enhance_latex_display(text)
119
- return text
120
-
121
- def stream_response(container, response: Generator) -> None:
122
- """Fonction de streaming améliorée avec meilleur support LaTeX"""
123
-
124
- # Configuration CSS améliorée pour le rendu LaTeX
125
  st.markdown("""
126
  <style>
127
- /* Amélioration du rendu LaTeX */
128
  .katex {
129
  font-size: 1.2em !important;
130
  padding: 0.2em 0;
@@ -136,24 +130,61 @@ def stream_response(container, response: Generator) -> None:
136
  padding: 0.5em;
137
  border-radius: 4px;
138
  }
139
- /* Amélioration de l'espacement des fractions */
140
  .katex .frac-line {
141
  border-bottom-width: 0.08em;
142
  }
143
  .katex .mfrac .frac-line {
144
  margin: 0.1em 0;
145
  }
146
- /* Meilleur rendu sur mobile */
 
 
 
 
 
 
 
 
 
 
 
 
147
  @media (max-width: 768px) {
148
- .katex { font-size: 1.1em !important; }
 
 
149
  .katex-display {
150
  padding: 0.3em;
151
  margin: 1em 0 !important;
 
152
  }
153
  }
 
 
 
 
 
 
 
 
 
 
 
 
154
  </style>
155
  """, unsafe_allow_html=True)
156
-
 
 
 
 
 
 
 
 
 
 
157
  try:
158
  for chunk in response:
159
  logger.debug(f"Chunk reçu: {chunk}")
@@ -186,8 +217,8 @@ def stream_response(container, response: Generator) -> None:
186
  continue
187
 
188
  # Formatage LaTeX du texte
189
- formatted_text = format_text_with_latex(text)
190
-
191
  if has_thought:
192
  if mode != "thinking":
193
  if thinking_placeholder is None:
@@ -216,7 +247,7 @@ def stream_response(container, response: Generator) -> None:
216
  except Exception as e:
217
  logger.error(f"Erreur fatale dans le streaming de la réponse: {e}")
218
  if not answer_text and not thinking_text:
219
- container.error("Une erreur est survenue lors de l'analyse de l'image. Veuillez réessayer.")
220
  raise
221
  finally:
222
  if not answer_text and not thinking_text:
@@ -236,32 +267,12 @@ def main():
236
  st.set_page_config(
237
  page_title="Mariam M-0",
238
  page_icon="🔍",
239
- layout="wide"
 
240
  )
241
 
242
  st.title("Mariam M-0")
243
-
244
- # Configuration supplémentaire pour LaTeX
245
- st.markdown("""
246
- <style>
247
- /* Styles globaux pour LaTeX */
248
- .latex-container {
249
- margin: 1em 0;
250
- padding: 0.5em;
251
- background: #f9f9f9;
252
- border-radius: 4px;
253
- }
254
- /* Amélioration de l'espacement des équations */
255
- .katex-display {
256
- margin: 1.5em 0 !important;
257
- padding: 0.5em 0;
258
- }
259
- /* Amélioration du rendu sur mobile */
260
- @media (max-width: 768px) {
261
- .katex { font-size: 1em !important; }
262
- }
263
- </style>
264
- """, unsafe_allow_html=True)
265
 
266
  # Récupération de la clé API
267
  try:
@@ -280,7 +291,7 @@ def main():
280
 
281
  # Interface utilisateur
282
  uploaded_file = st.file_uploader(
283
- "Choisissez une image géométrique",
284
  type=['png', 'jpg', 'jpeg'],
285
  help="Formats supportés: PNG, JPG, JPEG"
286
  )
@@ -293,6 +304,7 @@ def main():
293
  model_name = "gemini-2.0-flash-thinking-exp-01-21"
294
  prompt = "Résous cet exercice mathématique. La réponse doit être bien présentée et espacée pour faciliter la lecture. Réponds en français et utilise la notation LaTeX pour toutes les expressions mathématiques."
295
 
 
296
  if st.button("Analyser l'image", type="primary"):
297
  response_container = st.container()
298
 
 
5
  import json
6
  import logging
7
  import re
8
+ from typing import Optional, Generator, Any, Dict
9
  import sys
10
  from pathlib import Path
11
 
 
20
  )
21
  logger = logging.getLogger(__name__)
22
 
 
23
  class LatexFormatter:
24
  """Classe améliorée pour le formatage LaTeX"""
25
 
26
  @staticmethod
27
  def cleanup_latex_fractions(text: str) -> str:
28
  """Nettoie et formate correctement les fractions LaTeX"""
29
+ # Améliore le rendu des fractions
30
  text = re.sub(r'\\frac\{([^}]*)\}\{([^}]*)\}', r'$$\\frac{\1}{\2}$$', text)
31
+ # Gère les délimiteurs left/right
32
  text = re.sub(r'\\left\(', r'\\left(', text)
33
  text = re.sub(r'\\right\)', r'\\right)', text)
34
  return text
 
36
  @staticmethod
37
  def format_inline_math(text: str) -> str:
38
  """Formate les expressions mathématiques en ligne"""
39
+ # Améliore l'espacement autour des expressions inline
40
  text = re.sub(r'(?<!\\)\$([^$]+)(?<!\\)\$', r' $\1$ ', text)
41
+ # Gère les cas spéciaux où il y a déjà des $$ mais en inline
42
+ text = re.sub(r'(?<!\\)\$\$([^$]+)(?<!\\)\$\$', r' $\1$ ', text)
43
  return text
44
 
45
  @staticmethod
46
  def format_display_math(text: str) -> str:
47
  """Formate les expressions mathématiques en mode display"""
48
+ # Ajoute des sauts de ligne et de l'espacement
49
  text = re.sub(r'\$\$(.*?)\$\$', r'\n\n$$\1$$\n\n', text, flags=re.DOTALL)
50
  return text
51
 
52
+ @staticmethod
53
+ def format_special_environments(text: str) -> str:
54
+ """Formate les environnements mathématiques spéciaux"""
55
+ # Gère les environnements align, gather, etc.
56
+ envs = ['align', 'gather', 'equation', 'array', 'matrix']
57
+ for env in envs:
58
+ pattern = f'\\\\begin{{{env}}}(.*?)\\\\end{{{env}}}'
59
+ text = re.sub(pattern, f'\n\n$$\\\\begin{{{env}}}\\1\\\\end{{{env}}}$$\n\n',
60
+ text, flags=re.DOTALL)
61
+ return text
62
+
63
  @staticmethod
64
  def enhance_latex_display(text: str) -> str:
65
  """Améliore globalement l'affichage LaTeX"""
 
67
  text = text.replace('\\[', '$$').replace('\\]', '$$')
68
  text = text.replace('\\(', '$').replace('\\)', '$')
69
 
70
+ # Application des différentes améliorations
71
  text = LatexFormatter.cleanup_latex_fractions(text)
72
+ text = LatexFormatter.format_special_environments(text)
 
73
  text = LatexFormatter.format_inline_math(text)
 
 
74
  text = LatexFormatter.format_display_math(text)
75
 
76
+ # Assure un bon espacement des équations
77
  text = re.sub(r'(\n\s*\$\$[^$]+\$\$)', r'\n\n\1\n\n', text)
78
 
79
  return text
80
 
 
 
 
 
 
81
  class GeminiClient:
82
  """Classe pour gérer les interactions avec l'API Gemini"""
83
  def __init__(self, api_key: str):
 
106
  config={'thinking_config': {'include_thoughts': True}},
107
  contents=[
108
  image,
109
+ prompt + " Utilise la notation LaTeX appropriée avec $...$ pour les expressions en ligne et $$...$$ pour les équations importantes. Pour les fractions, utilise \\frac{num}{den}."
110
  ]
111
  )
112
  return response
 
114
  logger.error(f"Erreur lors de l'analyse de l'image: {e}")
115
  raise
116
 
117
+ def setup_latex_display():
118
+ """Configure l'affichage LaTeX dans Streamlit"""
 
 
 
 
 
 
 
 
 
 
119
  st.markdown("""
120
  <style>
121
+ /* Styles de base pour LaTeX */
122
  .katex {
123
  font-size: 1.2em !important;
124
  padding: 0.2em 0;
 
130
  padding: 0.5em;
131
  border-radius: 4px;
132
  }
133
+ /* Amélioration des fractions */
134
  .katex .frac-line {
135
  border-bottom-width: 0.08em;
136
  }
137
  .katex .mfrac .frac-line {
138
  margin: 0.1em 0;
139
  }
140
+ /* Style des matrices */
141
+ .katex .mord.matrix {
142
+ margin: 0.2em 0;
143
+ }
144
+ /* Amélioration des indices et exposants */
145
+ .katex .msupsub {
146
+ font-size: 0.9em;
147
+ }
148
+ /* Meilleure lisibilité des symboles */
149
+ .katex .mathdefault {
150
+ color: inherit;
151
+ }
152
+ /* Adaptation mobile */
153
  @media (max-width: 768px) {
154
+ .katex {
155
+ font-size: 1.1em !important;
156
+ }
157
  .katex-display {
158
  padding: 0.3em;
159
  margin: 1em 0 !important;
160
+ font-size: 0.9em !important;
161
  }
162
  }
163
+ /* Conteneur de réponse */
164
+ .response-container {
165
+ margin: 1em 0;
166
+ padding: 1em;
167
+ border-radius: 8px;
168
+ background: rgba(255, 255, 255, 0.05);
169
+ }
170
+ /* Mise en évidence des équations importantes */
171
+ .important-equation {
172
+ border-left: 3px solid #4CAF50;
173
+ padding-left: 1em;
174
+ }
175
  </style>
176
  """, unsafe_allow_html=True)
177
+
178
+ def stream_response(container, response: Generator) -> None:
179
+ """Gère le streaming de la réponse avec support LaTeX amélioré"""
180
+ mode = 'starting'
181
+ thinking_placeholder = None
182
+ answer_placeholder = None
183
+ thinking_text = ""
184
+ answer_text = ""
185
+
186
+ setup_latex_display()
187
+
188
  try:
189
  for chunk in response:
190
  logger.debug(f"Chunk reçu: {chunk}")
 
217
  continue
218
 
219
  # Formatage LaTeX du texte
220
+ formatted_text = LatexFormatter.enhance_latex_display(text)
221
+
222
  if has_thought:
223
  if mode != "thinking":
224
  if thinking_placeholder is None:
 
247
  except Exception as e:
248
  logger.error(f"Erreur fatale dans le streaming de la réponse: {e}")
249
  if not answer_text and not thinking_text:
250
+ container.error("Une erreur est survenue lors de l'analyse. Veuillez réessayer.")
251
  raise
252
  finally:
253
  if not answer_text and not thinking_text:
 
267
  st.set_page_config(
268
  page_title="Mariam M-0",
269
  page_icon="🔍",
270
+ layout="wide",
271
+ initial_sidebar_state="collapsed"
272
  )
273
 
274
  st.title("Mariam M-0")
275
+ setup_latex_display()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
276
 
277
  # Récupération de la clé API
278
  try:
 
291
 
292
  # Interface utilisateur
293
  uploaded_file = st.file_uploader(
294
+ "Choisissez une image contenant des mathématiques",
295
  type=['png', 'jpg', 'jpeg'],
296
  help="Formats supportés: PNG, JPG, JPEG"
297
  )
 
304
  model_name = "gemini-2.0-flash-thinking-exp-01-21"
305
  prompt = "Résous cet exercice mathématique. La réponse doit être bien présentée et espacée pour faciliter la lecture. Réponds en français et utilise la notation LaTeX pour toutes les expressions mathématiques."
306
 
307
+
308
  if st.button("Analyser l'image", type="primary"):
309
  response_container = st.container()
310