Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/linters/ct.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ chart-dirs:
helm-extra-args: --timeout 1000s
chart-repos:
- opensearch=https://opensearch-project.github.io/helm-charts
- ollama=https://otwld.github.io/ollama-helm
5 changes: 4 additions & 1 deletion .github/workflows/kubernetes-charts-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ jobs:
- name: Set up Helm
uses: azure/setup-helm@v4.3.1

- uses: actions/setup-python@v6.0.0
- name: Set up Python
uses: actions/setup-python@v6.0.0
with:
python-version: "3.x"
check-latest: true
Expand Down Expand Up @@ -131,6 +132,7 @@ jobs:
helm package ./medcat-service-helm --version ${{ steps.version.outputs.chart_version }}
helm package ./medcat-trainer-helm --version ${{ steps.version.outputs.chart_version }} --dependency-update
helm package ./cogstack-ce-helm --version ${{ steps.version.outputs.chart_version }} --dependency-update
helm package ./cogstack-cohorter-helm --version ${{ steps.version.outputs.chart_version }} --dependency-update
helm package ./cogstack-observability-helm --version ${{ steps.version.outputs.chart_version }} --dependency-update

- name: Helm OCI login to Docker Hub
Expand All @@ -141,6 +143,7 @@ jobs:
helm push ./medcat-service-helm-${{ steps.version.outputs.chart_version }}.tgz oci://registry-1.docker.io/cogstacksystems
helm push ./medcat-trainer-helm-${{ steps.version.outputs.chart_version }}.tgz oci://registry-1.docker.io/cogstacksystems
helm push ./cogstack-ce-helm-${{ steps.version.outputs.chart_version }}.tgz oci://registry-1.docker.io/cogstacksystems
helm push ./cogstack-cohorter-helm-${{ steps.version.outputs.chart_version }}.tgz oci://registry-1.docker.io/cogstacksystems
helm push ./cogstack-observability-helm-${{ steps.version.outputs.chart_version }}.tgz oci://registry-1.docker.io/cogstacksystems

- name: Release
Expand Down
23 changes: 23 additions & 0 deletions helm-charts/cogstack-cohorter-helm/.helmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/
9 changes: 9 additions & 0 deletions helm-charts/cogstack-cohorter-helm/Chart.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
dependencies:
- name: medcat-service-helm
repository: oci://registry-1.docker.io/cogstacksystems
version: 0.0.1
- name: ollama
repository: https://otwld.github.io/ollama-helm/
version: 1.54.0
digest: sha256:c19deffe7da9495af6f74b6a6bb26157bf7faf6abac6be8fc94638deff3bc6d3
generated: "2026-04-16T14:51:41.6563526+01:00"
27 changes: 27 additions & 0 deletions helm-charts/cogstack-cohorter-helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: v2
name: cogstack-cohorter-helm
description: CogStack Cohorter — cohort identification powered by Ollama and MedCAT
type: application
version: 0.0.1
appVersion: "latest"

maintainers:
- name: jocelyneholdbrook
email: jocelyne@cogstack.org

icon: "https://avatars.githubusercontent.com/u/28688163"

dependencies:
# MedCAT annotation service
- name: medcat-service-helm
version: "0.0.1"
repository: "oci://registry-1.docker.io/cogstacksystems"
alias: medcat
condition: medcat.enabled

# Ollama LLM serving — https://github.com/otwld/ollama-helm
- name: ollama
version: ">=0.1.0"
repository: "https://otwld.github.io/ollama-helm/"
alias: ollama
condition: ollama.enabled
225 changes: 225 additions & 0 deletions helm-charts/cogstack-cohorter-helm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
# CogStack Cohorter Helm Chart

CogStack Cohorter — cohort identification powered by Ollama and MedCAT

## Architecture

| Component | Image | Description |
|-----------|-------|-------------|
| **WebApp** | `cogstacksystems/cogstack-cohorter-webapp` | React + Node.js frontend and API |
| **NL2DSL** | `cogstacksystems/cogstack-cohorter-nl2dsl` | Natural language → cohort DSL compiler |
| **MedCAT** | `cogstacksystems/medcat-service` | Clinical NER and concept normalisation (subchart) |
| **Ollama** | `ollama/ollama` | LLM serving backend (subchart) |

