Керування Docling Pipelines через HTTP: від налаштування проекту до індексованих частин даних
Прослідкуйте роботу REST API Docling Pipelines крок за кроком: запустіть сервер, виявіть оператори, перевірте та запустіть DAG для імпорту даних, а також прочитайте інформацію про його виконання.
Джерела: **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, векторної бази даних та необхідних контейнерів. Штучний інтелект-агент для програмування, такий як 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 у браузері; локально вхід не потрібен. Розгорніть певний кінець шляху, натисніть Спробувати та надішліть наведені нижче дані без необхідності писати клієнт.
Огляд життєвого циклу запиту
Повний цикл включає сім викликів, від створення проекту до підсумку його виконання:
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.
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 приймає ID та назву потоку:
{
"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 кроку 5, а 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 пояснює причину ігнорування, наприклад "Filtered by branch condition".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 пропонує безголовий інтерфейс для обробки документів від початку до кінця. Кілька звичок роблять його надійним:
- Використовуйте
/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 та пройдіться по послідовності: проект, потік обробки, перевірка, запуск, журнали.