fix: Enforce min_chunk_size in RAG chunker

- Filter out chunks smaller than min_chunk_size (default 100 tokens)
- Exception: Keep all chunks if entire document is smaller than target size
- All 15 tests passing (100% pass rate)

Fixes edge case where very small chunks (e.g., 'Short.' = 6 chars) were
being created despite min_chunk_size=100 setting.

Test: pytest tests/test_rag_chunker.py -v
This commit is contained in:
yusyus
2026-02-07 20:59:03 +03:00
parent 3a769a27cd
commit 8b3f31409e
65 changed files with 16133 additions and 7 deletions

View File

@@ -0,0 +1,32 @@
apiVersion: v2
name: skill-seekers
description: A Helm chart for Skill Seekers - Convert documentation to AI skills
type: application
version: 1.0.0
appVersion: "2.9.0"
keywords:
- ai
- documentation
- skills
- mcp
- vector-database
- claude
- gemini
- openai
home: https://skillseekersweb.com
sources:
- https://github.com/your-org/skill-seekers
maintainers:
- name: Skill Seekers Team
email: noreply@skillseekers.dev
icon: https://skillseekersweb.com/icon.png
dependencies: []
annotations:
category: AI/ML
licenses: MIT

View File

@@ -0,0 +1,144 @@
🎉 Skill Seekers {{ .Chart.AppVersion }} has been installed!
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📦 DEPLOYMENT SUMMARY
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Release Name: {{ .Release.Name }}
Namespace: {{ .Release.Namespace }}
Chart Version: {{ .Chart.Version }}
App Version: {{ .Chart.AppVersion }}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🚀 SERVICES DEPLOYED
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{{- if .Values.mcpServer.enabled }}
✅ MCP Server ({{ .Values.mcpServer.replicaCount }} replicas)
- Port: {{ .Values.mcpServer.service.port }}
{{- if .Values.mcpServer.autoscaling.enabled }}
- Autoscaling: {{ .Values.mcpServer.autoscaling.minReplicas }}-{{ .Values.mcpServer.autoscaling.maxReplicas }} replicas
{{- end }}
{{- end }}
{{- if .Values.vectorDatabases.weaviate.enabled }}
✅ Weaviate Vector Database
- Port: {{ .Values.vectorDatabases.weaviate.service.port }}
{{- if .Values.vectorDatabases.weaviate.persistence.enabled }}
- Storage: {{ .Values.vectorDatabases.weaviate.persistence.size }}
{{- end }}
{{- end }}
{{- if .Values.vectorDatabases.qdrant.enabled }}
✅ Qdrant Vector Database
- HTTP Port: {{ .Values.vectorDatabases.qdrant.service.httpPort }}
- gRPC Port: {{ .Values.vectorDatabases.qdrant.service.grpcPort }}
{{- if .Values.vectorDatabases.qdrant.persistence.enabled }}
- Storage: {{ .Values.vectorDatabases.qdrant.persistence.size }}
{{- end }}
{{- end }}
{{- if .Values.vectorDatabases.chroma.enabled }}
✅ Chroma Vector Database
- Port: {{ .Values.vectorDatabases.chroma.service.port }}
{{- if .Values.vectorDatabases.chroma.persistence.enabled }}
- Storage: {{ .Values.vectorDatabases.chroma.persistence.size }}
{{- end }}
{{- end }}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔗 ACCESSING YOUR SERVICES
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{{- if .Values.mcpServer.enabled }}
MCP Server:
{{- if eq .Values.mcpServer.service.type "ClusterIP" }}
# Port-forward to access locally
kubectl port-forward -n {{ .Release.Namespace }} svc/{{ include "skill-seekers.fullname" . }}-mcp {{ .Values.mcpServer.service.port }}:{{ .Values.mcpServer.service.port }}
# Then connect to: http://localhost:{{ .Values.mcpServer.service.port }}
{{- else if eq .Values.mcpServer.service.type "LoadBalancer" }}
# Get external IP
kubectl get svc -n {{ .Release.Namespace }} {{ include "skill-seekers.fullname" . }}-mcp
{{- else if eq .Values.mcpServer.service.type "NodePort" }}
# Get node port
kubectl get svc -n {{ .Release.Namespace }} {{ include "skill-seekers.fullname" . }}-mcp
{{- end }}
{{- end }}
{{- if .Values.ingress.enabled }}
Ingress:
{{- range .Values.ingress.hosts }}
- https://{{ .host }}
{{- end }}
{{- end }}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📊 MONITORING
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# View pod status
kubectl get pods -n {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }}
# View logs
kubectl logs -n {{ .Release.Namespace }} -l app.kubernetes.io/component=mcp-server --tail=100 -f
# View events
kubectl get events -n {{ .Release.Namespace }} --sort-by='.lastTimestamp'
{{- if .Values.mcpServer.autoscaling.enabled }}
# View autoscaler status
kubectl get hpa -n {{ .Release.Namespace }} {{ include "skill-seekers.fullname" . }}-mcp
{{- end }}
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
🔧 CONFIGURATION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
{{- if not .Values.secrets.anthropicApiKey }}
⚠️ WARNING: ANTHROPIC_API_KEY not set
Set it with:
helm upgrade {{ .Release.Name }} skill-seekers/skill-seekers \
--set secrets.anthropicApiKey="sk-ant-..." \
--reuse-values
{{- end }}
View current configuration:
helm get values {{ .Release.Name }} -n {{ .Release.Namespace }}
Update configuration:
helm upgrade {{ .Release.Name }} skill-seekers/skill-seekers \
--set key=value \
--reuse-values
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📚 NEXT STEPS
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Configure API Keys (if not already set):
kubectl create secret generic {{ include "skill-seekers.fullname" . }} \
--from-literal=ANTHROPIC_API_KEY="sk-ant-..." \
-n {{ .Release.Namespace }}
2. Test MCP Server Connection:
curl http://localhost:{{ .Values.mcpServer.service.port }}/health
3. Use Skill Seekers CLI:
kubectl exec -it -n {{ .Release.Namespace }} \
deployment/{{ include "skill-seekers.fullname" . }}-mcp -- \
skill-seekers --help
4. Export to Vector Databases:
kubectl exec -it -n {{ .Release.Namespace }} \
deployment/{{ include "skill-seekers.fullname" . }}-mcp -- \
skill-seekers package /data/myskill --target weaviate
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
📖 DOCUMENTATION
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- Project: https://github.com/yourusername/skill-seekers
- Docs: https://skillseekersweb.com
- Issues: https://github.com/yourusername/skill-seekers/issues
Happy skill seeking! 🚀

