Галоўная / Артыкулы

Пайплайны Docling: стварэнне пайплайнаў дадзэнняў RAG на рэвэрсе антрапрэнерскага рангу

Як docling-pipelines заменяе нестабільныя скрыпты на базе клею на складныя аператары і потокі JSON: прыем дадзей, выкарыстоўванне дадзей, контроль якосці, імбеддынгі і сховышча вектараў.

Выдавец: REACTAPP.TOP15 хв чытання3498 слоў

Крыніцы: Introducing Docling Pipelines: Building Enterprise-Grade RAG Data Pipelines

Дзе пачынаеся проблема з кодам

Уявіце сабраны драйв, які мае 10 000 файлаў PDF, сайт SharePoint, заполнены файламі Word, а таксама накопічаныя запісы тэлефонных размов з кліентамі. Команда, якая працуе над продуктам, хочаць, каб усе гэта было збераганае ў базе дадзеных у вектарнай форме, з можлівасцю пошуку і роздзелення на часткі, пры чым персональныя даны мусяць быць адчыстаны, а дублікаты — усунуты.

Звычны інжынерны спосаб рашэння — гэта скрыпт, а потым ўжо другі скрыпт. Да гэтага прыўлекаюцца калькі бібліятэкаў, нотбук Pandas спаўяючы ўсё гэта разам, а задача cron запускае весь працэс кожную ночь, і ўсё гэта стае готавым. Гэта працуе, прынаймні на час.

Чыры месцы пасля, хтось спытаецца, чаму не хачуць новыя дакументы. След занікае пасля змены схемы ў аднай з століц, і скрыпт тых радоў проста адхіліў. Ніхто гэтага не бачыў, бо нічога не было відна. Пасля выправлення прыходзіць паўтарны запуск, і тады усвядомляецца, што няма запіса пра тые дакументы, якія ужо былі апрацаваны, таму всі 10 000 дакументаў зноў праходзяць апрацоўку.

Гэта тыпавая доля «склеючага элемента» пайплайна дакументаў. Ён пачынаецца проста і паступова, а потым раптам паслабляецца. Да яго дадаюць паўтарныя спробы, фільтрацыя якосці прыходзіць як наступна мера, а сочыць за залежнасцямі між крокамі няма, таму успех залежыць толькі ад таго, чырскрыпты запускаюцца у правым парадку. Інкрэментальныя абнаўленні ўскладненыя без стабільнай ідэнтыфікаціі дакументаў. У выніку застаёцца заплутанасць, якую можа расшыфраваць толькі яе создаталі, але нават ён ужэ не ўпевнены.

Што такое docling-пайплайны

Docling-pipelines — гэта модульная, апаратным з’явамі заснованая парадыгма для апрацоўкі дакументаў, прызначаная для стварэння цэлых каналаў апрацоўкі дадзенаў RAG. Яе дзеянне распрастраńяецца на весь жыцёвы цыкл: пачынаючы з прыёму дадзенаў з локальных або хмарных выкананняў, далей — выкарыстоўванняе тэксту і выяўленне ентытаў, фільтрацыя якосці, разбіўка на часткі і стварэнне вкладанняў, і заканчываючы запісам у базу дадзенаў вектараў. Гэта стандартны пат прабірання, і большасць каналаў у працэсе вырабоцтва ўскладненыя версіі гэтага пату.

Яго можна інсталаваць як звычайны пакет Python:

bash
pip install docling-pipelines

Ён працюе там, дзе працюе Python. Для базовага выкарыстоўвання ёму не трэба зовнішней інфраструктуры: ні Kafka, ні кластэру Spark, нічога, што трэба насталяваць. Пайплайн опісваецца у файле JSON, CLI нацэліваецца на гэты файл, і запускаецца выконанне.

Існуе тры спосабы выкарыстоўвання. CLI падходзіць для ексклюзыўных запускаў і локальнага развіцця. Бібліятэка на Python, якая базуецца на DocpipeFlowManager, падходзіць для запуску пайплайнаў з коду аплікацыі чыста з блокнэтаў. REST API прызначаны для пайплайнаў, якія працуюць як спяльная служба, якую выкарыстоўваюць калькі команд. Усе тры спосабы будуць рассмотраны ніжэй.

Праект ў фармаце адкрытага кода, а яго першая версія, v0.1.0, выйшла у ліпені 2025 года.

