fix(unstructured): keep table structure instead of flattening it to prose - #1263
fix(unstructured): keep table structure instead of flattening it to prose#1263cbcoutinho wants to merge 4 commits into
Conversation
…rose A Table element's `text` is every cell run together in one line, so the row/column association is lost -- a questionnaire becomes an unsearchable wall of words. The grid only survives in `metadata.text_as_html`, which the processor was discarding. Render that HTML as a markdown table via the existing `html_to_markdown` helper (markdownify is already a dependency). Measured on a 4-column questionnaire: 0 markdown table rows before, 18 after. `parse_mode` now reports "markdown" once a table has been rendered as one, so `utils/document_parser` labels the result correctly; documents without tables keep the previous "text_only" path byte for byte. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Claude finished @cbcoutinho's task in 2m 12s —— View job Review complete ✅
This PR is on its third round; the two prior rounds already caught and fixed the two substantive issues (the What the diff does
Correctness — verified by hand
Test coverageSix unit tests, and they hit the branches that matter: happy-path table→markdown, table without Minor / non-blocking observations
No changes requested. |
Review follow-up on #1263. Gate the `text_as_html` branch on `type == "Table"`. The API only populates that key for tables today, so this is not a behaviour change -- verified against a live container, still 18 markdown rows on the questionnaire -- but rendering HTML found on some other element as a table would misread it, while falling through to `text` degrades safely. Add the two uncovered paths the reviewer named: a Table with no `text_as_html` at all (its flattened text must still be indexed), and HTML on a non-Table element (must keep its own text rather than becoming a table). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Round-1 findings addressed in
3333 unit tests pass; ruff/ty green. Sonar reports no issues on this PR. |
… import vector Round-2 review follow-up on #1263. `document_processors/unstructured.py` imported `vector.html_processor`, which runs `vector/__init__.py` and pulls `qdrant-client` and `langchain-text-splitters` onto the document stack's import path. That is the cross-layer coupling issue #877 removed, reintroduced from the other side: `vector/spool.py` says outright that it lives where it does "because `document_processors` must not import `vector`", and `vector/processor.py` keeps the document stack off its own import path with TYPE_CHECKING and lazy imports for the same reason. Reaching for the existing helper was the right instinct and the wrong direction. The implementation moves to `utils/html.py`, which depends only on markdownify; `vector/html_processor.py` re-exports it so the four vector-side call sites are untouched. A test asserts the shared module names no vector import, so the boundary fails loudly rather than by review. Also: `html_to_markdown` returns regex-stripped *prose* when markdownify raises, and that string is truthy, so it was counted as a converted table and reported `parse_mode="markdown"` over exactly the flattened output this change exists to avoid. The branch now requires a pipe in the result, and prefers the element's own text otherwise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Round-2 findings addressed in
3335 unit tests pass; ruff/ty green. CI on this branch is green (the earlier red was the GitHub Actions outage, not the code). |
SonarCloud CRITICAL python:S3776 — the table-vs-text fallback chain pushed `_make_api_request`'s cognitive complexity to 18 against a limit of 15. The nesting was mine, added over two review rounds (the Table-type gate, then the pipe check for the markdownify fallback). `_element_text` now answers "what does this element contribute, and did it count as a rendered table" in one place, leaving the request method to accumulate. Behaviour is unchanged — the same 18 markdown rows come back from a live unstructured container, and the seven existing tests pass untouched. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Follow-up in Extracted Gate is OK on all four PRs in the stack now. |



A Table element's
textis every cell run together in one line, so therow/column association is lost -- a questionnaire becomes an unsearchable
wall of words. The grid only survives in
metadata.text_as_html, which theprocessor was discarding.
Render that HTML as a markdown table via the existing
html_to_markdownhelper (markdownify is already a dependency). Measured on a 4-column
questionnaire: 0 markdown table rows before, 18 after.
parse_modenow reports "markdown" once a table has been rendered as one,so
utils/document_parserlabels the result correctly; documents withouttables keep the previous "text_only" path byte for byte.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com
Stack created with GitHub Stacks CLI • Give Feedback 💬
This PR was generated with the help of AI, and reviewed by a Human