Fix for Maintain Table Formatting in Markdown Files #1645#1815
Fix for Maintain Table Formatting in Markdown Files #1645#1815pdubey28-sketch wants to merge 3 commits into
Conversation
|
Hi @pdubey28-sketch 👋 — thanks a lot for this, and especially for the really thorough write-up. The document-order fix and the row-boundary table splitting are exactly the right approach, and the conservative detection rules are nicely done. 🙌 Just two things I'd love your help understanding before we merge — both questions, not blockers:
No rush on any of this — happy to pair on it if that's easier. Thanks again for the great contribution! 🚀 |
|
@dimitri-tombroff Please find my answers inline
Q1 – Leading Pipe (|) Table Detection Mismatch Q2 – chunk_index Population |
Pull Request — Fix for Maintain Table Formatting in Markdown Files (#1645)
Branch:
pdubey28-sketch:Issue#1645→pdubey28-sketch:swiftCommit:
c8be3eb6066118b76bc2c2ae3d1d0f0308658e8d(single commit, 4 files, +256 / −26)1. What problem does this solve — and where is it tracked?
ID: no ID — mechanical fix. GitHub issue
ThalesGroup/fred#1645is the source of truth; no entry exists indocs/swift/data/id-legend.yaml. If tracking is wanted, propose adding aRUNTIME-xxrow (adapter dedup/sort) and a knowledge-flow ingestion row before merge.Problem in one sentence: Markdown tables ingested into the RAG store were returned to the LLM out of document order and with broken header/row structure, so row-level questions over tables (e.g. "what is the default of
property25?") returned wrong or empty answers.Backlog ref: none — no
[ ]item existed for this bug. Recommend adding one before merge.2. Before you wrote a single line of code
RFC written? Not required — mechanical fix. The change restores the documented "preserve tables" behaviour of
SemanticSplitterfor.md/.txtinputs and repairs a half-applied chunk-ordering fix in the v2 runtime adapter. No new contract or endpoint; one optional internal DTO field (VectorSearchHit.chunk_index) that the adapter was already trying to read.Plan presented to the team before implementation? No — the bug was diagnosed and patched in a single debugging session from a reproducible failure (
large-table-test_pd1.mdreturning tables in similarity-score order with repeated headers). The plan is captured retroactively indocs/MARKDOWN_TABLE_INGESTION_FIX.md.Confirmation received? No prior confirmation — this PR is the request for review.
3. What you built
One commit (
c8be3eb) with two coordinated fixes for the same regression:SemanticSplitter. Added_auto_annotate_unmarked_tablesso plain-markdown and text inputs get the same<!-- TABLE_START -->/<!-- TABLE_END -->wrapping thatPdfMarkdownProcessorandDocxMarkdownProcessoralready emit (detection is conservative: a pipe row must be immediately followed by a markdown separator row; fenced code blocks and quoted blocks are skipped). Tables that fit inchunk_sizeare emitted as a single atomic chunk. Oversized tables fall back to_split_large_table, which splits only at row boundaries and repeats the header + separator in every part, stampingblock_type="markdown_table",table_id,table_part,row_start,row_end.VectorSearchHit+_to_hit+_invoke_knowledge_search. Added the missingchunk_index: Optional[int] = Nonefield toVectorSearchHit, populated it from doc metadata inVectorSearchService._to_hit(), and added aprev_content_is_tableguard to the dedup loop in the v2-runtime adapter so the first table chunk keeps its header even when an intro/text chunk from the same document precedes it. The sort bychunk_indexin_invoke_knowledge_searchwas already in place but silently raisingAttributeError; it now works.Files changed
apps/knowledge-flow-backend/knowledge_flow_backend/core/processors/output/vectorization_processor/semantic_splitter.pyapps/knowledge-flow-backend/knowledge_flow_backend/features/vector_search/vector_search_service.pylibs/fred-core/fred_core/store/vector_search.pylibs/fred-runtime/fred_runtime/integrations/v2_runtime/adapters.py4. Proof of quality
Tests added or updated:
test_small_table_remains_in_one_chunkapps/knowledge-flow-backend/tests/processors/output/vectorization_processor/test_semantic_splitter_tables.pytest_text_before_and_after_table_chunked_separatelytest_large_table_splits_only_on_row_boundaries_and_repeats_headertest_split_preserves_row_order_in_metadatarow_start/row_endcontiguous and monotonictest_multiple_tables_are_each_preserved_independentlytest_pipe_text_without_separator_row_is_not_treated_as_tabletest_fenced_code_block_with_pipes_is_not_treated_as_tabletest_auto_annotation_does_not_misdetect_separator_inside_texttest_pre_annotated_tables_are_idempotentRetrieval-side change is covered by 5 manual assertions in
C:\tmp\probe_fix_verify.py(all pass). No formal pytest exists yet forFredKnowledgeSearchToolInvoker._invoke_knowledge_search(would require mocking the vector-search HTTP client) — recommended as a follow-up.make code-qualityoutput:Raw
basedpyrightoutput (required if a touched package keeps a non-empty baseline file):make testoutput:5. Docs updated
[ ]item is now donedocs/MARKDOWN_TABLE_INGESTION_FIX.md(new) — splitter behaviour + auto-annotation rulesexecution.py,agent_app.py, OpenAPI)VectorSearchHit.chunk_indexis an optional internal DTO field6. Close-out statement
7. Risk and rollback
What breaks if this is wrong?
_auto_annotate_unmarked_tablesmisclassifies pipe-using prose as a table, that block becomes a single atomic chunk instead of being prose-split. Detection is conservative (pipe row must be immediately followed by a markdown separator row of only|,-,:, whitespace) and covered bytest_pipe_text_without_separator_row_is_not_treated_as_tableandtest_fenced_code_block_with_pipes_is_not_treated_as_table.chunk_index. The adapter sort falls back to999_999for hits missingchunk_index, so legacy-indexed documents sort to the end of the result list. Acceptable degradation; re-ingestion restores correct ordering.prev_content_is_tableguard strips a header only when the immediately preceding same-document chunk was also a table chunk. Worst case: a continuation chunk keeps a duplicate header (cosmetic), not a wrong answer.How do we roll back?
Revert commit
c8be3eb(the four touched files + the new test file). The splitter change is process-local — restartknowledge-flow-backendafter revert. Already-ingested documents do not need re-ingestion to roll back (the new metadata fields are additive), but tables ingested under the new splitter will revert to the previous broken behaviour on next retrieval.