AI-автозаполнение форм из документов
Сценарий: клиент загружает паспорт → форма заявки заполняется автоматически. Или сотрудник фотографирует бумажный акт → данные уходят в ERP без ручного ввода. Это Document Understanding — более сложная задача, чем просто OCR: нужно не только распознать текст, но и понять структуру документа и смапировать поля на целевую форму.
Architecture Document-to-Form pipeline
from typing import Any
from dataclasses import dataclass
@dataclass
class FormField:
name: str # имя поля в целевой форме
value: Any # извлечённое значение
confidence: float # уверенность 0..1
source_location: str | None = None # откуда извлечено
class DocumentToFormPipeline:
"""
Пайплайн: документ → поля формы.
Шаги:
1. Классификация типа документа
2. OCR + layout analysis
3. NER/IE для извлечения полей
4. Маппинг на поля целевой формы
5. Валидация и нормализация
"""
def __init__(
self,
document_classifier, # модель классификации типа документа
extractors: dict, # {doc_type: extractor}
form_mapper: dict, # {doc_field: form_field} маппинг
validators: dict # {form_field: validator_fn}
):
self.classifier = document_classifier
self.extractors = extractors
self.form_mapper = form_mapper
self.validators = validators
def process(self, document_image) -> dict[str, FormField]:
# Шаг 1: определяем тип документа
doc_type = self.classifier.predict(document_image)
if doc_type not in self.extractors:
raise ValueError(f'Unsupported document type: {doc_type}')
# Шаг 2-3: извлечение полей
extractor = self.extractors[doc_type]
raw_fields = extractor.extract(document_image)
# Шаг 4: маппинг
form_fields = {}
mapping = self.form_mapper.get(doc_type, {})
for doc_field, value in raw_fields.items():
if doc_field in mapping:
form_field_name = mapping[doc_field]
form_fields[form_field_name] = FormField(
name=form_field_name,
value=value.get('text'),
confidence=value.get('confidence', 0.0),
source_location=doc_field
)
# Шаг 5: валидация
for field_name, field in form_fields.items():
if field_name in self.validators:
try:
field.value = self.validators[field_name](field.value)
except Exception as e:
field.confidence *= 0.5 # снижаем уверенность при ошибке валидации
return form_fields
LLM-подход для сложных форм
Для документов с нестандартной структурой или когда маппинг нетривиален — LLM с vision:
import anthropic
import base64
from pathlib import Path
def extract_form_fields_llm(
document_path: str,
form_schema: dict, # JSON Schema целевой формы
model: str = 'claude-opus-4-5'
) -> dict:
"""
Мультимодальный LLM как универсальный Document Understanding engine.
form_schema: {'field_name': {'type': 'str', 'description': '...', 'required': bool}}
"""
client = anthropic.Anthropic()
# Загружаем документ как base64
with open(document_path, 'rb') as f:
doc_b64 = base64.standard_b64encode(f.read()).decode()
ext = Path(document_path).suffix.lower()
media_type = {
'.jpg': 'image/jpeg', '.jpeg': 'image/jpeg',
'.png': 'image/png', '.pdf': 'application/pdf'
}.get(ext, 'image/jpeg')
# Формируем описание схемы формы
schema_desc = '\n'.join([
f'- {name}: {info["description"]} ({"обязательное" if info.get("required") else "опциональное"})'
for name, info in form_schema.items()
])
message = client.messages.create(
model=model,
max_tokens=2048,
messages=[{
'role': 'user',
'content': [
{
'type': 'image',
'source': {
'type': 'base64',
'media_type': media_type,
'data': doc_b64
}
},
{
'type': 'text',
'text': f"""Извлеки из документа следующие поля для заполнения формы:
{schema_desc}
Верни результат строго в формате JSON:
{{
"field_name": {{"value": "...", "confidence": 0.0-1.0, "not_found": false}},
...
}}
Если поле не найдено в документе, укажи "not_found": true.
Для confidence: 1.0 = точно уверен, 0.5 = сомневаюсь."""
}
]
}]
)
import json
try:
return json.loads(message.content[0].text)
except json.JSONDecodeError:
# Извлекаем JSON из текстового ответа
import re
match = re.search(r'\{.*\}', message.content[0].text, re.DOTALL)
return json.loads(match.group()) if match else {}
UI-компонент с confidence-подсветкой
Хорошая практика: показывать пользователю поля с confidence < 0.85 подсвеченными для ручной проверки.
def prepare_form_ui_state(
form_fields: dict,
confidence_threshold: float = 0.85
) -> dict:
"""
Подготовка состояния формы для UI:
- Поля с высокой уверенностью — автозаполнены
- Поля с низкой — помечены для проверки
- Обязательные не найденные — ошибка
"""
ui_state = {}
for field_name, field in form_fields.items():
status = 'autofilled'
if field.value is None:
status = 'not_found'
elif field.confidence < confidence_threshold:
status = 'needs_review'
ui_state[field_name] = {
'value': field.value,
'status': status,
'confidence': field.confidence,
'editable': status != 'autofilled' or True # всегда редактируемо
}
return ui_state
Сроки
| Задача | Срок |
|---|---|
| Автозаполнение из паспорта / 1–2 типов документов | 2–4 недели |
| Универсальная система (10+ типов, собственный маппинг) | 6–10 недель |
| Энтерпрайз-решение с LLM + LayoutLM + валидацией | 8–14 недель |