Асновная ідэя: аператары і праймы

Кожны, хто новы ў гэтым фрэймворку, павінен пасвятыць як максымум часу самэй гэтай частцы, адколі рэшта стане зрозумелым пасля гэтага.

Аператар — гэта базовая едыніца. Аператар — гэта клас у Python, які прыймае таблыцу дакументаў і вяртае таблыцу, можа, пасля ператворэння. Кожная можнасць у фрэймворку — будзь то прыем дакументаў, выкарыстоўванне інфармацыі, выявленне мовы, разбіўка на часткі чы ўключэнне дадзеных — являе сабою аператар.

Завяршанні ўсьмохаюцца:

  • short_name: строка, якую JSON выкарыстоўвае для пазначэння аператара
  • transform(table): прыймае pa.Table і вяртае спіс таблыцаў плюс слоўнік метададзэў
  • get_metadata(): @staticmethod, які вяртае метададзеі аператара, каб яго можна было знайсці
  • get_required_features(): паказвае, якія столбцы патрэбны аператару для вхідных дадзеных
  • validate(): неабавязковы элемент, які пераканальвае конфігурацыю пад час запуску

Мінімальны скелет выглядае так:

from docpipe.core.operators.abstract_operator import AbstractOperator, OperatorCategory
import pyarrow as pa

class MyOperator(AbstractOperator):
  short_name = "my_operator"
  category = OperatorCategory.Quality

  def __init__(self, config: dict) -> None:
    super().__init__(config)

  def transform(self, table: pa.Table) -> tuple[list[pa.Table], dict]:
    metadata = self.create_base_metadata(total_docs_count=len(table))
    # … process table …
    return [table], metadata

  @staticmethod
  def get_metadata() -> dict:
  return {"short_name": "my_operator", "description": "…"}

Адаптаваўчы гэтыя методы, мы прагтвараемы компонент першага класу, які можа саўместваць з кожным іншым аператарам у экасістэме.

Тэблы PyArrow несу даны. Кожнаму аператару даўаецца об’ект pa.Table і ён вяртае іншы такі ж об’ект. Гэта ўсвядомлена выбор, таму што столбчасты фармат PyArrow ёсць эфектываў і мае тыпаванне, і даны пераводзяцца межы стадыямі без копіювання. Неапранутыя строкі і слоўнікі Python ніколі не пераводзяцца межы этапамі.

Прыемны наследкам гэтага ёсць тое, што столбцы накапліваюцца па меры працэсу апрацоўкі даных. Функцыя Ingest дадае id, name, path і source; функцыя Extraction — content; функцыя Chunker — chunked_content, а функцыя Embeddings — embeddings. Калі рэкорд доходзіць да сховішча вектараў, ён мае цэлы запіс, уключаючы всі столбцы і метаданы, гатовыя да індэксавання.

Аператар касаецца толькі тых столбцоў, якія яго цікавяць, а ўсё інша праходзіць праз яго недаражана. Таму новы аператар можа быць дадзены ў будзь-ям месцы без змены яго суседзей.

Прыток — гэта DAG. Канвей знаходзіцца ў файле JSON. Кожны вузол адзначае type (короткая назва аператара), name, які ёсць унікальным у графе, блок config і спіс depends_on. Пад час запуску двайчык разв’язвае граф залежнасцяў і запускае вузлы па топалогічнам парадку, пры чым паралельныя галузі выконваюцца адразу.

Такім чынам структура канвею — гэта даны, а не код. Яе можна версіяваць, аналізаваць разніцы, статычна перакантроліваць і заменіць без змены якога-небудзь Python-кода. Параметр --validate выяўляе наявнасць нарушэнняў залежнасцяў, відсутныях столбцоў і памылак у налашчаннях пры перадачы хоць якога дакумента.

Чаму работае модэль. У практыцы выдзеляюця два прынтэжы.

Адны з іх — можлівасць складання. Аператар можа выконвацца пасля будзь-каго іншага, за ўмовы, што попераднія аператары створылі столбцы, якія ён перыявляе ў get_required_features(). Апаратная частка пераканальваецца в этам пад час запуску і паведамляе пра точныя відсутныя столбцы і вузел, які мяў бы іх задаць, ўсё гэта ўжо да пачатку выканання.

