Перейти к содержанию

AI extraction pipeline в n8n: как извлекать данные из писем, PDF, заявок и документов

Обновлено: 2026-05-29

Открыть мой план

Короткий ответ

AI extraction pipeline нужен, когда из неструктурированного текста нужно получить строгие поля: имя, email, ИНН, номер договора, сумму, дату, адрес, категорию, требования клиента или позиции заказа. Правильный pipeline не просто “просит модель найти данные”, а задаёт schema, нормализует документ, извлекает поля, проверяет типы, считает confidence, отправляет сомнительные случаи на human review и только потом записывает данные в CRM, таблицу или базу. Главная ошибка — сразу сохранять output LLM как правду без проверки, дедупликации и источника каждого поля.

Какие задачи закрывает extraction

Extraction полезен в процессах, где вход приходит в свободной форме: письма клиентов, заявки с сайта, PDF-счета, договоры, акты, коммерческие предложения, ответы поставщиков, резюме, обращения в поддержку, скриншоты с OCR, Telegram-сообщения. Вручную такие данные часто переносят в CRM, ERP или таблицы. AI позволяет снять рутину, но только если workflow не доверяет модели слепо.

Extraction не должен превращаться в генерацию. Если в документе нет даты договора, правильный результат — null, а не “примерная дата”. Если сумма встречается три раза и две суммы отличаются, pipeline должен вернуть конфликт. Если email найден в подписи пересланного письма, нужно понимать, относится ли он к клиенту или к предыдущему участнику переписки.

Схема production workflow

Типовой extraction workflow в n8n выглядит так:

  1. Trigger: Email Trigger, Webhook, Google Drive, Telegram, CRM event или ручная загрузка.
  2. File/Text loader: получить текст письма, вложение, OCR-текст или HTML.
  3. Normalizer: убрать подписи, quoted reply, HTML, мусор, повторяющиеся блоки.
  4. Document classifier: определить тип документа — invoice, contract, lead, support request.
  5. Schema selector: выбрать schema под тип документа.
  6. Information Extractor / LLM: извлечь поля по schema.
  7. Validation: типы, форматы, обязательные поля, диапазоны, checksum.
  8. Confidence scoring: оценить, какие поля надёжны, а какие сомнительны.
  9. Deduplication: проверить, нет ли уже такого клиента, заказа или документа.
  10. Human review: отправить сомнительные или критичные случаи оператору.
  11. Write step: записать данные в CRM/DB/Sheets.
  12. Audit log: сохранить источник, extracted JSON, ошибки и финальное решение.

Такой pipeline длиннее, чем один LLM node, но он спасает от типичных production-проблем: дублей, неверных сумм, потерянных вложений, hallucinated данных и ошибок записи.

Как проектировать schema

Schema должна отражать бизнес-решение, а не весь документ. Не пытайтесь извлечь “всё, что есть”. Извлекайте только поля, которые реально нужны downstream-process.

Пример schema для входящей заявки B2B:

{
  "type": "object",
  "required": ["company_name", "contact", "request_summary", "urgency"],
  "properties": {
    "company_name": { "type": ["string", "null"] },
    "contact": {
      "type": "object",
      "required": ["name", "email", "phone"],
      "properties": {
        "name": { "type": ["string", "null"] },
        "email": { "type": ["string", "null"] },
        "phone": { "type": ["string", "null"] }
      }
    },
    "request_summary": { "type": "string" },
    "budget_rub": { "type": ["number", "null"] },
    "deadline": { "type": ["string", "null"], "description": "ISO date if explicit" },
    "urgency": { "type": "string", "enum": ["low", "normal", "high", "critical"] },
    "evidence": {
      "type": "array",
      "items": { "type": "string" }
    }
  }
}

Поле evidence важно: оно заставляет систему хранить фрагменты текста, из которых извлечены значения. Если оператор спорит с результатом, он видит не только итоговый JSON, но и исходную цитату.

Нормализация входного текста

Большинство ошибок extraction появляются до LLM. Письма содержат подписи, пересылки, старые сообщения, юридические дисклеймеры, рекламные баннеры и HTML. PDF может дать кривой OCR. Таблица может потерять колонки. Поэтому перед извлечением нужен cleaning layer.

Что удалять:

  • подписи после “С уважением”;
  • quoted replies после “From:” или “-----Original Message-----”;
  • футеры рассылки;
  • HTML-теги и inline-стили;
  • повторяющиеся boilerplate-фразы;
  • файлы-вложения, которые не относятся к текущей задаче;
  • OCR-мусор, если confidence OCR низкий.

Пример грубой очистки письма:

const text = String($json.text || '')
  .replace(/<[^>]+>/g, ' ')
  .replace(/-----Original Message-----[\s\S]*/i, ' ')
  .replace(/On .* wrote:[\s\S]*/i, ' ')
  .replace(/С уважением,[\s\S]*/i, ' ')
  .replace(/\s+/g, ' ')
  .trim();

return [{ json: { ...$json, clean_text: text } }];

Для юридических документов лучше не удалять всё после “С уважением”, потому что это может быть часть шаблона. Cleaning rules должны зависеть от document_type.

Как выбирать поля для извлечения

Поля делятся на четыре группы:

Тип поля Пример Как проверять
Идентификаторы ИНН, order_id, contract_id regex, API lookup, uniqueness
Контакты email, phone, Telegram normalization, validation, dedupe
Финансы сумма, валюта, НДС numeric range, currency, evidence
Смысловые поля проблема, требования, категория confidence, human review, evals

