fix(pipelines): align incremental store schema guard with the full run - #250
abhishekKokadwar wants to merge 2 commits into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
`store_milvus` and `store_milvus_incremental` both write into the same `kubeflow_docs` collection, but only the full pipeline honoured `embedding_dim` and verified an existing collection's schema. `store_milvus_incremental` took no `embedding_dim` parameter at all and hardcoded `dim=768`, so pointing the stack at a non-768 TEI model made the two components disagree: whichever ran first fixed the dimension for the other, and the incremental run then inserted vectors of the wrong width into a collection it had silently created at 768. Adds `embedding_dim` to the component and the pipeline (defaulting to `DEFAULT_EMBEDDING_DIM`), uses it for the created vector field, and ports the versioned schema-compatibility check from `store_milvus` so a mismatch fails with the same actionable error instead of at insert time. Also floors `nlist` at 32 in the docs and code pipelines. Milvus recommends `nlist` in [32, 4096]; `min(1024, len(records))` would build a near-degenerate index on a small first run. The incremental and issues pipelines already carry `max(100, ...)` and `max(16, ...)` floors, so this only brings the two remaining copies in line. CI compiled three of the four pipelines; since this change touches `incremental-pipeline.py`, the missing KFP compile step is added too. Tests: adds `tests/test_incremental_pipeline.py`, the first coverage for this pipeline, pinning the created dimension, the mismatch rejection, and acceptance of a collection the full pipeline just created. Signed-off-by: Abhishek <abhikokadwar2@gmail.com>
Three test modules abort at collection on main:
ImportError: cannot import name 'clean_content' from 'utils'
(unknown location)
`pytest` exits 2, so the whole suite stops before running and both
workflows that invoke it are red.
kubeflow#249 moved `utils.py` into `pipelines/utils/`. These modules put only
`pipelines/` on `sys.path`, where the sibling directory of the same name
now shadows the module as a namespace package — `utils.__file__` is None
and `utils.__path__` is the directory, so no attribute resolves.
The pipelines themselves already handle this with a `_UTILS_DIR` entry
pointing at `pipelines/utils`; this applies the same thing to the tests
that import `utils` directly.
Recovers 72 tests across the four affected modules. The 7 failures and 63
errors that remain are pre-existing on dedbc84 and are not touched here:
`test_mcp_server.py` references `server.client`, removed when kubeflow#249 split
the MCP server, and `test_docs_pipeline.py` exercises the `store_milvus`
component that kubeflow#249 replaced with `utils/milvus_store.py`.
Signed-off-by: Abhishek <abhikokadwar2@gmail.com>
cb0a06a to
efad4a4
Compare
|
Rebased onto
|
| v4 requires, incremental never supplies | document_id, sparse_vector, title, section_path, doc_type, version, release_date |
| incremental inserts, v4 has no such field | file_unique_id, repo_name, file_name, last_updated |
The schemas are now disjoint rather than merely mismatched, and sparse_vector is the field milvus_search.py needs for BM25 — collection_has_bm25() gates hybrid search on its presence. So if the incremental pipeline ever created the collection, hybrid retrieval would silently degrade to dense-only.
With the guard in this PR, running it against the live v4 collection fails fast instead:
Schema version mismatch for kubeflow_docs. Expected compatible v=1;
description='RAG lean hybrid collection for documentation (v=4, hybrid=bm25+dense)' ...
That is the right outcome — it must not write v1 rows into a v4 collection — but it does mean this PR makes explicit that the incremental pipeline no longer has a valid target. Two reasonable directions, and I would rather have a maintainer pick than guess:
- Land this as a guard. The component fails loudly instead of corrupting the collection, and the v4 rewrite is a follow-up.
- Retire it.
legacy/pipelines/incremental-pipeline.pyalready exists as a copy; if the live one is not meant to be v4-aware, deleting it is simpler than guarding it.
I have no stake in which — happy to convert this to the deletion if that is the call.
Verification
pytest tests/test_incremental_pipeline.py— 3 passed; still fails onmainwithout the fix- The three repaired modules plus mine — 72 passed
incremental-pipeline.pyKFP-compiles, along withissues-andcode-.kubeflow-pipeline.pyneedspymilvuslocally, which I do not have installed; it is unmodified by this PR- DCO signed on both commits
Still blocked on CI
Workflows are still awaiting maintainer approval, so none of this has been confirmed by CI — including ruff, which I still cannot run locally (Application Control policy blocks the binary). Given main is red at the moment, approving the workflows here would also show whether efad4a4 turns the suite green.
|
Closing this, with a correction to my previous comment. The v1/v4 schema mismatch is already documented, and I overstated it. #249 records it in two places:
So it's a known, intentional limitation, not a new finding. Two claims above were also wrong:
Given that, a schema guard for a pipeline you've designated reference-only isn't worth review time, so I'm withdrawing it. The one part that did matter is split out as #258: since #249, One small docs/tree inconsistency, in case it's useful: |
Why
store_milvus(full pipeline) andstore_milvus_incrementalboth write into the samekubeflow_docscollection, but only the full one honouredembedding_dimor verified an existing collection's schema.store_milvus_incrementaltook noembedding_dimparameter at all and hardcodeddim=768. Point the stack at a non-768 TEI model and the two components disagree: whichever runs first fixes the dimension for the other, and the incremental run inserts vectors of the wrong width into a collection it silently created at 768 — with no guard to catch it, unlike its sibling.This is a port, not a new design. The guard already exists in
store_milvusand is copied field-for-field, so both components now accept and reject exactly the same schemas.What
pipelines/incremental-pipeline.pyembedding_dimon the component and the pipeline (defaultDEFAULT_EMBEDDING_DIM); created vector field uses it; versioned schema-compatibility check ported fromstore_milvuspipelines/kubeflow-pipeline.py,pipelines/code-pipeline.pynlistfloored at 32pipelines/README.mdembedding_dimrow in the incremental parameter table.github/workflows/oke-cicd.yamlincremental-pipeline.pytests/test_incremental_pipeline.pyWhy the nlist change
Milvus recommends
nlistin[32, 4096].min(1024, len(records))builds a near-degenerate index on a small first run. The incremental and issues pipelines already carrymax(100, ...)andmax(16, ...)floors, so this only brings the two remaining copies in line.To be precise about severity: this is latent, not a live crash.
create_indexsits insideif records:, sonlist=0is unreachable, and a real docs run indexes thousands of chunks and gets 1024 anyway.Verification
Written test-first. Against
mainthe new tests fail with:After the change all three pass. I also mutation-checked that they actually bite rather than passing either way:
dim=embedding_dimreverted todim=768assert 768 == 1024vector_dim != embedding_dimdropped from the guardpytest: 176 passed on this branch vs 173 onmain, same environment with the KFP SDK installed — 3 new tests, 0 regressionskubeflow-pipeline.py,issues-pipeline.py,code-pipeline.py,incremental-pipeline.pypython -m compileallover all six paths thePython compile checkjob uses: clean.yamlartifacts are gitignored; none committedOne caveat, stated rather than glossed over:
ruffcould not execute in my environment (Windows Application Control policy blocks the binary — module, executable, and shell invocation all refused). I verified withpyflakesinstead, which covers ruff's selectedFrules: zero findings on the new test file. The only hits anywhere are pre-existingF403/F405star imports inpipelines/*.py, whichpyproject.tomlalready ignores for that path.pycodestyle --select=E4,E7,E9is also clean and my longest added line is 114 characters against the 120 limit. CI runs the real thing and will confirm.Relationship to #100
#100 proposed this same idea and its description lists
store_milvus_incrementalamong its changes. Worth flagging clearly so this is not read as duplicate work:kubeflow-pipeline.py— the incremental change it describes was never includedstore_milvushalf it does contain has already landed upstream via fix: stop A2A answers truncating at 30s, and ground/cite agent replies #234, which is where theembedding_dimparameter this PR matches came from6b4caba(2026-03-02), now 15 commits behind, and editspipelines/..., a directory that no longer exists since the move todocs-agent-mcp/pipelines/So the remaining gap was the incremental component, which is what this PR closes. I kept upstream's
embedding_dimspelling rather than #100'sembedding_dimensionfor consistency withstore_milvus. Happy to close this if the author would prefer to refresh #100 instead.Notes for reviewers
PR Safetyskips them (it installs onlyrequirements-test.txt), exactly as it already skips the existing component tests.Build, Test, and Deploy to OKEinstallskfp kfp-kubernetesand runspyteston every pull request, so they do execute there. Happy to addkfptorequirements-test.txtif you would rather both jobs cover it.incremental-pipeline.py. Since this PR modifies that file, CI would otherwise have gone green without ever compiling the change. fix(pipelines): cite published docs URLs and align the incremental cleaner with the full run #244 flagged the same gap independently.store_milvus_incrementalwas explicitly left out of scope by fix(pipelines): cite published docs URLs and align the incremental cleaner with the full run #244 ("still hardcodesdim=768and has no schema check, unlikestore_milvus"). This closes that and deliberately touches nothing else in the file. TheZeroDivisionErrorin the same component's chunk-countprintis left to bug(pipelines): ZeroDivisionError in chunk_and_embed_incremental when text splitter returns empty chunks #163/fix(pipelines): guard against ZeroDivisionError in chunk_and_embed_incremental when chunk list is empty #164.oke-cicd.yamlcompile step. One-line overlap, trivial in either order — happy to drop mine if fix(pipelines): cite published docs URLs and align the incremental cleaner with the full run #244 lands first.embedding_dim=768: the guard accepts any collection the full pipeline created, and the new default matches what was previously hardcoded. The dimension only becomes configurable for operators who switch embedding models.