Add bulk embeddings pool for ingest (via the pipeline settings singleton) - #2282
Add bulk embeddings pool for ingest (via the pipeline settings singleton)#2282JSv4 wants to merge 2 commits into
Conversation
Search queries and batch ingest share one embeddings microservice URL, forcing a compromise between a warm query pod and an autoscaled ingest pool. This lets operators split them without adding a parallel configuration pathway. The bulk URL is a new optional field on MicroserviceEmbedder.Settings (embeddings_microservice_url_bulk), seeded from the EMBEDDINGS_MICROSERVICE_URL_BULK env var via migrate_pipeline_settings — configured through the same PipelineSettings singleton as the existing query URL, not read ad hoc from Django settings. The ingest Celery tasks in embeddings_task.py tag their embed calls with use_bulk_pool=True; MicroserviceEmbedder._get_service_config routes tagged calls to the bulk URL when one is configured and leaves every (untagged) search query on embeddings_microservice_url. When no bulk URL is set the flag is a no-op, so single-pool deployments are unaffected and no query call site changes. Because ingest is inherently bulk, the leaves just tag their embed calls — no override parameter is threaded through the task helpers, so their signatures are unchanged. Tests: MicroserviceEmbedder._get_service_config bulk selection + fallback + no-flag cases; ingest leaves (_create_text_embedding, _embed_relationship, _batch_embed_text_annotations) tag use_bulk_pool=True. Docs: performance_tuning.md section, sample env files, changelog fragment.
Review: Add bulk embeddings pool for ingestOverall this is a clean, well-scoped change that follows the existing Correctness of the routing logic — looks solid
Operational gap: the documented "how to enable it" steps will likely no-op on an existing deployment
EMBEDDINGS_MICROSERVICE_URL_BULK=http://vector-embedder-bulk:8000
python manage.py migrate_pipeline_settingsBut Once this PR merges and is deployed once, that auto-run will persist So an operator who deploys, later decides to set Suggested fix: update the three docs ( python manage.py migrate_pipeline_settings --component MicroserviceEmbedder --force( Minor / non-blocking
Nice, focused PR otherwise — the "tag intent, not URLs" design (ingest tags |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
The ingest tasks now tag their embedder calls with use_bulk_pool=True, which broke 15 tests that either used mock embedders with a narrow embed_text(self, text) signature or asserted the exact embed_text/embed_texts_batch call args: - test_dual_embeddings.py: MockEmbedder / MockCorpusEmbedder embed_text now accept **kwargs, matching the BaseEmbedder.embed_text(self, text, **direct_kwargs) contract that every real embedder already satisfies. - test_embeddings_task.py: the embed_text / embed_texts_batch call assertions on ingest paths (annotation text, multimodal fallback, relationship single + batch) now expect use_bulk_pool=True. Also address the review note that migrate_pipeline_settings preserves existing PipelineSettings values without --force, so an operator who sets EMBEDDINGS_MICROSERVICE_URL_BULK on an already-deployed instance and runs the plain command would keep the seeded empty value. Docs and both sample env files now use 'migrate_pipeline_settings --component MicroserviceEmbedder --force', and note the shared api-key/Cloud-Run-auth scope limitation.
Summary
Search queries and batch ingest share a single embeddings microservice URL
(
EMBEDDINGS_MICROSERVICE_URL), forcing a compromise: a pool sized to keeplatency-sensitive search queries warm also absorbs the load of batch
ingest (thousands of embeddings, happy to hit an autoscaled / scale-to-zero
pool), and vice versa.
This lets operators point ingest at a separate bulk pool while query call
sites stay on the always-warm pod — routed entirely through the existing
PipelineSettingssingleton, not a separate configuration pathway.Changes
MicroserviceEmbedder.Settingsgains anoptional
embeddings_microservice_url_bulkfield(
opencontractserver/pipeline/embedders/sent_transformer_microservice.py),seeded from the
EMBEDDINGS_MICROSERVICE_URL_BULKenv var viamigrate_pipeline_settings— the samePipelineSettingspathway as theexisting
embeddings_microservice_url._get_service_configroutes calls taggeduse_bulk_pool=Trueto the bulk URL when one is configured, and falls back toembeddings_microservice_urlotherwise (and for every untagged search query).opencontractserver/tasks/embeddings_task.pytag their three text embed calls(
_create_text_embedding,_batch_embed_text_annotations,_embed_relationship) withuse_bulk_pool=True. Because ingest is inherentlybulk, no override parameter is threaded through the task helpers — their
signatures are unchanged, and no query call site changes.
config/settings/base.pyaddsEMBEDDINGS_MICROSERVICE_URL_BULK(default empty) purely as the seed sourcefor
migrate_pipeline_settings; it is not read directly at runtime.docs/deployment/performance_tuning.mdgains a "Separate bulkembeddings pool" section; sample env files note the optional variable;
changelog fragment
changelog.d/bulk-embeddings-pool.added.md.Opt-in and backwards compatible: when no bulk URL is configured the
use_bulk_poolflag is a no-op, so single-pool deployments are unaffected.Hosted / multimodal embedders (which read distinct kwargs) ignore the flag.
Test plan
MicroserviceEmbedder._get_service_config— bulk selection when flagged,fallback to query URL when the bulk URL is empty, and no bulk use without
the flag (
opencontractserver/tests/test_batch_embedding.py).use_bulk_pool=True—_create_text_embedding/_embed_relationship(test_embeddings_task.py) and the batch path_batch_embed_text_annotations(test_batch_embedding.py).black,isort,flake8clean on all changed files; targetedmypycleanon the embedder and task modules.
python scripts/collate_changelog.py --checkpasses.environment; the URL-selection logic was verified in isolation and the rest is
left to CI (
pytest).Checklist
black/isort/flake8pass on changed files; targetedmypyclean (no frontend changes, so no prettier/TS)changelog.d/Contributor License Agreement
By submitting this pull request, you agree to license your contribution
under the project's Contributor License Agreement.
Generated by Claude Code