Управление потоками Docling через 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направляет операции с встраиваемыми моделями и большими языковыми моделями к 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 пятого шага, а значение 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 и пройдитесь по последовательности операций: проект, поток обработки, проверка, запуск, логи.