Другі прынтэж — можлівасць тэставання. Кожны аператар паводзіцца як чыстая функцыя ад адной таблыцы да іншай, таму яго можна тэставаць окрэма: створыць pa.Table з неабходнымі столбцамі, вызваць transform() і пераканальвацца ў выніку. Не трэба мок-об’ектаў, побачных эфектаў і жывога канвэю.

Экскурсія па аператарах

Існуе 22 вбудованыя аператары, разбітыя на пяць катэгорыяў. Гэта стыкавы аптак.

Узяць даны. IngestSource — ўсё, што трэба для збору даных, і ён падтрымлець як локальныя, так і хмарныя крыніцы. Для локальных паўтакоў вікорыстоўваецца падаўчык filesystem, а той жа вузол можа перэйсці на будзь-якога з восьміх хмарных падаўчыкаў (S3, IBM COS, SharePoint, OneDrive, Google Drive, Box, файлы CSV і веб-сторанкі) без жадных змян у працэсе. Ён выдае адну строчку на кожны файл, толькі з метаданымі, без самога контэнту. Крок выкарыстоўвання даных запошчае контэнт пазней, што дапамагае шыбкаа збіраць даны і эканоміць памяць, нават у вялікіх масштабах.

Выкарыстоўваць даны. Extract ператварае необработаныя файлы на структураваны тэкст. PDF, DOCX, HTML, адпраўкі, аудыо і відэа ператвараюцца ў фармат markdown за дапамогою Docling, як у рэжыме бібліятэкі (локальна, без зв’язку па сеці) так і праз Docling Serve у рэжыме API, што дапамагае пераказваць важкія задачы выкарыстоўвання даных на спецыяльную службу.

Экстракцыя элементаў ў даных ёсць необавязковай, і існуе трое прадаўцоў такіх апцыянаў: LiteLLM (які паўязвае з аднадзесятамі прадаўцоў модэляў), IBM watsonx.ai і метод экстракцыі на аднойчынных шаблонах ад Docling. Выбор залежыць ад можлівасцяў доступу да модэляў і ўскладненняў.

ACLOperator ўходзіць у стадыю экстракцыі. Ён выкалывае метаданы кантролю доступу з дакументаў і размешчае іх у аднойчынным столбцы, такім чынам сістэмы, якія працуюць далей, можу прымаць заходы безпекі на рэвэле дакументаў, не прабываючы зноў чытаць вучорашні файл.

Функцыональныя. У гэтай катэгорыі знаходзіцца логіка апаратнага комплексу: аператары, якія трансфармуюць, направляюць і перакашталтаваюць даны, а не прыбавляюць да іх новую інфармацыю.

ChunkerOperator дзельне роздзеляе выявлены тэкст на часткі, выкарыстоўваючы адну з трох стратэгій: простую (фіксаваны размер літэр, налаштовыяя перакрыцця), сэмантычную (з урахоўваннем зместу) або гібрыдную (частковае роздзеленне, пры яком утрымваецца структура дакумента). Ён таксама можа ствараць кіявкі для кожнай часткі за дапамою LLM, што дае можлівасць атрымваць болей шырокую інформацыю пад час пошуку.

EmbeddingsOperator стварае вектарныя кіявкі для кожнай часткі. Ён працуе з мадэлямі HuggingFace, якія запускаюцца локальна, з LiteLLM (больш чым 100 прадаўцоў хмарных сервісаў) і з IBM watsonx.ai; змена модэлі кіявак адбываецца за дапамою адной лініі ў файле flow JSON.

BranchingOperator — гэта тое месца, дзе прабэгі становяцца цікавымі. Ён дзельніць дакументы на адзінлічныя падтрубкі на адваротах значэнняў столбцоў, умовах у стылі SQL або метках класыфікацыі. Кожны падтрубак працуе самастойна і пазначаецца па імені ў depends_on за дапамою знака календара, напрыклад "depends_on": ["branch_node.branch_name"].

MergeOperator з’еднае падзельніцы прабэгоў знову ў адны, аднойчы складаючы радкі або з’еднаючы столбцы, ў залежнасці ад таго, чаго чакаюць наступныя аператары.