MedCAT and Ollama are deployed as **subcharts**:
- MedCAT: [`cogstacksystems/medcat-service-helm`](https://hub.docker.com/r/cogstacksystems/medcat-service-helm) (OCI)
- Ollama: [`otwld/ollama`](https://github.com/otwld/ollama-helm)

## Prerequisites

- Kubernetes 1.21+
- Helm 3.10+
- Sufficient node resources for the Ollama model (the default `gpt-oss:20b` requires ~14 GB of memory/VRAM)

## Installation

From Docker Hub OCI (published chart):

```bash
helm install cogstack-cohorter oci://registry-1.docker.io/cogstacksystems/cogstack-cohorter-helm
```

## Configuration

All configurable values are in [`values.yaml`](./values.yaml). Key sections:

### Ollama

```yaml
ollama:
enabled: true
ollama:
models:
pull:
- gpt-oss:20b # pulled automatically on first startup
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we default to a smaller one? So it can demo on small hardware / CI easily - for example the Azure tutorial is bringing up just 4GB nodes - would prefer it running with bad results to then justify additional recommended hardware

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah - happy to do this as part of a separate task. Would need to assess what can provide comparable results with less etc. At a glance, I'm thinking medgemma (I've heard David mention this) or qwen 3. thoughts?

persistentVolume:
enabled: true
size: 10Gi
```

Models are pulled automatically by the otwld subchart's built-in init container. Change `ollama.ollama.models.pull` to use a different model — make sure `nl2dsl.env.OLLAMA_MODEL` matches.

### MedCAT

```yaml
medcat:
enabled: true
env:
APP_MEDCAT_MODEL_PACK: "/cat/models/examples/example-medcat-v2-model-pack.zip"
```

To use a custom model pack, provide a download URL:

```yaml
medcat:
model:
downloadUrl: "https://your-host/medcat_model_pack.zip"
name: "medcat_model_pack.zip"
```

### WebApp data volume

The WebApp requires a SNOMED data directory mounted at `/usr/src/app/server/data`. A PVC is provisioned automatically:

```yaml
webapp:
persistence:
enabled: true
size: 5Gi
```

Populate the PVC with either:
- `snomed_terms_data.tar.gz` — auto-extracted by the entrypoint on first startup, or
- Pre-extracted files: `snomed_terms.json`, `cui_pt2ch.json`, and patient data files

To generate synthetic patient data on first startup (demo mode):

```yaml
webapp:
env:
RANDOM_DATA: "true"
```

### Ingress

```yaml
ingress:
enabled: true
className: nginx
hosts:
- host: cohorter.example.com
paths:
- path: /
pathType: ImplementationSpecific
tls:
- secretName: cohorter-tls
hosts:
- cohorter.example.com
```

### Autoscaling (webapp only)

```yaml
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 3
targetCPUUtilizationPercentage: 80
```

## Uninstallation

```bash
helm uninstall cogstack-cohorter
```

## Support

For issues and questions, please visit the [CogStack GitHub repository](https://github.com/CogStack/cogstack-platform).

## Requirements

| Repository | Name | Version |
|------------|------|---------|
| https://otwld.github.io/ollama-helm/ | ollama(ollama) | >=0.1.0 |
| oci://registry-1.docker.io/cogstacksystems | medcat(medcat-service-helm) | 0.0.1 |

## Values

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| autoscaling.enabled | bool | `false` | |
| autoscaling.maxReplicas | int | `3` | |
| autoscaling.minReplicas | int | `1` | |
| autoscaling.targetCPUUtilizationPercentage | int | `80` | |
| fullnameOverride | string | `""` | |
| global.imagePullSecrets | list | `[]` | |
| ingress.annotations | object | `{}` | |
| ingress.className | string | `""` | |
| ingress.enabled | bool | `false` | |
| ingress.hosts[0].host | string | `"cogstack-cohort.local"` | |
| ingress.hosts[0].paths[0].path | string | `"/"` | |
| ingress.hosts[0].paths[0].pathType | string | `"ImplementationSpecific"` | |
| ingress.tls | list | `[]` | |
| medcat.enabled | bool | `true` | |
| medcat.env.APP_ENABLE_METRICS | string | `"true"` | |
| medcat.env.APP_MEDCAT_MODEL_PACK | string | `"/cat/models/examples/example-medcat-v2-model-pack.zip"` | |
| medcat.image.tag | string | `"latest"` | |
| medcat.resources | object | `{}` | |
| medcat.service.port | int | `5000` | |
| nameOverride | string | `""` | |
| nl2dsl.affinity | object | `{}` | |
| nl2dsl.enabled | bool | `true` | |
| nl2dsl.env.ALLOW_ORIGINS | string | `"*"` | |
| nl2dsl.env.OLLAMA_MODEL | string | `"gpt-oss:20b"` | |
| nl2dsl.image.pullPolicy | string | `"IfNotPresent"` | |
| nl2dsl.image.repository | string | `"cogstacksystems/cogstack-cohorter-nl2dsl"` | |
| nl2dsl.image.tag | string | `"latest"` | |
| nl2dsl.livenessProbe.httpGet.path | string | `"/"` | |
| nl2dsl.livenessProbe.httpGet.port | string | `"http"` | |
| nl2dsl.livenessProbe.initialDelaySeconds | int | `30` | |
| nl2dsl.livenessProbe.periodSeconds | int | `10` | |
| nl2dsl.nodeSelector | object | `{}` | |
| nl2dsl.readinessProbe.httpGet.path | string | `"/"` | |
| nl2dsl.readinessProbe.httpGet.port | string | `"http"` | |
| nl2dsl.readinessProbe.initialDelaySeconds | int | `10` | |
| nl2dsl.readinessProbe.periodSeconds | int | `5` | |
| nl2dsl.replicaCount | int | `1` | |
| nl2dsl.resources | object | `{}` | |
| nl2dsl.service.port | int | `3002` | |
| nl2dsl.service.type | string | `"ClusterIP"` | |
| nl2dsl.tolerations | list | `[]` | |
| ollama.enabled | bool | `true` | |
| ollama.ollama.models.pull[0] | string | `"gpt-oss:20b"` | |
| ollama.persistentVolume.enabled | bool | `true` | |
| ollama.persistentVolume.size | string | `"10Gi"` | |
| ollama.persistentVolume.storageClass | string | `""` | |
| ollama.resources | object | `{}` | |
| ollama.service.port | int | `11434` | |
| ollama.service.type | string | `"ClusterIP"` | |
| podAnnotations | object | `{}` | |
| podLabels | object | `{}` | |
| podSecurityContext | object | `{}` | |
| securityContext | object | `{}` | |
| serviceAccount.annotations | object | `{}` | |
| serviceAccount.automount | bool | `true` | |
| serviceAccount.create | bool | `true` | |
| serviceAccount.name | string | `""` | |
| webapp.affinity | object | `{}` | |
| webapp.enabled | bool | `true` | |
| webapp.env.RANDOM_DATA | string | `"false"` | |
| webapp.image.pullPolicy | string | `"IfNotPresent"` | |
| webapp.image.repository | string | `"cogstacksystems/cogstack-cohorter-webapp"` | |
| webapp.image.tag | string | `"latest"` | |
| webapp.livenessProbe.httpGet.path | string | `"/"` | |
| webapp.livenessProbe.httpGet.port | string | `"http"` | |
| webapp.livenessProbe.initialDelaySeconds | int | `60` | |
| webapp.livenessProbe.periodSeconds | int | `15` | |
| webapp.nodeSelector | object | `{}` | |
| webapp.persistence.accessMode | string | `"ReadWriteOnce"` | |
| webapp.persistence.enabled | bool | `true` | |
| webapp.persistence.existingClaim | string | `""` | |
| webapp.persistence.size | string | `"5Gi"` | |
| webapp.persistence.storageClass | string | `""` | |
| webapp.readinessProbe.httpGet.path | string | `"/"` | |
| webapp.readinessProbe.httpGet.port | string | `"http"` | |
| webapp.readinessProbe.initialDelaySeconds | int | `30` | |
| webapp.readinessProbe.periodSeconds | int | `10` | |
| webapp.replicaCount | int | `1` | |
| webapp.resources | object | `{}` | |
| webapp.service.port | int | `3000` | |
| webapp.service.type | string | `"ClusterIP"` | |
| webapp.tolerations | list | `[]` | |

----------------------------------------------
Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2)
Loading
Loading