Bulk embeddings pool for ingest (remediates #2282) - #2403
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.
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.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoR99QxfqaXZFesYRGcBiC
- embedding_identity: drop embeddings_microservice_url_bulk from the fingerprint. Adding the field re-hashed every existing MicroserviceEmbedder vector (breaking valid_embeddings/readiness and the existing legacy-fingerprint test); the bulk pool is routing, not a model. - Budgeted runs (embed_text_accounted) stay on the policy-validated, endpoint-pinned query URL. - Collapse the three _get_service_config tests into one table test; drop tests duplicating existing use_bulk_pool assertions; add an identity regression test. - Trim comments, docs, sample env notes and the changelog fragment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoR99QxfqaXZFesYRGcBiC
Code ReviewReviewed the bulk-embeddings-pool routing changes ( Two issues found, one docs/ops risk and one latent code gap: 1. Docs recommend a command with a broader blast radius than described
to seed the new 2. Multimodal ingest path not updated to use the bulk pool
Minor / non-blocking
Positives
|
--force on migrate_pipeline_settings resets env-less settings (embedding_model_revision, no_external_provider_fees) to defaults. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CoR99QxfqaXZFesYRGcBiC
|
Thanks, I checked each point against the code.
Generated by Claude Code |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
This carries #2282 forward: ingest embeddings can go to a separate autoscaled microservice pool while search queries stay on the warm one. It is configured only through the
PipelineSettingssingleton. #2282 is merged in here onto currentmainand fixed.The blocking bug: #2282 was cut before
utils/embedding_identity.pylanded.embedding_configuration()hashes every non-secret setting onMicroserviceEmbedder.Settings, so addingembeddings_microservice_url_bulk(even with its empty default) would change the fingerprint of every existing microservice vector on deploy.valid_embeddingsfilters on that fingerprint, so existing vectors would drop out of readiness and search. The existingtest_billing_setting_does_not_change_vector_identity_or_legacy_fingerprintfails on the merged #2282 code for exactly this reason.Changes
utils/embedding_identity.py: the bulk URL is removed from the fingerprint, likeno_external_provider_fees. It only controls routing; the bulk pool must serve the same model.MicroserviceEmbedder._get_service_config: same routing as Add bulk embeddings pool for ingest (via the pipeline settings singleton) #2282 (use_bulk_pool=Trueplus a configured bulk URL goes to the bulk pool; anything else goes to the query URL), with less code.embed_text_accounted) deliberately stay on the query URL, whichrun_policy.resolve_providervalidates and pins as the endpoint. Routing them elsewhere would bypass that check._get_service_configtests are now one table test. I removedTestIngestBulkPoolRoutingandtest_batch_tags_bulk_pool, which repeated assertions the updated existing tests already make. Addedtest_bulk_pool_url_does_not_change_vector_identity.performance_tuning.md): existing installs should set the bulk URL in System Settings. I dropped Add bulk embeddings pool for ingest (via the pipeline settings singleton) #2282'smigrate_pipeline_settings --forceadvice: that command resets settings that have no env var (embedding_model_revision,no_external_provider_fees), which breaks budgeted runs. Comments, sample env notes and the changelog fragment are trimmed.Test plan
Ran against local Postgres + pgvector:
With the
embedding_identity.pyfix reverted, the existing legacy-fingerprint test and the new identity test both fail. The full backend suite also passes in CI.Checklist
pre-commit runpasses on changed files (black, isort, flake8, mypy, changelog check)changelog.d/Contributor License Agreement
By submitting this pull request, you agree to license your contribution under the project's Contributor License Agreement.
🤖 Generated with Claude Code
https://claude.ai/code/session_01CoR99QxfqaXZFesYRGcBiC