fix: skip Docling processing for structured data files (csv, xlsx, xls)#12487
fix: skip Docling processing for structured data files (csv, xlsx, xls)#12487jaehee-bae wants to merge 11 commits into
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
WalkthroughThe changes add support for treating XLSX/XLS files as structured data formats alongside CSV and Parquet. Updates include modifying configuration UI display for these formats, adjusting output handling, removing them from Docling-only processing, and introducing early-exit structured-data handling in the file processing pipeline. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 5 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py (1)
119-147: Use the real node template in these build-config tests.Hand-building
build_confighere makes the assertions insensitive to schema changes into_frontend_node(). Please start from the component’s actual frontend node and then callupdate_build_config()on that payload for the XLSX/XLS cases.Based on learnings, Test component build config updates by calling
to_frontend_node()to get the node template, then callingupdate_build_config()to apply configuration changes.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/tests/unit/components/files_and_knowledge/test_file_component.py` around lines 119 - 147, The tests hand-construct a build_config making them brittle; instead obtain the real frontend node template from the component and use its build_config when calling update_build_config. In the tests (test_advanced_mode_not_available_for_xlsx and test_advanced_mode_not_available_for_xls) instantiate FileComponent(), call FileComponent.to_frontend_node() to get the node template, extract the node's build_config (the settings/template field the component exposes), then pass that build_config into FileComponent.update_build_config([...], "path") with the appropriate file_path values and assert the advanced_mode.show/value results; this ensures the tests follow the actual schema produced by to_frontend_node().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/lfx/src/lfx/components/files_and_knowledge/file.py`:
- Around line 448-449: Replace the fragile endswith-based extension check with a
normalized-suffix comparison: build a set of normalized structured extensions
from self.STRUCTURED_DATA_EXTENSIONS (lowercased, no leading dot), and for each
file_path compute Path(file_path).suffix.lower().lstrip(".") and test
membership; update the logic that sets allow_advanced and
build_config["advanced_mode"]["show"] to use this check, and apply the same
normalization fix to the similar check used around the process_files()/lines
~508-509 (where file suffixes are tested) so both places use identical
normalized-suffix matching.
- Around line 1122-1128: The current fast-path short-circuits when any
structured file exists and returns rollup_data(structured_files,
structured_data), which drops non-structured files; change this so the shortcut
only runs when every input is structured (i.e., if len(structured_files) ==
len(file_list) then build structured_data using
Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) and return
self.rollup_data(structured_files, structured_data)); otherwise, do NOT return
early—convert structured_files to Data entries and merge them back with
non-structured files preserving the original file_list order (use file.path or
an index map) before calling rollup_data so no files are lost (refer to
structured_files, STRUCTURED_DATA_EXTENSIONS, SERVER_FILE_PATH_FIELDNAME,
rollup_data, Data, and file_list).
---
Nitpick comments:
In
`@src/backend/tests/unit/components/files_and_knowledge/test_file_component.py`:
- Around line 119-147: The tests hand-construct a build_config making them
brittle; instead obtain the real frontend node template from the component and
use its build_config when calling update_build_config. In the tests
(test_advanced_mode_not_available_for_xlsx and
test_advanced_mode_not_available_for_xls) instantiate FileComponent(), call
FileComponent.to_frontend_node() to get the node template, extract the node's
build_config (the settings/template field the component exposes), then pass that
build_config into FileComponent.update_build_config([...], "path") with the
appropriate file_path values and assert the advanced_mode.show/value results;
this ensures the tests follow the actual schema produced by to_frontend_node().
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: ea873474-4a36-4847-a12d-17f19535893c
📒 Files selected for processing (7)
src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.jsonsrc/backend/tests/unit/components/files_and_knowledge/test_file_component.pysrc/lfx/src/lfx/_assets/component_index.jsonsrc/lfx/src/lfx/components/files_and_knowledge/file.py
| # Handle structured data files (xlsx, xls, csv, parquet) - just pass through file path | ||
| # These are parsed by pandas in load_files_structured_helper, not here | ||
| structured_files = [f for f in file_list if f.path.suffix[1:].lower() in self.STRUCTURED_DATA_EXTENSIONS] | ||
| if structured_files: | ||
| # For structured data files, just return Data with file_path - no text parsing needed | ||
| structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files] | ||
| return self.rollup_data(structured_files, structured_data) |
There was a problem hiding this comment.
Don't short-circuit mixed batches here.
Line 1125 returns as soon as any structured file is present, but rollup_data() is called with structured_files only. A mixed upload like table.csv + notes.txt will silently drop the non-structured file from the result. This fast path needs to run only when every input is structured, or the structured and non-structured subsets need to be processed separately and merged back in order.
Possible guard if this shortcut is only intended for all-structured batches
- if structured_files:
+ if structured_files and len(structured_files) == len(file_list):
# For structured data files, just return Data with file_path - no text parsing needed
structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files]
return self.rollup_data(structured_files, structured_data)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| # Handle structured data files (xlsx, xls, csv, parquet) - just pass through file path | |
| # These are parsed by pandas in load_files_structured_helper, not here | |
| structured_files = [f for f in file_list if f.path.suffix[1:].lower() in self.STRUCTURED_DATA_EXTENSIONS] | |
| if structured_files: | |
| # For structured data files, just return Data with file_path - no text parsing needed | |
| structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files] | |
| return self.rollup_data(structured_files, structured_data) | |
| # Handle structured data files (xlsx, xls, csv, parquet) - just pass through file path | |
| # These are parsed by pandas in load_files_structured_helper, not here | |
| structured_files = [f for f in file_list if f.path.suffix[1:].lower() in self.STRUCTURED_DATA_EXTENSIONS] | |
| if structured_files and len(structured_files) == len(file_list): | |
| # For structured data files, just return Data with file_path - no text parsing needed | |
| structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files] | |
| return self.rollup_data(structured_files, structured_data) |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lfx/src/lfx/components/files_and_knowledge/file.py` around lines 1122 -
1128, The current fast-path short-circuits when any structured file exists and
returns rollup_data(structured_files, structured_data), which drops
non-structured files; change this so the shortcut only runs when every input is
structured (i.e., if len(structured_files) == len(file_list) then build
structured_data using Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)})
and return self.rollup_data(structured_files, structured_data)); otherwise, do
NOT return early—convert structured_files to Data entries and merge them back
with non-structured files preserving the original file_list order (use file.path
or an index map) before calling rollup_data so no files are lost (refer to
structured_files, STRUCTURED_DATA_EXTENSIONS, SERVER_FILE_PATH_FIELDNAME,
rollup_data, Data, and file_list).
2d6cbf7 to
c0aab93
Compare
75392f6 to
b106578
Compare
…s, parquet)
Structured data files were incorrectly routed through Docling, which is
designed for document parsing (PDFs, Word docs, etc.), causing an
"Advanced Parser" exception when uploading .xlsx, .xls, .csv, or .parquet
files via the File component.
Per official docs: "Advanced parsing is not needed for .csv, .xlsx, and
.parquet files because it is designed for document processing."
Changes:
- Remove .xls and .xlsx from DOCLING_ONLY_EXTENSIONS
- Add STRUCTURED_DATA_EXTENSIONS tuple (csv, xlsx, xls, parquet)
- Exclude structured data files from _is_docling_compatible()
- Route structured data files to pandas path, bypassing Docling
- Use STRUCTURED_DATA_EXTENSIONS constant in place of hardcoded tuples
- Add tests: Docling exclusion, advanced mode hiding, and output types
for xlsx/xls files
[autofix.ci] apply automated fixes
[autofix.ci] apply automated fixes (attempt 2/3)
fix: use Path.suffix for case-insensitive structured data extension checks
- Replace str.endswith() with Path().suffix.lower().lstrip('.') in
update_build_config and update_outputs for consistent, case-insensitive,
false-positive-safe extension matching (.XLSX, .XLS, .CSV now handled)
- Revert STRUCTURED_DATA_EXTENSIONS back to list for consistency
- Add parametrized tests for uppercase extensions (XLSX, XLS, CSV, PARQUET)
- Add mixed batch upload scenarios (structured + docling files)
- Add false-positive tests (e.g. myxlsx.txt must not match as structured)
test: remove TestStructuredDataExtensions class
fix: remove unnecessary structured data early return in process_files
csv/xlsx/xls/parquet are not in _is_docling_compatible(), so they
already bypass Docling without the early return. The shortcut also
broke S3 flows by skipping the get_file() download step.
fix: remove parquet from STRUCTURED_DATA_EXTENSIONS
… check for structured data routing
…D_EXTENSIONS Define _STRUCTURED_DATA_EXTENSIONS and _TEXT_EXTENSIONS at module level to resolve Python 3 class scope limitation with list comprehensions, and prevent csv/xls/xlsx from appearing twice in VALID_EXTENSIONS.
… order csv moved to STRUCTURED_DATA_EXTENSIONS, so compact display now shows json, pdf, txt as the first three types. hover list updated accordingly.
8598cb8 to
4f0e841
Compare
Summary
Root Cause
.xlsand.xlsxwere listed inDOCLING_ONLY_EXTENSIONS-
.csv,.xls,.xlsxwere included in _is_docling_compatible() via the Docling extension setChanges
.xlsand.xlsxfromDOCLING_ONLY_EXTENSIONS.csv,.xls,.xlsxfrom the Docling-compatible extension check in_is_docling_compatible()STRUCTURED_DATA_EXTENSIONS = ["csv", "xls", "xlsx"]as a class constant (backed by module-level _STRUCTURED_DATA_EXTENSIONS)TEXT_EXTENSIONSto exclude structured data extensions via module-level constantSTRUCTURED_DATA_EXTENSIONSlookupsTest plan
VALID_EXTENSIONScorrectly reflects all three extension groups without duplicationVALID_EXTENSIONSorderSummary by CodeRabbit
Release Notes
New Features
Tests