Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -265,7 +265,10 @@ def upload_file_to_mistral(client, path: str, filename: str | None = None, purpo
|
|
| 265 |
fid = None
|
| 266 |
if fid:
|
| 267 |
if progress is not None:
|
| 268 |
-
|
|
|
|
|
|
|
|
|
|
| 269 |
return fid
|
| 270 |
except Exception as e:
|
| 271 |
last_sdk_error = e
|
|
@@ -276,21 +279,88 @@ def upload_file_to_mistral(client, path: str, filename: str | None = None, purpo
|
|
| 276 |
raise RuntimeError("MISTRAL_API_KEY missing or empty")
|
| 277 |
url = "https://api.mistral.ai/v1/files"
|
| 278 |
headers = {"Authorization": f"Bearer {api_key}"}
|
| 279 |
-
|
|
|
|
| 280 |
with open(path, "rb") as fh:
|
| 281 |
files = {"file": (fname, fh)}
|
| 282 |
-
data = {"purpose":
|
| 283 |
r = requests.post(url, headers=headers, files=files, data=data, timeout=timeout)
|
| 284 |
r.raise_for_status()
|
| 285 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 286 |
if progress is not None:
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
|
| 292 |
-
|
| 293 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 294 |
|
| 295 |
def determine_media_type(src: str, progress=None) -> Tuple[bool, bool]:
|
| 296 |
is_image = False
|
|
|
|
| 265 |
fid = None
|
| 266 |
if fid:
|
| 267 |
if progress is not None:
|
| 268 |
+
try:
|
| 269 |
+
progress(0.6)
|
| 270 |
+
except TypeError:
|
| 271 |
+
progress(0.6, desc="Upload complete (SDK)")
|
| 272 |
return fid
|
| 273 |
except Exception as e:
|
| 274 |
last_sdk_error = e
|
|
|
|
| 279 |
raise RuntimeError("MISTRAL_API_KEY missing or empty")
|
| 280 |
url = "https://api.mistral.ai/v1/files"
|
| 281 |
headers = {"Authorization": f"Bearer {api_key}"}
|
| 282 |
+
|
| 283 |
+
def do_rest_upload(purpose_value: str):
|
| 284 |
with open(path, "rb") as fh:
|
| 285 |
files = {"file": (fname, fh)}
|
| 286 |
+
data = {"purpose": purpose_value}
|
| 287 |
r = requests.post(url, headers=headers, files=files, data=data, timeout=timeout)
|
| 288 |
r.raise_for_status()
|
| 289 |
+
return r.json()
|
| 290 |
+
|
| 291 |
+
# Build purpose retry list (prefer image if file extension suggests image)
|
| 292 |
+
tried = set()
|
| 293 |
+
purposes_to_try = [purpose] if purpose else []
|
| 294 |
+
ext = os.path.splitext(fname)[1].lower()
|
| 295 |
+
if ext in (".png", ".jpg", ".jpeg", ".gif", ".webp", ".bmp", ".tiff"):
|
| 296 |
+
if "image" not in purposes_to_try:
|
| 297 |
+
purposes_to_try.append("image")
|
| 298 |
+
for p in ("batch", "fine-tune", "image"):
|
| 299 |
+
if p not in purposes_to_try:
|
| 300 |
+
purposes_to_try.append(p)
|
| 301 |
+
|
| 302 |
+
last_rest_exception = None
|
| 303 |
+
for p in purposes_to_try:
|
| 304 |
+
if p in tried:
|
| 305 |
+
continue
|
| 306 |
+
tried.add(p)
|
| 307 |
+
try:
|
| 308 |
+
jr = do_rest_upload(p)
|
| 309 |
if progress is not None:
|
| 310 |
+
try:
|
| 311 |
+
progress(0.65)
|
| 312 |
+
except TypeError:
|
| 313 |
+
progress(0.65, desc=f"Upload complete (REST, purpose={p})")
|
| 314 |
+
fid = jr.get("id") or jr.get("data", [{}])[0].get("id")
|
| 315 |
+
if fid:
|
| 316 |
+
return fid
|
| 317 |
+
# fallback: search for any 'id' in the JSON
|
| 318 |
+
if isinstance(jr, dict):
|
| 319 |
+
def find_id(obj):
|
| 320 |
+
if isinstance(obj, dict):
|
| 321 |
+
if "id" in obj and isinstance(obj["id"], str):
|
| 322 |
+
return obj["id"]
|
| 323 |
+
for v in obj.values():
|
| 324 |
+
found = find_id(v)
|
| 325 |
+
if found:
|
| 326 |
+
return found
|
| 327 |
+
elif isinstance(obj, list):
|
| 328 |
+
for item in obj:
|
| 329 |
+
found = find_id(item)
|
| 330 |
+
if found:
|
| 331 |
+
return found
|
| 332 |
+
return None
|
| 333 |
+
fid = find_id(jr)
|
| 334 |
+
if fid:
|
| 335 |
+
return fid
|
| 336 |
+
raise RuntimeError(f"REST upload returned no file id for purpose={p}: {jr}")
|
| 337 |
+
except requests.exceptions.HTTPError as he:
|
| 338 |
+
status = getattr(he.response, "status_code", None) or getattr(he.response, "status", None)
|
| 339 |
+
last_rest_exception = he
|
| 340 |
+
if status == 422:
|
| 341 |
+
# try next purpose value
|
| 342 |
+
continue
|
| 343 |
+
else:
|
| 344 |
+
err_msg = f"File upload failed. REST error: {he}"
|
| 345 |
+
if last_sdk_error:
|
| 346 |
+
err_msg += f" | SDK error: {last_sdk_error}"
|
| 347 |
+
raise RuntimeError(err_msg)
|
| 348 |
+
except requests.exceptions.RequestException as re:
|
| 349 |
+
last_rest_exception = re
|
| 350 |
+
err_msg = f"File upload failed. REST error: {re}"
|
| 351 |
+
if last_sdk_error:
|
| 352 |
+
err_msg += f" | SDK error: {last_sdk_error}"
|
| 353 |
+
raise RuntimeError(err_msg)
|
| 354 |
+
except Exception as exc:
|
| 355 |
+
last_rest_exception = exc
|
| 356 |
+
continue
|
| 357 |
+
|
| 358 |
+
err_msg = "File upload failed. REST attempts exhausted."
|
| 359 |
+
if last_rest_exception:
|
| 360 |
+
err_msg += f" Last REST error: {last_rest_exception}"
|
| 361 |
+
if last_sdk_error:
|
| 362 |
+
err_msg += f" | SDK error: {last_sdk_error}"
|
| 363 |
+
raise RuntimeError(err_msg)
|
| 364 |
|
| 365 |
def determine_media_type(src: str, progress=None) -> Tuple[bool, bool]:
|
| 366 |
is_image = False
|