DocIdHashOperator вылучае дэтэрміністычны, стабільны хеш-ID з кантэнту кожнага дакумента. Гэты ID ўтварае аднойчыну для аднаковых дакументаў і служыць аднойчынай для іх апрацоўкі: той самы дакумент завжды атрымле той самы ID, незалежна ад таго, дзе і калі ён быў прыйманы.

EntityCurationOperator і NOOPOperator дапамагаюць завершыць гэты набор. Першыя адпрацоўваюць элементы пасля ўзьяць іх, а другія ўжо ўсё толькі перадаюць даны, чым спрыяюць стварэнню схемы DAG.

Якасць. Аператары з гэтай групы паказваюць разлік межы простага наявнасці потока апрацоўкі дадзеных і наявнасці потока, які можна паверыць.

LanguageDetect выявляе мову дакумента за дапамою fastText і дадае століцю lang_name, якая можа выкорыстоўвацца для фільтрацыі, направлення дадзеных аб іх атрыбутавання.

ReadabilityOperator оцінюе кожны дакумент па пяць пунктаў ў чысці чытаемасці: Flesch reading ease, Flesch-Kincaid grade, Gunning Fog, Dale-Chall і колькасць складных слоў. Гэтыя показнікі ўтвараюць корыстныя сігналы для направлення дадзеных, напрыклад, для разліку тэхнічных дакументаў ад звычайнага контэнту пры выборы стратэгіі ўскладнення дакументаў.

PIIAndHAPAnnotator выкарыстоўвае адказ на базе LLM для выявлення і замаскавання персональных даных (адрэсы электронной пошты, номеры тэлефонаў, номеры соцыяльных страхавання, номеры картоц, банкавыя рахункі, IP-адрэсы), а таксама выражэнняя ненавісы, кабалы і вульгарнасці, пры чым для кожнай катэгорыі задаюцца адпаведныя прагрызы.

RedactionOperator апыходзіцца маскаваннем на аднойчынных шаблонах, калі фарматы знаёмы, такія як внутрашніі ідэнтыфікаторы, коды продуктав або ўсё, што можа падаць під патэрн regex.

EdedupOperator адключае абсалютныя дуплікаты ў сэтку дакументаў, выкарыстоўваючы столбец doc_id_hash для дэтэрміністычнага выканання гэтага задання.

SQLFilterOperator ўваходзіць у чысло недаабраных элементаў. Ён фільтруее рэядкі за дапамою умовы SQL WHERE на значэннях столбцоў, таму "docq_total_words > 100 AND lang_name = 'en'" стварае цэлысную сістэму контролю якосці без выкарыстоўвання Python. Разам з рэйтынгамі чытаемасці і адгукамі на мову ён дазваляе ствараць даскладныя маршрутызацыйныя схемы без напісання коду.

DocumentClassifierOperator сортавае дакументы па настаўляемых катэгорыях. DocQuality вычысляе паметры якосці для всего корпусу, а MLEnrichmentOperator дадае прыкладнія прогнозы ML як дапаможныя столбцы. Шырэйшая мысль, яку падтрымліваюць і іншыя опісы пайплайнаў, заключаецца у тым, што якосць дадзеных часта больш вплывае на рэзультаты RAG, чым выбор модэлю.

VectorDB і зберагчыцель. VectorDBOperator запісвае дакументы, роздзеленыя на часткі, у сховішча вектарных дакументаў, пры чым падтрымліваюцься OpenSearch і Milvus як бэкенды. Спадзяванні поль, настройкі індэксаў і нормалізацыя метадаў усе задаюцца ў JSON-файле потока.

DocumentSetOperator зберагае апрацаваныя табліцы ў набор дакументаў, падтрымваны DuckDB. Гэта дапамагае, калі апрацаваныя дакументы павінны быць доступныя для запытанняў без сховішча вектарных дакументаў, або калі патрэбны стойкія контрольныя пункты на этапы апрацоўкі.

StorageOutputOperator запісвае дакументы знову у зовнішніх месцах (S3, SharePoint, Google Drive або локальную файлавую сістэму) у апрацаванай або первісной форме, што падходзіць для схемы „апрацоўка і архіваўванне“.

Усе гэтыя элементы можна выкорыстоўваць у будзь-якой парады, як толькі будуць задовольненыя паказніцы вышэй у ланцоўцы, таму ланцоўка не прыкрэпленая да фіксаванага фармата.

Рэальны поток

