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

Кераванне пайплайнаў Docling прачынам HTTP: ад наладкі проекту да індексаваных частак

Практычны ўрок па шагоўцы: як выкарыстоваць REST API Docling Pipelines — запуск сервера, адкрыцце оператараў, перакананне і запуск DAG для прыемы дадзеных, а таксама чытанне метрык пра яго выконанне.

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

Крыніцы: **A Hands-On Guide to the Docling Pipelines REST API**

Канвэртаванне папкі з файламі PDF і Word у пошукавыя вектарныя часткі зазвычай выкалывае патрэбу ў кодзе для выявлення, разбіўкі, уключэння і індексавання. Docling Pipelines аб’еднвае гэтыя этапы ў аператары за допамогай REST-сервера на базе FastAPI, тады будь-які кліент, такі як сервіс Node.js або інтэрфейс адміністрацыі, можа ствараць модульныя DAG-пайплайны, пераканаліваць іх і запускать асінхронныя задання через HTTP. У гэтым кераванні сервер запускаецца за допамогай Ollama і OpenSearch, а пасля — працюецца з цэлым жыццёвым циклам запита, ад стварэння проекту да чытання статыстыкі запуску кожнага вузла.

Падготовка супорных сервісаў

Сервер керуе работай, але процес уключэння даных і ўтриманне іх відбываецца ў іншым месцы: тут Ollama для модэляў і OpenSearch як сховішча вектарных даных. Спачатку запускайце іх.

Спадзейны шлях — это QUICKSTART.md проекта, які за кальколька хвілі ствароўвае скрыпты для Ollama, базы векторных дадзеных і неабходных контейнераў. Агенты для кодавання на базе AI, такія як Cursor, Claude Code чыста Copilot, таксама можуць выконваць настройку і перакананне; у будзь-якім случае, трэба паказаць, што кожны сервіс працуе.

Выбор базы векторных дадзеных

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

Запуск сервера API

Актывацыюйце віртуальную среду, дзе інсталаваны пакет, і запускайце супакованный каманду:

source .venv/bin/activate
docling-pipelines-api

Для гарячага перазнарабатвання падчас разработкі крануце аплікацыю безпосередня через uvicorn, прыўязаваючы яе да всіх інтерфейсоў на порту 8080:

uvicorn docpipe.api.main:app --reload --host 0.0.0.0 --port 8080

Потым ў наявнасці чатыры URL:

  • http://localhost:8080/health для пераканання ў стане аплікацыі;
  • http://localhost:8080/api/v1/docs для інтэрактыўнага інтерфейсу Swagger UI;
  • http://localhost:8080/api/v1/redoc для дакументацыі ReDoc;
  • http://localhost:8080/api/v1/openapi.json для сырога шэмы OpenAPI.

У TypeScript можна падаць дакумент OpenAPI да генератора кліента замест таго, каб рукамі пісаць типы запитаў.

Зменныя сераўіса, якія вплываюць на сервер

Установіце іх пры запуску, каб налаштаваць працэс аплікацыі:

  • DS_LOG_LEVEL задае ступень деталізавання лог-запісаў. По замовчанню ён становіць INFO, а можа прыймаць значэння DEBUG, INFO, WARNING або ERROR.
  • DOCPIPE_STORAGE_BACKEND выбірае месца зберагчыка метаданых: duckdb (по замовчанню, локальна база) або postgres.
  • CORS_ORIGINS пераказуе список адрес, якім разрашаецца выклікаць API з браузернага фронт-энда. По замовчанню ён становіць http://localhost:3000.
  • OLLAMA_HOST наказвае прыстроям для імбеддінгу та обробкі LLM працаваць з Ollama. По замовчанню ён становіць http://localhost:11434; зменіце яго, якщо Ollama працуе на іншым порту або на іншай машыне.

Дакладна інформацыя пра канцэнтры ў Swagger UI

Ачыніце http://localhost:8080/api/v1/docs у браузеры; для роботы на месцы логін не патрэбен. Раскройце адпаведны эндпаўт, нажміце Try it out, і адправьце наведзеныя нижэй даны без неабходнасці пісаць кліента.

Жыцёвы цикл запиту ў кароткай форме

Полны цикл включае семь вызоў, ад стварэння проекту да падсумку його выканання:

1. Create Project ──▶ 2. Discover Operators ──▶ 3. Validate Flow ──▶ 4. Create Flow ──▶ 5. Execute Run ──▶ 6. Fetch Logs ──▶ 7. Summary

Крок 1: стварыць проект

Проекты групуюць адпаведныя процесы і фіксуюць ўзнятыя статыстыкі ўсіх выкананняў. Створыце проект за дапамою POST /api/v1/projects:

{
  "name": "Sample Docling Pipeline Project",
  "description": "Flows for processing invoice documents",
  "tags": ["finance", "pdf", "q3"]
}

