feat(извлечение): надёжное распознавание колонки названий + добор трудных PDF через Vision
- grid: колонки «Код …» и «№» исключены из кандидатов на колонку названий (ключ «услуг» ловил «Код услуги») — клиника с 5181 строкой больше не даёт 0. - vision: авто-добор PDF при пустом или подозрительно низком выходе строк/страницу, замена недобора полным распознаванием, ретраи на лимиты, лимит размера документа. - презентация статуса проекта на /day2; маршрут /day2 в Caddy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -70,8 +70,14 @@ def _parse_response(text: str) -> list[RawRow]:
|
||||
return rows
|
||||
|
||||
|
||||
def extract_with_vision(path: str, max_pages: int = 12, dpi: int = 140) -> list[RawRow]:
|
||||
"""Извлечь позиции из PDF через Gemini Vision. Возвращает список RawRow."""
|
||||
def extract_with_vision(path: str, max_pages: int = 40, dpi: int = 140) -> list[RawRow]:
|
||||
"""Извлечь позиции из PDF через Gemini Vision. Возвращает список RawRow.
|
||||
|
||||
Страницы распознаются по одной. При превышении квоты (429) делается пауза и
|
||||
повтор — большой документ не должен срываться из-за лимита запросов в минуту.
|
||||
"""
|
||||
import time
|
||||
|
||||
api_key = os.environ.get("GEMINI_API_KEY")
|
||||
if not api_key:
|
||||
raise RuntimeError("нет GEMINI_API_KEY в окружении")
|
||||
@@ -85,10 +91,17 @@ def extract_with_vision(path: str, max_pages: int = 12, dpi: int = 140) -> list[
|
||||
|
||||
rows: list[RawRow] = []
|
||||
for png in _render_pages(path, max_pages, dpi):
|
||||
response = client.models.generate_content(
|
||||
model=model,
|
||||
contents=[types.Part.from_bytes(data=png, mime_type="image/png"), _PROMPT],
|
||||
config=config,
|
||||
)
|
||||
rows.extend(_parse_response(response.text))
|
||||
part = types.Part.from_bytes(data=png, mime_type="image/png")
|
||||
for attempt in range(6):
|
||||
try:
|
||||
response = client.models.generate_content(
|
||||
model=model, contents=[part, _PROMPT], config=config
|
||||
)
|
||||
rows.extend(_parse_response(response.text))
|
||||
break
|
||||
except Exception as exc: # пауза и повтор при превышении квоты (429)
|
||||
if ("RESOURCE_EXHAUSTED" in str(exc) or "429" in str(exc)) and attempt < 5:
|
||||
time.sleep(15)
|
||||
continue
|
||||
raise
|
||||
return rows
|
||||
|
||||
Reference in New Issue
Block a user