Ёсць стандартны алгорытм шырокага запуску — цэлыя лінія працы ад прыёму дадзейнаў да хранення ў вектарных базах дадзэйнаў, якая выкарыстоўвае Ollama для стварэння вкладкі і OpenSearch для хранення:

{
  "flow_name": "complete-document-pipeline",
  "global_config": {
    "doc_column": "content",
    "storage": "in-memory"
  },
  "flow": [
    {
      "type": "ingest_source",
      "name": "ingest_local_folder",
      "config": {
        "provider": "filesystem",
        "connection_params": {
          "paths": [
            "./sample_documents"
          ]
        },
        "include_filter": "pdf,txt,docx"
      }
    },
    {
      "type": "extract_operator",
      "name": "extract_with_docling",
      "config": {
        "text_extraction": {
          "provider": "docling_library"
        },
        "entity_extraction": {
          "provider": "none"
        }
      },
      "depends_on": [
        "ingest_local_folder"
      ]
    },
    {
      "type": "chunker",
      "name": "simple_chunker",
      "config": {
        "chunk_type": "simple",
        "chunk_size": 512,
        "chunk_overlap": 50
      },
      "depends_on": [
        "extract_with_docling"
      ]
    },
    {
      "type": "embeddings",
      "name": "ollama_embeddings",
      "config": {
        "provider": "litellm",
        "provider_config": {
          "model_id": "openai/nomic-embed-text",
          "api_base": "http://localhost:11434/v1"
        },
        "embeddings_column": "embeddings"
      },
      "depends_on": [
        "simple_chunker"
      ]
    },
    {
      "type": "vectordb",
      "name": "opensearch_vector_store",
      "config": {
        "provider": "opensearch",
        "doc_id_column": "doc_id_hash",
        "embeddings_column": "embeddings",
        "provider_config": {
          "index_name": "sample-documents-index",
          "host": "localhost",
          "port": 9200
        }
      },
      "depends_on": [
        "ollama_embeddings"
      ]
    }
  ]
}

