openrag 0.5.0.dev33__tar.gz → 0.5.0.dev34__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openrag-0.5.0.dev33/src/openrag.egg-info → openrag-0.5.0.dev34}/PKG-INFO +1 -1
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/pyproject.toml +1 -1
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34/src/openrag.egg-info}/PKG-INFO +1 -1
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/ingestion_flow.json +16 -16
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/managers/docling_manager.py +42 -45
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/LICENSE +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/MANIFEST.in +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/README.md +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/setup.cfg +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/agent.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/auth.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/chat.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/connector_router.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/connectors.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/docling.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/documents.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/flows.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/keys.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/knowledge_filter.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/langflow_files.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/models.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/nudges.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/oidc.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/provider_health.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/provider_validation.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/router.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/search.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/settings.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/tasks.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/upload.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/v1/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/v1/chat.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/v1/documents.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/v1/knowledge_filters.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/v1/models.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/v1/search.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/api/v1/settings.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/auth/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/auth/ibm_auth.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/auth_context.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/bootstrap.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/config/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/config/config_manager.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/config/embedding_constants.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/config/model_constants.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/config/paths.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/config/settings.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/aws_s3/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/aws_s3/api.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/aws_s3/auth.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/aws_s3/connector.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/aws_s3/models.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/aws_s3/support.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/base.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/connection_manager.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/google_drive/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/google_drive/connector.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/google_drive/oauth.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/ibm_cos/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/ibm_cos/api.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/ibm_cos/auth.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/ibm_cos/connector.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/ibm_cos/models.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/ibm_cos/support.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/langflow_connector_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/onedrive/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/onedrive/connector.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/onedrive/oauth.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/sharepoint/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/sharepoint/connector.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/sharepoint/oauth.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/connectors/sharepoint/utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/dependencies.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/main.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/mcp_http/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/mcp_http/server.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/models/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/models/processors.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/models/tasks.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/models/url.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/openrag.egg-info/SOURCES.txt +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/openrag.egg-info/dependency_links.txt +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/openrag.egg-info/entry_points.txt +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/openrag.egg-info/requires.txt +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/openrag.egg-info/top_level.txt +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/api_key_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/auth_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/chat_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/conversation_persistence_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/document_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/flows_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/knowledge_filter_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/langflow_file_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/langflow_history_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/langflow_mcp_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/models_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/monitor_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/search_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/session_ownership_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/task_service.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/session_manager.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/docker-compose.gpu.yml +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/docker-compose.yml +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/ollama_embedding.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/ollama_llm.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/ollama_llm_text.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/watsonx_embedding.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/watsonx_llm.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/watsonx_llm_text.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/openrag_agent.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/openrag_nudges.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/openrag_url_mcp.json +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/openrag-documents/docling.pdf +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/openrag-documents/warmup_ocr.pdf +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/cli.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/config_fields.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/main.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/managers/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/managers/container_manager.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/managers/env_manager.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/screens/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/screens/config.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/screens/diagnostics.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/screens/logs.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/screens/monitor.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/screens/welcome.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/utils/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/utils/clipboard.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/utils/platform.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/utils/startup_checks.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/utils/validation.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/utils/version_check.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/command_modal.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/diagnostics_notification.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/error_notification.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/factory_reset_warning_modal.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/flow_backup_warning_modal.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/prune_options_modal.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/upgrade_instructions_modal.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/version_mismatch_warning_modal.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/waves.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/acl_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/container_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/docling_client.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/document_processing.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/embedding_fields.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/embeddings.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/encryption.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/env_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/file_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/gpu_detection.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/hash_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/langflow_headers.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/langflow_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/logging_config.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/opensearch_queries.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/opensearch_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/paths.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/run_mode_utils.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/telemetry/__init__.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/telemetry/category.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/telemetry/client.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/telemetry/message_id.py +0 -0
- {openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/utils/version_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrag
|
|
3
|
-
Version: 0.5.0.
|
|
3
|
+
Version: 0.5.0.dev34
|
|
4
4
|
Summary: OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations.
|
|
5
5
|
Classifier: Development Status :: 4 - Beta
|
|
6
6
|
Classifier: Environment :: Console
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "openrag"
|
|
7
|
-
version = "0.5.0.
|
|
7
|
+
version = "0.5.0.dev34"
|
|
8
8
|
description = "OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.13"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openrag
|
|
3
|
-
Version: 0.5.0.
|
|
3
|
+
Version: 0.5.0.dev34
|
|
4
4
|
Summary: OpenRAG is a comprehensive Retrieval-Augmented Generation platform that enables intelligent document search and AI-powered conversations.
|
|
5
5
|
Classifier: Development Status :: 4 - Beta
|
|
6
6
|
Classifier: Environment :: Console
|
|
@@ -828,7 +828,7 @@
|
|
|
828
828
|
],
|
|
829
829
|
"frozen": false,
|
|
830
830
|
"icon": "braces",
|
|
831
|
-
"last_updated": "2026-
|
|
831
|
+
"last_updated": "2026-05-26T19:04:35.148Z",
|
|
832
832
|
"legacy": false,
|
|
833
833
|
"lf_version": "1.7.0.dev21",
|
|
834
834
|
"metadata": {},
|
|
@@ -878,7 +878,7 @@
|
|
|
878
878
|
"value": "5488df7c-b93f-4f87-a446-b67028bc0813"
|
|
879
879
|
},
|
|
880
880
|
"_frontend_node_folder_id": {
|
|
881
|
-
"value": "
|
|
881
|
+
"value": "d61134a0-3f8e-4e89-9165-ce13f2a14ac6"
|
|
882
882
|
},
|
|
883
883
|
"_type": "Component",
|
|
884
884
|
"code": {
|
|
@@ -1337,7 +1337,7 @@
|
|
|
1337
1337
|
"icon": "Docling",
|
|
1338
1338
|
"legacy": false,
|
|
1339
1339
|
"metadata": {
|
|
1340
|
-
"code_hash": "
|
|
1340
|
+
"code_hash": "dcf9aeedd059",
|
|
1341
1341
|
"dependencies": {
|
|
1342
1342
|
"dependencies": [
|
|
1343
1343
|
{
|
|
@@ -1346,7 +1346,7 @@
|
|
|
1346
1346
|
},
|
|
1347
1347
|
{
|
|
1348
1348
|
"name": "docling_core",
|
|
1349
|
-
"version": "2.
|
|
1349
|
+
"version": "2.74.1"
|
|
1350
1350
|
},
|
|
1351
1351
|
{
|
|
1352
1352
|
"name": "pydantic",
|
|
@@ -1354,7 +1354,7 @@
|
|
|
1354
1354
|
},
|
|
1355
1355
|
{
|
|
1356
1356
|
"name": "lfx",
|
|
1357
|
-
"version":
|
|
1357
|
+
"version": "0.4.3"
|
|
1358
1358
|
}
|
|
1359
1359
|
],
|
|
1360
1360
|
"total_dependencies": 4
|
|
@@ -1447,7 +1447,7 @@
|
|
|
1447
1447
|
"show": true,
|
|
1448
1448
|
"title_case": false,
|
|
1449
1449
|
"type": "code",
|
|
1450
|
-
"value": "import base64\nimport time\nfrom concurrent.futures import Future, ThreadPoolExecutor\nfrom pathlib import Path\nfrom typing import Any\n\nimport httpx\nfrom docling_core.types.doc import DoclingDocument\nfrom pydantic import ValidationError\n\nfrom lfx.base.data import BaseFileComponent\nfrom lfx.inputs import IntInput, NestedDictInput, StrInput\nfrom lfx.inputs.inputs import FloatInput\nfrom lfx.schema import Data\nfrom lfx.utils.util import transform_localhost_url\n\n\nclass DoclingRemoteComponent(BaseFileComponent):\n display_name = \"Docling Serve\"\n description = \"Uses Docling to process input documents connecting to your instance of Docling Serve.\"\n documentation = \"https://docling-project.github.io/docling/\"\n trace_type = \"tool\"\n icon = \"Docling\"\n name = \"DoclingRemote\"\n\n MAX_500_RETRIES = 5\n\n # https://docling-project.github.io/docling/usage/supported_formats/\n VALID_EXTENSIONS = [\n \"adoc\",\n \"asciidoc\",\n \"asc\",\n \"bmp\",\n \"csv\",\n \"dotx\",\n \"dotm\",\n \"docm\",\n \"docx\",\n \"htm\",\n \"html\",\n \"jpeg\",\n \"jpg\",\n \"json\",\n \"md\",\n \"pdf\",\n \"png\",\n \"potx\",\n \"ppsx\",\n \"pptm\",\n \"potm\",\n \"ppsm\",\n \"pptx\",\n \"tiff\",\n \"txt\",\n \"xls\",\n \"xlsx\",\n \"xhtml\",\n \"xml\",\n \"webp\",\n ]\n\n inputs = [\n *BaseFileComponent.get_base_inputs(),\n StrInput(\n name=\"api_url\",\n display_name=\"Server address\",\n info=\"URL of the Docling Serve instance.\",\n required=True,\n ),\n IntInput(\n name=\"max_concurrency\",\n display_name=\"Concurrency\",\n info=\"Maximum number of concurrent requests for the server.\",\n advanced=True,\n value=2,\n input_types=[\"Message\"],\n ),\n FloatInput(\n name=\"max_poll_timeout\",\n display_name=\"Maximum poll time\",\n info=\"Maximum waiting time for the document conversion to complete.\",\n advanced=True,\n value=3600,\n input_types=[\"Message\"],\n ),\n NestedDictInput(\n name=\"api_headers\",\n display_name=\"HTTP headers\",\n advanced=True,\n required=False,\n info=(\"Optional dictionary of additional headers required for connecting to Docling Serve.\"),\n input_types=[\"Message\"],\n ),\n NestedDictInput(\n name=\"docling_serve_opts\",\n display_name=\"Docling options\",\n advanced=True,\n required=False,\n info=(\n \"Optional dictionary of additional options. \"\n \"See https://github.com/docling-project/docling-serve/blob/main/docs/usage.md for more information.\"\n ),\n input_types=[\"Message\"],\n ),\n ]\n\n outputs = [\n *BaseFileComponent.get_base_outputs(),\n ]\n\n def process_files(self, file_list: list[BaseFileComponent.BaseFile]) -> list[BaseFileComponent.BaseFile]:\n # Transform localhost URLs to container-accessible hosts when running in a container\n transformed_url = transform_localhost_url(self.api_url)\n base_url = f\"{transformed_url}/v1\"\n\n def _convert_document(client: httpx.Client, file_path: Path, options: dict[str, Any]) -> Data | None:\n encoded_doc = base64.b64encode(file_path.read_bytes()).decode()\n payload = {\n \"options\": options,\n \"sources\": [{\"kind\": \"file\", \"base64_string\": encoded_doc, \"filename\": file_path.name}],\n }\n\n response = client.post(f\"{base_url}/convert/source/async\", json=payload)\n response.raise_for_status()\n task = response.json()\n\n http_failures = 0\n retry_status_start = 500\n retry_status_end = 600\n start_wait_time = time.monotonic()\n while task[\"task_status\"] not in (\"success\", \"failure\"):\n # Check if processing exceeds the maximum poll timeout\n processing_time = time.monotonic() - start_wait_time\n if processing_time >= self.max_poll_timeout:\n msg = (\n f\"Processing time {processing_time=} exceeds the maximum poll timeout {self.max_poll_timeout=}.\"\n \"Please increase the max_poll_timeout parameter or review why the processing \"\n \"takes long on the server.\"\n )\n self.log(msg)\n raise RuntimeError(msg)\n\n # Call for a new status update\n time.sleep(2)\n response = client.get(f\"{base_url}/status/poll/{task['task_id']}\")\n\n # Check if the status call gets into 5xx errors and retry\n if retry_status_start <= response.status_code < retry_status_end:\n http_failures += 1\n if http_failures > self.MAX_500_RETRIES:\n self.log(f\"The status requests got a http response {response.status_code} too many times.\")\n return None\n continue\n\n # Update task status\n task = response.json()\n\n result_resp = client.get(f\"{base_url}/result/{task['task_id']}\")\n result_resp.raise_for_status()\n result = result_resp.json()\n\n if \"json_content\" not in result[\"document\"] or result[\"document\"][\"json_content\"] is None:\n self.log(\"No JSON DoclingDocument found in the result.\")\n return None\n\n try:\n doc = DoclingDocument.model_validate(result[\"document\"][\"json_content\"])\n return Data(data={\"doc\": doc, \"file_path\": str(file_path)})\n except ValidationError as e:\n self.log(f\"Error validating the document. {e}\")\n return None\n\n docling_options = {\n \"to_formats\": [\"json\"],\n \"image_export_mode\": \"placeholder\",\n **(self.docling_serve_opts or {}),\n }\n\n processed_data: list[Data | None] = []\n with (\n httpx.Client(headers=self.api_headers) as client,\n ThreadPoolExecutor(max_workers=self.max_concurrency) as executor,\n ):\n futures: list[tuple[int, Future]] = []\n for i, file in enumerate(file_list):\n if file.path is None:\n processed_data.append(None)\n continue\n\n futures.append((i, executor.submit(_convert_document, client, file.path, docling_options)))\n\n for _index, future in futures:\n try:\n result_data = future.result()\n processed_data.append(result_data)\n except (httpx.HTTPStatusError, httpx.RequestError, KeyError, ValueError) as exc:\n self.log(f\"Docling remote processing failed: {exc}\")\n raise\n\n return self.rollup_data(file_list, processed_data)\n"
|
|
1450
|
+
"value": "from __future__ import annotations\n\nimport base64\nimport json\nimport time\nfrom concurrent.futures import Future, ThreadPoolExecutor\nfrom pathlib import Path # noqa: TC003\nfrom typing import Any\n\nimport httpx\nfrom docling_core.types.doc import DoclingDocument\nfrom pydantic import ValidationError\n\nfrom lfx.base.data import BaseFileComponent\nfrom lfx.inputs import IntInput, NestedDictInput, StrInput, TableInput\nfrom lfx.inputs.inputs import FloatInput\nfrom lfx.schema import Data, dotdict\nfrom lfx.utils.util import transform_localhost_url\n\n\nclass DoclingRemoteComponent(BaseFileComponent):\n display_name = \"Docling Serve\"\n description = (\n \"Uses Docling to process input documents connecting to your instance of Docling Serve.\"\n )\n documentation = \"https://docling-project.github.io/docling/\"\n trace_type = \"tool\"\n icon = \"Docling\"\n name = \"DoclingRemote\"\n\n MAX_500_RETRIES = 5\n\n # https://docling-project.github.io/docling/usage/supported_formats/\n VALID_EXTENSIONS = [\n \"adoc\",\n \"asciidoc\",\n \"asc\",\n \"bmp\",\n \"csv\",\n \"dotx\",\n \"dotm\",\n \"docm\",\n \"docx\",\n \"htm\",\n \"html\",\n \"jpeg\",\n \"jpg\",\n \"json\",\n \"md\",\n \"pdf\",\n \"png\",\n \"potx\",\n \"ppsx\",\n \"pptm\",\n \"potm\",\n \"ppsm\",\n \"pptx\",\n \"tiff\",\n \"txt\",\n \"xls\",\n \"xlsx\",\n \"xhtml\",\n \"xml\",\n \"webp\",\n ]\n\n inputs = [\n *BaseFileComponent.get_base_inputs(),\n StrInput(\n name=\"api_url\",\n display_name=\"Server address\",\n info=\"URL of the Docling Serve instance.\",\n required=True,\n ),\n StrInput(\n name=\"task_id\",\n display_name=\"Task ID\",\n info=(\n \"Optional task ID from a previous Docling Serve upload. \"\n \"If provided, file input is ignored and the component polls for this task's results.\"\n ),\n required=False,\n ),\n IntInput(\n name=\"max_concurrency\",\n display_name=\"Concurrency\",\n info=\"Maximum number of concurrent requests for the server.\",\n advanced=True,\n value=2,\n input_types=[\"Message\"],\n ),\n FloatInput(\n name=\"max_poll_timeout\",\n display_name=\"Maximum poll time\",\n info=\"Maximum waiting time for the document conversion to complete.\",\n advanced=True,\n value=3600,\n input_types=[\"Message\"],\n ),\n TableInput(\n name=\"api_headers\",\n display_name=\"HTTP headers\",\n advanced=True,\n required=False,\n info=(\"Optional headers required for connecting to Docling Serve.\"),\n table_schema=[\n {\n \"name\": \"key\",\n \"display_name\": \"Key\",\n \"type\": \"string\",\n \"description\": \"Key name\",\n },\n {\n \"name\": \"value\",\n \"display_name\": \"Value\",\n \"load_from_db\": True,\n \"type\": \"string\",\n \"description\": \"Value of the header\",\n },\n ],\n value=[],\n real_time_refresh=True,\n input_types=[\"Data\", \"JSON\"],\n ),\n NestedDictInput(\n name=\"docling_serve_opts\",\n display_name=\"Docling options\",\n advanced=True,\n required=False,\n info=(\n \"Optional dictionary of additional options. \"\n \"See https://github.com/docling-project/docling-serve/blob/main/docs/usage.md for more information.\"\n ),\n input_types=[\"Message\"],\n ),\n ]\n\n outputs = [\n *BaseFileComponent.get_base_outputs(),\n ]\n\n def _process_headers(self) -> dict[str, str]:\n \"\"\"Process the headers input into a valid dictionary.\"\"\"\n if not self.api_headers:\n return {}\n\n component_headers_dict = {}\n # TableInput normalizes to list\n items = self.api_headers if isinstance(self.api_headers, list) else [self.api_headers]\n\n for item in items:\n if not item:\n continue\n\n # Case 1: Data object\n if hasattr(item, \"data\") and isinstance(item.data, dict):\n data = item.data\n if \"key\" in data and \"value\" in data:\n component_headers_dict[str(data[\"key\"])] = str(data[\"value\"])\n else:\n # Fallback: merge all keys from Data object\n for k, v in data.items():\n if k not in (\"text_key\", \"default_value\"):\n component_headers_dict[str(k)] = str(v)\n\n # Case 2: Dictionary (Table row)\n elif isinstance(item, dict):\n if \"key\" in item and \"value\" in item:\n component_headers_dict[str(item[\"key\"])] = str(item[\"value\"])\n else:\n # Fallback: merge all keys\n for k, v in item.items():\n component_headers_dict[str(k)] = str(v)\n\n # Case 3: Message object\n elif hasattr(item, \"text\") and isinstance(item.text, str):\n try:\n parsed = json.loads(item.text)\n if isinstance(parsed, dict):\n for k, v in parsed.items():\n component_headers_dict[str(k)] = str(v)\n except json.JSONDecodeError:\n pass\n\n return component_headers_dict\n\n def update_build_config(\n self, build_config: dotdict, field_value: Any, field_name: str | None = None\n ) -> dotdict:\n if field_name == \"api_headers\":\n if isinstance(field_value, dict):\n # If it's a dict, convert to list of {key, value} pairs for TableInput\n # This handles migration from NestedDictInput to TableInput\n new_value = [{\"key\": k, \"value\": v} for k, v in field_value.items()]\n build_config[\"api_headers\"][\"value\"] = new_value\n return build_config\n if field_value is None:\n build_config[\"api_headers\"][\"value\"] = []\n return build_config\n\n # Default behavior\n return super().update_build_config(build_config, field_value, field_name)\n\n def _poll_and_fetch_result(\n self, client: httpx.Client, base_url: str, task_id: str, file_path: str | None = None\n ) -> Data | None:\n \"\"\"Poll for task completion and fetch the result.\n\n Args:\n client: The HTTP client to use for requests.\n base_url: The base URL of the Docling Serve API.\n task_id: The task ID to poll for.\n file_path: Optional file path to include in the result data.\n\n Returns:\n Data object with the DoclingDocument, or None if processing failed.\n \"\"\"\n http_failures = 0\n retry_status_start = 500\n retry_status_end = 600\n start_wait_time = time.monotonic()\n\n response = client.get(f\"{base_url}/status/poll/{task_id}\")\n response.raise_for_status()\n task = response.json()\n\n while task[\"task_status\"] not in (\"success\", \"failure\"):\n processing_time = time.monotonic() - start_wait_time\n if processing_time >= self.max_poll_timeout:\n msg = (\n f\"Processing time {processing_time=} exceeds the maximum poll timeout {self.max_poll_timeout=}.\"\n \"Please increase the max_poll_timeout parameter or review why the processing \"\n \"takes long on the server.\"\n )\n self.log(msg)\n raise RuntimeError(msg)\n\n time.sleep(2)\n response = client.get(f\"{base_url}/status/poll/{task_id}\")\n\n if retry_status_start <= response.status_code < retry_status_end:\n http_failures += 1\n if http_failures > self.MAX_500_RETRIES:\n self.log(\n f\"The status requests got a http response {response.status_code} too many times.\"\n )\n return None\n continue\n\n task = response.json()\n\n result_resp = client.get(f\"{base_url}/result/{task_id}\")\n result_resp.raise_for_status()\n result = result_resp.json()\n\n if result.get(\"status\") == \"failure\" or result.get(\"errors\"):\n errors = result.get(\"errors\", [])\n err_msg_list = []\n for err in errors:\n if isinstance(err, dict) and \"error_message\" in err:\n err_msg_list.append(err[\"error_message\"])\n elif isinstance(err, str):\n err_msg_list.append(err)\n\n err_details = \"; \".join(err_msg_list) if err_msg_list else \"Unknown Docling processing error\"\n\n msg = f\"Docling processing failed: {err_details}\"\n raise ValueError(msg)\n\n if \"json_content\" not in result[\"document\"] or result[\"document\"][\"json_content\"] is None:\n self.log(\"No JSON DoclingDocument found in the result.\")\n return None\n\n try:\n doc = DoclingDocument.model_validate(result[\"document\"][\"json_content\"])\n data_dict: dict[str, Any] = {\"doc\": doc}\n if file_path:\n data_dict[\"file_path\"] = file_path\n return Data(data=data_dict)\n except ValidationError as e:\n self.log(f\"Error validating the document. {e}\")\n return None\n\n def _process_task_id(self) -> list[Data]:\n \"\"\"Process an existing task by polling for status and retrieving results.\n\n Returns:\n List containing the result Data object, or empty list if processing failed.\n \"\"\"\n transformed_url = transform_localhost_url(self.api_url)\n base_url = f\"{transformed_url}/v1\"\n\n with httpx.Client(headers=self._process_headers()) as client:\n result = self._poll_and_fetch_result(client, base_url, self.task_id)\n return [result] if result else []\n\n def load_files_base(self) -> list[Data]:\n \"\"\"Load and process files, or poll an existing task if task_id is provided.\n\n Returns:\n list[Data]: Parsed data from the processed files or task.\n \"\"\"\n if self.task_id:\n return self._process_task_id()\n return super().load_files_base()\n\n def process_files(\n self, file_list: list[BaseFileComponent.BaseFile]\n ) -> list[BaseFileComponent.BaseFile]:\n transformed_url = transform_localhost_url(self.api_url)\n base_url = f\"{transformed_url}/v1\"\n\n def _convert_document(\n client: httpx.Client, file_path: Path, options: dict[str, Any]\n ) -> Data | None:\n encoded_doc = base64.b64encode(file_path.read_bytes()).decode()\n payload = {\n \"options\": options,\n \"sources\": [\n {\"kind\": \"file\", \"base64_string\": encoded_doc, \"filename\": file_path.name}\n ],\n }\n\n response = client.post(f\"{base_url}/convert/source/async\", json=payload)\n response.raise_for_status()\n task = response.json()\n\n return self._poll_and_fetch_result(client, base_url, task[\"task_id\"], str(file_path))\n\n docling_options = {\n \"to_formats\": [\"json\"],\n \"image_export_mode\": \"placeholder\",\n **(self.docling_serve_opts or {}),\n }\n\n processed_data: list[Data | None] = []\n with (\n httpx.Client(headers=self._process_headers()) as client,\n ThreadPoolExecutor(max_workers=self.max_concurrency) as executor,\n ):\n futures: list[tuple[int, Future]] = []\n for i, file in enumerate(file_list):\n if file.path is None:\n processed_data.append(None)\n continue\n\n futures.append(\n (i, executor.submit(_convert_document, client, file.path, docling_options))\n )\n\n for _index, future in futures:\n try:\n result_data = future.result()\n processed_data.append(result_data)\n except (httpx.HTTPStatusError, httpx.RequestError, KeyError, ValueError) as exc:\n self.log(f\"Docling remote processing failed: {exc}\")\n raise\n\n return self.rollup_data(file_list, processed_data)\n"
|
|
1451
1451
|
},
|
|
1452
1452
|
"delete_server_file_after_processing": {
|
|
1453
1453
|
"_input_type": "BoolInput",
|
|
@@ -1727,8 +1727,8 @@
|
|
|
1727
1727
|
"width": 192
|
|
1728
1728
|
},
|
|
1729
1729
|
"position": {
|
|
1730
|
-
"x": -
|
|
1731
|
-
"y":
|
|
1730
|
+
"x": -41.950234273170665,
|
|
1731
|
+
"y": 1766.6851884082719
|
|
1732
1732
|
},
|
|
1733
1733
|
"selected": false,
|
|
1734
1734
|
"type": "genericNode"
|
|
@@ -4619,7 +4619,7 @@
|
|
|
4619
4619
|
"value": "5488df7c-b93f-4f87-a446-b67028bc0813"
|
|
4620
4620
|
},
|
|
4621
4621
|
"_frontend_node_folder_id": {
|
|
4622
|
-
"value": "
|
|
4622
|
+
"value": "d61134a0-3f8e-4e89-9165-ce13f2a14ac6"
|
|
4623
4623
|
},
|
|
4624
4624
|
"_type": "Component",
|
|
4625
4625
|
"api_base": {
|
|
@@ -6371,7 +6371,7 @@
|
|
|
6371
6371
|
"value": "5488df7c-b93f-4f87-a446-b67028bc0813"
|
|
6372
6372
|
},
|
|
6373
6373
|
"_frontend_node_folder_id": {
|
|
6374
|
-
"value": "
|
|
6374
|
+
"value": "d61134a0-3f8e-4e89-9165-ce13f2a14ac6"
|
|
6375
6375
|
},
|
|
6376
6376
|
"_type": "Component",
|
|
6377
6377
|
"api_base": {
|
|
@@ -6899,7 +6899,7 @@
|
|
|
6899
6899
|
"value": "5488df7c-b93f-4f87-a446-b67028bc0813"
|
|
6900
6900
|
},
|
|
6901
6901
|
"_frontend_node_folder_id": {
|
|
6902
|
-
"value": "
|
|
6902
|
+
"value": "d61134a0-3f8e-4e89-9165-ce13f2a14ac6"
|
|
6903
6903
|
},
|
|
6904
6904
|
"_type": "Component",
|
|
6905
6905
|
"api_base": {
|
|
@@ -7351,16 +7351,16 @@
|
|
|
7351
7351
|
}
|
|
7352
7352
|
],
|
|
7353
7353
|
"viewport": {
|
|
7354
|
-
"x":
|
|
7355
|
-
"y": -
|
|
7356
|
-
"zoom": 0.
|
|
7354
|
+
"x": 239.96894590419038,
|
|
7355
|
+
"y": -373.3174538705754,
|
|
7356
|
+
"zoom": 0.475706358533402
|
|
7357
7357
|
}
|
|
7358
7358
|
},
|
|
7359
7359
|
"description": "Load your data for chat context with Retrieval Augmented Generation.",
|
|
7360
7360
|
"endpoint_name": null,
|
|
7361
7361
|
"id": "5488df7c-b93f-4f87-a446-b67028bc0813",
|
|
7362
7362
|
"is_component": false,
|
|
7363
|
-
"last_tested_version": "1.9.
|
|
7363
|
+
"last_tested_version": "1.9.3",
|
|
7364
7364
|
"locked": true,
|
|
7365
7365
|
"name": "OpenSearch Ingestion Flow",
|
|
7366
7366
|
"tags": [
|
|
@@ -7369,4 +7369,4 @@
|
|
|
7369
7369
|
"rag",
|
|
7370
7370
|
"q-a"
|
|
7371
7371
|
]
|
|
7372
|
-
}
|
|
7372
|
+
}
|
|
@@ -7,7 +7,9 @@ import sys
|
|
|
7
7
|
import tempfile
|
|
8
8
|
import threading
|
|
9
9
|
import time
|
|
10
|
-
from
|
|
10
|
+
from collections.abc import AsyncIterator
|
|
11
|
+
from typing import Any
|
|
12
|
+
|
|
11
13
|
from utils.logging_config import get_logger
|
|
12
14
|
|
|
13
15
|
logger = get_logger(__name__)
|
|
@@ -29,7 +31,7 @@ class DoclingManager:
|
|
|
29
31
|
if self._initialized:
|
|
30
32
|
return
|
|
31
33
|
|
|
32
|
-
self._process:
|
|
34
|
+
self._process: subprocess.Popen | None = None
|
|
33
35
|
self._port = 5001
|
|
34
36
|
# Bind to all interfaces by default (can be overridden with DOCLING_BIND_HOST env var)
|
|
35
37
|
self._host = os.getenv("DOCLING_BIND_HOST", "0.0.0.0")
|
|
@@ -47,7 +49,7 @@ class DoclingManager:
|
|
|
47
49
|
self._log_file_path = self._tui_dir / "docling-serve.log"
|
|
48
50
|
|
|
49
51
|
# Log storage - simplified, no queue
|
|
50
|
-
self._log_buffer:
|
|
52
|
+
self._log_buffer: list[str] = []
|
|
51
53
|
self._max_log_lines = 1000
|
|
52
54
|
self._log_lock = threading.Lock() # Thread-safe access to log buffer
|
|
53
55
|
|
|
@@ -71,7 +73,7 @@ class DoclingManager:
|
|
|
71
73
|
except Exception as e:
|
|
72
74
|
self._add_log_entry(f"Failed to save PID file: {e}")
|
|
73
75
|
|
|
74
|
-
def _load_pid(self) ->
|
|
76
|
+
def _load_pid(self) -> int | None:
|
|
75
77
|
"""Load the process PID from file."""
|
|
76
78
|
try:
|
|
77
79
|
if self._pid_file.exists():
|
|
@@ -105,9 +107,7 @@ class DoclingManager:
|
|
|
105
107
|
pid = self._load_pid()
|
|
106
108
|
if pid is not None:
|
|
107
109
|
if self._is_process_running(pid):
|
|
108
|
-
self._add_log_entry(
|
|
109
|
-
f"Recovered existing docling-serve process (PID: {pid})"
|
|
110
|
-
)
|
|
110
|
+
self._add_log_entry(f"Recovered existing docling-serve process (PID: {pid})")
|
|
111
111
|
# Mark as external process since we didn't start it in this session
|
|
112
112
|
self._external_process = True
|
|
113
113
|
self._running = True
|
|
@@ -150,7 +150,7 @@ class DoclingManager:
|
|
|
150
150
|
self._external_process = False
|
|
151
151
|
return False
|
|
152
152
|
|
|
153
|
-
def check_port_available(self) -> tuple[bool,
|
|
153
|
+
def check_port_available(self) -> tuple[bool, str | None]:
|
|
154
154
|
"""Check if the native service port is available.
|
|
155
155
|
|
|
156
156
|
Returns:
|
|
@@ -173,7 +173,7 @@ class DoclingManager:
|
|
|
173
173
|
# If we can't check, assume it's available
|
|
174
174
|
return True, None
|
|
175
175
|
|
|
176
|
-
def get_status(self) ->
|
|
176
|
+
def get_status(self) -> dict[str, Any]:
|
|
177
177
|
"""Get current status of docling serve."""
|
|
178
178
|
# Check for starting state first
|
|
179
179
|
if self._starting:
|
|
@@ -230,10 +230,10 @@ class DoclingManager:
|
|
|
230
230
|
enable_ui: bool = False,
|
|
231
231
|
workers: int | None = None,
|
|
232
232
|
timeout: int = 10,
|
|
233
|
-
) ->
|
|
233
|
+
) -> tuple[bool, str]:
|
|
234
234
|
"""Start docling serve as external process.
|
|
235
235
|
|
|
236
|
-
|
|
236
|
+
|
|
237
237
|
Args:
|
|
238
238
|
port: Port to listen on (default: 5001)
|
|
239
239
|
host: Host to bind to (default: from env or 0.0.0.0)
|
|
@@ -280,24 +280,33 @@ class DoclingManager:
|
|
|
280
280
|
# override file is needed to *replace* (not merely supplement)
|
|
281
281
|
# opencv-python, because docling-ibm-models hard-depends on it and
|
|
282
282
|
# the resolver would install both packages otherwise.
|
|
283
|
-
override_path:
|
|
283
|
+
override_path: str | None = None
|
|
284
284
|
if sys.platform != "darwin":
|
|
285
|
-
fd, override_path = tempfile.mkstemp(
|
|
286
|
-
suffix=".txt", prefix="docling_cv_override_"
|
|
287
|
-
)
|
|
285
|
+
fd, override_path = tempfile.mkstemp(suffix=".txt", prefix="docling_cv_override_")
|
|
288
286
|
with os.fdopen(fd, "w") as f:
|
|
289
287
|
f.write('opencv-python ; python_version < "0"\n')
|
|
290
288
|
|
|
291
289
|
try:
|
|
292
|
-
docling_extras =
|
|
290
|
+
docling_extras = (
|
|
291
|
+
"ocrmac,easyocr,rapidocr,vlm"
|
|
292
|
+
if sys.platform == "darwin"
|
|
293
|
+
else "easyocr,rapidocr,vlm"
|
|
294
|
+
)
|
|
293
295
|
|
|
294
296
|
cmd = [
|
|
295
297
|
"uvx",
|
|
296
|
-
"--from",
|
|
297
|
-
"
|
|
298
|
-
"--with",
|
|
299
|
-
"
|
|
300
|
-
"--with",
|
|
298
|
+
"--from",
|
|
299
|
+
"docling-serve[ui]==1.20.0",
|
|
300
|
+
"--with",
|
|
301
|
+
"onnxruntime",
|
|
302
|
+
"--with",
|
|
303
|
+
"easyocr",
|
|
304
|
+
"--with",
|
|
305
|
+
f"docling[{docling_extras}]",
|
|
306
|
+
"--with",
|
|
307
|
+
"docling-core==2.77.1",
|
|
308
|
+
"--with",
|
|
309
|
+
"transformers>=5.8.1,<5.9.0",
|
|
301
310
|
]
|
|
302
311
|
if override_path:
|
|
303
312
|
cmd += ["--override", override_path, "--with", "opencv-python-headless"]
|
|
@@ -343,9 +352,7 @@ class DoclingManager:
|
|
|
343
352
|
self._start_output_capture()
|
|
344
353
|
|
|
345
354
|
# Wait for the process to start and begin listening
|
|
346
|
-
self._add_log_entry(
|
|
347
|
-
f"Waiting up to {timeout}s for docling-serve to start listening..."
|
|
348
|
-
)
|
|
355
|
+
self._add_log_entry(f"Waiting up to {timeout}s for docling-serve to start listening...")
|
|
349
356
|
|
|
350
357
|
for i in range(timeout):
|
|
351
358
|
await asyncio.sleep(1.0)
|
|
@@ -369,8 +376,8 @@ class DoclingManager:
|
|
|
369
376
|
)
|
|
370
377
|
self._starting = False
|
|
371
378
|
break
|
|
372
|
-
except:
|
|
373
|
-
|
|
379
|
+
except Exception as e:
|
|
380
|
+
self._add_log_entry(f"Error waiting for docling-serve: {e}")
|
|
374
381
|
|
|
375
382
|
if (i + 1) % 10 == 0:
|
|
376
383
|
self._add_log_entry(f"Waiting for startup... ({i + 1}/{timeout}s)")
|
|
@@ -382,9 +389,7 @@ class DoclingManager:
|
|
|
382
389
|
except OSError:
|
|
383
390
|
pass
|
|
384
391
|
|
|
385
|
-
self._add_log_entry(
|
|
386
|
-
f"Process PID: {self._process.pid}, Poll: {self._process.poll()}"
|
|
387
|
-
)
|
|
392
|
+
self._add_log_entry(f"Process PID: {self._process.pid}, Poll: {self._process.poll()}")
|
|
388
393
|
|
|
389
394
|
if self._process.poll() is not None:
|
|
390
395
|
# Process already exited - get return code and any output
|
|
@@ -447,7 +452,7 @@ class DoclingManager:
|
|
|
447
452
|
|
|
448
453
|
self._add_log_entry("Starting log file capture thread")
|
|
449
454
|
try:
|
|
450
|
-
with open(self._log_file_path
|
|
455
|
+
with open(self._log_file_path) as f:
|
|
451
456
|
while self._running and self._process and self._process.poll() is None:
|
|
452
457
|
line = f.readline()
|
|
453
458
|
if line:
|
|
@@ -466,7 +471,7 @@ class DoclingManager:
|
|
|
466
471
|
|
|
467
472
|
self._add_log_entry("Log file capture thread started")
|
|
468
473
|
|
|
469
|
-
async def stop(self) ->
|
|
474
|
+
async def stop(self) -> tuple[bool, str]:
|
|
470
475
|
"""Stop docling serve."""
|
|
471
476
|
if not self.is_running():
|
|
472
477
|
return False, "Docling serve is not running"
|
|
@@ -497,18 +502,14 @@ class DoclingManager:
|
|
|
497
502
|
# This is a process we recovered from PID file
|
|
498
503
|
pid_to_stop = self._load_pid()
|
|
499
504
|
if pid_to_stop and self._is_process_running(pid_to_stop):
|
|
500
|
-
self._add_log_entry(
|
|
501
|
-
f"Stopping process from PID file (PID: {pid_to_stop})"
|
|
502
|
-
)
|
|
505
|
+
self._add_log_entry(f"Stopping process from PID file (PID: {pid_to_stop})")
|
|
503
506
|
try:
|
|
504
507
|
os.kill(pid_to_stop, 15) # SIGTERM
|
|
505
508
|
# Wait a bit for graceful shutdown
|
|
506
509
|
await asyncio.sleep(2)
|
|
507
510
|
if self._is_process_running(pid_to_stop):
|
|
508
511
|
# Still running, force kill
|
|
509
|
-
self._add_log_entry(
|
|
510
|
-
f"Force killing process (PID: {pid_to_stop})"
|
|
511
|
-
)
|
|
512
|
+
self._add_log_entry(f"Force killing process (PID: {pid_to_stop})")
|
|
512
513
|
os.kill(pid_to_stop, 9) # SIGKILL
|
|
513
514
|
except Exception as e:
|
|
514
515
|
self._add_log_entry(f"Error stopping external process: {e}")
|
|
@@ -533,10 +534,10 @@ class DoclingManager:
|
|
|
533
534
|
|
|
534
535
|
async def restart(
|
|
535
536
|
self,
|
|
536
|
-
port:
|
|
537
|
-
host:
|
|
537
|
+
port: int | None = None,
|
|
538
|
+
host: str | None = None,
|
|
538
539
|
enable_ui: bool = False,
|
|
539
|
-
) ->
|
|
540
|
+
) -> tuple[bool, str]:
|
|
540
541
|
"""Restart docling serve."""
|
|
541
542
|
# Use current settings if not specified
|
|
542
543
|
if port is None:
|
|
@@ -560,7 +561,7 @@ class DoclingManager:
|
|
|
560
561
|
"""Add a manual log entry - useful for debugging."""
|
|
561
562
|
self._add_log_entry(f"MANUAL: {message}")
|
|
562
563
|
|
|
563
|
-
def get_logs(self, lines: int = 50) ->
|
|
564
|
+
def get_logs(self, lines: int = 50) -> tuple[bool, str]:
|
|
564
565
|
"""Get logs from the docling-serve process."""
|
|
565
566
|
if self.is_running():
|
|
566
567
|
with self._log_lock:
|
|
@@ -577,10 +578,6 @@ class DoclingManager:
|
|
|
577
578
|
|
|
578
579
|
async def follow_logs(self) -> AsyncIterator[str]:
|
|
579
580
|
"""Follow logs from the docling-serve process in real-time."""
|
|
580
|
-
# First yield status message and any existing logs
|
|
581
|
-
display_host = "localhost" if self._host == "0.0.0.0" else self._host
|
|
582
|
-
status_msg = f"Docling serve is running on http://{display_host}:{self._port}"
|
|
583
|
-
|
|
584
581
|
with self._log_lock:
|
|
585
582
|
if self._log_buffer:
|
|
586
583
|
yield "\n".join(self._log_buffer)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/services/conversation_persistence_service.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/ollama_embedding.json
RENAMED
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/ollama_llm.json
RENAMED
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/ollama_llm_text.json
RENAMED
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/watsonx_embedding.json
RENAMED
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/watsonx_llm.json
RENAMED
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/flows/components/watsonx_llm_text.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/openrag-documents/ibm_anthropic.pdf
RENAMED
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/_assets/openrag-documents/warmup_ocr.pdf
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openrag-0.5.0.dev33 → openrag-0.5.0.dev34}/src/tui/widgets/version_mismatch_warning_modal.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|