mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 08:57:31 +08:00
fix: disable advanced mode in read file components on cloud (#11124)
* disable advanced mode * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix ruff errors * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * add a helper method to handle cloud env * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix ruff errors * [autofix.ci] apply automated fixes * disable docling components on cloud * fix ruff errors * [autofix.ci] apply automated fixes * fix ruff errors * template updates * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -644,3 +644,77 @@ class TestFileComponentToolMode:
|
||||
)
|
||||
new_temp_files = temp_files_after - temp_files_before
|
||||
assert len(new_temp_files) == 0, f"Temp files not cleaned up: {new_temp_files}"
|
||||
|
||||
|
||||
class TestFileComponentCloudEnvironment:
|
||||
"""Test FileComponent behavior in cloud environments."""
|
||||
|
||||
def test_advanced_mode_disabled_in_cloud(self, monkeypatch):
|
||||
"""Test that advanced_mode and all Docling fields are disabled when ASTRA_CLOUD_DISABLE_COMPONENT is set."""
|
||||
# Set the environment variable to simulate cloud environment
|
||||
monkeypatch.setenv("ASTRA_CLOUD_DISABLE_COMPONENT", "true")
|
||||
|
||||
component = FileComponent()
|
||||
build_config = {
|
||||
"advanced_mode": {"show": True, "value": False},
|
||||
"pipeline": {"show": False},
|
||||
"ocr_engine": {"show": False},
|
||||
"doc_key": {"show": False},
|
||||
"md_image_placeholder": {"show": False},
|
||||
"md_page_break_placeholder": {"show": False},
|
||||
"path": {"file_path": ["document.pdf"]},
|
||||
}
|
||||
|
||||
result = component.update_build_config(build_config, ["document.pdf"], "path")
|
||||
|
||||
# In cloud, advanced_mode should be hidden regardless of file type
|
||||
assert result["advanced_mode"]["show"] is False, "advanced_mode should be hidden in cloud"
|
||||
assert result["advanced_mode"]["value"] is False, "advanced_mode value should be False in cloud"
|
||||
# All related fields should be hidden
|
||||
assert result["pipeline"]["show"] is False
|
||||
assert result["ocr_engine"]["show"] is False
|
||||
assert result["ocr_engine"]["value"] == "None"
|
||||
assert result["doc_key"]["show"] is False
|
||||
assert result["md_image_placeholder"]["show"] is False
|
||||
assert result["md_page_break_placeholder"]["show"] is False
|
||||
|
||||
def test_advanced_mode_toggle_disabled_in_cloud(self, monkeypatch):
|
||||
"""Test that toggling advanced_mode in cloud doesn't show Docling fields."""
|
||||
monkeypatch.setenv("ASTRA_CLOUD_DISABLE_COMPONENT", "true")
|
||||
|
||||
component = FileComponent()
|
||||
build_config = {
|
||||
"advanced_mode": {"show": True, "value": True},
|
||||
"pipeline": {"show": False},
|
||||
"ocr_engine": {"show": False},
|
||||
"doc_key": {"show": False},
|
||||
"md_image_placeholder": {"show": False},
|
||||
"md_page_break_placeholder": {"show": False},
|
||||
}
|
||||
|
||||
result = component.update_build_config(build_config, field_value=True, field_name="advanced_mode")
|
||||
|
||||
# Even if advanced_mode is toggled to True, it should be disabled in cloud
|
||||
assert result["advanced_mode"]["show"] is False
|
||||
assert result["advanced_mode"]["value"] is False
|
||||
# All Docling fields should remain hidden
|
||||
assert result["pipeline"]["show"] is False
|
||||
assert result["ocr_engine"]["show"] is False
|
||||
assert result["ocr_engine"]["value"] == "None"
|
||||
|
||||
def test_pipeline_change_disabled_in_cloud(self, monkeypatch):
|
||||
"""Test that changing pipeline in cloud doesn't show OCR engine."""
|
||||
monkeypatch.setenv("ASTRA_CLOUD_DISABLE_COMPONENT", "true")
|
||||
|
||||
component = FileComponent()
|
||||
build_config = {
|
||||
"advanced_mode": {"show": False, "value": False},
|
||||
"pipeline": {"show": False},
|
||||
"ocr_engine": {"show": False, "value": "easyocr"},
|
||||
}
|
||||
|
||||
result = component.update_build_config(build_config, "standard", "pipeline")
|
||||
|
||||
# Even if pipeline is set to "standard", OCR engine should be disabled in cloud
|
||||
assert result["ocr_engine"]["show"] is False
|
||||
assert result["ocr_engine"]["value"] == "None"
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -3,35 +3,69 @@ from __future__ import annotations
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from lfx.components._importing import import_mod
|
||||
from lfx.utils.validate_cloud import is_astra_cloud_environment
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .chunk_docling_document import ChunkDoclingDocumentComponent
|
||||
from .docling_inline import DoclingInlineComponent
|
||||
from .docling_remote import DoclingRemoteComponent
|
||||
from .export_docling_document import ExportDoclingDocumentComponent
|
||||
from .chunk_docling_document import ChunkDoclingDocumentComponent # noqa: F401
|
||||
from .docling_inline import DoclingInlineComponent # noqa: F401
|
||||
from .docling_remote import DoclingRemoteComponent # noqa: F401
|
||||
from .export_docling_document import ExportDoclingDocumentComponent # noqa: F401
|
||||
|
||||
_dynamic_imports = {
|
||||
"ChunkDoclingDocumentComponent": "chunk_docling_document",
|
||||
"DoclingInlineComponent": "docling_inline",
|
||||
"DoclingRemoteComponent": "docling_remote",
|
||||
"ExportDoclingDocumentComponent": "export_docling_document",
|
||||
}
|
||||
|
||||
__all__ = [
|
||||
_all_components = [
|
||||
"ChunkDoclingDocumentComponent",
|
||||
"DoclingInlineComponent",
|
||||
"DoclingRemoteComponent",
|
||||
"ExportDoclingDocumentComponent",
|
||||
]
|
||||
|
||||
_all_dynamic_imports = {
|
||||
"ChunkDoclingDocumentComponent": "chunk_docling_document",
|
||||
"DoclingInlineComponent": "docling_inline",
|
||||
"DoclingRemoteComponent": "docling_remote",
|
||||
"ExportDoclingDocumentComponent": "export_docling_document",
|
||||
}
|
||||
|
||||
# Components that require local Docling/EasyOCR dependencies (disabled in cloud)
|
||||
_cloud_disabled_components = {
|
||||
"ChunkDoclingDocumentComponent",
|
||||
"DoclingInlineComponent",
|
||||
"ExportDoclingDocumentComponent",
|
||||
}
|
||||
|
||||
|
||||
def _get_available_components() -> list[str]:
|
||||
"""Get list of available components, filtering out cloud-disabled ones."""
|
||||
if is_astra_cloud_environment():
|
||||
# Only show DoclingRemoteComponent (Docling Serve) in cloud
|
||||
return [comp for comp in _all_components if comp not in _cloud_disabled_components]
|
||||
return _all_components
|
||||
|
||||
|
||||
def _get_dynamic_imports() -> dict[str, str]:
|
||||
"""Get dynamic imports dict, filtering out cloud-disabled ones."""
|
||||
if is_astra_cloud_environment():
|
||||
# Only allow DoclingRemoteComponent (Docling Serve) in cloud
|
||||
return {k: v for k, v in _all_dynamic_imports.items() if k not in _cloud_disabled_components}
|
||||
return _all_dynamic_imports
|
||||
|
||||
|
||||
# Dynamically set __all__ and _dynamic_imports based on cloud environment
|
||||
__all__: list[str] = _get_available_components() # noqa: PLE0605
|
||||
_dynamic_imports: dict[str, str] = _get_dynamic_imports()
|
||||
|
||||
|
||||
def __getattr__(attr_name: str) -> Any:
|
||||
"""Lazily import docling components on attribute access."""
|
||||
if attr_name not in _dynamic_imports:
|
||||
# Check if component is available (not disabled in cloud)
|
||||
if is_astra_cloud_environment() and attr_name in _cloud_disabled_components:
|
||||
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
||||
raise AttributeError(msg)
|
||||
|
||||
if attr_name not in _all_dynamic_imports:
|
||||
msg = f"module '{__name__}' has no attribute '{attr_name}'"
|
||||
raise AttributeError(msg)
|
||||
try:
|
||||
result = import_mod(attr_name, _dynamic_imports[attr_name], __spec__.parent)
|
||||
result = import_mod(attr_name, _all_dynamic_imports[attr_name], __spec__.parent)
|
||||
except (ModuleNotFoundError, ImportError, AttributeError) as e:
|
||||
msg = f"Could not import '{attr_name}' from '{__name__}': {e}"
|
||||
raise AttributeError(msg) from e
|
||||
@ -40,4 +74,4 @@ def __getattr__(attr_name: str) -> Any:
|
||||
|
||||
|
||||
def __dir__() -> list[str]:
|
||||
return list(__all__)
|
||||
return _get_available_components()
|
||||
|
||||
@ -189,7 +189,8 @@ class FileComponent(BaseFileComponent):
|
||||
"Enable advanced document processing and export with Docling for PDFs, images, and office documents. "
|
||||
"Note that advanced document processing can consume significant resources."
|
||||
),
|
||||
show=True,
|
||||
# Disabled in cloud
|
||||
show=not is_astra_cloud_environment(),
|
||||
),
|
||||
DropdownInput(
|
||||
name="pipeline",
|
||||
@ -345,6 +346,20 @@ class FileComponent(BaseFileComponent):
|
||||
"""Return the list of currently selected file paths from the template."""
|
||||
return template.get("path", {}).get("file_path", [])
|
||||
|
||||
def _disable_docling_fields_in_cloud(self, build_config: dict[str, Any]) -> None:
|
||||
"""Disable all Docling-related fields in cloud environments."""
|
||||
if "advanced_mode" in build_config:
|
||||
build_config["advanced_mode"]["show"] = False
|
||||
build_config["advanced_mode"]["value"] = False
|
||||
# Hide all Docling-related fields
|
||||
docling_fields = ("pipeline", "ocr_engine", "doc_key", "md_image_placeholder", "md_page_break_placeholder")
|
||||
for field in docling_fields:
|
||||
if field in build_config:
|
||||
build_config[field]["show"] = False
|
||||
# Also disable OCR engine specifically
|
||||
if "ocr_engine" in build_config:
|
||||
build_config["ocr_engine"]["value"] = "None"
|
||||
|
||||
def update_build_config(
|
||||
self,
|
||||
build_config: dict[str, Any],
|
||||
@ -422,25 +437,50 @@ class FileComponent(BaseFileComponent):
|
||||
if field_name == "path":
|
||||
paths = self._path_value(build_config)
|
||||
|
||||
# If all files can be processed by docling, do so
|
||||
allow_advanced = all(not file_path.endswith((".csv", ".xlsx", ".parquet")) for file_path in paths)
|
||||
build_config["advanced_mode"]["show"] = allow_advanced
|
||||
if not allow_advanced:
|
||||
build_config["advanced_mode"]["value"] = False
|
||||
for f in ("pipeline", "ocr_engine", "doc_key", "md_image_placeholder", "md_page_break_placeholder"):
|
||||
if f in build_config:
|
||||
build_config[f]["show"] = False
|
||||
# Disable in cloud environments
|
||||
if is_astra_cloud_environment():
|
||||
self._disable_docling_fields_in_cloud(build_config)
|
||||
else:
|
||||
# If all files can be processed by docling, do so
|
||||
allow_advanced = all(not file_path.endswith((".csv", ".xlsx", ".parquet")) for file_path in paths)
|
||||
build_config["advanced_mode"]["show"] = allow_advanced
|
||||
if not allow_advanced:
|
||||
build_config["advanced_mode"]["value"] = False
|
||||
docling_fields = (
|
||||
"pipeline",
|
||||
"ocr_engine",
|
||||
"doc_key",
|
||||
"md_image_placeholder",
|
||||
"md_page_break_placeholder",
|
||||
)
|
||||
for field in docling_fields:
|
||||
if field in build_config:
|
||||
build_config[field]["show"] = False
|
||||
|
||||
# Docling Processing
|
||||
elif field_name == "advanced_mode":
|
||||
for f in ("pipeline", "ocr_engine", "doc_key", "md_image_placeholder", "md_page_break_placeholder"):
|
||||
if f in build_config:
|
||||
build_config[f]["show"] = bool(field_value)
|
||||
if f == "pipeline":
|
||||
build_config[f]["advanced"] = not bool(field_value)
|
||||
# Disable in cloud environments - don't show Docling fields even if advanced_mode is toggled
|
||||
if is_astra_cloud_environment():
|
||||
self._disable_docling_fields_in_cloud(build_config)
|
||||
else:
|
||||
docling_fields = (
|
||||
"pipeline",
|
||||
"ocr_engine",
|
||||
"doc_key",
|
||||
"md_image_placeholder",
|
||||
"md_page_break_placeholder",
|
||||
)
|
||||
for field in docling_fields:
|
||||
if field in build_config:
|
||||
build_config[field]["show"] = bool(field_value)
|
||||
if field == "pipeline":
|
||||
build_config[field]["advanced"] = not bool(field_value)
|
||||
|
||||
elif field_name == "pipeline":
|
||||
if field_value == "standard":
|
||||
# Disable in cloud environments - don't show OCR engine even if pipeline is changed
|
||||
if is_astra_cloud_environment():
|
||||
self._disable_docling_fields_in_cloud(build_config)
|
||||
elif field_value == "standard":
|
||||
build_config["ocr_engine"]["show"] = True
|
||||
build_config["ocr_engine"]["value"] = "easyocr"
|
||||
else:
|
||||
@ -1043,10 +1083,16 @@ class FileComponent(BaseFileComponent):
|
||||
for file in file_list:
|
||||
extension = file.path.suffix[1:].lower()
|
||||
if extension in self.DOCLING_ONLY_EXTENSIONS:
|
||||
msg = (
|
||||
f"File '{file.path.name}' has extension '.{extension}' which requires "
|
||||
f"Advanced Parser mode. Please enable 'Advanced Parser' to process this file."
|
||||
)
|
||||
if is_astra_cloud_environment():
|
||||
msg = (
|
||||
f"File '{file.path.name}' has extension '.{extension}' which requires "
|
||||
f"Advanced Parser mode. Advanced Parser is not available in cloud environments."
|
||||
)
|
||||
else:
|
||||
msg = (
|
||||
f"File '{file.path.name}' has extension '.{extension}' which requires "
|
||||
f"Advanced Parser mode. Please enable 'Advanced Parser' to process this file."
|
||||
)
|
||||
self.log(msg)
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user