Пераходзім даўжынюючы па вузлах:

  • ingest_local_folder скануе падмет ./sample_documents на наявнасць файлаў PDF, тэксту і DOCX за дапамою ingest_source і яго прадаўца файлавой сістэмы. Кожны файл стае адной строчкай, якая мае ідэнтыфікатор, назву, шлях і месца выклікання. У гэты момент змест не чытаецца, таму крок вядзецца быстра: працоўнае програма шукае файлы, а не завантажае іх.
  • extract_with_docling берае гэтыя строчкі з метаданымі, чытае кожны файл за дапамою Docling і дадае столбець content, які мае выкараныя даныя у фармаце markdown. Самэль гэтага моменту PDF-файлы ператвараюцца на структураваны, можна выкарыстоўваць для запытанняў тэкст. Прадаўца docling_library працюе выключна внутры процэса, таму не патрэбныя жадныя зовнішнія службы.
  • simple_chunker дзельніцья столбець з контэнтам на часткі по 512 сімвалаў, пры чым межы частак перакрываюцца на 50 сімвалаў. Ён стварае chunked_content — структураваны спіс об’ектаў частак, кожны з якіх мае свой тэкст і пазычную пазіцыю ў вучэнай дасягліне.
  • ollama_embeddings адправляе кожную частку да локальна запускаемага модэлю nomic-embed-text і зберагае отрыманы вектары ў новым столбце embeddings. Гэта проста версія LiteLLM, прызначаная для Ollama; змена значэння model_id і api_base дазволяе перэнаправіць задачу да будзь-каго з падтрымваных LiteLLM падаўчыкаў (больш чым 100), без іншых змян.
  • opensearch_vector_store дадае або заменіць рэкорды з часткамі і вектарамі ў індэксе OpenSearch, выкорыстоўваючы doc_id_hash як первычны ключ. Таму паўтарны запуск ніколі не стварае дуплікатаў.
  • Калькольвае нешта структурныя моманты, якія заслуговаюць на увагу. depends_on — гэта ўсё, што трэба для наладкі: няма явнага перадачы дадзеных, няма рэгістраціі калебэкаў і няма спяльнага стану, адтуды што двыжок сам разрашвае граф і перадае дадзеныя. Блок global_config задае стандартныя настройкі, якія успадковуе кожны аператар. doc_column паказвае, якая століца мае мейнавы тэкст, а storage: "in-memory" зберагае проміжныя табелі ў RAM між крокамі, што падходзіць для большасці запускаў, і гэта можа быць замененае на спосаб для вялікіх набораў дадзеных.

    Усё калькольвае працюе за аднам камандам:

    docling-pipelines - flow-file pipeline.json
    

    Развірнутыя шаблоны

    Потокі не павінны быць лінейнымі ланцюгамі. У рэальных рэалізаціях павтараюцься тры шаблоны.

    Разгалужэнне і злічыненне. Разгалужэнне перадае дакументы да разных падпайплайнаў на адповіднасць налаштавальным крэтэрыям. Кожна галузь — гэта іменаваны выхід, які ноды, якія знаходзяцца ніжэй па потоку, апісваюць за дапамою знака крапкі ў атрыбуце depends_on. Галузь маршрутацыі, якая керуецца рэйтынгам чытаемасці, выглядае так:

    {
      "name": "quality_branching",
      "type": "branching",
      "config": {
        "branches": {
          "high_quality_branch": {
            "link_name": "High Quality Documents",
            "criteria_json": {
              "criteria_list": [
                {
                  "variable": "flesch_reading_ease",
                  "operator": ">",
                  "value": 60
                }
              ],
              "logical_operator": "AND"
            }
          },
          "low_quality_branch": {
            "link_name": "Low Quality Documents",
            "criteria_json": {
              "criteria_list": [
                {
                  "variable": "flesch_reading_ease",
                  "operator": "<=",
                  "value": 60
                }
              ],
              "logical_operator": "AND"
            }
          }
        }
      },
      "depends_on": [
        "readability"
      ]
    }
    

    Версія з высокай якосцю можа працаваць па шляху ML-падзеўкі пры прадаўленні, тады як версія з нізкай якосцю праходзіць праз іншы SQLFilterOperator, які адхоўляе дакументы з нульмаі словамі пры прадаўленні. Обе версіі потым падаюць у разныя індэксы OpenSearch, а MergeOperator можа знову з’едыніць этыя потокі, калі пазнейшая логіка захоча адзінны відказ.

    Маршрутацыя на адзынку якосці. Ідэя заключаецца у тым, каб спачатку запрацаваць дышэўскія аператары якосці, а пасля дазволіць SQLFilterOperator адхоўляць радкі пры якомнай дорогай стэпе LLM. Полны механізм маршрутацыі можа выглядаць так:

    lang_detect → ededup → doc_quality → readability → sql_filter → embeddings
    

    Умова sql_filter — гэта проста клазула SQL WHERE, выражаная у вачынках:

    {
      "criteria_list": [
        {
          "variable": "docq_total_words",
          "operator": ">",
          "value": 100
        },
        {
          "variable": "lang_name",
          "operator": "=",
          "value": "en"
        }
      ],
      "logical_operator": "AND"
    }
    

    Няма Python і няма спецыяльных аператараў, ўсё, што ёсць — гэта умова ў JSON, і кожны радок, які яе не выпанавляе, ніколі не доходзіць да вызову функцыі embedding.

    Багатаступенчатая адзначка інформацыі. Парадок класыфікацыя, направленне, выкарыстоўванне, адзначка інформацыі, зберагчыце часта вікорыстоўваецца ў практычнай працы. Дакументы можна спачатку класыфікацыяваць: тэхнічныя дакументы направляюцца да апарата для выкарыстоўвання інформацыі, настроюванага для тэхнічнага кантэнту, а дакументы з правіламі — да іншага. Кожны варыант дадае столбцы, спецыфічныя для свага тыпу, і стрэмы з’едынаюцца ўсё раней, чым вядзецца до чанкавання і embedding, такім чынам застаецца спяльны застатак для наступных крокаў.

    Кожны ступень дадае новыя столбцы, і аператары, якія працуюць далей, бачаць табліцу, якая стае ўсё багатшай. Нічыя з гэтых процэсаў не выкорыстоўвае спецыяльных рэжымаў чы флагаў. Гэта звычайныя аператары, якія з’едынаюцца разам, і гэта ёсць парадок модэлю аператараў.

    Тры спосабы ўпрацоўкі

    Эта праметра — не простае інструмента для працы з командным радкам і падходзіць для разных інжынерных сцэнарыёў.

    CLI. Гэта найшырэшы спосаб прыступіць да працюючага канвею:

    docling-pipelines - flow-file pipeline.json
    docling-pipelines - flow-file pipeline.json - validate # validate without running
    docling-pipelines - list-operators - verbose # discover all registered operators
    

    --validate дапамагае пад час стварэння прабегу: нарушэнні залежнасцяў, абсэнцыя неабходных столбцоў і бяглыя памылкі тыпу конфігурацыі выяўляюцца ўсе раней, чым ўсё гэта будзе прачытана або запісана. Выкананне яго ў CI перад выкладкай змян у прабегу — гарная прычынка.

    Бібліятэка Python. Калі пайплайны патрэбуюць запуску з коду аплікацыі:

    from docpipe.lib.docpipe_flow_manager import DocpipeFlowManager
    manager = DocpipeFlowManager(flow_file="pipeline.json")
    manager.execute()
    

    Гэта падходзіць для коду, які ўтрамбаваны ў большую аплікацыю, зошык нотатак або скрыпт керавання, які павінен кераваць самым цыклам выканання.

    REST API. Для работы як абслюютна дыягональная служба:

    uvicorn docpipe.api.main:app - host 0.0.0.0 - port 8000
    

    Сервер FastAPI адмініструе тры групы маршрутаў: /api/v1/flows для керавання прабегамі, /api/v1/job_runs для керавання запускамі заданняў, і /api/v1/operators для выявлення аператараў. Пользоватары аўтэнтыфікуюцца праз LDAP або OAuth2/OIDC за дапамогою токенаў JWT, а дакументацыя OpenAPI/Swagger генеруецца аўтаматычна на адрэсе /docs. этае ўсё — інтэрфейс для спільнай службы, якую вікорыстоўваюць калькі команд, якая запускаецца зовнішнімі запускамі, а таксама для запытанняў пра статус і рэзультаты.

    Розшырэнне за дапамогою спецыяльных аператараў

    Для стойкага вжывання ў рэальных арганізаціях гэта, можна сказаць, найважлівейшая частка дызайну.

    Контракт настолькі цікавы, што на яго рэалізацыю аператару трэба прыблізна 30 ліній коду. Клас на Python падходзіць, калі ён спадчынае ад AbstractOperator і рэалізуе методы transform(), get_metadata() і get_required_features(). Ён можа сумешчвацца з усіма вбудованымі аператарамі, прадстаўляецца ў выходных даных --list-operators, а у фармаце JSON яго пазначаюць за дапамогою short_name, так сама як і вбудованыя аператары.

    Рэгістрацыя ведзецца трыма способамі, якія залежаць ад этапы разработкі.

    Шлях у файлавай сістэме вікорыстоўваецца пад час разработкі. Неабходна настроіць зменную сераўіса на местную дырэктарыю:

    DOCPIPE_CUSTOM_OPERATORS=./my_operators docling-pipelines - flow-file pipeline.json
    

    Усе, што знаходзіцца ў тым каталозе, імпортуецца пад час запуску. Не трэба нічога інсталаваць, таму працэс відбуваецца быстра.

    Пакет Python прызначаны для распространення. Аператары можна публікаваць у віглядзе пакета pip з правільным точкай входу, інсталаваць яго ў той самы сераў, і ўсе яны самі сабе рэгіструюць. Самэ так аператары можаць даступаць да іншых команд без таго, каб хтось чырапаў у основны код.

    S3 URI — гэта варыянт для карпоратыўных праектаў. Неабходна настроіць DOCPIPE_CUSTOM_OPERATORS на удалены пакет аператараў, і фрэймворк за час працы яго завантажыць і рэгіструець. Гэта дазволяе централізавана кераваць аператарамі у розных розгортаннях: ўсе змены можна адкрыць у аднам месцы, а кожна версія пры наступным запуске ўзяць іх у сабе.

    Логіка, спецыязавучаная для падпрыемства, таму не паўтрапляе ў ядро. Прасэсары дакладнасці, выдлічвальнікі элементаў, спецыфічных для домэна, і прыналежныя модэлі ацэнкі можна упакаваць у вачыннікі, складаць іх з вбудоўаных элементаў у фармаце JSON і запускаць без змены самай рамкі.

    Аперацыйныя аспекты

    Справядлівы вопыт пра такі інструмент — чы ён ўжо хорашы прататып чы справжні інструмент прыменнага рангу. Дэталі пасля.

    Возможнасць аблікавання. Убудована падтрымка OpenTelemetry, і кожны запуск вачынніка стварае элемент аблікавання. Журналы ў фармаце структураванага JSON з корэляцыяй трэсаў, у кожнай лініі якіх ёсць trace_id і span_id. Гэта працюе з Jaeger, Grafana Tempo, Datadog і AWS X-Ray без якой-лібо настройкі з боку прыменні, а калі тэлеметрыя выключана, накладныя вітраты ўзятыя ў расчыт не ўрахоўваюцца.

    Інкрэментальная обработка. Сістэма выкалывання выкарыстоўвае дэтэрміністычны ID з DocIdHashOperator для стачырання таго, што ужо было обработана. Пры паўтарной запускі обрабатываюцься толькі новыя або змененыя дакументы, а той самы дакумент, паданы два разы, атрымвае той самы хэш і ўскаквае. Установка force_ingest: true у global_config перакрывае гэта і перэобрабатвае ўсё. Метаданы для інкрэментальных запускаў можа храніцца ў DuckDB (за замовчаннем), PostgreSQL або у файлавай сістэме.

    Безпека. ACLOperator адаптава метаданы прав належнасці як столбець для подальшага выканання правіл, а PIIAndHAPAnnotator знаходзіць і маскуюць чутлівы контэнт пры тым, калі ён яшчэ не дасягае сховішча вектараў. Секрэты ў настройках прабегу можу выйшаць з HashiCorp Vault: шлях у фармаце vault://path/to/secret, запісаны ў JSON, адначасова з выкананням програмы адначасова перакладваецца двайчыным механізам. Доступ да REST API захоўваецца за дапамогою LDAP і OAuth2/OIDC.

    Масштабаванне. Выконанне адбываецца у трох рэжымах, якія падыходзяць як для ноутбука, так і для распрацоўкі ў распадзеленай сітцы. За замовчаннем выкарыстоўваецца пул нітак у межах адноўы процэса, які ёсць быстрым, простым і не выкарыстоўвае додатковых залежнасцей. Пул процэса запускае аператарыў у окрэмых процэсах для задаў, якія выкарыстоўваюць моц CPU на аднай вузле. Для распадзеленых завад у працэсе выкарыстоўваецца пул работ Prefect, які запускае контэйнеры Docker, што дазволяе масштабаванне па горызонталі і цэнтралізаванае кераванне выконанням задаў. Настройкі мікрагрупавання керуюць выкарыстоўваннем памяці ў кожным рэжыме, што мае значэнне, калі большыя дакументы праходзяць праз працэс выкарыстоўвання LLM.

    Куды далей

    Праект размешчаны на GitHub пад адміністрацыяй IBM, а яго кераванне для швырага запуску ёсць найшырэйшы спосаб прыступіць да працы сістэмы. Сферы, якія заслугваюць на болей даклэглыя даследжэнні, включаюць шар выкарыстоўвання дадзэнняў (інтэграцыя з Docling, сістэмы VLM для дакументаў з вялікай колькасцю зображэнняў, апрантазія голасу і відэа), стварэнне спецыяльнага аператара з нестандартной логікай, начынна з першага апісання класа і да тэставання, рэгістрацыі і размешчэння, запуск Prefect з Docker для вялікіх об’ёмаў працы, а таксама можлівасці каратэрызацыі поль і шаблонаў схемы для VectorDBOperator у OpenSearch.

    Супаўязаныя матэрыялы

  • Прыем дакументаў з урахоўваннем якосці RAG: кераванне дакументамі па ўжыванасці — дэкларатыўны прайсупутак даклюнг-пайплайнаў, які ацэнюе мову, дуплікаты і ужыванасць за шкалай Флеша, а пасля адправляе дакументы ў два індэксы OpenSearch для пошуку калектараў і распрацоўшчыкаў.
  • Як даклюнг-пайплайны зберагаюць вектары дакументаў для RAG з адной стороны з OpenSearch, а з іншай — з Milvus — аналіз аператара vectordb у даклюнг-пайплайнах IBM: адаптары вектарных сховішчаў, якія можна падключыць, чыстка застарэлых частак, аўтадыектаваныя выміры і прайсупутакі, керованыя JSON.