scan, split, OCR, prepare for LLM
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

qwen_client.py 2.4KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. from __future__ import annotations
  2. import base64
  3. import logging
  4. import os
  5. import time as _time
  6. import cv2
  7. import requests
  8. from src.env import load_env
  9. logger = logging.getLogger(__name__)
  10. API_URL: str = "https://opencode.ai/zen/go/v1/messages"
  11. DEFAULT_MODEL: str = "qwen3.8-max"
  12. IMAGE_QUALITY: int = 90
  13. _ENV_LOADED: bool = False
  14. def _ensure_env() -> None:
  15. global _ENV_LOADED
  16. if _ENV_LOADED:
  17. return
  18. load_env()
  19. _ENV_LOADED = True
  20. def _api_key() -> str:
  21. _ensure_env()
  22. return os.environ.get("OPENCODE_API_KEY", "")
  23. def image_to_base64(image) -> str:
  24. _, buf = cv2.imencode(".jpg", image, [cv2.IMWRITE_JPEG_QUALITY, IMAGE_QUALITY])
  25. return base64.b64encode(buf).decode("utf-8")
  26. def call_qwen_vlm(
  27. image_b64: str,
  28. prompt: str,
  29. model: str = DEFAULT_MODEL,
  30. max_tokens: int = 300,
  31. ) -> str | None:
  32. """Отправляет изображение + prompt в Qwen3.8 Max API и возвращает текст ответа."""
  33. if not _api_key():
  34. logger.warning("OPENCODE_API_KEY не задан")
  35. return None
  36. messages = [{
  37. "role": "user",
  38. "content": [
  39. {"type": "image", "source": {"type": "base64", "media_type": "image/jpeg", "data": image_b64}},
  40. {"type": "text", "text": prompt},
  41. ],
  42. }]
  43. for attempt in (1, 2):
  44. try:
  45. r = requests.post(
  46. API_URL,
  47. headers={"x-api-key": _api_key(), "anthropic-version": "2023-06-01", "Content-Type": "application/json"},
  48. json={"model": model, "max_tokens": max_tokens, "messages": messages},
  49. timeout=120,
  50. )
  51. r.raise_for_status()
  52. data = r.json()
  53. for item in data.get("content", []):
  54. if item.get("type") == "text":
  55. return item.get("text", "").strip()
  56. return None
  57. except requests.HTTPError as e:
  58. if e.response is not None and e.response.status_code == 500 and attempt == 1:
  59. logger.info("Qwen API: HTTP 500, ожидание 5с и повтор...")
  60. _time.sleep(5)
  61. continue
  62. logger.warning("Qwen API: ошибка — %s", e)
  63. return None
  64. except (requests.RequestException, KeyError, IndexError) as e:
  65. logger.warning("Qwen API: ошибка — %s", e)
  66. return None
  67. return None