* feat(helm): add persistent volume for local model cache When using local reranker (e.g., BAAI/bge-reranker-v2-m3) or local embedding models, the models are downloaded to /home/hindsight/.cache on every pod restart, causing slow startup and unnecessary bandwidth. Add optional persistent volume support: - api: PVC mounted at /home/hindsight/.cache - worker: volumeClaimTemplate (StatefulSet) at same path Disabled by default. Enable via: api.persistence.modelCache.enabled: true worker.persistence.modelCache.enabled: true Closes #860 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(helm): add extraVolumes and extraVolumeMounts for api and worker Allow users to mount arbitrary volumes (configMaps, secrets, emptyDir, etc.) into api and worker pods via values, following common helm chart library conventions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
433 lines
9.5 KiB
YAML
433 lines
9.5 KiB
YAML
# Default values for hindsight
|
|
|
|
# Global version override - use this to set a consistent image tag across all components
|
|
# If not set, defaults to Chart.appVersion from Chart.yaml
|
|
# version: ""
|
|
|
|
# Use an existing secret instead of creating one from values
|
|
# When set, all keys from this secret are injected as environment variables via envFrom
|
|
# Required keys:
|
|
# - postgres-password: PostgreSQL password (when postgresql.enabled=false)
|
|
# Optional keys (any key becomes an env var):
|
|
# - HINDSIGHT_API_LLM_API_KEY: API key for LLM provider
|
|
# - Any other env vars you want to inject
|
|
# existingSecret: "my-hindsight-secret"
|
|
|
|
# Global settings
|
|
replicaCount: 1
|
|
|
|
# Image settings for api
|
|
api:
|
|
enabled: true
|
|
replicaCount: 1
|
|
image:
|
|
repository: ghcr.io/vectorize-io/hindsight-api
|
|
pullPolicy: IfNotPresent
|
|
# tag defaults to .Values.version if not specified
|
|
|
|
service:
|
|
type: ClusterIP
|
|
port: 8888
|
|
targetPort: 8888
|
|
|
|
# Resource limits and requests
|
|
resources:
|
|
limits:
|
|
cpu: 2000m
|
|
memory: 4Gi
|
|
requests:
|
|
cpu: 500m
|
|
memory: 1Gi
|
|
|
|
# Liveness and readiness probes
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8888
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8888
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
timeoutSeconds: 3
|
|
failureThreshold: 3
|
|
|
|
# Pod disruption budget
|
|
podDisruptionBudget:
|
|
enabled: false
|
|
minAvailable: 1
|
|
# maxUnavailable: 1
|
|
|
|
# Pod affinity/anti-affinity (overrides global affinity for this component)
|
|
# affinity: {}
|
|
|
|
# Persistent volume for local model cache (reranker, embeddings)
|
|
# Models are downloaded to /home/hindsight/.cache on first use.
|
|
# Without persistence, models are re-downloaded on every pod restart.
|
|
persistence:
|
|
modelCache:
|
|
enabled: false
|
|
size: 5Gi
|
|
storageClass: ""
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
annotations: {}
|
|
|
|
# Extra volume mounts for the api container
|
|
# e.g.
|
|
# extraVolumeMounts:
|
|
# - name: my-volume
|
|
# mountPath: /mnt/my-volume
|
|
extraVolumeMounts: []
|
|
|
|
# Extra volumes for the api pod
|
|
# e.g.
|
|
# extraVolumes:
|
|
# - name: my-volume
|
|
# configMap:
|
|
# name: my-configmap
|
|
extraVolumes: []
|
|
|
|
# Environment variables
|
|
env:
|
|
#HINDSIGHT_API_LLM_PROVIDER: "groq"
|
|
HINDSIGHT_API_LLM_MODEL: "openai/gpt-oss-120b"
|
|
|
|
# Secret environment variables
|
|
secrets:
|
|
# HINDSIGHT_API_LLM_API_KEY: "your-api-key"
|
|
# HINDSIGHT_API_LLM_BASE_URL: "https://api.groq.com/openai/v1"
|
|
|
|
# Worker settings (distributed task processing)
|
|
# When enabled, dedicated worker pods process tasks and the API's internal worker is disabled
|
|
worker:
|
|
enabled: false
|
|
replicaCount: 2
|
|
image:
|
|
repository: ghcr.io/vectorize-io/hindsight-api
|
|
pullPolicy: IfNotPresent
|
|
# tag: "" # defaults to .Values.version, then Chart.appVersion if not specified
|
|
|
|
service:
|
|
# Service for metrics scraping (headless for StatefulSet)
|
|
port: 8889
|
|
targetPort: 8889
|
|
|
|
# Resource limits and requests
|
|
resources:
|
|
limits:
|
|
cpu: 2000m
|
|
memory: 4Gi
|
|
requests:
|
|
cpu: 500m
|
|
memory: 1Gi
|
|
|
|
# Liveness and readiness probes
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8889
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8889
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
timeoutSeconds: 3
|
|
failureThreshold: 3
|
|
|
|
# Worker-specific environment variables
|
|
env:
|
|
# Poll interval in milliseconds (how often to check for new tasks)
|
|
HINDSIGHT_API_WORKER_POLL_INTERVAL_MS: "500"
|
|
# Number of tasks to claim per poll cycle
|
|
HINDSIGHT_API_WORKER_BATCH_SIZE: "10"
|
|
# Max retries before marking a task as failed
|
|
HINDSIGHT_API_WORKER_MAX_RETRIES: "3"
|
|
# HTTP port for metrics/health (matches service.targetPort)
|
|
HINDSIGHT_API_WORKER_HTTP_PORT: "8889"
|
|
|
|
# Pod disruption budget
|
|
podDisruptionBudget:
|
|
enabled: false
|
|
minAvailable: 1
|
|
# maxUnavailable: 1
|
|
|
|
# Pod affinity/anti-affinity (overrides global affinity for this component)
|
|
# affinity: {}
|
|
|
|
# Persistent volume for local model cache (reranker, embeddings)
|
|
# Uses volumeClaimTemplates since worker is a StatefulSet.
|
|
persistence:
|
|
modelCache:
|
|
enabled: false
|
|
size: 5Gi
|
|
storageClass: ""
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
annotations: {}
|
|
|
|
# Extra volume mounts for the worker container
|
|
# e.g.
|
|
# extraVolumeMounts:
|
|
# - name: my-volume
|
|
# mountPath: /mnt/my-volume
|
|
extraVolumeMounts: []
|
|
|
|
# Extra volumes for the worker pod
|
|
# e.g.
|
|
# extraVolumes:
|
|
# - name: my-volume
|
|
# configMap:
|
|
# name: my-configmap
|
|
extraVolumes: []
|
|
|
|
# Secret environment variables (inherited from api.secrets if not specified)
|
|
secrets: {}
|
|
|
|
# Image settings for control plane
|
|
controlPlane:
|
|
enabled: true
|
|
replicaCount: 1
|
|
image:
|
|
repository: ghcr.io/vectorize-io/hindsight-control-plane
|
|
pullPolicy: IfNotPresent
|
|
# tag defaults to .Values.version if not specified
|
|
|
|
service:
|
|
type: ClusterIP
|
|
port: 3000
|
|
targetPort: 3000
|
|
|
|
# Resource limits and requests
|
|
resources:
|
|
limits:
|
|
cpu: 1000m
|
|
memory: 2Gi
|
|
requests:
|
|
cpu: 250m
|
|
memory: 512Mi
|
|
|
|
# Liveness and readiness probes (TCP check)
|
|
livenessProbe:
|
|
tcpSocket:
|
|
port: 3000
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
readinessProbe:
|
|
tcpSocket:
|
|
port: 3000
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
timeoutSeconds: 3
|
|
failureThreshold: 3
|
|
|
|
# Pod disruption budget
|
|
podDisruptionBudget:
|
|
enabled: false
|
|
minAvailable: 1
|
|
# maxUnavailable: 1
|
|
|
|
# Pod affinity/anti-affinity (overrides global affinity for this component)
|
|
# affinity: {}
|
|
|
|
# Environment variables
|
|
env:
|
|
NODE_ENV: "production"
|
|
HINDSIGHT_CP_HOSTNAME: "0.0.0.0"
|
|
HINDSIGHT_CP_PORT: "3000"
|
|
|
|
# PostgreSQL configuration
|
|
postgresql:
|
|
# Set to true to deploy PostgreSQL as part of this chart
|
|
enabled: true
|
|
|
|
image:
|
|
repository: ankane/pgvector
|
|
tag: latest
|
|
pullPolicy: IfNotPresent
|
|
|
|
auth:
|
|
username: "hindsight"
|
|
password: "hindsight"
|
|
database: "hindsight"
|
|
|
|
service:
|
|
port: 5432
|
|
|
|
persistence:
|
|
enabled: true
|
|
size: 8Gi
|
|
# storageClass: ""
|
|
|
|
resources:
|
|
limits:
|
|
cpu: 1000m
|
|
memory: 1Gi
|
|
requests:
|
|
cpu: 250m
|
|
memory: 256Mi
|
|
|
|
# External PostgreSQL connection details
|
|
# Only used if postgresql.enabled is false
|
|
external:
|
|
host: "postgresql"
|
|
port: 5432
|
|
database: "hindsight"
|
|
username: "hindsight"
|
|
# password: ""
|
|
|
|
# Ingress configuration
|
|
ingress:
|
|
enabled: false
|
|
className: "nginx"
|
|
annotations: {}
|
|
# cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
|
# nginx.ingress.kubernetes.io/ssl-redirect: "true"
|
|
|
|
hosts:
|
|
- host: hindsight.example.com
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
service: controlPlane
|
|
- path: /api
|
|
pathType: Prefix
|
|
service: api
|
|
|
|
tls: []
|
|
# - secretName: hindsight-tls
|
|
# hosts:
|
|
# - hindsight.example.com
|
|
|
|
# Service Account
|
|
serviceAccount:
|
|
create: true
|
|
annotations: {}
|
|
name: ""
|
|
|
|
# Pod annotations
|
|
podAnnotations: {}
|
|
|
|
# Pod security context
|
|
podSecurityContext:
|
|
fsGroup: 1000
|
|
|
|
# Security context
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1000
|
|
capabilities:
|
|
drop:
|
|
- ALL
|
|
readOnlyRootFilesystem: false
|
|
allowPrivilegeEscalation: false
|
|
|
|
# Node selector
|
|
nodeSelector: {}
|
|
|
|
# Tolerations
|
|
tolerations: []
|
|
|
|
# Affinity (applied to all components unless overridden per-component)
|
|
affinity: {}
|
|
|
|
# TEI (Text Embeddings Inference) - optional standalone deployments
|
|
# for reranking and/or embedding models
|
|
tei:
|
|
reranker:
|
|
enabled: false
|
|
replicaCount: 1
|
|
image:
|
|
repository: ghcr.io/huggingface/text-embeddings-inference
|
|
tag: cpu-1.8.3
|
|
pullPolicy: IfNotPresent
|
|
model: "cross-encoder/ms-marco-MiniLM-L-6-v2"
|
|
port: 8090
|
|
args:
|
|
- "--auto-truncate"
|
|
env:
|
|
PAYLOAD_LIMIT: "10000000"
|
|
MAX_CLIENT_BATCH_SIZE: "256"
|
|
resources:
|
|
limits:
|
|
cpu: 2000m
|
|
memory: 2Gi
|
|
requests:
|
|
cpu: 500m
|
|
memory: 1Gi
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8090
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 6
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8090
|
|
initialDelaySeconds: 15
|
|
periodSeconds: 5
|
|
timeoutSeconds: 3
|
|
failureThreshold: 3
|
|
|
|
embedding:
|
|
enabled: false
|
|
replicaCount: 1
|
|
image:
|
|
repository: ghcr.io/huggingface/text-embeddings-inference
|
|
tag: cpu-1.8.3
|
|
pullPolicy: IfNotPresent
|
|
model: "sentence-transformers/all-MiniLM-L6-v2"
|
|
port: 8091
|
|
args: []
|
|
env:
|
|
PAYLOAD_LIMIT: "10000000"
|
|
MAX_CLIENT_BATCH_SIZE: "256"
|
|
resources:
|
|
limits:
|
|
cpu: 2000m
|
|
memory: 2Gi
|
|
requests:
|
|
cpu: 500m
|
|
memory: 1Gi
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8091
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 6
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8091
|
|
initialDelaySeconds: 15
|
|
periodSeconds: 5
|
|
timeoutSeconds: 3
|
|
failureThreshold: 3
|
|
|
|
# Autoscaling
|
|
autoscaling:
|
|
enabled: false
|
|
minReplicas: 1
|
|
maxReplicas: 10
|
|
targetCPUUtilizationPercentage: 80
|
|
targetMemoryUtilizationPercentage: 80
|