diff --git a/ollamamuseglimmer30bdflashv3/.helmignore b/ollamamuseglimmer30bdflashv3/.helmignore new file mode 100644 index 00000000..414bb6e8 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/.helmignore @@ -0,0 +1,18 @@ +# Patterns to ignore when building packages. +.DS_Store +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +*.swp +*.bak +*.tmp +*.orig +*~ +.project +.idea/ +*.tmproj +.vscode/ diff --git a/ollamamuseglimmer30bdflashv3/Chart.yaml b/ollamamuseglimmer30bdflashv3/Chart.yaml new file mode 100644 index 00000000..79c17279 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +appVersion: 0.32.8-rc0 +description: Muse Glimmer 30B Q4_K_M + DFlash served with Ollama + llm-init (GPU only) +name: ollamamuseglimmer30bdflashv3 +type: application +version: 1.0.1 diff --git a/ollamamuseglimmer30bdflashv3/OlaresManifest.yaml b/ollamamuseglimmer30bdflashv3/OlaresManifest.yaml new file mode 100644 index 00000000..b6bdefd2 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/OlaresManifest.yaml @@ -0,0 +1,199 @@ +olaresManifest.version: '0.12.0' +olaresManifest.type: app +apiVersion: 'v3' +metadata: + name: ollamamuseglimmer30bdflashv3 + icon: https://app.cdn.olares.com/appstore/ollama/icon.png + description: "Muse Glimmer 30B Q4_K_M + DFlash speculative decoding via Ollama." + appid: ollamamuseglimmer30bdflashv3 + title: Muse Glimmer 30B DFlash + version: '1.0.1' + categories: + - AI +sharedEntrances: + - name: ollamamuseglimmer30bdflashv3 + host: sharedentrances-api + port: 0 + title: Muse Glimmer 30B DFlash + invisible: true + authLevel: internal + icon: https://app.cdn.olares.com/appstore/ollama/icon.png +entrances: + - name: ollamaclient + port: 8090 + host: download-svc + title: Muse Glimmer 30B DFlash + icon: https://app.cdn.olares.com/appstore/ollama/icon.png + openMethod: window + authLevel: internal +workloadReplicas: + ollamamuseglimmer30bdflashv3: 1 + llminit: 1 +spec: + onlyAdmin: true + versionName: 'muse-glimmer:30b-q4_K_M-dflash' + upgradeDescription: | + v1.0.1: fix zh-CN i18n encoding; document DFlash decode throughput (~35-65 tok/s). + v1.0.0: initial release - Muse Glimmer 30B Q4_K_M with bundled DFlash drafter via Ollama 0.32.8-rc0. + fullDescription: | + **Model Overview** + Same Muse Glimmer 30B Q4_K_M multimodal agent as the standard tag, plus a bundled **DFlash** speculative-decoding drafter (~1.6GB) for faster generation. Pulls `muse-glimmer:30b-q4_K_M-dflash` (~20GB total, 128K context) from the Ollama library. Output quality matches standard autoregressive decoding; typical decode throughput is **~35-65 tok/s** (GPU- and context-dependent; usually higher than the standard tag on long agent replies). + Requires **Ollama 0.32.8-rc0 or newer**. + **Preset Configuration** + - Model: `muse-glimmer:30b-q4_K_M-dflash` + - Capabilities: thinking, tools, vision + - Modelfile default: `draft_num_predict=3` (DFlash; set to 0 in a custom Modelfile to disable) + - Engine args: `OLLAMA_KEEP_ALIVE=-1 OLLAMA_CONTEXT_LENGTH=131072 OLLAMA_FLASH_ATTENTION=1 OLLAMA_KV_CACHE_TYPE=q8_0 OLLAMA_NUM_PARALLEL=1` + - Required GPU memory: `22Gi` + - Typical decode throughput: **~35-65 tok/s** (GPU-dependent) + **Recommended API parameters:** `temperature=1.0`, `top_p=0.95`, `top_k=64`; reasoning effort `high`/`xhigh` for agent tasks. + **Accelerator modes** + | Mode | Device | Details | + |----------------|-------------------|----------------------------------------------------------------------| + | `nvidia` | GPU (CUDA) | Uses `22Gi` GPU memory | + | `nvidia-gb10` | GPU (Spark) | Like above, but memory is managed by the pod | + **Stack** + - **Ollama daemon** (port 11434, `ollama/ollama:0.32.8-rc0`) + - **Model Console** (port 8090): OpenAI API proxy + **Model Storage** + Shared at `appCommon/ollama` (blobs dedupe with other Ollama apps). + developer: Meta + website: https://ollama.com/library/muse-glimmer + sourceCode: https://github.com/ollama/ollama + submitter: Olares + locale: + - en-US + - zh-CN + license: + - text: Apache-2.0 + url: https://www.apache.org/licenses/LICENSE-2.0 + accelerator: + - mode: nvidia + limitedCpu: "15360m" + requiredCpu: "1300m" + requiredDisk: 50Mi + limitedDisk: 500Gi + limitedMemory: "30Gi" + requiredMemory: "20Gi" + requiredGPUMemory: "22Gi" + limitedGPUMemory: "24Gi" + - mode: nvidia-gb10 + limitedCpu: "15360m" + requiredCpu: "1300m" + requiredDisk: 50Mi + limitedDisk: 500Gi + limitedMemory: "28Gi" + requiredMemory: "24Gi" + supportArch: + - amd64 + - arm64 +permission: + appData: true + appCommon: true +options: + apiTimeout: 0 + LLMGatewaySupported: true + shared: true + templateOnly: false + dependencies: + - name: olares + version: '>=1.12.6-0' + type: system +envs: + - envName: MODEL_SOURCE + required: true + type: string + editable: false + applyOnChange: false + default: "ollama://muse-glimmer:30b-q4_K_M-dflash" + description: "Fixed to ollama://muse-glimmer:30b-q4_K_M-dflash (main model + DFlash drafter)." + regex: "^ollama://" + - envName: MODEL_NAME + required: true + type: string + editable: false + applyOnChange: false + default: "muse-glimmer:30b-q4_K_M-dflash" + description: "OpenAI alias. Fixed to muse-glimmer:30b-q4_K_M-dflash." + - envName: MODEL_MODE + required: true + type: string + editable: false + applyOnChange: false + default: "chat" + options: + - title: Chat + value: chat + - title: Embedding + value: embedding + - envName: MODEL_SUPPORTS + required: true + type: string + editable: false + applyOnChange: false + default: "thinking,tools,vision" + multiSelect: true + splitter: "," + options: + - title: Vision + value: vision + - title: Tools + value: tools + - title: Thinking + value: thinking + - title: None + value: none + - envName: ENGINE_ARGS + required: true + default: "OLLAMA_KEEP_ALIVE=-1 OLLAMA_CONTEXT_LENGTH=131072 OLLAMA_FLASH_ATTENTION=1 OLLAMA_KV_CACHE_TYPE=q8_0 OLLAMA_NUM_PARALLEL=1" + type: string + editable: true + applyOnChange: true + description: "Ollama daemon env. DFlash draft count is in the Ollama Modelfile (draft_num_predict=3), not here." + - envName: LOG_LEVEL + required: false + type: string + editable: true + applyOnChange: true + default: "info" + options: + - title: Debug + value: debug + - title: Info + value: info + - title: Warn + value: warn + - title: Error + value: error + - envName: OLLAMA_CPU_REQUEST + required: true + default: "200m" + type: string + editable: false + applyOnChange: false + - envName: OLLAMA_MEMORY_REQUEST + required: true + default: "19Gi" + type: string + editable: false + applyOnChange: false + - envName: OLLAMA_CPU_LIMIT + required: true + default: "6" + type: string + editable: false + applyOnChange: false + - envName: OLLAMA_MEMORY_LIMIT + required: true + default: "28Gi" + type: string + editable: false + applyOnChange: false + - envName: OLLAMA_REQUIRED_GPU_MEMORY + required: true + type: string + editable: false + applyOnChange: false + default: "22Gi" + description: "GPU memory for ~20GB tag (main + DFlash drafter) plus 128K KV headroom." + regex: "^[0-9]+(Gi|Mi)?$" diff --git a/ollamamuseglimmer30bdflashv3/i18n/en-US/OlaresManifest.yaml b/ollamamuseglimmer30bdflashv3/i18n/en-US/OlaresManifest.yaml new file mode 100644 index 00000000..68b65438 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/i18n/en-US/OlaresManifest.yaml @@ -0,0 +1,24 @@ +metadata: + + description: "Muse Glimmer 30B Q4_K_M + DFlash speculative decoding via Ollama." + + title: Muse Glimmer 30B DFlash + + + +spec: + + fullDescription: | + + **Model Overview** + + Same Muse Glimmer 30B Q4_K_M as the standard tag, with bundled DFlash drafter for faster generation. Tag: `muse-glimmer:30b-q4_K_M-dflash` (~20GB, 128K context). Requires Ollama 0.32.8-rc0+. + + + + **Preset:** thinking + tools + vision; `22Gi` GPU; Modelfile `draft_num_predict=3`; typical decode throughput **~35-65 tok/s** (GPU-dependent). + + + + **Stack:** Ollama daemon (11434) + Model Console (8090). Models stored at `appCommon/ollama`. + diff --git a/ollamamuseglimmer30bdflashv3/i18n/zh-CN/OlaresManifest.yaml b/ollamamuseglimmer30bdflashv3/i18n/zh-CN/OlaresManifest.yaml new file mode 100644 index 00000000..72eda816 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/i18n/zh-CN/OlaresManifest.yaml @@ -0,0 +1,33 @@ +metadata: + description: "Muse Glimmer 30B Q4_K_M + DFlash 推测解码加速,基于 Ollama 运行。" + title: Muse Glimmer 30B DFlash + +spec: + fullDescription: | + **模型概述** + 与标准 `30b-q4_K_M` 标签相同的主模型,额外 bundled DFlash drafter(约 1.6GB)用于更快生成。从 Ollama 库拉取 `muse-glimmer:30b-q4_K_M-dflash`(约 20GB,128K 上下文)。输出质量与标准自回归解码一致;长 Agent 回复场景吞吐通常更高。 + + 需要 **Ollama 0.32.8-rc0 或更新版本**。 + + **预设配置** + - 模型:`muse-glimmer:30b-q4_K_M-dflash` + - 能力:thinking、tools、vision + - Modelfile 默认:`draft_num_predict=3`(DFlash;自定义 Modelfile 设为 0 可关闭) + - 引擎参数:`OLLAMA_KEEP_ALIVE=-1 OLLAMA_CONTEXT_LENGTH=131072 OLLAMA_FLASH_ATTENTION=1 OLLAMA_KV_CACHE_TYPE=q8_0 OLLAMA_NUM_PARALLEL=1` + - 所需 GPU 显存:`22Gi` + - 典型解码吞吐:约 **35–65 tok/s**(视 GPU 与上下文长度而定;通常高于标准标签) + + **推荐 API 参数:** `temperature=1.0`、`top_p=0.95`、`top_k=64`;复杂 Agent 任务使用较高 reasoning effort(`high`/`xhigh`)。 + + **加速器模式** + | 模式 | 设备 | 说明 | + |----------------|------------------|--------------------------------------------------------------| + | `nvidia` | GPU (CUDA) | 使用 `22Gi` 显存 | + | `nvidia-gb10` | GPU (Spark) | 类似上方,显存由 pod 管理 | + + **技术栈** + - **Ollama 守护进程**(11434 端口) + - **Model Console**(8090 端口):OpenAI API 代理 + + **模型存储** + 位于共享目录 `appCommon/ollama`,与其他 Ollama 应用共用(blob 按 digest 去重)。 diff --git a/ollamamuseglimmer30bdflashv3/owners b/ollamamuseglimmer30bdflashv3/owners new file mode 100644 index 00000000..48e63a53 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/owners @@ -0,0 +1,7 @@ +owners: +- 'LittleLollipop' +- 'TShentu' +- 'hysyeah' +- 'pengpeng' +- 'harveyff' +- 'FantasticCode2019' diff --git a/ollamamuseglimmer30bdflashv3/templates/_helpers.tpl b/ollamamuseglimmer30bdflashv3/templates/_helpers.tpl new file mode 100644 index 00000000..60d9e7fe --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/templates/_helpers.tpl @@ -0,0 +1,47 @@ +{{- /* llmbase.gpuMiB: normalize a GPU-memory quantity to a BARE MiB integer for + HAMi's nvidia.com/gpumem. Its base unit is MiB and the value MUST be a + plain integer — a Mi/Gi suffix is misread by the scheduler (e.g. "6144Mi" + -> 6442450944). Accepts 8Gi / 8G / 8192Mi / 8192M / 8192 and returns MiB. + Usage: {{ include "llmbase.gpuMiB" ($oe.X_REQUIRED_GPU_MEMORY | default "4096") }} */ -}} +{{- define "llmbase.gpuMiB" -}} +{{- $g := trim . -}} +{{- if hasSuffix "Gi" $g -}} +{{- mul (int (trimSuffix "Gi" $g)) 1024 -}} +{{- else if hasSuffix "G" $g -}} +{{- mul (int (trimSuffix "G" $g)) 1024 -}} +{{- else if hasSuffix "Mi" $g -}} +{{- int (trimSuffix "Mi" $g) -}} +{{- else if hasSuffix "M" $g -}} +{{- int (trimSuffix "M" $g) -}} +{{- else -}} +{{- int $g -}} +{{- end -}} +{{- end -}} +{{- /* ollamamuseglimmer30bdflashv3.engineArgs: merge clone ENGINE_ARGS with chart defaults. + OLLAMA_KEEP_ALIVE=-1 (forever in VRAM) on the ollama daemon unless set. + llm-init ENGINE_ARGS strips this key (see engineArgsForLlminit). + Usage: {{ include "ollamamuseglimmer30bdflashv3.engineArgs" (dict "Args" ($oe.ENGINE_ARGS | default "")) }} */ -}} +{{- define "ollamamuseglimmer30bdflashv3.engineArgs" -}} +{{- $in := . -}} +{{- $args := trim ($in.Args | default "") -}} +{{- if not (contains "OLLAMA_KEEP_ALIVE" $args) -}} +{{- if $args -}} +{{- $args = printf "%s OLLAMA_KEEP_ALIVE=-1" $args -}} +{{- else -}} +{{- $args = "OLLAMA_KEEP_ALIVE=-1" -}} +{{- end -}} +{{- end -}} +{{- $args -}} +{{- end -}} +{{- /* ollamamuseglimmer30bdflashv3.engineArgsForLlminit: user ENGINE_ARGS for llm-init only. + Never inject OLLAMA_KEEP_ALIVE (llm-init forwards it on /api/chat as "-1"). + Strip if user set it. + Usage: {{ include "ollamamuseglimmer30bdflashv3.engineArgsForLlminit" (dict "Args" ($oe.ENGINE_ARGS | default "")) }} */ -}} +{{- define "ollamamuseglimmer30bdflashv3.engineArgsForLlminit" -}} +{{- $in := . -}} +{{- $args := trim ($in.Args | default "") -}} +{{- $args = regexReplaceAll ` ?OLLAMA_KEEP_ALIVE=[^ ]+` "" $args -}} +{{- $args = regexReplaceAll ` +` " " $args -}} +{{- $args = trim $args -}} +{{- $args -}} +{{- end -}} diff --git a/ollamamuseglimmer30bdflashv3/templates/llm-init.yaml b/ollamamuseglimmer30bdflashv3/templates/llm-init.yaml new file mode 100644 index 00000000..f9948e7f --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/templates/llm-init.yaml @@ -0,0 +1,160 @@ +{{- $ollamaclientDomainENV := split "," .Values.domain.ollamaclient -}} +{{- $ollamaclientDomain := index $ollamaclientDomainENV "_0" -}} +{{- /* Model identity + source are clone-configurable via olaresEnv. This + base currently supports the ollama:// source shape only + (MODEL_SOURCE=ollama://); hf:// GGUF support was + intentionally removed for now. */ -}} +{{- $oe := .Values.olaresEnv | default dict -}} +{{- $modelSource := $oe.MODEL_SOURCE | default "" -}} +{{- $modelName := $oe.MODEL_NAME | default "" -}} +{{- $modelMode := $oe.MODEL_MODE | default "" -}} +{{- /* MODEL_SUPPORTS is a multi-select of coarse capability GROUPS (vision / + tools / thinking / embedding). Expand each group one-to-many into the + supports_* keys llm-init validates against its gateway AllSupports mirror, + then re-join into the CSV the container env expects. "none" is the + required-field fallback (no extra capabilities); legacy "embedding" + token is kept as an alias. Unknown tokens pass through verbatim so a raw supports_* key still + works. */ -}} +{{- $supportsGroups := dict + "vision" "supports_vision" + "tools" "supports_function_calling,supports_parallel_function_calling,supports_tool_choice" + "thinking" "supports_reasoning,supports_reasoning_effort" + "none" "" + "embedding" "" -}} +{{- $modelSupports := $oe.MODEL_SUPPORTS | default "" -}} +{{- $expandedSupports := list -}} +{{- range $tok := splitList "," $modelSupports -}} +{{- $tok = trim $tok -}} +{{- if $tok -}} +{{- if hasKey $supportsGroups $tok -}} +{{- $mapped := index $supportsGroups $tok -}} +{{- if $mapped -}} +{{- $expandedSupports = append $expandedSupports $mapped -}} +{{- end -}} +{{- else -}} +{{- $expandedSupports = append $expandedSupports $tok -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- $modelSupports = join "," $expandedSupports -}} +{{- $logLevel := $oe.LOG_LEVEL | default "debug" -}} +{{- $gpuType := .Values.gpu | default "" -}} +{{- if not $gpuType -}} +{{- $gpuType = .Values.GPU.Type | default "nvidia" -}} +{{- end -}} +{{- /* User ENGINE_ARGS for llm-init: never OLLAMA_KEEP_ALIVE (see engineArgsForLlminit). + Empty when user leaves ENGINE_ARGS blank — keep_alive is ollama-daemon-only. */ -}} +{{- $engineArgs := include "ollamamuseglimmer30bdflashv3.engineArgsForLlminit" (dict "Args" ($oe.ENGINE_ARGS | default "")) -}} +--- +# llm-init Pod (no GPU). Talks to the ollama daemon via the "ollama" +# Service on :11434 (defined in templates/ollama.yaml). llm-init derives +# that URL from ENGINE_KIND, so the Service name must be "ollama". +# Exposes the OpenAI-compatible /v1/* +# surface and the unified /api/progress + /healthz endpoints on :8090. +apiVersion: apps/v1 +kind: Deployment +metadata: + # Static name (llminit) — engine Deployment uses {{ .Release.Name }} for + # allowMultipleInstall. Label stays io.kompose.service: llm-init. + name: llminit + namespace: '{{ .Release.Namespace }}' + labels: + io.kompose.service: llm-init +spec: + replicas: {{ .Values.workloads.llminit.replicaCount }} + selector: + matchLabels: + io.kompose.service: llm-init + strategy: + type: Recreate + template: + metadata: + labels: + io.kompose.network/chrome-default: "true" + io.kompose.service: llm-init + spec: + restartPolicy: Always + containers: + - name: llm-init + image: docker.io/beclab/llm-init:v1.3.1 + imagePullPolicy: IfNotPresent + env: + - name: ENGINE_KIND + value: ollama + - name: ENGINE_ARGS + value: "{{ $engineArgs }}" + - name: MODEL_NAME + value: "{{ $modelName }}" + - name: MODEL_SOURCE + value: "{{ $modelSource }}" + - name: MODEL_MODE + value: "{{ $modelMode }}" +{{- if $modelSupports }} + - name: MODEL_SUPPORTS + value: "{{ $modelSupports }}" +{{- end }} + - name: PORT + value: "8090" + - name: LOG_LEVEL + value: "{{ $logLevel }}" + - name: LOG_FORMAT + value: json + - name: APP_URL + value: "https://{{ $ollamaclientDomain }}" + ports: + - name: http + containerPort: 8090 + livenessProbe: + httpGet: + path: /livez + port: 8090 + periodSeconds: 30 + readinessProbe: + httpGet: + path: /livez + port: 8090 + initialDelaySeconds: 3 + periodSeconds: 5 + timeoutSeconds: 3 + failureThreshold: 3 + resources: + requests: + cpu: 200m + memory: 256Mi + limits: + # model pull needs headroom; 256Mi can get OOMKilled mid-pull + # -> pod restart -> state machine wedges. 1Gi is safe. + cpu: "1" + memory: 2Gi +--- +apiVersion: v1 +kind: Service +metadata: + name: download-svc + namespace: {{ .Release.Namespace }} + labels: + io.kompose.service: llm-init +spec: + selector: + io.kompose.service: llm-init + ports: + - name: http + port: 8090 + targetPort: 8090 + type: ClusterIP +--- +apiVersion: v1 +kind: Service +metadata: + name: sharedentrances-api + namespace: {{ .Release.Namespace }} + labels: + io.kompose.service: llm-init +spec: + selector: + io.kompose.service: llm-init + ports: + - name: http + port: 80 + targetPort: 8090 + type: ClusterIP diff --git a/ollamamuseglimmer30bdflashv3/templates/ollama.yaml b/ollamamuseglimmer30bdflashv3/templates/ollama.yaml new file mode 100644 index 00000000..f316650b --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/templates/ollama.yaml @@ -0,0 +1,145 @@ +{{- /* ENGINE_ARGS is the daemon-tuning surface: OLLAMA_* env exported by ollama.sh + before `ollama serve`. llm-init uses engineArgsForLlminit (no KEEP_ALIVE). */ -}} +{{- $oe := .Values.olaresEnv | default dict -}} +{{- $gpuType := .Values.gpu | default "" -}} +{{- if not $gpuType -}} +{{- $gpuType = .Values.GPU.Type | default "nvidia" -}} +{{- end -}} +{{- $unifiedMem := eq $gpuType "nvidia-gb10" -}} +{{- $engineArgs := include "ollamamuseglimmer30bdflashv3.engineArgs" (dict "Args" ($oe.ENGINE_ARGS | default "")) -}} +{{- $modelSource := $oe.MODEL_SOURCE | default "" -}} +{{- $modelName := $oe.MODEL_NAME | default "" -}} +{{- $modelMode := $oe.MODEL_MODE | default "chat" -}} +{{- $cpuRequest := trim ($oe.OLLAMA_CPU_REQUEST | default "200m") -}} +{{- $memRequest := trim ($oe.OLLAMA_MEMORY_REQUEST | default "19Gi") -}} +{{- $cpuLimit := trim ($oe.OLLAMA_CPU_LIMIT | default "6") -}} +{{- $memLimit := trim ($oe.OLLAMA_MEMORY_LIMIT | default "28Gi") -}} +{{- $gpuMiB := include "llmbase.gpuMiB" ($oe.OLLAMA_REQUIRED_GPU_MEMORY | default "22Gi") -}} +{{- if $unifiedMem -}} +{{- $memRequest = printf "%sMi" $gpuMiB -}} +{{- $memLimit = printf "%sMi" $gpuMiB -}} +{{- end -}} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: '{{ .Release.Name }}' + namespace: {{ .Release.Namespace }} + labels: + io.kompose.service: ollama + annotations: + applications.app.bytetrade.io/gpu-inject: "true" +spec: + replicas: {{ .Values.workloads.ollamamuseglimmer30bdflashv3.replicaCount }} + selector: + matchLabels: + io.kompose.service: ollama + strategy: + type: Recreate + template: + metadata: + labels: + io.kompose.network/chrome-default: "true" + io.kompose.service: ollama + spec: + restartPolicy: Always + volumes: + - name: ollama-data + hostPath: + path: "{{ .Values.userspace.appCommon }}/ollama" + type: DirectoryOrCreate + - name: cuda-compute-cache + hostPath: + path: "{{ .Values.userspace.appCommon }}/ollama/.nv" + type: DirectoryOrCreate + - name: wrappers + configMap: + name: llm-init-wrappers + defaultMode: 0555 + containers: + - name: ollama + image: docker.io/ollama/ollama:0.32.8-rc0 + imagePullPolicy: IfNotPresent + command: ["/bin/sh", "/llm-init/wrappers/ollama.sh"] + env: + - name: ENGINE_KIND + value: ollama + - name: ENGINE_ARGS + value: "{{ $engineArgs }}" + - name: MODEL_SOURCE + value: "{{ $modelSource }}" + - name: MODEL_NAME + value: "{{ $modelName }}" + - name: MODEL_MODE + value: "{{ $modelMode }}" + - name: OLLAMA_PRELOAD + value: "true" + - name: OLLAMA_HOST + value: "0.0.0.0:11434" + - name: OLLAMA_NOPRUNE + value: "1" + - name: OLLAMA_ORIGINS + value: "*" + - name: PGID + value: "1000" + - name: PUID + value: "1000" + - name: TZ + value: Etc/UTC + - name: GGML_CUDA_DISABLE_GRAPHS + value: "1" + ports: + - name: ollama + containerPort: 11434 + startupProbe: + tcpSocket: + port: 11434 + timeoutSeconds: 5 + periodSeconds: 10 + failureThreshold: 30 + livenessProbe: + httpGet: + path: / + port: 11434 + initialDelaySeconds: 30 + timeoutSeconds: 60 + periodSeconds: 60 + failureThreshold: 10 + volumeMounts: + - name: ollama-data + mountPath: /root/.ollama + - name: cuda-compute-cache + mountPath: /root/.nv/ComputeCache + subPath: ComputeCache + - name: wrappers + mountPath: /llm-init/wrappers + readOnly: true + resources: + requests: + cpu: "{{ $cpuRequest }}" + memory: "{{ $memRequest }}" +{{- if not $unifiedMem }} + nvidia.com/gpumem: {{ $gpuMiB }} +{{- end }} + limits: + cpu: "{{ $cpuLimit }}" + memory: "{{ $memLimit }}" +{{- if not $unifiedMem }} + nvidia.com/gpumem: {{ $gpuMiB }} +{{- end }} +--- +apiVersion: v1 +kind: Service +metadata: + name: ollama + namespace: {{ .Release.Namespace }} + labels: + io.kompose.service: ollama +spec: + selector: + io.kompose.service: ollama + ports: + - name: http + port: 11434 + targetPort: 11434 + type: ClusterIP diff --git a/ollamamuseglimmer30bdflashv3/templates/wrappers.yaml b/ollamamuseglimmer30bdflashv3/templates/wrappers.yaml new file mode 100644 index 00000000..6f5d4ee0 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/templates/wrappers.yaml @@ -0,0 +1,160 @@ +# Engine wrapper script, mounted into the Ollama daemon container at +# /llm-init/wrappers. Exports ENGINE_ARGS, starts ollama serve, then preloads +# the install-time model into VRAM after llm-init pull (name from MODEL_SOURCE). +apiVersion: v1 +kind: ConfigMap +metadata: + name: llm-init-wrappers + namespace: {{ .Release.Namespace }} + labels: + io.kompose.service: ollama +data: + ollama.sh: | + #!/bin/sh + set -eu + + ENGINE=ollama + log() { printf '[wrapper-%s] %s\n' "$ENGINE" "$*"; } + + engine_args_export_env() { + args="${ENGINE_ARGS:-}" + [ -z "$args" ] && return 0 + # shellcheck disable=SC2086 + set -- $args + for tok in "$@"; do + case "$tok" in + *=*) export "$tok" && log "engine_args export: $tok" ;; + *) log "engine_args drop non-KV token: $tok" ;; + esac + done + } + + # Ollama names are model:tag. MODEL_SOURCE (ollama://qwen3.5:4b) is authoritative; + # MODEL_NAME may use a hyphen (qwen3.5-4b) which show/run will not resolve. + add_model_candidate() { + cand="$1" + [ -z "$cand" ] && return 0 + case " ${OLLAMA_MODEL_CANDIDATES:-} " in + *" ${cand} "*) return 0 ;; + esac + OLLAMA_MODEL_CANDIDATES="${OLLAMA_MODEL_CANDIDATES:+${OLLAMA_MODEL_CANDIDATES} }${cand}" + } + + normalize_keep_alive() { + case "${OLLAMA_KEEP_ALIVE:-}" in + '-1s$1') export OLLAMA_KEEP_ALIVE=-1 ;; + esac + } + + build_model_candidates() { + OLLAMA_MODEL_CANDIDATES="" + case "${MODEL_SOURCE:-}" in + ollama://*) + ref="${MODEL_SOURCE#ollama://}" + ref="${ref%% *}" + add_model_candidate "$ref" + ;; + esac + add_model_candidate "${MODEL_NAME:-}" + mn="${MODEL_NAME:-}" + case "$mn" in + *:*) ;; + *) + base="${mn%-*}" + tag="${mn##*-}" + if [ -n "$base" ] && [ -n "$tag" ] && [ "$base" != "$mn" ]; then + add_model_candidate "${base}:${tag}" + fi + ;; + esac + log "preload candidates: ${OLLAMA_MODEL_CANDIDATES:-}" + } + + find_ready_model() { + for cand in $OLLAMA_MODEL_CANDIDATES; do + if ollama show "$cand" >/dev/null 2>&1; then + printf '%s' "$cand" + return 0 + fi + done + return 1 + } + + preload_via_api() { + model="$1" + host="${OLLAMA_HOST#http://}" + host="${host#https://}" + case "${MODEL_MODE:-chat}" in + embedding|embed) + if ollama embed "$model" "warmup" >/dev/null 2>&1; then + return 0 + fi + ;; + esac + # Load weights into VRAM; keep_alive inherits OLLAMA_KEEP_ALIVE (default -1). + ollama run "$model" "Hello" >/dev/null 2>&1 + } + + preload_model() { + case "${OLLAMA_PRELOAD:-true}" in + false|FALSE|0|no|NO|off|OFF) + log "preload disabled (OLLAMA_PRELOAD=$OLLAMA_PRELOAD)" + return 0 + ;; + esac + if [ -z "${OLLAMA_MODEL_CANDIDATES:-}" ]; then + log "preload skipped: no model candidates (set MODEL_SOURCE / MODEL_NAME)" + return 0 + fi + + timeout="${OLLAMA_PRELOAD_TIMEOUT:-3600}" + elapsed=0 + ready_model="" + log "waiting for model (ollama show, llm-init pull, timeout=${timeout}s)..." + while [ -z "$ready_model" ]; do + ready_model=$(find_ready_model 2>/dev/null || true) + if [ -n "$ready_model" ]; then + break + fi + if [ "$elapsed" -ge "$timeout" ]; then + log "WARN: preload timed out after ${timeout}s (model not ready)" + return 0 + fi + sleep 5 + elapsed=$((elapsed + 5)) + done + log "model $ready_model ready after ${elapsed}s" + + log "preloading $ready_model (mode=${MODEL_MODE:-chat})..." + start=$(date +%s) + set +e + preload_via_api "$ready_model" + rc=$? + set -e + end=$(date +%s) + if [ "$rc" -eq 0 ]; then + log "preload completed in $((end - start))s" + else + log "WARN: preload failed (exit $rc); daemon still running" + fi + } + + export OLLAMA_HOST="${OLLAMA_HOST:-0.0.0.0:11434}" + engine_args_export_env + normalize_keep_alive + export OLLAMA_KEEP_ALIVE="${OLLAMA_KEEP_ALIVE:--1}" + build_model_candidates + + log "starting ollama serve on $OLLAMA_HOST" + ollama serve "$@" & + SERVER_PID=$! + trap 'kill "$SERVER_PID" 2>/dev/null; wait "$SERVER_PID" 2>/dev/null; exit 0' INT TERM + + until ollama list >/dev/null 2>&1; do + sleep 1 + done + log "ollama API ready" + + preload_model + + wait "$SERVER_PID" diff --git a/ollamamuseglimmer30bdflashv3/values.yaml b/ollamamuseglimmer30bdflashv3/values.yaml new file mode 100644 index 00000000..c414adb1 --- /dev/null +++ b/ollamamuseglimmer30bdflashv3/values.yaml @@ -0,0 +1,9 @@ +# Per-workload replica counts (keys match Deployment metadata.name and +# workloadReplicas in OlaresManifest). +# ollamamuseglimmer30bdflashv3 - engine Deployment (== appid / Release.Name) +# llminit - llm-init / entrance Deployment +workloads: + llminit: + replicaCount: 1 + ollamamuseglimmer30bdflashv3: + replicaCount: 1