- vlm.model was 'llama3.1-8b' which doesn't exist on astro-orbiter's /v1/models, causing every summarization call to 400 and endless circuit-breaker retries. Correct id: Meta-Llama-3.1-8B-Instruct-Q4_K_M. - embedding.max_input_tokens=1536 still let chunks through that actually tokenized to 2000-2860 real tokens (estimator undercounts vs llama.cpp's tokenizer by 1.35x-1.86x on this corpus). Lowered to 1024 for real margin under the 2048 n_ctx ceiling.
241 lines
9.3 KiB
YAML
241 lines
9.3 KiB
YAML
# ============================================================================
|
|
# OpenViking Helm Chart Values
|
|
# Cluster: fastpass (Talos Kubernetes)
|
|
# Wave: 8 (after Harbor at Wave 7)
|
|
# Pilot scope: Two corpora (hermes/ skills, personal/homelab/)
|
|
# ============================================================================
|
|
#
|
|
# KEY CONSTRAINT: Vault (~/friday) is the CANONICAL source of truth.
|
|
# OpenViking's index is a derived cache, rebuilt from vault source files.
|
|
# If index and vault ever diverge, vault wins and re-index runs.
|
|
# See inbox/ryan/2026-08-13-openviking-pilot-deployment-plan.md for full context.
|
|
#
|
|
|
|
replicaCount: 1
|
|
|
|
image:
|
|
repository: ghcr.io/volcengine/openviking
|
|
# Pin to a stable release tag (not "latest" for production-ish pilot)
|
|
tag: v0.3.17
|
|
pullPolicy: IfNotPresent
|
|
|
|
imagePullSecrets: []
|
|
nameOverride: ""
|
|
fullnameOverride: ""
|
|
|
|
serviceAccount:
|
|
create: false
|
|
annotations: {}
|
|
name: ""
|
|
|
|
podAnnotations: {}
|
|
podLabels:
|
|
app: openviking
|
|
wave: "8"
|
|
|
|
# Security context: run as non-root if the image supports it
|
|
podSecurityContext: {}
|
|
securityContext: {}
|
|
|
|
# Service: ClusterIP (no direct external exposure; MCP proxy handles agent access)
|
|
service:
|
|
type: ClusterIP
|
|
port: 1933
|
|
|
|
# ============================================================================
|
|
# Ingress: enabled, INTERNAL-ONLY
|
|
# Constraint from Phase 0 (Ryan's decision, 2026-08-13):
|
|
# Standard nginx-ingress fronting the service (consistent with Harbor pattern),
|
|
# but internal DNS only — no external/public DNS entry, no public-facing cert-manager issuer.
|
|
# Use internal CA / self-signed cert to get ingress consistency without expanding public attack surface.
|
|
# ============================================================================
|
|
ingress:
|
|
enabled: true
|
|
className: nginx
|
|
annotations:
|
|
# Internal cert-manager cluster issuer (DNS-01 via Cloudflare)
|
|
cert-manager.io/cluster-issuer: "letsencrypt-prod"
|
|
# Block external DNS registration (internal only)
|
|
external-dns.alpha.kubernetes.io/enabled: "false"
|
|
hosts:
|
|
- host: openviking.local.mk-labs.cloud
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
tls:
|
|
- secretName: openviking-tls
|
|
hosts:
|
|
- openviking.local.mk-labs.cloud
|
|
|
|
# ============================================================================
|
|
# Resources: start conservative, tune after pilot
|
|
# ============================================================================
|
|
resources:
|
|
limits:
|
|
cpu: "2"
|
|
memory: 4Gi
|
|
requests:
|
|
cpu: 500m
|
|
memory: 1Gi
|
|
|
|
# ============================================================================
|
|
# Persistence: RocksDB index + workspace
|
|
# Storage class: px-fa-direct-access (Portworx direct access to Pure FlashArray)
|
|
# Rationale (from Phase 0 / t_77b3ff79): 40+ days of proven production history on fastpass,
|
|
# RocksDB-optimized (direct block access, not NFS), RAID 6 durability via FlashArray.
|
|
# Access mode: ReadWriteOnce (single replica only — RocksDB does not support concurrent access)
|
|
# Update strategy: Recreate (no rolling updates; single-replica RocksDB workload)
|
|
# ============================================================================
|
|
persistence:
|
|
enabled: true
|
|
storageClass: px-fa-direct-access
|
|
accessMode: ReadWriteOnce
|
|
size: 30Gi # 30Gi provides headroom for ~6 months of pilot corpus growth (~2GB actual use at launch)
|
|
existingClaim: ""
|
|
mountPath: /app/.openviking
|
|
|
|
# Pod disruption budget: single replica, no HA
|
|
# Explicit Recreate strategy (handled via Deployment patch in ArgoCD Application)
|
|
podDisruptionBudget: {}
|
|
|
|
# ============================================================================
|
|
# Bot feature: disabled (scope out vikingbot for this phase)
|
|
# ============================================================================
|
|
bot:
|
|
enabled: false
|
|
|
|
# ============================================================================
|
|
# OpenViking server configuration (ov.conf)
|
|
# Rendered into a ConfigMap mounted at ${persistence.mountPath}/ov.conf
|
|
# ============================================================================
|
|
config:
|
|
storage:
|
|
workspace: "" # Defaults to /app/.openviking/openviking_workspace
|
|
vectordb:
|
|
name: context
|
|
backend: local
|
|
project: default
|
|
agfs:
|
|
backend: local
|
|
timeout: 10
|
|
log:
|
|
level: INFO
|
|
output: stdout
|
|
server:
|
|
host: "0.0.0.0"
|
|
port: 1933
|
|
workers: 1
|
|
# root_api_key injected via environment variable + ExternalSecret
|
|
root_api_key: "${OPENVIKING_ROOT_API_KEY}"
|
|
cors_origins:
|
|
- "*"
|
|
|
|
# ============================================================================
|
|
# Embedding configuration (dense)
|
|
# Provider: openai-compatible endpoint (local llama-server router)
|
|
# Model: nomic-embed-text-v1.5-Q4_K_M (137M params, 768-dim, local inference)
|
|
# Endpoint: http://astro-orbiter:8002/v1 (folded into existing astro-orbiter router per t_eb36eb2e)
|
|
# No cloud key needed; internal unauthenticated endpoint
|
|
# ============================================================================
|
|
embedding:
|
|
dense:
|
|
provider: "openai"
|
|
api_base: "http://astro-orbiter:8002/v1"
|
|
api_key: "${OPENVIKING_EMBEDDING_API_KEY}" # Placeholder: "local-nomic" or similar
|
|
model: "nomic-embed-text-v1.5"
|
|
dimension: 768
|
|
input: "text"
|
|
max_concurrent: 5
|
|
# max_input_tokens caps the raw text tokens OpenViking sends per chunk to the
|
|
# embedding model. astro-orbiter's llama.cpp router hard-caps nomic-embed-text-v1.5's
|
|
# effective context at 2048 tokens regardless of ctx-size config (known llama.cpp
|
|
# nomic-bert limitation, not fixable via server flags). OpenViking's chunker was
|
|
# observed producing 2000-3400 token chunks, well over that ceiling, causing
|
|
# `400 exceed_context_size_error, n_ctx: 2048` and endless circuit-breaker re-enqueues.
|
|
# Set well under 2048 (1536) to leave headroom: OpenViking's chunk-time token
|
|
# estimator is not the same tokenizer llama.cpp uses to count context, so token
|
|
# counts won't match 1:1 between the two. Approved by Ryan as lowest-risk fix
|
|
# (option 1 of 3) vs. touching the astro-orbiter serving stack further.
|
|
#
|
|
# ROOT CAUSE (2026-08-15 incident): 1536 was still not low enough. Observed
|
|
# llama.cpp actual n_prompt_tokens vs. OpenViking's own max_input_tokens=1536
|
|
# estimate ratio ranged 1.35x-1.86x across real ingested chunks (see homelab
|
|
# re-ingest circuit-breaker errors, e.g. estimate 1536 -> actual 2860 tokens,
|
|
# 2124, 2088, 2066... all > 2048 n_ctx ceiling). OpenViking's estimator
|
|
# (likely a chars/4 or similar heuristic) undercounts vs. llama.cpp's real
|
|
# BPE/wordpiece tokenizer for this corpus's content (dense code/config
|
|
# snippets tokenize denser than the estimator assumes). Lowering to 1536 alone
|
|
# does not hold for all chunks; using worst-observed ratio (1.86x) with margin,
|
|
# 2048 / 1.86 ~= 1100, rounded down further for safety across untested
|
|
# corpora -> 1024.
|
|
max_input_tokens: 1024
|
|
|
|
# ============================================================================
|
|
# VLM / Summarization configuration (L0/L1/L2 generation)
|
|
# Provider: openai-compatible endpoint (local llama-server router)
|
|
# Model: Llama-3.1-8B (already resident on astro-orbiter per Phase 0 analysis)
|
|
# Endpoint: http://astro-orbiter:8002/v1 (same router as embedding)
|
|
# No cloud key needed; internal unauthenticated endpoint
|
|
# max_concurrent: 4 (recommend capping background indexing load on shared VLM)
|
|
# ============================================================================
|
|
vlm:
|
|
api_base: "http://astro-orbiter:8002/v1"
|
|
api_key: "${OPENVIKING_VLM_API_KEY}" # Placeholder: "local-llama" or similar
|
|
# Fixed 2026-08-15: "llama3.1-8b" does not exist on astro-orbiter's /v1/models
|
|
# (caused every summarization call to fail with 400 model not found, endless
|
|
# circuit-breaker retries). Actual served model id/alias confirmed via
|
|
# /home/hermes/git/homelab/ansible/playbooks/day2_add_nomic_embed.yml and
|
|
# day2_per_model_ctx_size.yml: "Meta-Llama-3.1-8B-Instruct-Q4_K_M".
|
|
model: "Meta-Llama-3.1-8B-Instruct-Q4_K_M"
|
|
provider: "openai"
|
|
temperature: 0.0
|
|
max_retries: 2
|
|
thinking: false
|
|
max_concurrent: 4 # Cap background indexing pressure on shared VLM
|
|
|
|
# ============================================================================
|
|
# Extra environment variables: secrets from ExternalSecret
|
|
# Injected by ArgoCD Application via kustomize or helm hook
|
|
# ============================================================================
|
|
extraEnv:
|
|
- name: OPENVIKING_ROOT_API_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: openviking-credentials
|
|
key: root_api_key
|
|
- name: OPENVIKING_EMBEDDING_API_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: openviking-credentials
|
|
key: embedding_api_key
|
|
- name: OPENVIKING_VLM_API_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: openviking-credentials
|
|
key: vlm_api_key
|
|
|
|
# ============================================================================
|
|
# Probes
|
|
# ============================================================================
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: http
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 30
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /ready
|
|
port: http
|
|
initialDelaySeconds: 15
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
nodeSelector: {}
|
|
tolerations: []
|
|
affinity: {}
|