Поле:

  • name — гэта обавязковая строка дыялектаў 1-255, якая унікальна ідентыфікуе проект.
  • description — необавязкова короткая ахвалка прызначэння проекту.
  • tags — необавязковы масіў строкаў для класыфікацыі.

У разы ўспеху вяртаецца 201 Created з суставленым project_id, flow_count равным нулю, пазначкамі часу і href, які вядуць да ресурса:

{
  "project_id": "84c718b2-5f36-4d2c-9a4f-561234bcde01",
  "name": "Sample Docling Pipeline Project",
  "description": "Flows for processing invoice documents",
  "tags": ["finance", "pdf", "q3"],
  "flow_count": 0,
  "created_on": "2026-09-07T10:00:00Z",
  "modified_on": "2026-09-07T10:00:00Z",
  "href": "/api/v1/projects/84c718b2-5f36-4d2c-9a4f-561234bcde01"
}

Шаг 2: выявленне аператараў і модэляў

У замяну на спадчыцтво імен і опцый аператараў, запытайце сервер.

Метаданы аператараў

GET /api/v1/operators/metadata вяртае дакладную схему для кожнага аператара, якая включае 20+ вбудованых аператараў плюс будзь-якія зовнішнія аператары, якія вы зарэгістравалі. Параметр запыту internal_features па значчыцы за замовчаннем ўстановліваецца як false.

У кожнай заносцы features описвае колонкі, які генеруе аператар, required_features — колонкі, які ён патрэбуе ад вышэйшага роўня, а attributes — яго параметры з типамі і значэннямі за значычным становішчам. Аператар extract выдае content і doc_id_hash; аператар chunker патрэбуе content:

{
  "extract_operator": {
    "label": "Extract Operator",
    "category": "Extract",
    "description": "Extracts structured content from documents using Docling",
    "features": {
      "content": {
        "name": "Document Content",
        "description": "The markdown content extracted from the document",
        "type": "string",
        "required": true
      },
      "doc_id_hash": {
        "name": "Hash ID",
        "description": "Hash ID of the document row",
        "type": "string",
        "required": true
      }
    },
    "required_features": [],
    "attributes": {
      "text_extraction_mode": {
        "type": "string",
        "description": "Text extraction strategy (docling_library or docling_serve)",
        "required": true,
        "default": "docling_library"
      },
      "entity_extraction_mode": {
        "type": "string",
        "description": "Entity extraction strategy (litellm, watsonx, docling, or none)",
        "required": false,
        "default": "none"
      }
    }
  },
  "chunker": {
    "label": "Chunker Operator",
    "category": "Functional",
    "description": "Splits documents into smaller semantic or fixed-size passages",
    "features": {
      "content": { "name": "Chunk Content", "type": "string", "required": true }
    },
    "required_features": ["content"],
    "attributes": {
      "chunker_type": {
        "type": "string",
        "description": "Chunking strategy (fixed, semantic, or hybrid)",
        "required": false,
        "default": "hybrid"
      }
    }
  }
}

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

Модэлі прадаўцоў

GET /api/v1/providers/{provider}/models запытае жывога прадаўцу (‹ollama› або ‹watsonx›), таму відсутны модэль або неправильна запісаны таг будуць выявлены ўжо до запуску:

curl -s http://localhost:8080/api/v1/providers/ollama/models | jq

Кожны модэль паказаны з іменем, тагам, часам модыфікацыі і розмерам у байтах:

{
  "provider": "ollama",
  "models": [
    {
      "name": "nomic-embed-text:latest",
      "model": "nomic-embed-text:latest",
      "modified_at": "2026-08-15T12:00:00Z",
      "size": 274302450
    },
    {
      "name": "llama3:8b",
      "model": "llama3:8b",
      "modified_at": "2026-08-20T14:30:00Z",
      "size": 4661224676
    }
  ]
}

Шаг 3: пераканацца ў правільнасці прабегу пры запісе

POST /api/v1/validation/validate_flow пераглядае структуру DAG на наявнасць некоректных параметраў і абрываючыхся залежнасцяў без яе запісу чы рэалізаціі.

