diff --git a/ADR-vision-embedding-rollout.md b/ADR-vision-embedding-rollout.md new file mode 100644 index 00000000..2f102af7 --- /dev/null +++ b/ADR-vision-embedding-rollout.md @@ -0,0 +1,53 @@ +# ADR: Vision Embedding Rollout (Flag-Gated) + +- Status: Accepted +- Date: 2026-02-16 + +## Context + +STACKIT published a vision-capable embedder. We want to integrate image-native retrieval into the existing RAG pipeline without destabilizing production traffic. + +The current platform already supports `IMAGE` as a content type, but image ingestion/retrieval behavior is not yet consistently routed through a dedicated vision lane end-to-end. + +## Decision + +Roll out vision support behind explicit feature flags that default to `false`: + +- `VISION_IMAGE_LANE_ENABLED=false` +- `VISION_EMBEDDING_ENABLED=false` +- `VISION_IMAGE_RETRIEVER_ENABLED=false` + +Flags are exposed via Helm values and a shared config map consumed by backend, admin-backend, and extractor. + +## Consequences + +### Positive + +- No behavior change on merge while flags stay off. +- Safe staged rollout with reversible steps. +- Easier incident response by disabling a specific lane. + +### Negative + +- Temporary configuration overhead while both legacy and vision paths exist. +- Additional test matrix during rollout. + +## Rollout Notes + +- Keep all three flags `false` until the final rollout PR is merged and staging is validated. +- Enable in sequence on staging: + 1. `VISION_IMAGE_LANE_ENABLED` + 2. `VISION_EMBEDDING_ENABLED` + 3. `VISION_IMAGE_RETRIEVER_ENABLED` +- Promote to production only after mixed-modality retrieval checks pass. + +## Telemetry Baseline (No Behavior Change in This ADR) + +Track these counters from the first behavior PR onward: + +- `vision.image_documents_ingested_total` +- `vision.image_embeddings_written_total` +- `vision.image_retrieval_hits_total` +- `vision.image_retrieval_errors_total` + +This ADR only defines the rollout contract; metric instrumentation is introduced in later PRs. diff --git a/infrastructure/rag/templates/_backend_helpers.tpl b/infrastructure/rag/templates/_backend_helpers.tpl index b186f22b..280d844c 100644 --- a/infrastructure/rag/templates/_backend_helpers.tpl +++ b/infrastructure/rag/templates/_backend_helpers.tpl @@ -103,6 +103,10 @@ basic-auth {{- printf "%s-retriever-configmap" .Release.Name | trunc 63 | trimSuffix "-" -}} {{- end -}} +{{- define "configmap.visionName" -}} +{{- printf "%s-vision-configmap" .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + {{- define "configmap.langfuseName" -}} {{- printf "%s-langfuse-configmap" .Release.Name | trunc 63 | trimSuffix "-" -}} {{- end -}} diff --git a/infrastructure/rag/templates/admin-backend/deployment.yaml b/infrastructure/rag/templates/admin-backend/deployment.yaml index e0694d18..9de5e21d 100644 --- a/infrastructure/rag/templates/admin-backend/deployment.yaml +++ b/infrastructure/rag/templates/admin-backend/deployment.yaml @@ -117,6 +117,8 @@ spec: name: {{ template "configmap.keyValueStoreName" . }} - configMapRef: name: {{ template "configmap.sourceUploaderName" . }} + - configMapRef: + name: {{ template "configmap.visionName" . }} - configMapRef: name: {{ template "configmap.retryDecoratorName" . }} - configMapRef: diff --git a/infrastructure/rag/templates/backend/configmap.yaml b/infrastructure/rag/templates/backend/configmap.yaml index c5621c64..265ce3c3 100644 --- a/infrastructure/rag/templates/backend/configmap.yaml +++ b/infrastructure/rag/templates/backend/configmap.yaml @@ -18,6 +18,15 @@ data: --- apiVersion: v1 kind: ConfigMap +metadata: + name: {{ template "configmap.visionName" . }} +data: + {{- range $key, $value := .Values.shared.envs.vision }} + {{ $key }}: {{ $value | quote }} + {{- end }} +--- +apiVersion: v1 +kind: ConfigMap metadata: name: {{ template "configmap.langfuseName" . }} data: diff --git a/infrastructure/rag/templates/backend/deployment.yaml b/infrastructure/rag/templates/backend/deployment.yaml index 5a89b19a..0e996e7d 100644 --- a/infrastructure/rag/templates/backend/deployment.yaml +++ b/infrastructure/rag/templates/backend/deployment.yaml @@ -109,6 +109,8 @@ spec: name: {{ template "configmap.embedderClassTypesName" . }} - configMapRef: name: {{ template "configmap.retrieverName" . }} + - configMapRef: + name: {{ template "configmap.visionName" . }} - configMapRef: name: {{ template "configmap.rerankerName" . }} - configMapRef: diff --git a/infrastructure/rag/templates/extractor/deployment.yaml b/infrastructure/rag/templates/extractor/deployment.yaml index d51aaf88..0160633c 100644 --- a/infrastructure/rag/templates/extractor/deployment.yaml +++ b/infrastructure/rag/templates/extractor/deployment.yaml @@ -112,6 +112,8 @@ spec: name: {{ template "configmap.s3Name" . }} - configMapRef: name: {{ template "configmap.extractorSitemapName" . }} + - configMapRef: + name: {{ template "configmap.visionName" . }} - secretRef: name: {{ template "secret.s3RefName" . }} {{- $hfCacheDir := include "extractor.huggingfaceCacheDir" . }} diff --git a/infrastructure/rag/values.yaml b/infrastructure/rag/values.yaml index dd452881..f936e6b9 100644 --- a/infrastructure/rag/values.yaml +++ b/infrastructure/rag/values.yaml @@ -539,6 +539,10 @@ shared: s3: S3_ENDPOINT: http://rag-minio:9000 S3_BUCKET: documents + vision: + VISION_IMAGE_LANE_ENABLED: false + VISION_EMBEDDING_ENABLED: false + VISION_IMAGE_RETRIEVER_ENABLED: false retryDecorator: RETRY_DECORATOR_MAX_RETRIES: "5" RETRY_DECORATOR_RETRY_BASE_DELAY: "0.5"