Stage 3: the caller supplies the bundle and the context budget - #185
Merged
Merged
Conversation
Two module-level facts become arguments, closing out the retriever
rewrite (FR-005, FR-006, SC-006).
The bundle. Each create_*_rag had
embeddings_directory: Path = EmbeddingEnvironment.get_dir("reactome")
as a default argument, so it was evaluated at import time: importing a
rag module required an installed bundle, which is why they could not be
unit tested. get_dir returns `Path | None`, and None travelled into a
parameter typed `Path` -- four mypy baseline entries existed solely to
suppress that, and a ruff B008 suppression sat on each line. All five
suppressions are now deleted rather than annotated.
EmbeddingEnvironment.require_dir replaces the lookup at the three call
sites that cannot proceed without a bundle, and also checks the
directory exists. That second check is not tidiness: get_dir built a
path without touching the disk, and Chroma CREATES a missing
persist_directory rather than complaining, so an `embeddings/current`
left pointing at a deleted bundle produced a chatbot that answered
every question from an empty collection. Verified against main, the
missing-bundle failure was "AttributeError: 'NoneType' object has no
attribute 'glob'"; it now names the database, lists what is installed,
and gives the command to fix it.
The userguide bundle is deliberately optional, and react_to_me.py
already resolved it itself and degraded on absence -- that path keeps
get_dir, and require_dir raises FileNotFoundError precisely so the
existing `except FileNotFoundError` there still means what it meant.
The budget. MAX_DOCUMENTS_PER_COLLECTION is now
DEFAULT_MAX_DOCUMENTS_PER_COLLECTION, the default of a constructor
argument. As a module constant, comparing two budgets meant editing the
file and restarting -- so the answer-quality evaluation that is
supposed to settle the number could not be run at all.
Verified end to end against the Release95 bundle: the assembled chain
answers a real question identically through invoke and ainvoke (40 docs
each), budget=3 over 4 collections yields 12 documents and budget=10
yields 40, and all three profiles construct or refuse correctly.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes out the retriever rewrite (spec FR-005, FR-006, SC-006). Two module-level facts become arguments.
The bundle
Each
create_*_raghadA default argument is evaluated at import time, so importing a rag module required an installed bundle — which is why these were untestable. And
get_dirreturnsPath | None, soNoneflowed into a parameter typedPath; four mypy baseline entries existed only to suppress that. All five suppressions are deleted, not re-annotated.EmbeddingEnvironment.require_dirreplaces the lookup at the three call sites that cannot run without a bundle. It also checks the directory exists — which is not tidiness:Measured against
main:AttributeError: 'NoneType' object has no attribute 'glob'No embeddings bundle installed for 'uniprot' (installed: reactome). Run ./bin/embeddings_manager install <embedding-id>.The userguide bundle is deliberately optional;
react_to_me.pyalready resolved it itself and degraded on absence. That path keepsget_dir, andrequire_dirraisesFileNotFoundErrorspecifically so the existingexcept FileNotFoundErrorthere still means what it meant.The budget
MAX_DOCUMENTS_PER_COLLECTIONbecomesDEFAULT_MAX_DOCUMENTS_PER_COLLECTION, the default of a constructor argument. As a module constant, comparing two budgets meant editing the file and restarting — so the answer-quality evaluation meant to settle the number could not be run.Verification
Against the Release95 reactome bundle:
invokeandainvoke, 40 documents each (constitution Article I)budget=3over 4 collections → 12 documents;budget=10→ 40Each new test was checked to be non-vacuous by perturbing the thing it pins — ignoring the budget argument, reinstating a default, and removing the
is_dircheck each make exactly the relevant test fail.