global_config задае параметры для всей роботы (колонка дакумента, локальная експансія, запам’ятовуванне ў памяці, прымусовая переробка дакументаў). flow паказвае вузлы, кожны з якіх мае type, унікальны name, config і масэвы depends_on, які паказвае вузлы, на якія ён залежыць. Працэс обробкі:

  • зчитвае файлы PDF, TXT і DOCX з каталога ./sample_documents у локальной файловай системе;
  • выдзяляе текст з гэтых файлоў за дапамогою бібліятэкі Docling і прыглашае выдзяляванне ентытаў;
  • дробіць контэнт на фрагменты по 512 елементаў з перакрыцчам у 50 елементаў;
  • вбудоввае кожны фрагмент через LiteLLM, паказваючы на адпаведны канцэнтр OpenAI, сумесны з Ollama, з викорыстаннем моделі nomic-embed-text;
  • Запісвае вектары ў індэкс OpenSearch за дапамою двіжка FAISS, алгорытму HNSW і відстані L2 з 768 выразамі, праўячы атрыбуты пайплайну на поля індэкса через feature_mappings.
  • {
      "flow_name": "complete-document-pipeline",
      "global_config": {
        "doc_column": "content",
        "disable_validation": true,
        "force_ingest": true,
        "storage": "in-memory",
        "execute_type": "local"
      },
      "flow": [
        {
          "type": "ingest_source",
          "name": "ingest_source_filesystem",
          "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",
              "doc_column": "content"
            },
            "entity_extraction": {
              "provider": "none"
            }
          },
          "depends_on": ["ingest_source_filesystem"]
        },
        {
          "type": "chunker",
          "name": "simple_chunker",
          "config": {
            "chunk_type": "simple",
            "chunk_size": 512,
            "chunk_overlap": 50,
            "retain_original_content": false
          },
          "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",
              "api_key": "<ollama-api-key>"
            },
            "embeddings_column": "embeddings",
            "overlap_ratio": 0.1
          },
          "depends_on": ["simple_chunker"]
        },
        {
          "type": "vectordb",
          "name": "opensearch_vector_store",
          "config": {
            "provider": "opensearch",
            "doc_id_column": "doc_id_hash",
            "embeddings_column": "embeddings",
            "vector_dimension": 768,
            "create_index": true,
            "provider_config": {
              "index_name": "sample-documents-index",
              "host": "localhost",
              "port": 9200,
              "username": "${OPENSEARCH_USERNAME}",
              "password": "${OPENSEARCH_PASSWORD}",
              "use_ssl": false,
              "verify_certs": false,
              "batch_size": 100,
              "engine": "faiss",
              "algorithm": "hnsw",
              "space_type": "l2"
            },
            "feature_mappings": [
              { "feature_name": "doc_id_hash",  "mapped_column_name": "pk" },
              { "feature_name": "content",      "mapped_column_name": "text" },
              { "feature_name": "name",         "mapped_column_name": "doc_name" },
              { "feature_name": "path",         "mapped_column_name": "file_path" },
              { "feature_name": "embeddings",   "mapped_column_name": "vector_embeddings" },
              { "feature_name": "chunk_id",     "mapped_column_name": "chunk_id" },
              { "feature_name": "chunk_index",  "mapped_column_name": "chunk_index" }
            ]
          },
          "depends_on": ["ollama_embeddings"]
        }
      ]
    }
    

    Дзеяныя деталі маюць значэнне. vector_dimension (768) павінен адпавядаць розмеру выходных дадзенаў моделі эмбеддынгу. Кранцы автанаціі паказваюцца як заместнікі у стыле ${OPENSEARCH_USERNAME} і <ollama-api-key>; справжні секрэты трэба зберагаць у зменных сераўісу або спецыяльных сховішчах секрэтнаў, а не ў збераганых потоках. Выключэнне use_ssl і verify_certs дапускаецца локальна, але не на спільнай кластэрной сетцы. Кроме таго, чанкер выкарыстоўвае chunk_type: "simple", тады як у дакументах метаданых chunker_type пазначаецца як fixed, semantic або hybrid; пераканайцеся, што ваш сервер вярнэ правільныя даны.

    Правільна дэфініцыя вяртае 200 OK, is_valid: true, порожніе errors і warnings, а таксама колькість вузлаў:

    {
      "is_valid": true,
      "errors": [],
      "warnings": [],
      "node_count": 5
    }
    

    Крок 4: рэўіструйце поток

    Зберагуйте падтверджаную дэфініцыю за дапамою POST /api/v1/flows (is_elyra за замовчаннем равнае false). У тэле знаходзіцца той самы DAG плюс апісанне і тагі:

    {
      "flow_name": "complete-document-pipeline",
      "description": "Complete document processing pipeline: Ingest -> Extract -> Chunk -> Embed -> Store in OpenSearch",
      "tags": ["docling", "embeddings", "opensearch"],
    
      "global_config": {
        "doc_column": "content",
        "disable_validation": true,
        "force_ingest": true,
        "storage": "in-memory",
        "execute_type": "local"
      },
      "flow": [
        {
          "type": "ingest_source",
          "name": "ingest_source_filesystem",
          "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", "doc_column": "content" },
            "entity_extraction": { "provider": "none" }
          },
          "depends_on": ["ingest_source_filesystem"]
        },
        {
          "type": "chunker",
          "name": "simple_chunker",
          "config": {
            "chunk_type": "simple",
            "chunk_size": 512,
            "chunk_overlap": 50,
            "retain_original_content": false
          },
          "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",
              "api_key": "<ollama-api-key>"
            },
            "embeddings_column": "embeddings",
            "overlap_ratio": 0.1
          },
          "depends_on": ["simple_chunker"]
        },
        {
          "type": "vectordb",
          "name": "opensearch_vector_store",
          "config": {
            "provider": "opensearch",
            "doc_id_column": "doc_id_hash",
            "embeddings_column": "embeddings",
            "vector_dimension": 768,
            "create_index": true,
            "provider_config": {
              "index_name": "sample-documents-index",
              "host": "localhost",
              "port": 9200,
              "username": "${OPENSEARCH_USERNAME}",
              "password": "${OPENSEARCH_PASSWORD}",
              "use_ssl": false,
              "verify_certs": false,
              "batch_size": 100,
              "engine": "faiss",
              "algorithm": "hnsw",
              "space_type": "l2"
            },
            "feature_mappings": [
              { "feature_name": "doc_id_hash", "mapped_column_name": "pk" },
              { "feature_name": "content", "mapped_column_name": "text" },
              { "feature_name": "name", "mapped_column_name": "doc_name" },
              { "feature_name": "path", "mapped_column_name": "file_path" },
              { "feature_name": "embeddings", "mapped_column_name": "vector_embeddings" },
              { "feature_name": "chunk_id", "mapped_column_name": "chunk_id" },
              { "feature_name": "chunk_index", "mapped_column_name": "chunk_index" }
            ]
          },
          "depends_on": ["ollama_embeddings"]
        }
      ]
    }
    

    Тут важлівыя два глобальныя настройкі:

    • execute_type: "local" запускае пайплайн усередзіне процэса сервера.
    • force_ingest: true перапрацоўвае ранейша запрацаваныя дакументы: корыстна пад час ітерацый, але марнатрацыя ресурсоў у стацыонарным стане.

    Адпаведнае адказаў — 201 Created з новым flow_id і зберажанымі настройкамі:

    {
      "flow_id": "e2c31e42-7719-482a-a53d-2490b830d971",
      "flow_name": "complete-document-pipeline",
      "description": "Complete document processing pipeline: Ingest -> Extract -> Chunk -> Embed -> Store in OpenSearch",
      "tags": ["docling", "embeddings", "opensearch"],
      "global_config": {
        "doc_column": "content",
        "disable_validation": true,
        "force_ingest": true,
        "storage": "in-memory",
        "execute_type": "local"
      },
      "created_on": "2026-09-07T10:05:00Z",
      "modified_on": "2026-09-07T10:05:00Z"
    }
    

    Крок 5: запускайце рэжым

    Выкананні ўрадзейваюць асінхронна. POST /api/v1/job_runs прыме як ідэнтыфікатор, так і назву праблемы:

    {
      "flow_id": "e2c31e42-7719-482a-a53d-2490b830d971",
      "flow_name": "complete-document-pipeline"
    }
    

    Яно адразу вяртае код 201 Created разам з job_run_id і статусам Starting, тады калі робота продовжваецца на фоне:

    {
      "job_run_id": "99ecd646-bb8e-494a-a0c5-86b40c1d4f90",
      "status": "Starting",
      "message": "Job run created successfully"
    }
    

    Шаг 6: перакантролюванне статусу, показнікаў і логаў

    Працаваць з GET /api/v1/job_runs/{job_run_id}, дадаўшы параметр include_logs=true для логаў кожнага вузла, пакуль статус не стане тэрмінальным (напрыклад, Completed), жадаўна з адным большым інтэрвалам часу.

    Дзейнавальны рэспанс 200 OK містыць node_sequence (парад выканання), job_stats (каляндары для всіх вузлаў, а таксама node_stats для кожнага вузла і batch_node_stats для кожной пачкі) і масэвы node_metadata. У даным прыкладзе два текстовыя файлы пройшлі через усе пяць вузлаў, чыгунуўшы чатыры фрагменты, якія ўсе індексаваны:

    {
      "node_sequence": [
        "ca564648-1715-45c3-be67-7c654344a99c",
        "49f285b0-3afa-40eb-8111-3ec6a57c4904",
        "447e0511-5125-4ffb-8396-edb972976080",
        "2636f8b6-ef9a-4805-bda0-9fcaa853e16a",
        "0c773955-f1c7-4b68-b157-38966382cb9c"
      ],
      "job_stats": {
        "job_id": "9be63026-c08c-49c1-ba12-600838f3b22f",
        "job_run_id": "13bd4219-7947-4977-bc69-1ae6628567d3",
        "status": "Completed",
        "message": "",
        "start_time": 1788943163,
        "end_time": 1788943166,
        "duration": 3,
        "heartbeat_timestamp": 0,
        "total_docs": 2,
        "processed_docs": 2,
        "completed_docs": 2,
        "failed_docs": 0,
        "skipped_docs": 0,
        "deleted_doc_count": 0,
        "total_pages_processed": 2,
        "page_type_stats": {
          "txt": 2
        },
        "execution_time": 0,
        "orchestrator": "Python",
        "container_kind": null,
        "container_id": "",
        "flow_id": "unknown",
        "user_id": null,
        "account_id": null,
        "user_entitlements": {},
        "report_status": "NOT_AVAILABLE",
        "report_generation_started_at": null,
        "report_generation_completed_at": null,
        "node_stats": {
          "ca564648-1715-45c3-be67-7c654344a99c": {
            "id": "ca564648-1715-45c3-be67-7c654344a99c",
            "name": "extract_with_docling",
            "node_status": "Completed",
            "error": "",
            "start_time": 1788943163,
            "end_time": 1788943163,
            "time_taken": 0,
            "col_names": [
              "content",
              "doc_id_hash",
              "document_format",
              "id",
              "metadata",
              "modified_time",
              "name",
              "pages_processed",
              "path",
              "source_id"
            ],
            "total_docs": 2,
            "failed_docs": 0,
            "skipped_docs": 0,
            "docs_completed": 2,
            "docs_completed_count": 2,
            "node_metadata": {
              "node_metadata": {
                "failed_docs": [],
                "processed_docs": 2,
                "node_status": "Completed",
                "total_pages_converted": 2,
                "page_type_stats": {
                  "txt": 2
                },
                "failed_docs_count": 0,
                "skipped_docs": [],
                "documents_in_scope": 2,
                "skipped_docs_count": 0,
                "completed_docs_count": 2,
                "Progress": "1 of 1 batches (100.0%) | Completed: 1"
              },
              "id": "ca564648-1715-45c3-be67-7c654344a99c",
              "operator": "extract_with_docling"
            },
            "batch_id": null,
            "batch_num": null
          },
          "49f285b0-3afa-40eb-8111-3ec6a57c4904": {
            "id": "49f285b0-3afa-40eb-8111-3ec6a57c4904",
            "name": "ingest_source_filesystem",
            "node_status": "Completed",
            "error": "",
            "start_time": 1788943163,
            "end_time": 1788943163,
            "time_taken": 0,
            "col_names": [
              "id",
              "name",
              "document_format",
              "metadata",
              "source_id",
              "path",
              "modified_time"
            ],
            "total_docs": 2,
            "failed_docs": 0,
            "skipped_docs": 0,
            "docs_completed": 2,
            "docs_completed_count": 2,
            "node_metadata": {
              "id": "49f285b0-3afa-40eb-8111-3ec6a57c4904",
              "operator": "ingest_source_filesystem",
              "node_metadata": {
                "documents_in_scope": 2,
                "processed_docs": 2,
                "failed_docs_count": 0,
                "failed_docs": [],
                "skipped_docs_count": 0,
                "skipped_docs": [],
                "node_status": "Completed"
              }
            },
            "batch_id": null,
            "batch_num": null
          },
          "447e0511-5125-4ffb-8396-edb972976080": {
            "id": "447e0511-5125-4ffb-8396-edb972976080",
            "name": "simple_chunker",
            "node_status": "Completed",
            "error": "",
            "start_time": 1788943163,
            "end_time": 1788943164,
            "time_taken": 1,
            "col_names": [
              "chunked_content",
              "doc_id_hash",
              "document_format",
              "id",
              "metadata",
              "modified_time",
              "name",
              "pages_processed",
              "path",
              "source_id"
            ],
            "total_docs": 2,
            "failed_docs": 0,
            "skipped_docs": 0,
            "docs_completed": 2,
            "docs_completed_count": 2,
            "node_metadata": {
              "node_metadata": {
                "failed_docs": [],
                "total_chunks": 4,
                "processed_docs": 2,
                "node_status": "Completed",
                "failed_docs_count": 0,
                "skipped_docs": [],
                "documents_in_scope": 2,
                "skipped_docs_count": 0,
                "completed_docs_count": 2,
                "Progress": "1 of 1 batches (100.0%) | Completed: 1"
              },
              "id": "447e0511-5125-4ffb-8396-edb972976080",
              "operator": "simple_chunker"
            },
            "batch_id": null,
            "batch_num": null
          },
          "2636f8b6-ef9a-4805-bda0-9fcaa853e16a": {
            "id": "2636f8b6-ef9a-4805-bda0-9fcaa853e16a",
            "name": "ollama_embeddings",
            "node_status": "Completed",
            "error": "",
            "start_time": 1788943164,
            "end_time": 1788943164,
            "time_taken": 0,
            "col_names": [
              "chunked_content",
              "doc_id_hash",
              "document_format",
              "embeddings",
              "id",
              "metadata",
              "modified_time",
              "name",
              "pages_processed",
              "path",
              "source_id"
            ],
            "total_docs": 2,
            "failed_docs": 0,
            "skipped_docs": 0,
            "docs_completed": 2,
            "docs_completed_count": 2,
            "node_metadata": {
              "node_metadata": {
                "failed_docs": [],
                "processed_docs": 2,
                "node_status": "Completed",
                "failed_docs_count": 0,
                "skipped_docs": [],
                "documents_in_scope": 2,
                "skipped_docs_count": 0,
                "completed_docs_count": 2,
                "Progress": "1 of 1 batches (100.0%) | Completed: 1"
              },
              "id": "2636f8b6-ef9a-4805-bda0-9fcaa853e16a",
              "operator": "ollama_embeddings"
            },
            "batch_id": null,
            "batch_num": null
          },
          "0c773955-f1c7-4b68-b157-38966382cb9c": {
            "id": "0c773955-f1c7-4b68-b157-38966382cb9c",
            "name": "opensearch_vector_store",
            "node_status": "Completed",
            "error": "",
            "start_time": 1788943164,
            "end_time": 1788943165,
            "time_taken": 1,
            "col_names": [
              "chunked_content",
              "doc_id_hash",
              "document_format",
              "embeddings",
              "id",
              "metadata",
              "modified_time",
              "name",
              "pages_processed",
              "path",
              "source_id"
            ],
            "total_docs": 2,
            "failed_docs": 0,
            "skipped_docs": 0,
            "docs_completed": 2,
            "docs_completed_count": 2,
            "node_metadata": {
              "node_metadata": {
                "failed_docs": [],
                "chunks_indexed_successfully": 4,
                "processed_docs": 2,
                "total_chunks_to_index": 4,
                "node_status": "Completed",
                "chunks_failed_to_index": 0,
                "number_of_batches": 1,
                "failed_docs_count": 0,
                "skipped_docs": [],
                "documents_in_scope": 2,
                "skipped_docs_count": 0,
                "completed_docs_count": 2,
                "Progress": "1 of 1 batches (100.0%) | Completed: 1"
              },
              "id": "0c773955-f1c7-4b68-b157-38966382cb9c",
              "operator": "opensearch_vector_store"
            },
            "batch_id": null,
            "batch_num": null
          }
        },
        "batch_node_stats": {
          "2636f8b6-ef9a-4805-bda0-9fcaa853e16a": {
            "d9467158-dc5a-422e-92f7-d389776f8e50": {
              "id": "2636f8b6-ef9a-4805-bda0-9fcaa853e16a",
              "name": "ollama_embeddings",
              "node_status": "Completed",
              "error": "",
              "start_time": 1788943164,
              "end_time": 1788943164,
              "time_taken": 0,
              "col_names": [
                "id",
                "name",
                "document_format",
                "metadata",
                "source_id",
                "path",
                "modified_time",
                "pages_processed",
                "chunked_content",
                "embeddings",
                "doc_id_hash"
              ],
              "total_docs": 2,
              "failed_docs": 0,
              "skipped_docs": 0,
              "docs_completed": 2,
              "docs_completed_count": 2,
              "node_metadata": {
                "id": "2636f8b6-ef9a-4805-bda0-9fcaa853e16a",
                "operator": "ollama_embeddings",
                "node_metadata": {
                  "documents_in_scope": 2,
                  "processed_docs": 2,
                  "failed_docs_count": 0,
                  "failed_docs": [],
                  "skipped_docs_count": 0,
                  "skipped_docs": [],
                  "node_status": "Completed"
                }
              },
              "batch_id": "d9467158-dc5a-422e-92f7-d389776f8e50",
              "batch_num": 0
            }
          },
          "0c773955-f1c7-4b68-b157-38966382cb9c": {
            "d9467158-dc5a-422e-92f7-d389776f8e50": {
              "id": "0c773955-f1c7-4b68-b157-38966382cb9c",
              "name": "opensearch_vector_store",
              "node_status": "Completed",
              "error": "",
              "start_time": 1788943164,
              "end_time": 1788943165,
              "time_taken": 1,
              "col_names": [
                "id",
                "name",
                "document_format",
                "metadata",
                "source_id",
                "path",
                "modified_time",
                "pages_processed",
                "chunked_content",
                "embeddings",
                "doc_id_hash"
              ],
              "total_docs": 2,
              "failed_docs": 0,
              "skipped_docs": 0,
              "docs_completed": 2,
              "docs_completed_count": 2,
              "node_metadata": {
                "id": "0c773955-f1c7-4b68-b157-38966382cb9c",
                "operator": "opensearch_vector_store",
                "node_metadata": {
                  "documents_in_scope": 2,
                  "processed_docs": 2,
                  "failed_docs_count": 0,
                  "failed_docs": [],
                  "skipped_docs_count": 0,
                  "skipped_docs": [],
                  "node_status": "Completed",
                  "number_of_batches": 1,
                  "total_chunks_to_index": 4,
                  "chunks_indexed_successfully": 4,
                  "chunks_failed_to_index": 0
                }
              },
              "batch_id": "d9467158-dc5a-422e-92f7-d389776f8e50",
              "batch_num": 0
            }
          },
          "447e0511-5125-4ffb-8396-edb972976080": {
            "d9467158-dc5a-422e-92f7-d389776f8e50": {
              "id": "447e0511-5125-4ffb-8396-edb972976080",
              "name": "simple_chunker",
              "node_status": "Completed",
              "error": "",
              "start_time": 1788943163,
              "end_time": 1788943164,
              "time_taken": 1,
              "col_names": [
                "id",
                "name",
                "document_format",
                "metadata",
                "source_id",
                "path",
                "modified_time",
                "pages_processed",
                "doc_id_hash",
                "chunked_content"
              ],
              "total_docs": 2,
              "failed_docs": 0,
              "skipped_docs": 0,
              "docs_completed": 2,
              "docs_completed_count": 2,
              "node_metadata": {
                "id": "447e0511-5125-4ffb-8396-edb972976080",
                "operator": "simple_chunker",
                "node_metadata": {
                  "documents_in_scope": 2,
                  "processed_docs": 2,
                  "failed_docs_count": 0,
                  "failed_docs": [],
                  "skipped_docs_count": 0,
                  "skipped_docs": [],
                  "node_status": "Completed",
                  "total_chunks": 4
                }
              },
              "batch_id": "d9467158-dc5a-422e-92f7-d389776f8e50",
              "batch_num": 0
            }
          },
          "ca564648-1715-45c3-be67-7c654344a99c": {
            "d9467158-dc5a-422e-92f7-d389776f8e50": {
              "id": "ca564648-1715-45c3-be67-7c654344a99c",
              "name": "extract_with_docling",
              "node_status": "Completed",
              "error": "",
              "start_time": 1788943163,
              "end_time": 1788943163,
              "time_taken": 0,
              "col_names": [
                "id",
                "name",
                "document_format",
                "metadata",
                "source_id",
                "path",
                "modified_time",
                "content",
                "pages_processed",
                "doc_id_hash"
              ],
              "total_docs": 2,
              "failed_docs": 0,
              "skipped_docs": 0,
              "docs_completed": 2,
              "docs_completed_count": 2,
              "node_metadata": {
                "id": "ca564648-1715-45c3-be67-7c654344a99c",
                "operator": "extract_with_docling",
                "node_metadata": {
                  "documents_in_scope": 2,
                  "processed_docs": 2,
                  "failed_docs_count": 0,
                  "failed_docs": [],
                  "skipped_docs_count": 0,
                  "skipped_docs": [],
                  "node_status": "Completed",
                  "page_type_stats": {
                    "txt": 2
                  },
                  "total_pages_converted": 2
                }
              },
              "batch_id": "d9467158-dc5a-422e-92f7-d389776f8e50",
              "batch_num": 0
            }
          }
        }
      },
      "node_metadata": [
        {
          "id": "ca564648-1715-45c3-be67-7c654344a99c",
          "operator": "extract_with_docling",
          "node_metadata": {
            "failed_docs": [],
            "processed_docs": 2,
            "node_status": "Completed",
            "total_pages_converted": 2,
            "page_type_stats": {
              "txt": 2
            },
            "failed_docs_count": 0,
            "skipped_docs": [],
            "documents_in_scope": 2,
            "skipped_docs_count": 0,
            "completed_docs_count": 2,
            "Progress": "1 of 1 batches (100.0%) | Completed: 1"
          }
        },
        {
          "id": "49f285b0-3afa-40eb-8111-3ec6a57c4904",
          "operator": "ingest_source_filesystem",
          "node_metadata": {
            "documents_in_scope": 2,
            "processed_docs": 2,
            "failed_docs_count": 0,
            "failed_docs": [],
            "skipped_docs_count": 0,
            "skipped_docs": [],
            "node_status": "Completed"
          }
        },
        {
          "id": "447e0511-5125-4ffb-8396-edb972976080",
          "operator": "simple_chunker",
          "node_metadata": {
            "failed_docs": [],
            "total_chunks": 4,
            "processed_docs": 2,
            "node_status": "Completed",
            "failed_docs_count": 0,
            "skipped_docs": [],
            "documents_in_scope": 2,
            "skipped_docs_count": 0,
            "completed_docs_count": 2,
            "Progress": "1 of 1 batches (100.0%) | Completed: 1"
          }
        },
        {
          "id": "2636f8b6-ef9a-4805-bda0-9fcaa853e16a",
          "operator": "ollama_embeddings",
          "node_metadata": {
            "failed_docs": [],
            "processed_docs": 2,
            "node_status": "Completed",
            "failed_docs_count": 0,
            "skipped_docs": [],
            "documents_in_scope": 2,
            "skipped_docs_count": 0,
            "completed_docs_count": 2,
            "Progress": "1 of 1 batches (100.0%) | Completed: 1"
          }
        },
        {
          "id": "0c773955-f1c7-4b68-b157-38966382cb9c",
          "operator": "opensearch_vector_store",
          "node_metadata": {
            "failed_docs": [],
            "chunks_indexed_successfully": 4,
            "processed_docs": 2,
            "total_chunks_to_index": 4,
            "node_status": "Completed",
            "chunks_failed_to_index": 0,
            "number_of_batches": 1,
            "failed_docs_count": 0,
            "skipped_docs": [],
            "documents_in_scope": 2,
            "skipped_docs_count": 0,
            "completed_docs_count": 2,
            "Progress": "1 of 1 batches (100.0%) | Completed: 1"
          }
        }
      ]
    }
    

    Гэты прыклад не ўсё цалка адпаведны: job_run_id у job_stats не збігаецца з ID пятага крока, а flow_id мае значэнне unknown. Спраўляйце кореляцыю запускаў па ID, які вы отрымалі на пачатку.

    Што чытаць перша ў рэспансе

    • job_stats паводзіць высокага рэвялюцыі кальканары, такія як total_docs, processed_docs, completed_docs і duration.
  • node_stats паказвае трываласць і статус кожнага крока; перш за ўсё яго трэба пераканацца, калі запуск працюе повольна або збываеся.
  • З параметрам include_logs=true у коране адпаведзі даўаюцца форматаваныя лог-файлы, пазначаныя іменамі кожнага вузла (пачынаючы з вузла інгестаўвання і дахоўваючы хранілішча OpenSearch).
  • Інтэрпретацыя метаданых вузла

    Кожны аператар фіксуе тэлеметрычную інфармацыю пад ключам node_metadata: праўіну обробкі, адхыленняя і канверсіі па кожнам этапе. Галоўныя атрыбуты:

    • documents_in_scope: цэлычасловая колькасць необработаных дакументаў, якія знайшоў і заваносіў аператар інгестаўвання; гэта ваша базовая вялічына.
    • processed_docs: цэлычасловая колькасць дакументаў, якія аператар успешна обрабаваў пад час запуску; равнае documents_in_scope, калі нічога не збываеся.
    • failed_docs_count: цэлычасловая колькасць дакументаў, у якіх тут з’явіліся адхыленняя.
  • failed_docs: масэв, у яком лісты ўтримваюць id, первасны name файла, прычыну адказа reason і document_url (пусты, калі файлы выйшлі з локальнага диска).
  • skipped_docs_count: цэлычасовы лік дакументаў, якія былі намерна прыхованы, напрыклад, праз адзначэнне дублікаў, логіку галузей або інкрементальныя запускі.
  • skipped_docs: масэв, падобны failed_docs, дзе reason адпавядае за паспрабоўку прыховаць дакумент, напрыклад "Фільтравана па умове галузі".
  • page_type_stats: адзвярцается толькі аператарам выкарыстоўвання, это слоўнік, у яком ключамі ёсць расширэнняя файлоў, а значэннямі — лік распакаваных стораначак, напрыклад {"pdf": 45, "docx": 12, "txt": 3}.
  • Таксама, толькі для выкарыстоўвання: total_pages_converted — это цэлыя значэння сумы стораначакоў у всіх форматах, пры чым для цифровых файлаў выкарыстоўваецца ўласны пісьмовы лік, а для сканаваных копій — пісьмовы лік, апрацоўваны OCR.
  • Швайны пераконтальнік стану: паравярце documents_in_scope на этапе запрашэння дакументаў з processed_docs на последнім вузле; failed_docs і skipped_docs адпавядаюць за будзь-якія розбіжнасці.

    Шаг 7: перагляд прабегаў і історыі запускаў для проекту

    GET /api/v1/projects/{project_id}/flows паказвае прабегі проекту з аптуткам запуска (загальная колькасць запускаў, ID последнего запуску, статус і час пачатку, колькасць дакументаў па статусу), пагрупаваныя за total_count, offset і limit:

    {
      "flows": [
        {
          "flow_id": "e2c31e42-7719-482a-a53d-2490b830d971",
          "name": "complete-document-pipeline",
          "tags": ["docling", "embeddings", "opensearch"],
          "created_on": "2026-09-07T10:05:00Z",
          "job_run_summary": {
            "total_runs": 1,
            "last_run_id": "99ecd646-bb8e-494a-a0c5-86b40c1d4f90",
            "last_run_status": "Completed",
            "last_run_start_time": 1788775200000,
            "status_counts": { "Completed": 1 }
          }
        }
      ],
      "total_count": 1,
      "offset": 0,
      "limit": 100
    }
    

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

    Галоўныя вывары

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

    • Выкарыстоўваюце /operators/metadata і /providers/{provider}/models, каб програмна адкрываць поля оператараў і доступныя тагі модэляў, у замест на ўведчыце іх у код напраму.
    • Выконваюце кожную дэфініцыю DAG через /validation/validate_flow, каб выявіць некоректныя типы параметраў і зламаныя з’ёднанні вузлаў прычым рэалізацыі.
    • Спрыяйце выконанню як асінхронным заданням: зберагаюце job_run_id, адслежвайце стан задання з include_logs=true, і чытайце node_stats і node_metadata, каб выявіць неудачы па этапах.
    • Не залягайце кранты наявных дакументаў з паролямі ў схованых дэфініцыях прабегаў і пераканайцеся, што vector_dimension паспаўляе вашаму модэлю імбеддінгу.

    Ёнклікаць, запусцыце Ollama і OpenSearch (альбо Milvus), адзейнаце docling-pipelines-api, ачыніце Swagger UI і працавайце па следуючай сэрыі: проект, трактаванне, аправарэнне, запуск, логі.