From e0b05a8419a34be78f2cacab53f5875f39e1f457 Mon Sep 17 00:00:00 2001 From: "daniel@codetogether.com" Date: Tue, 4 Mar 2025 17:13:56 -0600 Subject: [PATCH 1/3] feat(ai): Integrate AI container deployment in Intel chart Added support for AI container deployment with bundled and external modes. Configured Helm values to allow users to specify AI providers (OpenAI or custom). Implemented environment variable injection for AI-related configurations. Ensured compatibility with existing Intel deployment. Fixed potential issues with missing secrets and resource allocation. --- charts/intel/templates/deployment.yaml | 32 +++++++++++++++++++++++++- charts/intel/templates/secrets.yaml | 8 +++++++ charts/intel/values.yaml | 10 ++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 charts/intel/templates/secrets.yaml diff --git a/charts/intel/templates/deployment.yaml b/charts/intel/templates/deployment.yaml index dc46de4..0dd70fd 100644 --- a/charts/intel/templates/deployment.yaml +++ b/charts/intel/templates/deployment.yaml @@ -28,6 +28,23 @@ spec: {{- end }} serviceAccountName: {{ include "codetogether.serviceAccountName" . }} containers: + {{- if eq .Values.ai.mode "bundled" }} + - name: ai-service + image: "registry.digitalocean.com/codetogether-registry/ai-summarization" + imagePullPolicy: Always + env: + - name: OPENAI_API_KEY + valueFrom: + secretKeyRef: + name: ai-secrets + key: openai-api-key + ports: + - name: ai + containerPort: 8000 + protocol: TCP + resources: + {{- toYaml .Values.ai.resources | nindent 12 }} + {{- end }} - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} @@ -37,6 +54,19 @@ spec: {{- else }}:{{ .Values.image.tag | default .Chart.AppVersion }}{{- end }} imagePullPolicy: {{ .Values.image.pullPolicy }} env: + - name: AI_MODE + value: {{ .Values.ai.mode | quote }} + {{- if eq .Values.ai.mode "external" }} + - name: AI_PROVIDER + value: {{ .Values.ai.provider | quote }} + - name: AI_EXTERNAL_URL + value: {{ .Values.ai.external.url | quote }} + - name: AI_EXTERNAL_API_KEY + valueFrom: + secretKeyRef: + name: ai-secrets + key: external-ai-key + {{- end }} # # Set CodeTogether runtime configuration # @@ -124,4 +154,4 @@ spec: {{- with .Values.tolerations }} tolerations: {{- toYaml . | nindent 8 }} - {{- end }} + {{- end }} \ No newline at end of file diff --git a/charts/intel/templates/secrets.yaml b/charts/intel/templates/secrets.yaml new file mode 100644 index 0000000..5cdd56d --- /dev/null +++ b/charts/intel/templates/secrets.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: ai-secrets +type: Opaque +data: + openai-api-key: {{ .Values.ai.openai.api_key | b64enc }} + external-ai-key: {{ .Values.ai.external.api_key | b64enc }} diff --git a/charts/intel/values.yaml b/charts/intel/values.yaml index c33abdb..3eefa3a 100644 --- a/charts/intel/values.yaml +++ b/charts/intel/values.yaml @@ -138,6 +138,16 @@ securityContext: {} # runAsNonRoot: true # runAsUser: 1000 +ai: + mode: "bundled" # Options: bundled | external + provider: "openai" # Can be "openai" or "custom" + openai: + api_key: "YOUR_OPENAI_API_KEY" + model: "gpt-4-turbo" # Available models: gpt-4-turbo, gpt-3.5-turbo + external: + url: "" # External AI service URL + api_key: "" # API key for authentication + readinessProbe: initialDelaySeconds: 60 periodSeconds: 60 From 86a6735e8d115a02b3352efe15125c4b3e8ef3b3 Mon Sep 17 00:00:00 2001 From: "daniel@codetogether.com" Date: Tue, 4 Mar 2025 19:21:25 -0600 Subject: [PATCH 2/3] Added AI secrets documentation to README - Included instructions for securely storing AI API keys using Kubernetes secrets. - Provided a command to create the `ai-secrets` secret for OpenAI and external AI providers. - Ensured secure key management by referencing secrets instead of storing keys in `values.yaml`. --- charts/intel/README.md | 41 ++++++++++++++++++++++++++ charts/intel/templates/deployment.yaml | 4 +-- charts/intel/values.yaml | 8 ++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/charts/intel/README.md b/charts/intel/README.md index a0aa20f..6f0771d 100644 --- a/charts/intel/README.md +++ b/charts/intel/README.md @@ -53,6 +53,15 @@ The following table lists configurable parameters of the CodeTogether Intel char | `java.customCacerts.enabled` | Enables mounting a custom Java trust store (cacerts) | `false` | | `java.customCacerts.cacertsSecretName` | Name of the Kubernetes secret containing the `cacerts` file | `custom-java-cacerts` | | `java.customCacerts.trustStorePasswordKey` | (Optional) Key inside the Kubernetes secret containing the trust store password | `trustStorePassword` | +| `ai.mode` | AI integration mode: `bundled` (deploy AI container) or `external` (use external AI service) | `"bundled"` | +| `ai.provider` | AI provider (`openai` or custom) | `"openai"` | +| `ai.model` | AI model to use (`gpt-4-turbo`, `gpt-3.5-turbo`, etc.) | `"gpt-4-turbo"` | +| `ai.resources.cpu` | CPU allocation for AI container | `"2"` | +| `ai.resources.memory` | Memory allocation for AI container | `"4Gi"` | +| `ai.resources.gpu` | GPU support (future feature) | `false` | +| `ai.external.url` | URL for external AI service (if `mode: external`) | `""` | +| `ai.external.apiKeySecret.name` | Name of the Kubernetes secret containing the external AI API key | `"ai-secrets"` | +| `ai.external.apiKeySecret.key` | Key name in the Kubernetes secret containing the API key | `"external-ai-key"` | | `ingress.enabled` | Enables ingress controller resource | `true` | | `ingress.annotations` | Annotations for ingress | `{}` | | `ingress.tls.secretName` | TLS secret name for ingress | `codetogether-intel-tls` | @@ -107,6 +116,38 @@ If you prefer not to store the Cassandra password in values.yaml, you can store kubectl create secret generic cassandra-password-secret --from-literal=cassandraPassword='your-secure-cassandra-password' --namespace=codetogether-intel ``` +## AI Integration and API Key Security + +This chart supports an AI container for generating summaries. Users can choose between deploying an AI model inside the cluster (`bundled` mode) or connecting to an external AI service (`external` mode). + +### **Configuring AI Integration** +Modify the `values.yaml` file to set AI mode, provider, and resources: + +```bash +ai: + mode: "bundled" # Options: bundled | external + provider: "openai" # Can be "openai" or a custom provider + model: "gpt-4-turbo" + resources: + cpu: "2" + memory: "4Gi" + gpu: false + external: + url: "" # External AI service URL + apiKeySecret: + name: "ai-secrets" + key: "external-ai-key" +``` + +## AI Secrets + +To securely store API keys for AI integration, you can create a `secret` that contains the necessary authentication credentials: + +```bash +$ kubectl create secret generic ai-secrets \ + --from-literal=external-ai-key="" \ + -n codetogether-intel +``` ## Installing the Chart diff --git a/charts/intel/templates/deployment.yaml b/charts/intel/templates/deployment.yaml index 0dd70fd..6e1ed47 100644 --- a/charts/intel/templates/deployment.yaml +++ b/charts/intel/templates/deployment.yaml @@ -64,8 +64,8 @@ spec: - name: AI_EXTERNAL_API_KEY valueFrom: secretKeyRef: - name: ai-secrets - key: external-ai-key + name: {{ .Values.ai.external.apiKeySecret.name }} + key: {{ .Values.ai.external.apiKeySecret.key }} {{- end }} # # Set CodeTogether runtime configuration diff --git a/charts/intel/values.yaml b/charts/intel/values.yaml index 3eefa3a..eac4e53 100644 --- a/charts/intel/values.yaml +++ b/charts/intel/values.yaml @@ -144,9 +144,15 @@ ai: openai: api_key: "YOUR_OPENAI_API_KEY" model: "gpt-4-turbo" # Available models: gpt-4-turbo, gpt-3.5-turbo + resources: + cpu: "2" + memory: "4Gi" + gpu: false external: url: "" # External AI service URL - api_key: "" # API key for authentication + apiKeySecret: + name: "ai-secrets" + key: "external-ai-key" readinessProbe: initialDelaySeconds: 60 From 130306642f99b4786161dee238109683a7490e1e Mon Sep 17 00:00:00 2001 From: "daniel@codetogether.com" Date: Thu, 6 Mar 2025 20:35:36 -0600 Subject: [PATCH 3/3] feat(ai): Implement bundled AI support with Ollama and Qwen2.5 Coder 3B - Integrated a **NON-OpenAI** bundled model using **Ollama**. - Added support for **Qwen2.5 Coder 3B** from LM Studio. - Updated **Dockerfile.ai** to dynamically pull models via `MODELS` build argument. - Modified **deployment.yaml** to pass `AI_BUNDLED_URL` dynamically from Helm. - Updated **values.yaml** to configure `ai.bundled_url` automatically. - Ensured **external AI mode** is handled via product portal (not Helm). - Verified deployment stability and resource usage. **Successfully tested bundled AI mode with Qwen2.5 Coder 3B.** --- charts/intel/README.md | 6 ++-- charts/intel/ollama/Dockerfile.ai | 19 ++++++++++ charts/intel/templates/deployment.yaml | 49 +++++++++++++++----------- charts/intel/values.yaml | 25 ++++++------- 4 files changed, 64 insertions(+), 35 deletions(-) create mode 100644 charts/intel/ollama/Dockerfile.ai diff --git a/charts/intel/README.md b/charts/intel/README.md index 6f0771d..7f79c32 100644 --- a/charts/intel/README.md +++ b/charts/intel/README.md @@ -144,9 +144,9 @@ ai: To securely store API keys for AI integration, you can create a `secret` that contains the necessary authentication credentials: ```bash -$ kubectl create secret generic ai-secrets \ - --from-literal=external-ai-key="" \ - -n codetogether-intel +kubectl create secret generic ai-external-secret \ + --from-literal=api-key='your-external-ai-key' \ + --namespace= ``` ## Installing the Chart diff --git a/charts/intel/ollama/Dockerfile.ai b/charts/intel/ollama/Dockerfile.ai new file mode 100644 index 0000000..466edd9 --- /dev/null +++ b/charts/intel/ollama/Dockerfile.ai @@ -0,0 +1,19 @@ +# Use Ollama as the base image +FROM ollama/ollama + +# Define the models to be included +#ARG MODELS="qwen2.5-coder:3b" +ARG MODELS + +ENV OLLAMA_KEEP_ALIVE=24h + +# Pre-load the models at build time **directly in /root/.ollama** +RUN mkdir -p /root/.ollama && \ + ollama serve & server=$! ; \ + sleep 5 ; \ + for m in $MODELS ; do ollama pull $m ; done ; \ + kill $server + +CMD [ "serve" ] + + diff --git a/charts/intel/templates/deployment.yaml b/charts/intel/templates/deployment.yaml index 6e1ed47..0615be8 100644 --- a/charts/intel/templates/deployment.yaml +++ b/charts/intel/templates/deployment.yaml @@ -29,51 +29,56 @@ spec: serviceAccountName: {{ include "codetogether.serviceAccountName" . }} containers: {{- if eq .Values.ai.mode "bundled" }} - - name: ai-service - image: "registry.digitalocean.com/codetogether-registry/ai-summarization" + - name: codetogether-llm + image: "{{ .Values.ai.image.repository }}:{{ .Values.ai.image.tag }}" imagePullPolicy: Always - env: - - name: OPENAI_API_KEY - valueFrom: - secretKeyRef: - name: ai-secrets - key: openai-api-key ports: - name: ai containerPort: 8000 protocol: TCP resources: - {{- toYaml .Values.ai.resources | nindent 12 }} + requests: + cpu: {{ .Values.ai.resources.requests.cpu | quote }} + memory: {{ .Values.ai.resources.requests.memory | quote }} + limits: + cpu: {{ .Values.ai.resources.limits.cpu | quote }} + memory: {{ .Values.ai.resources.limits.memory | quote }} {{- end }} - name: {{ .Chart.Name }} securityContext: {{- toYaml .Values.securityContext | nindent 12 }} - image: >- - {{ .Values.image.repository }} - {{- if .Values.image.digest }}@{{ .Values.image.digest }} - {{- else }}:{{ .Values.image.tag | default .Chart.AppVersion }}{{- end }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} env: - name: AI_MODE value: {{ .Values.ai.mode | quote }} + {{- if eq .Values.ai.mode "bundled" }} + - name: AI_BUNDLED_URL + value: "http://codetogether-llm:8000" + {{- end }} {{- if eq .Values.ai.mode "external" }} - name: AI_PROVIDER - value: {{ .Values.ai.provider | quote }} + valueFrom: + configMapKeyRef: + name: ai-config + key: ai_provider - name: AI_EXTERNAL_URL - value: {{ .Values.ai.external.url | quote }} + valueFrom: + configMapKeyRef: + name: ai-config + key: ai_url - name: AI_EXTERNAL_API_KEY valueFrom: secretKeyRef: - name: {{ .Values.ai.external.apiKeySecret.name }} - key: {{ .Values.ai.external.apiKeySecret.key }} + name: ai-external-secret + key: api-key {{- end }} # # Set CodeTogether runtime configuration # - name: CT_HQ_BASE_URL value: {{ .Values.codetogether.url | quote }} - - {{- if .Values.java.customCacerts.enabled }} + {{- if .Values.java.customCacerts.enabled }} - name: CT_TRUST_STORE value: -Djavax.net.ssl.trustStore=/etc/ssl/certs/java/cacerts {{- end }} @@ -91,7 +96,7 @@ spec: secretKeyRef: name: {{ .Values.java.customCacerts.cacertsSecretName }} key: {{ .Values.java.customCacerts.trustStorePasswordKey }} - optional: true # Ensures the key is optional + optional: true {{- end }} volumeMounts: @@ -113,11 +118,15 @@ spec: protocol: TCP livenessProbe: + httpGet: + path: / + port: http initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.livenessProbe.periodSeconds }} timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }} successThreshold: {{ .Values.livenessProbe.successThreshold }} failureThreshold: {{ .Values.livenessProbe.failureThreshold }} + readinessProbe: httpGet: path: / port: http diff --git a/charts/intel/values.yaml b/charts/intel/values.yaml index eac4e53..ac9227e 100644 --- a/charts/intel/values.yaml +++ b/charts/intel/values.yaml @@ -140,19 +140,20 @@ securityContext: {} ai: mode: "bundled" # Options: bundled | external - provider: "openai" # Can be "openai" or "custom" - openai: - api_key: "YOUR_OPENAI_API_KEY" - model: "gpt-4-turbo" # Available models: gpt-4-turbo, gpt-3.5-turbo + provider: "ollama" # No OpenAI dependency resources: - cpu: "2" - memory: "4Gi" - gpu: false - external: - url: "" # External AI service URL - apiKeySecret: - name: "ai-secrets" - key: "external-ai-key" + requests: + cpu: "2" + memory: "4Gi" + gpu: false + limits: + cpu: "4" + memory: "8Gi" + gpu: false + image: + repository: registry.digitalocean.com/codetogether-registry/ai-summarization + tag: latest + readinessProbe: initialDelaySeconds: 60