↩️ Назад

Категории

Распознавание счетов-фактур через VL-модель

23.07.2026 | Статья из категории: python

Мы построили конвейер, который забирает счета-фактуры из почты, распознаёт их через qwen3-vl:30b-a3b-instruct и возвращает структурированный JSON для загрузки в 1С.

В этой заметке — готовый скрипт распознавания, примеры запросов и инструкция по интеграции.

📦 Готовый скрипт

Скрипт recognize_invoice.py принимает на вход путь к файлу (PDF или JPG), кодирует его в base64 и отправляет в VL-модель.

#!/usr/bin/env python3
import base64
import json
import sys
import requests
import traceback

# ====== КОНФИГ ======
OLLAMA_URL = 'http://10.11.23.170:12434/api/generate'
MODEL = 'qwen3-vl:30b-a3b-instruct'

# ====== ОСНОВНАЯ ФУНКЦИЯ ======
def recognize_invoice(file_path):
    print(f"📄 Обрабатываем файл: {file_path}", file=sys.stderr)

    try:
        with open(file_path, 'rb') as f:
            b64 = base64.b64encode(f.read()).decode('utf-8')
    except FileNotFoundError:
        print(f"❌ Файл не найден: {file_path}", file=sys.stderr)
        sys.exit(1)

    print(f"📊 Размер base64: {len(b64)} символов", file=sys.stderr)

    payload = {
        "model": MODEL,
        "prompt": (
            "Извлеки данные из документа в JSON. "
            "Если это счёт-фактура — укажи контрагента, ИНН, сумму, НДС, номер, дату, позиции."
        ),
        "images": [b64],
        "stream": False
    }

    print("📤 Отправляем запрос к модели...", file=sys.stderr)

    try:
        response = requests.post(OLLAMA_URL, json=payload, timeout=180)
        print(f"📥 Статус ответа: {response.status_code}", file=sys.stderr)

        if response.status_code != 200:
            print(f"❌ Ошибка HTTP: {response.status_code}", file=sys.stderr)
            print(response.text, file=sys.stderr)
            sys.exit(1)

        result = response.json()
        answer = result.get('response', '')

        if not answer:
            print("❌ Модель вернула пустой ответ", file=sys.stderr)
            print(json.dumps(result, indent=2, ensure_ascii=False), file=sys.stderr)
            sys.exit(1)

        try:
            parsed = json.loads(answer)
            print(json.dumps(parsed, indent=2, ensure_ascii=False))
        except json.JSONDecodeError:
            print(answer)

    except requests.exceptions.Timeout:
        print("❌ Таймаут: модель не ответила за 180 секунд", file=sys.stderr)
        sys.exit(1)
    except requests.exceptions.ConnectionError:
        print("❌ Не удалось подключиться к Ollama", file=sys.stderr)
        sys.exit(1)
    except Exception as e:
        print(f"❌ Ошибка: {e}", file=sys.stderr)
        traceback.print_exc(file=sys.stderr)
        sys.exit(1)

if __name__ == '__main__':
    if len(sys.argv) < 2:
        print("Использование: recognize_invoice.py <путь_к_файлу>")
        sys.exit(1)
    recognize_invoice(sys.argv[1])

🧪 Пример запуска

python3 /usr/local/bin/recognize_invoice.py /tmp/invoice.jpg

Ожидаемый вывод

{
  "type": "счет-фактура",
  "number": "118",
  "date": "21.10.2024",
  "seller": {
    "name": "ООО «Альфа»",
    "inn_kpp": "7722345678/772201001"
  },
  "buyer": {
    "name": "ООО «Омега»",
    "inn_kpp": "5040456789/504001001"
  },
  "positions": [],
  "total_amount": null,
  "vat_rate": null
}

🔧 Установка и настройка

1. Размести скрипт

sudo nano /usr/local/bin/recognize_invoice.py
sudo chmod +x /usr/local/bin/recognize_invoice.py

2. Убедись, что модель доступна

curl -s http://10.11.23.170:12434/api/tags | jq '.models[].name'

3. Протестируй

python3 /usr/local/bin/recognize_invoice.py /tmp/test.jpg

🧠 Как это работает

📌 Куда дальше


✅ Итог: мы построили конвейер, который забирает счета из почты, распознаёт их через VL-модель и возвращает JSON для 1С. Весь код — открытый, работает локально, без облаков.
👍 Оцените статью
Всего голосов: 0



Категории:

Категории

Комментарии

Пока нет комментариев. Будьте первым!

Оставить комментарий

← Назад к списку статей

Посетителей сегодня: 0
о блоге | карта блога | 📡 Подписаться на RSS

© Digital Specialist | Не являемся сотрудниками Google, Яндекса и NASA