Svngoku commited on
Commit
58a3898
·
verified ·
1 Parent(s): e851339

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +29 -15
app.py CHANGED
@@ -3,12 +3,13 @@ import base64
3
  import gradio as gr
4
  from mistralai import Mistral
5
  from mistralai.models import OCRResponse
 
6
  from pathlib import Path
7
  from pydantic import BaseModel
8
  import pycountry
9
  import json
10
  import logging
11
- from tenacity import retry, stop_after_attempt, wait_fixed
12
  import tempfile
13
  from typing import Union, Dict, List
14
  from contextlib import contextmanager
@@ -29,6 +30,11 @@ class OCRProcessor:
29
  raise ValueError("API key must be provided")
30
  self.api_key = api_key
31
  self.client = Mistral(api_key=self.api_key)
 
 
 
 
 
32
 
33
  @staticmethod
34
  def _encode_image(image_path: str) -> str:
@@ -47,13 +53,21 @@ class OCRProcessor:
47
  if os.path.exists(temp_file.name):
48
  os.unlink(temp_file.name)
49
 
50
- @retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
51
  def _call_ocr_api(self, document: Dict) -> OCRResponse:
52
- return self.client.ocr.process(model="mistral-ocr-latest", document=document)
 
 
 
 
53
 
54
- @retry(stop=stop_after_attempt(3), wait=wait_fixed(2))
55
  def _call_chat_complete(self, model: str, messages: List[Dict], **kwargs) -> Dict:
56
- return self.client.chat.complete(model=model, messages=messages, **kwargs)
 
 
 
 
57
 
58
  def _get_file_content(self, file_input: Union[str, bytes]) -> bytes:
59
  if isinstance(file_input, str):
@@ -181,26 +195,27 @@ def create_interface():
181
  api_key_input = gr.Textbox(
182
  label="Mistral API Key",
183
  placeholder="Enter your Mistral API key here",
184
- type="password" # Hide the API key for security
185
  )
186
 
187
  # Function to initialize processor with API key
188
  def initialize_processor(api_key):
189
  try:
190
- return OCRProcessor(api_key)
 
 
 
191
  except Exception as e:
192
- return str(e)
193
 
194
  # Store processor state
195
  processor_state = gr.State()
 
196
 
197
  # Button to set API key
198
  set_api_button = gr.Button("Set API Key")
199
- api_status = gr.Markdown("API key not set. Please enter and set your key.")
200
-
201
- # Update processor and status when API key is set
202
  set_api_button.click(
203
- fn=lambda key: (initialize_processor(key), "**Success:** API key set!" if not isinstance(initialize_processor(key), str) else f"**Error:** {initialize_processor(key)}"),
204
  inputs=api_key_input,
205
  outputs=[processor_state, api_status]
206
  )
@@ -222,9 +237,8 @@ def create_interface():
222
  output = gr.Markdown(label="Result")
223
  button_label = name.replace("OCR with ", "").replace("Structured ", "Get Structured ")
224
 
225
- # Wrapper function to use processor from state
226
  def process_with_api(processor, input_data):
227
- if not processor or isinstance(processor, str):
228
  return "**Error:** Please set a valid API key first."
229
  fn = getattr(processor, fn_name)
230
  return fn(input_data)
@@ -241,7 +255,7 @@ def create_interface():
241
  output = gr.Markdown(label="Answer")
242
 
243
  def doc_understanding_with_api(processor, url, q):
244
- if not processor or isinstance(processor, str):
245
  return "**Error:** Please set a valid API key first."
246
  return processor.document_understanding(url, q)
247
 
 
3
  import gradio as gr
4
  from mistralai import Mistral
5
  from mistralai.models import OCRResponse
6
+ from mistralai.exceptions import MistralException # Import Mistral-specific exceptions
7
  from pathlib import Path
8
  from pydantic import BaseModel
9
  import pycountry
10
  import json
11
  import logging
12
+ from tenacity import retry, stop_after_attempt, wait_fixed, retry_if_exception_type
13
  import tempfile
14
  from typing import Union, Dict, List
15
  from contextlib import contextmanager
 
30
  raise ValueError("API key must be provided")
31
  self.api_key = api_key
32
  self.client = Mistral(api_key=self.api_key)
33
+ # Test API key validity on initialization
34
+ try:
35
+ self.client.models.list() # Simple API call to validate key
36
+ except MistralException as e:
37
+ raise ValueError(f"Invalid API key: {str(e)}")
38
 
39
  @staticmethod
40
  def _encode_image(image_path: str) -> str:
 
53
  if os.path.exists(temp_file.name):
54
  os.unlink(temp_file.name)
55
 
56
+ @retry(stop=stop_after_attempt(3), wait=wait_fixed(2), retry_if_exception_type(MistralException))
57
  def _call_ocr_api(self, document: Dict) -> OCRResponse:
58
+ try:
59
+ return self.client.ocr.process(model="mistral-ocr-latest", document=document)
60
+ except MistralException as e:
61
+ logger.error(f"OCR API call failed: {str(e)}")
62
+ raise
63
 
64
+ @retry(stop=stop_after_attempt(3), wait=wait_fixed(2), retry_if_exception_type(MistralException))
65
  def _call_chat_complete(self, model: str, messages: List[Dict], **kwargs) -> Dict:
66
+ try:
67
+ return self.client.chat.complete(model=model, messages=messages, **kwargs)
68
+ except MistralException as e:
69
+ logger.error(f"Chat complete API call failed: {str(e)}")
70
+ raise
71
 
72
  def _get_file_content(self, file_input: Union[str, bytes]) -> bytes:
73
  if isinstance(file_input, str):
 
195
  api_key_input = gr.Textbox(
196
  label="Mistral API Key",
197
  placeholder="Enter your Mistral API key here",
198
+ type="password"
199
  )
200
 
201
  # Function to initialize processor with API key
202
  def initialize_processor(api_key):
203
  try:
204
+ processor = OCRProcessor(api_key)
205
+ return processor, "**Success:** API key set and validated!"
206
+ except ValueError as e:
207
+ return None, f"**Error:** {str(e)}"
208
  except Exception as e:
209
+ return None, f"**Error:** Unexpected error: {str(e)}"
210
 
211
  # Store processor state
212
  processor_state = gr.State()
213
+ api_status = gr.Markdown("API key not set. Please enter and set your key.")
214
 
215
  # Button to set API key
216
  set_api_button = gr.Button("Set API Key")
 
 
 
217
  set_api_button.click(
218
+ fn=initialize_processor,
219
  inputs=api_key_input,
220
  outputs=[processor_state, api_status]
221
  )
 
237
  output = gr.Markdown(label="Result")
238
  button_label = name.replace("OCR with ", "").replace("Structured ", "Get Structured ")
239
 
 
240
  def process_with_api(processor, input_data):
241
+ if not processor:
242
  return "**Error:** Please set a valid API key first."
243
  fn = getattr(processor, fn_name)
244
  return fn(input_data)
 
255
  output = gr.Markdown(label="Answer")
256
 
257
  def doc_understanding_with_api(processor, url, q):
258
+ if not processor:
259
  return "**Error:** Please set a valid API key first."
260
  return processor.document_understanding(url, q)
261