Идентификаторы и финансы нельзя оставлять без строгой проверки. Смысловые поля допускают некоторую вариативность, но их нужно проверять на usefulness: summary должен быть кратким и не терять важные условия.

Confidence: как не доверять модели слепо

Многие модели могут вернуть confidence, но это не абсолютная истина. Лучше считать комбинированный score:

  • есть ли поле в исходном тексте;
  • прошёл ли формат regex;
  • совпал ли результат с внешним API;
  • есть ли конфликтующие значения;
  • насколько поле важно для downstream action;
  • есть ли evidence.

Пример scoring:

const r = $json.extracted;
let score = 1;
const issues = [];

if (!r.contact?.email) { score -= 0.2; issues.push('missing_email'); }
if (r.contact?.email && !/^\S+@\S+\.\S+$/.test(r.contact.email)) {
  score -= 0.4; issues.push('invalid_email');
}
if (r.budget_rub && r.budget_rub > 5000000) {
  score -= 0.2; issues.push('large_budget_review');
}
if (!r.evidence || r.evidence.length < 2) {
  score -= 0.2; issues.push('weak_evidence');
}

return [{ json: { ...$json, confidence_score: Math.max(0, score), review_issues: issues } }];

Если score ниже порога, не пишите данные автоматически. Создайте задачу на review.

Human review: когда обязателен

Human review нужен, если ошибка может стоить денег, нарушить договор, испортить клиентские данные или создать юридический риск. Не нужно отправлять человеку каждый простой lead, иначе автоматизация потеряет смысл. Делайте review по правилам.

Отправлять на review, если:

  • сумма больше лимита;
  • документ относится к договору/счёту/акту;
  • найдено несколько разных ИНН или email;
  • нет evidence для обязательного поля;
  • модель вернула low confidence;
  • downstream action — создание сделки, возврат, изменение реквизитов;
  • документ на неожиданном языке;
  • OCR confidence низкий.

В review-карточке оператор должен видеть: исходный фрагмент, extracted JSON, подсветку спорных полей, предлагаемое действие и кнопки approve/edit/reject.

Deduplication перед записью

Даже идеально извлечённые данные могут создать дубль. Перед записью в CRM проверьте существующие записи по email, phone, company_name, ИНН, domain, order_id. Для русских телефонов нормализуйте +7, 8, пробелы, скобки и дефисы. Для email приводите домен к lowercase.

Пример нормализации телефона:

function normalizePhone(v) {
  if (!v) return null;
  let digits = String(v).replace(/\D/g, '');
  if (digits.length === 11 && digits.startsWith('8')) digits = '7' + digits.slice(1);
  if (digits.length === 10) digits = '7' + digits;
  return digits.length === 11 ? '+' + digits : null;
}

return [{ json: { ...$json, phone_normalized: normalizePhone($json.extracted?.contact?.phone) } }];

Дедупликация должна быть отдельным шагом. Не просите LLM “решить, дубль ли это” без фактической проверки базы.

Ошибки extraction pipeline

Симптом Причина Что делать
Поля заполнены выдуманными значениями prompt не запрещает guessing требовать null + evidence
Даты в неправильном формате нет ISO-нормализации добавить date parser и timezone
Сумма без валюты schema не требует currency разделить amount и currency
CRM заполняется дублями нет dedupe step искать по email/phone/ИНН
Оператор не доверяет AI нет evidence показывать цитаты источника
Pipeline дорогой всё письмо отправляется в LLM cleaning + chunking + rule prefilter
Ошибка на таблицах OCR/парсер потерял структуру использовать специализированный parser или review

Тестирование перед запуском

Соберите test set из реальных документов. Не используйте только идеальные примеры. Нужны:

  • короткие письма;
  • длинные цепочки переписки;
  • документы с несколькими суммами;
  • PDF со сканом;
  • неполные заявки;
  • документы с ошибками клиента;
  • повторные заявки от того же клиента;
  • документы на русском и английском;
  • кейсы, где правильный ответ — null.

Метрики:

  • field accuracy;
  • exact match для id/email/phone;
  • tolerance для сумм;
  • rate of hallucinated fields;
  • human review rate;
  • duplicate creation rate;
  • time saved per document;
  • cost per document.

Если extraction экономит 5 минут, но создаёт 3% критичных ошибок, такой pipeline нельзя пускать без review.

Что логировать

Лог должен позволять ответить: какой документ пришёл, что модель извлекла, почему данные записаны, кто подтвердил спорные поля и где исходный evidence.

Минимум:

  • document_id;
  • source_channel;
  • document_type;
  • schema_version;
  • model;
  • extracted_json;
  • validation_errors;
  • confidence_score;
  • review_decision;
  • crm_record_id;
  • created_at.

Не храните секреты и лишние персональные данные в обычном execution log. Для чувствительных полей используйте masking.

Production checklist

  • [ ] Для каждого document_type есть schema.
  • [ ] Prompt запрещает guessing.
  • [ ] Каждое важное поле имеет evidence.
  • [ ] Есть validation layer.
  • [ ] Есть deduplication перед записью.
  • [ ] Есть human review для risky cases.
  • [ ] Есть test dataset.
  • [ ] Есть лог schema_version/model/output.
  • [ ] Есть retry/fallback для parser errors.
  • [ ] Есть privacy policy для документов с PII.