↩️ Назад

Категории

AI-агент для бухгалтерии: конвейер обработки счетов-фактур из почты

23.07.2026 | Статья из категории: Нейросети

Представьте: бухгалтер получает сотни писем с документами — счетами-фактурами, актами, накладными. Каждое нужно открыть, проверить, вручную перенести данные в 1С. Это занимает часы, а ошибки стоят дорого.

Что если нейросеть будет делать это за секунды?

В этой статье я покажу, как построить локального AI-агента, который:

Всё работает локально, без облаков, без передачи данных наружу.

📐 Архитектура конвейера

Конвейер состоит из четырех последовательных этапов:

  1. Захват письма — подключение к почтовому ящику по IMAP.
  2. Извлечение вложений — загрузка PDF и изображений.
  3. Анализ нейросетью — распознавание типа документа и извлечение реквизитов.
  4. Генерация JSON для 1С — структурированный вывод.
💡 Почему это важно: по данным Smart Engines, даже при выборочной проверке бухгалтер обрабатывает 200–300 документов в день [citation:15]. ИИ-агент способен распознавать до 900 страниц в минуту [citation:15], что эквивалентно месячной работе целого отдела [citation:4].

🧠 Выбор нейросети

Для решения задачи я использовал уже знакомую нам модель Qwen3-30b-a3b-instruct через OpenAI-совместимый API. Почему она:

🔧 Интеграция с почтовым ящиком

Агент подключается к почтовому ящику через IMAP и ищет письма с вложениями.

Аналогичный принцип используют корпоративные решения: агенты O2C отслеживают общие почтовые ящики финансового отдела (например, ar@company.com, billing@company.com) и обрабатывают входящие письма в реальном времени [citation:2].

📝 Пример скрипта для проверки почты

import imaplib
import email
from email.policy import default

def fetch_invoices_from_mailbox(host, user, password):
    mail = imaplib.IMAP4_SSL(host)
    mail.login(user, password)
    mail.select('inbox')

    status, messages = mail.search(None, 'UNSEEN')
    if status != 'OK':
        return []

    invoices = []
    for msg_id in messages[0].split():
        _, data = mail.fetch(msg_id, '(RFC822)')
        raw = data[0][1]
        msg = email.message_from_bytes(raw, policy=default)

        for part in msg.walk():
            if part.get_content_maintype() == 'multipart':
                continue
            if part.get_content_disposition() is None:
                continue

            filename = part.get_filename()
            if filename and (filename.endswith('.pdf') or filename.endswith(('.jpg', '.jpeg', '.png'))):
                content = part.get_payload(decode=True)
                invoices.append({
                    'from': msg['From'],
                    'subject': msg['Subject'],
                    'filename': filename,
                    'content': content,
                    'date': msg['Date']
                })

    mail.close()
    mail.logout()
    return invoices

📊 Структурированный вывод для 1С

Ключевая фишка — вызов инструментов (function calling). Модель возвращает строгий JSON, который можно сразу передавать в 1С через API.

📝 Инструмент для генерации JSON

{
  "type": "function",
  "function": {
    "name": "save_invoice_to_1c",
    "description": "Создает JSON для загрузки счета-фактуры в 1С",
    "parameters": {
      "type": "object",
      "properties": {
        "vendor": {
          "type": "object",
          "properties": {
            "name": {"type": "string", "description": "Название контрагента"},
            "inn": {"type": "string", "description": "ИНН контрагента"},
            "kpp": {"type": "string", "description": "КПП контрагента"}
          }
        },
        "invoice": {
          "type": "object",
          "properties": {
            "number": {"type": "string", "description": "Номер счета-фактуры"},
            "date": {"type": "string", "description": "Дата счета-фактуры (YYYY-MM-DD)"},
            "total": {"type": "number", "description": "Итоговая сумма"},
            "nds": {"type": "number", "description": "Сумма НДС"},
            "items": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "name": {"type": "string", "description": "Наименование товара"},
                  "quantity": {"type": "number", "description": "Количество"},
                  "price": {"type": "number", "description": "Цена за единицу"},
                  "total": {"type": "number", "description": "Сумма по позиции"}
                }
              }
            }
          }
        }
      },
      "required": ["vendor", "invoice"]
    }
  }
}

📝 Пример ответа нейросети (JSON для 1С)

{
  "vendor": {
    "name": "ООО Техно-Плюс",
    "inn": "7708123456",
    "kpp": "770801001"
  },
  "invoice": {
    "number": "СФ-2026-0042",
    "date": "2026-07-20",
    "total": 124580.00,
    "nds": 20763.33,
    "items": [
      {"name": "Системный блок", "quantity": 3, "price": 28500.00, "total": 85500.00},
      {"name": "Монитор 27\"", "quantity": 2, "price": 19540.00, "total": 39080.00}
    ]
  }
}

🚀 Запуск конвейера

1. Загрузка модели

Используем визуально-языковую модель qwen3-vl:30b-a3b-instruct [citation:1]. Она умеет распознавать как текстовые PDF, так и сканы документов [citation:5].

ollama pull qwen3-vl:30b-a3b-instruct

Qwen3-VL поддерживает работу с изображениями через Ollama, начиная с версии 0.12.7 [citation:1][citation:9].

2. Сборка конвейера (Python)

import base64
import json
from ollama import chat  # библиотека для работы с Ollama

def process_invoice(file_content, filename):
    # Кодируем файл в base64 для передачи в модель
    b64 = base64.b64encode(file_content).decode('utf-8')

    response = chat(
        model='qwen3-vl:30b-a3b-instruct',
        messages=[{
            'role': 'user',
            'content': 'Извлеки данные из счета-фактуры. Верни JSON с полями: vendor (name, inn, kpp), invoice (number, date, total, nds, items).',
            'images': [b64]  # передаём изображение или скан
        }]
    )

    # Парсим ответ модели в JSON
    return json.loads(response.message.content)

# Основной цикл
for invoice in fetch_invoices_from_mailbox('imap.yandex.ru', 'user', 'pass'):
    result = process_invoice(invoice['content'], invoice['filename'])
    if result:
        print(json.dumps(result, indent=2, ensure_ascii=False))
        # Отправляем JSON в 1С через API
        # requests.post('http://1c-server/hs/Invoice', json=result)

⚡ Производительность

На сервере с CPU (60 ГБ RAM) модель показывает:


📌 Заключение

Мы построили полностью локального AI-агента, который:

Это не просто концепция — аналогичные решения уже внедряются в российских компаниях. Например, Smart Engines разработала ИИ-агента, который за час выполняет месячную работу 10 бухгалтеров [citation:15].

✅ Итог: Вы можете собрать такого агента за вечер, используя открытые инструменты. Экономия времени бухгалтеров — сотни часов в месяц. Данные — под вашим полным контролем.
👍 Оцените статью
Всего голосов: 0



Категории:

Категории

Комментарии

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

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

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

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

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