Last updated: 2026-03-10
This file is a handoff log for future sessions (human or LLM). It summarizes what was changed, why it was changed, how to validate it, and what still needs attention.
- Audited repository for multimodal retrieval readiness and local llama.cpp embedding flow.
- Migrated notebook-oriented abstractions into runtime code.
- Built and iterated smoke diagnostics for OpenAI-compatible and native multimodal embeddings.
- Added benchmark tooling for Flickr8k cross-modal metric-space checks.
- Fixed benchmark methodology issues (notably text embedding extraction/pooling behavior and protocol correctness).
- Added embedding backend configuration plumbing (prefix logic, defaults, max_seq_len, env-sanitized loading).
- Added standalone diagnostics utility and Makefile target for embedding checks.
- Introduced and later removed a temporary master/runtime config layer during the config migration.
- Extended eval CLI to read defaults from config and support dotted CLI overrides.
- Removed duplicated legacy config sources and moved remaining defaults to scenario configs or in-code compatibility defaults.
- Refactored training orchestration into class-based jobs and generalized train APIs away from gamma-specific naming.
- Introduced streaming training-row preparation with lazy iterators, reservoir sampling, and backend-aware eager/lazy handling.
- Added follow-up inline documentation in
justatom/api/train.pyto make dataset-vs-batch-vs-row-stream semantics explicit.
- Added and/or stabilized abstractions in
justatom/running/llm.pyfor task/wrapper migration from notebook logic. - Kept exports in
justatom/api/__init__.pyaligned with runtime placement. - Iterated snapshot/log persistence behavior in async paths.
Key outcome:
- Core abstractions moved out of notebooks and into production-oriented runtime modules.
- Created/updated
scripts/smoke_embed_qwen_vl.pyfor multimodal probing against llama.cpp server. - Added official-style native payload handling (
/embeddingswithprompt_string+multimodal_data). - Hardened probe ordering and diagnostics to reduce false positives from text fallback behavior.
Key outcome:
- Reliable operator script for quick pass/fail checks and endpoint mode identification.
- Created and improved
scripts/benchmark_flickr8k_metric_space.py. - Added support for multi-caption protocol and full-run artifact export (
.npz, metrics json). - Corrected methodology to avoid misleading near-random results caused by extraction/pooling mismatch.
Key outcome:
- End-to-end benchmark execution and saved artifacts for reproducible evaluation.
- Added env-aware builtins loader behavior in
justatom/configuring/builtins.py. - Added/updated
justatom/builtins/configs/embeddings.yamldefaults. - Added
justatom/builtins/prompts/embedding_prefix_guide.txt. - Extended
justatom/running/embeddings/openai_compatible.pywith:- query/passage prefix strategy
- default request knobs (pooling, encoding_format)
max_seq_lenhandling
- Updated factory/wiring in:
justatom/running/embeddings/__init__.pyjustatom/running/service.py
Key outcome:
- Prefix-aware OpenAI-compatible embeddings with centralized defaults and runtime override hooks.
- Added
scripts/embedding_doctor.pyas a standalone (dependency-light) diagnostics utility. - Utility checks:
- config resolution and unresolved placeholder reporting
- server reachability (
GET /v1/models) - OpenAI-compatible text embedding probes
- native multimodal probe (
POST /embeddings)
- Added Makefile target:
check-embeddings
Key outcome:
- One-command diagnostics for local embedding stack health.
- Scenario configs became the primary source for
trainandevalflows. - Legacy
Configcompatibility was reduced to in-code defaults injustatom/configuring/prime.py. - Temporary master/runtime catalog files used during migration were removed after consumers were migrated away.
Key outcome:
- No runtime dependency on the removed master/runtime config layer.
- Updated
justatom/api/eval.pyto:- load structured defaults from scenario config
- keep backward compatibility with existing legacy flags
- support dotted CLI overrides, e.g.:
--model.name="..."--search.pipeline=keywords--search.top_k=7--metrics.top_k="['HitRate','mrr']"
Key outcome:
- Structured defaults in config with ergonomic runtime overrides from CLI.
- Extracted class-based training orchestration into
justatom/running/trainer_jobs.py. - Generalized training entrypoints and helpers to avoid gamma-specific naming in runtime APIs.
- Kept the public train flow compatible while moving orchestration details out of the API layer.
Key outcome:
- Train flow is easier to extend and reason about because job orchestration is separated from CLI/API glue.
- Refactored
justatom/api/train.pyso training examples can be prepared as a stream instead of materializing the full dataset up front. - Added/cleaned up helpers around the train-data path:
_frame_batches_from_source(...)_iterate_from_frame_batches(...)iterate_training_rows(...)_reservoir_sample_rows(...)sample_training_rows(...)prepare_training_data(...)
- Introduced a lazy row iterator + bounded reservoir sample flow:
- iterate rows lazily from the source
- keep only a fixed-size in-memory sample for fitting
- preserve compatibility for downstream consumers that still expect materialized sampled rows
- Important backend behavior discovered and preserved:
- eager
pl.DataFramesources are wrapped as[source]so downstream code can always consumeIterable[pl.DataFrame] - lazy
pl.LazyFramesources usecollect_batches(maintain_order=True) - non-polars sources return
Nonefrom_frame_batches_from_source(...), which intentionally triggers the adapter fallback branch
- eager
Key outcome:
- Training data prep now supports true streaming for supported backends while keeping backward-compatible sampled output.
- Reviewed
justatom/storing/dataset.pyto confirm actual iterator contracts. - Verified current behavior:
JSONDataset.iterator(lazy=True)still returns eagerpl.DataFrameJSONLinesDataset.iterator(lazy=True)can returnpl.LazyFramePARQUETDataset.iterator(...)andCSVDataset.iterator(...)can use polars eager/lazy pathsJUSTATOMDataset.iterator(lazy=True)currently resolves through the JSON backend and therefore behaves eagerlyHFDataset.iterator(...)returns Hugging Face dataset objects, not polars frames
- Consequence for
justatom/api/train.py:_frame_batches_from_source(...)returningNoneis expected and correct for non-polars backends, especiallyhf://...
Key outcome:
- The
Nonereturn from_frame_batches_from_source(...)is a deliberate control-flow signal, not an error condition.
- Added focused inline comments in
justatom/api/train.pyto disambiguate the following concepts:- whole dataset source
- one materialized DataFrame batch
- lazy row iterator
- bounded sampled subset kept in memory
- Clarified the reason for wrapping eager frames as
[source]:- normalize eager and lazy paths into the same
for batch in frame_batchescontract
- normalize eager and lazy paths into the same
- Clarified fallback semantics near the non-polars branch.
- Removed a misleading narrow type annotation on
sourcebecause actual backends are broader thanpl.DataFrame | pl.LazyFrame.
Key outcome:
- Future readers should be able to understand the train-data flow directly from
justatom/api/train.pywithout re-deriving backend behavior from scratch.
- Validate scenario configs and focused config-loader tests.
make check-embeddings- Expected (when server is up):
/v1/modelsreachable- text embedding probes succeed
- native multimodal probe succeeds
source "$(conda info --base)/etc/profile.d/conda.sh" && conda activate justatompython -m pytest -q tests/test_retriever_shape_and_factory.py tests/test_eval_metrics.py tests/test_eval_data_normalization.py- Latest known status in-session: passing.
- Full suite previously passed after the larger refactor:
53 passed, 6 warnings
- Targeted integration coverage exists in
tests/test_eval_streaming_integration.py. - Dev verification scripts used during the lazy/eager investigation:
scripts/dev/check_lazy_json_justatom.pyscripts/dev/check_lazy_jsonl_from_justatom.py
- What those checks established:
.jsonrequests asking for lazy iteration still fall back to eager frame loading.jsonlrequests can use a truly lazy path
- After the later comment-only edit to
justatom/api/train.py, diagnostics for that file were checked and no errors were reported.
- Some scripts require
PYTHONPATH=.when run directly from shell. - Local environment was primarily tested in conda env
justatom. - llama.cpp behavior may vary by launch flags (
--embeddings, pooling mode, batch/token constraints).
- Multimodal stability can still depend heavily on model build and llama-server launch configuration.
- Train-data laziness is backend-dependent. "lazy=True" at the API level does not guarantee a lazy backend implementation.
- The
justatomnamed dataset path currently behaves eagerly because it resolves through the JSON backend. - Hugging Face datasets follow the adapter fallback path in
justatom/api/train.py; they do not use the polars batch fast path.
- Call
iterate_training_rows(...)when you want a lazy stream of normalized training rows. - If the backend returns polars frames:
- eager
DataFramebecomes[source]and is treated as one batch - lazy
LazyFrameyields multiple materialized batches viacollect_batches(...)
- If the backend is not polars:
_frame_batches_from_source(...)returnsNone- code falls back to
DatasetRecordAdapter.from_source(...)
sample_training_rows(...)consumes that lazy stream and applies reservoir sampling.prepare_training_data(...)materializes only the sampled subset needed by the existing fit/train consumers.
- Add a short README section documenting config layering and dotted override examples for
justatom.api.eval. - Add unit tests for
_parse_argsdotted override behavior injustatom/api/eval.py. - Add a small unit test that documents
_frame_batches_from_source(...) -> Nonefor a mocked non-polars/HF-like source. - Consider adding optional local override file support (for developer-only changes) if needed later.