View File

@@ -0,0 +1,60 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "skill-seekers.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "skill-seekers.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "skill-seekers.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "skill-seekers.labels" -}}
helm.sh/chart: {{ include "skill-seekers.chart" . }}
{{ include "skill-seekers.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "skill-seekers.selectorLabels" -}}
app.kubernetes.io/name: {{ include "skill-seekers.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "skill-seekers.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "skill-seekers.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,49 @@
{{- if .Values.vectorDatabases.chroma.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "skill-seekers.fullname" . }}-chroma
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: chroma
spec:
replicas: {{ .Values.vectorDatabases.chroma.replicaCount }}
selector:
matchLabels:
{{- include "skill-seekers.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: chroma
template:
metadata:
labels:
{{- include "skill-seekers.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: chroma
spec:
containers:
- name: chroma
image: "{{ .Values.vectorDatabases.chroma.image.repository }}:{{ .Values.vectorDatabases.chroma.image.tag }}"
imagePullPolicy: {{ .Values.vectorDatabases.chroma.image.pullPolicy }}
ports:
- name: http
containerPort: 8000
protocol: TCP
env:
- name: IS_PERSISTENT
value: "TRUE"
- name: PERSIST_DIRECTORY
value: "/chroma/chroma"
- name: ANONYMIZED_TELEMETRY
value: "FALSE"
resources:
{{- toYaml .Values.vectorDatabases.chroma.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /chroma/chroma
volumes:
- name: data
{{- if .Values.vectorDatabases.chroma.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ include "skill-seekers.fullname" . }}-chroma-data
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "skill-seekers.fullname" . }}
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
data:
{{- range $key, $value := .Values.env }}
{{ $key }}: {{ $value | quote }}
{{- end }}
SKILL_SEEKERS_HOME: "/data"
SKILL_SEEKERS_OUTPUT: "/output"

View File

@@ -0,0 +1,33 @@
{{- if .Values.mcpServer.autoscaling.enabled }}
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: {{ include "skill-seekers.fullname" . }}-mcp
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: mcp-server
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ include "skill-seekers.fullname" . }}-mcp
minReplicas: {{ .Values.mcpServer.autoscaling.minReplicas }}
maxReplicas: {{ .Values.mcpServer.autoscaling.maxReplicas }}
metrics:
{{- if .Values.mcpServer.autoscaling.targetCPUUtilizationPercentage }}
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: {{ .Values.mcpServer.autoscaling.targetCPUUtilizationPercentage }}
{{- end }}
{{- if .Values.mcpServer.autoscaling.targetMemoryUtilizationPercentage }}
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: {{ .Values.mcpServer.autoscaling.targetMemoryUtilizationPercentage }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,41 @@
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "skill-seekers.fullname" . }}
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.className }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ .path }}
pathType: {{ .pathType }}
backend:
service:
name: {{ include "skill-seekers.fullname" $ }}-{{ .backend.service.name }}
port:
number: {{ .backend.service.port }}
{{- end }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,99 @@
{{- if .Values.mcpServer.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "skill-seekers.fullname" . }}-mcp
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: mcp-server
spec:
{{- if not .Values.mcpServer.autoscaling.enabled }}
replicas: {{ .Values.mcpServer.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "skill-seekers.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: mcp-server
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
checksum/secret: {{ include (print $.Template.BasePath "/secret.yaml") . | sha256sum }}
{{- with .Values.mcpServer.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "skill-seekers.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: mcp-server
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "skill-seekers.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.mcpServer.podSecurityContext | nindent 8 }}
containers:
- name: mcp-server
securityContext:
{{- toYaml .Values.mcpServer.securityContext | nindent 12 }}
image: "{{ .Values.mcpServer.image.repository }}:{{ .Values.mcpServer.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.mcpServer.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.mcpServer.service.targetPort }}
protocol: TCP
envFrom:
- configMapRef:
name: {{ include "skill-seekers.fullname" . }}
- secretRef:
name: {{ include "skill-seekers.fullname" . }}
livenessProbe:
{{- toYaml .Values.mcpServer.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.mcpServer.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.mcpServer.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /data
- name: output
mountPath: /output
- name: configs
mountPath: /configs
readOnly: true
volumes:
- name: data
{{- if .Values.persistence.data.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.data.existingClaim | default (printf "%s-data" (include "skill-seekers.fullname" .)) }}
{{- else }}
emptyDir: {}
{{- end }}
- name: output
{{- if .Values.persistence.output.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.output.existingClaim | default (printf "%s-output" (include "skill-seekers.fullname" .)) }}
{{- else }}
emptyDir: {}
{{- end }}
- name: configs
{{- if .Values.persistence.configs.enabled }}
persistentVolumeClaim:
claimName: {{ .Values.persistence.configs.existingClaim | default (printf "%s-configs" (include "skill-seekers.fullname" .)) }}
{{- else }}
emptyDir: {}
{{- end }}
{{- with .Values.mcpServer.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.mcpServer.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.mcpServer.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,110 @@
{{- if .Values.persistence.data.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "skill-seekers.fullname" . }}-data
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.persistence.data.accessMode }}
{{- if .Values.persistence.data.storageClass }}
storageClassName: {{ .Values.persistence.data.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.data.size }}
{{- end }}
---
{{- if .Values.persistence.output.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "skill-seekers.fullname" . }}-output
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.persistence.output.accessMode }}
{{- if .Values.persistence.output.storageClass }}
storageClassName: {{ .Values.persistence.output.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.output.size }}
{{- end }}
---
{{- if .Values.persistence.configs.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "skill-seekers.fullname" . }}-configs
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
spec:
accessModes:
- {{ .Values.persistence.configs.accessMode }}
{{- if .Values.persistence.configs.storageClass }}
storageClassName: {{ .Values.persistence.configs.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.persistence.configs.size }}
{{- end }}
---
{{- if and .Values.vectorDatabases.weaviate.enabled .Values.vectorDatabases.weaviate.persistence.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "skill-seekers.fullname" . }}-weaviate-data
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: weaviate
spec:
accessModes:
- ReadWriteOnce
{{- if .Values.vectorDatabases.weaviate.persistence.storageClass }}
storageClassName: {{ .Values.vectorDatabases.weaviate.persistence.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.vectorDatabases.weaviate.persistence.size }}
{{- end }}
---
{{- if and .Values.vectorDatabases.qdrant.enabled .Values.vectorDatabases.qdrant.persistence.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "skill-seekers.fullname" . }}-qdrant-data
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: qdrant
spec:
accessModes:
- ReadWriteOnce
{{- if .Values.vectorDatabases.qdrant.persistence.storageClass }}
storageClassName: {{ .Values.vectorDatabases.qdrant.persistence.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.vectorDatabases.qdrant.persistence.size }}
{{- end }}
---
{{- if and .Values.vectorDatabases.chroma.enabled .Values.vectorDatabases.chroma.persistence.enabled }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ include "skill-seekers.fullname" . }}-chroma-data
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: chroma
spec:
accessModes:
- ReadWriteOnce
{{- if .Values.vectorDatabases.chroma.persistence.storageClass }}
storageClassName: {{ .Values.vectorDatabases.chroma.persistence.storageClass | quote }}
{{- end }}
resources:
requests:
storage: {{ .Values.vectorDatabases.chroma.persistence.size }}
{{- end }}

View File

@@ -0,0 +1,50 @@
{{- if .Values.vectorDatabases.qdrant.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "skill-seekers.fullname" . }}-qdrant
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: qdrant
spec:
replicas: {{ .Values.vectorDatabases.qdrant.replicaCount }}
selector:
matchLabels:
{{- include "skill-seekers.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: qdrant
template:
metadata:
labels:
{{- include "skill-seekers.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: qdrant
spec:
containers:
- name: qdrant
image: "{{ .Values.vectorDatabases.qdrant.image.repository }}:{{ .Values.vectorDatabases.qdrant.image.tag }}"
imagePullPolicy: {{ .Values.vectorDatabases.qdrant.image.pullPolicy }}
ports:
- name: http
containerPort: 6333
protocol: TCP
- name: grpc
containerPort: 6334
protocol: TCP
env:
- name: QDRANT__SERVICE__HTTP_PORT
value: "6333"
- name: QDRANT__SERVICE__GRPC_PORT
value: "6334"
resources:
{{- toYaml .Values.vectorDatabases.qdrant.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /qdrant/storage
volumes:
- name: data
{{- if .Values.vectorDatabases.qdrant.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ include "skill-seekers.fullname" . }}-qdrant-data
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,20 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "skill-seekers.fullname" . }}
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
type: Opaque
data:
{{- if .Values.secrets.anthropicApiKey }}
ANTHROPIC_API_KEY: {{ .Values.secrets.anthropicApiKey | b64enc | quote }}
{{- end }}
{{- if .Values.secrets.googleApiKey }}
GOOGLE_API_KEY: {{ .Values.secrets.googleApiKey | b64enc | quote }}
{{- end }}
{{- if .Values.secrets.openaiApiKey }}
OPENAI_API_KEY: {{ .Values.secrets.openaiApiKey | b64enc | quote }}
{{- end }}
{{- if .Values.secrets.githubToken }}
GITHUB_TOKEN: {{ .Values.secrets.githubToken | b64enc | quote }}
{{- end }}

View File

@@ -0,0 +1,83 @@
{{- if .Values.mcpServer.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "skill-seekers.fullname" . }}-mcp
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: mcp-server
spec:
type: {{ .Values.mcpServer.service.type }}
ports:
- port: {{ .Values.mcpServer.service.port }}
targetPort: {{ .Values.mcpServer.service.targetPort }}
protocol: {{ .Values.mcpServer.service.protocol }}
name: http
selector:
{{- include "skill-seekers.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: mcp-server
{{- end }}
---
{{- if .Values.vectorDatabases.weaviate.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "skill-seekers.fullname" . }}-weaviate
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: weaviate
spec:
type: {{ .Values.vectorDatabases.weaviate.service.type }}
ports:
- port: {{ .Values.vectorDatabases.weaviate.service.port }}
targetPort: 8080
protocol: TCP
name: http
selector:
{{- include "skill-seekers.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: weaviate
{{- end }}
---
{{- if .Values.vectorDatabases.qdrant.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "skill-seekers.fullname" . }}-qdrant
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: qdrant
spec:
type: {{ .Values.vectorDatabases.qdrant.service.type }}
ports:
- port: {{ .Values.vectorDatabases.qdrant.service.httpPort }}
targetPort: 6333
protocol: TCP
name: http
- port: {{ .Values.vectorDatabases.qdrant.service.grpcPort }}
targetPort: 6334
protocol: TCP
name: grpc
selector:
{{- include "skill-seekers.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: qdrant
{{- end }}
---
{{- if .Values.vectorDatabases.chroma.enabled -}}
apiVersion: v1
kind: Service
metadata:
name: {{ include "skill-seekers.fullname" . }}-chroma
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: chroma
spec:
type: {{ .Values.vectorDatabases.chroma.service.type }}
ports:
- port: {{ .Values.vectorDatabases.chroma.service.port }}
targetPort: 8000
protocol: TCP
name: http
selector:
{{- include "skill-seekers.selectorLabels" . | nindent 4 }}
app.kubernetes.io/component: chroma
{{- end }}

View File

@@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "skill-seekers.serviceAccountName" . }}
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,55 @@
{{- if .Values.vectorDatabases.weaviate.enabled -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "skill-seekers.fullname" . }}-weaviate
labels:
{{- include "skill-seekers.labels" . | nindent 4 }}
app.kubernetes.io/component: weaviate
spec:
replicas: {{ .Values.vectorDatabases.weaviate.replicaCount }}
selector:
matchLabels:
{{- include "skill-seekers.selectorLabels" . | nindent 6 }}
app.kubernetes.io/component: weaviate
template:
metadata:
labels:
{{- include "skill-seekers.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: weaviate
spec:
containers:
- name: weaviate
image: "{{ .Values.vectorDatabases.weaviate.image.repository }}:{{ .Values.vectorDatabases.weaviate.image.tag }}"
imagePullPolicy: {{ .Values.vectorDatabases.weaviate.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
protocol: TCP
env:
- name: QUERY_DEFAULTS_LIMIT
value: "25"
- name: AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED
value: "true"
- name: PERSISTENCE_DATA_PATH
value: "/var/lib/weaviate"
- name: DEFAULT_VECTORIZER_MODULE
value: "none"
- name: ENABLE_MODULES
value: ""
- name: CLUSTER_HOSTNAME
value: "node1"
resources:
{{- toYaml .Values.vectorDatabases.weaviate.resources | nindent 12 }}
volumeMounts:
- name: data
mountPath: /var/lib/weaviate
volumes:
- name: data
{{- if .Values.vectorDatabases.weaviate.persistence.enabled }}
persistentVolumeClaim:
claimName: {{ include "skill-seekers.fullname" . }}-weaviate-data
{{- else }}
emptyDir: {}
{{- end }}
{{- end }}

View File

@@ -0,0 +1,313 @@
# Default values for skill-seekers Helm chart
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
# Global configuration
global:
# Environment: development, staging, production
environment: production
# Main application (CLI)
app:
enabled: true
name: skill-seekers
replicaCount: 1
image:
repository: skill-seekers
pullPolicy: IfNotPresent
tag: "latest"
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
podAnnotations: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
allowPrivilegeEscalation: false
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 500m
memory: 1Gi
nodeSelector: {}
tolerations: []
affinity: {}
# MCP Server
mcpServer:
enabled: true
name: mcp-server
replicaCount: 2
image:
repository: skill-seekers-mcp
pullPolicy: IfNotPresent
tag: "latest"
service:
type: ClusterIP
port: 8765
targetPort: 8765
protocol: TCP
podAnnotations: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 1000
securityContext:
capabilities:
drop:
- ALL
readOnlyRootFilesystem: false
allowPrivilegeEscalation: false
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 250m
memory: 512Mi
# Horizontal Pod Autoscaler
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80
# Health checks
livenessProbe:
httpGet:
path: /health
port: 8765
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /health
port: 8765
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
successThreshold: 1
failureThreshold: 3
nodeSelector: {}
tolerations: []
affinity: {}
# Environment variables (non-sensitive)
env:
MCP_TRANSPORT: "http"
MCP_PORT: "8765"
PYTHONUNBUFFERED: "1"
PYTHONDONTWRITEBYTECODE: "1"
# Secrets (sensitive values)
# Set these via --set or external secret management
secrets:
# Claude AI / Anthropic API
anthropicApiKey: ""
# Google Gemini API (optional)
googleApiKey: ""
# OpenAI API (optional)
openaiApiKey: ""
# GitHub Token (optional)
githubToken: ""
# Persistent storage
persistence:
enabled: true
data:
enabled: true
storageClass: ""
accessMode: ReadWriteOnce
size: 10Gi
existingClaim: ""
output:
enabled: true
storageClass: ""
accessMode: ReadWriteOnce
size: 20Gi
existingClaim: ""
configs:
enabled: true
storageClass: ""
accessMode: ReadOnlyMany
size: 1Gi
existingClaim: ""
# Vector Databases
vectorDatabases:
# Weaviate
weaviate:
enabled: true
replicaCount: 1
image:
repository: semitechnologies/weaviate
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8080
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 500m
memory: 1Gi
persistence:
enabled: true
storageClass: ""
size: 50Gi
# Qdrant
qdrant:
enabled: true
replicaCount: 1
image:
repository: qdrant/qdrant
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
httpPort: 6333
grpcPort: 6334
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 500m
memory: 1Gi
persistence:
enabled: true
storageClass: ""
size: 50Gi
# Chroma
chroma:
enabled: true
replicaCount: 1
image:
repository: ghcr.io/chroma-core/chroma
tag: latest
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 8000
resources:
limits:
cpu: 1000m
memory: 2Gi
requests:
cpu: 250m
memory: 512Mi
persistence:
enabled: true
storageClass: ""
size: 30Gi
# Ingress configuration
ingress:
enabled: false
className: "nginx"
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: skill-seekers.example.com
paths:
- path: /mcp
pathType: Prefix
backend:
service:
name: mcp-server
port: 8765
tls:
- secretName: skill-seekers-tls
hosts:
- skill-seekers.example.com
# Service Monitor (Prometheus)
serviceMonitor:
enabled: false
interval: 30s
scrapeTimeout: 10s
labels: {}
# Network Policies
networkPolicy:
enabled: false
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
egress:
- to:
- namespaceSelector: {}
# RBAC
rbac:
create: true
rules: []
# Pod Disruption Budget
podDisruptionBudget:
enabled: true
minAvailable: 1
# Resource Quotas
resourceQuota:
enabled: false
hard:
requests.cpu: "10"
requests.memory: "20Gi"
persistentvolumeclaims: "10"