Skip to content

openpalm/services: unified local AI container — voice + embeddings + chat + image gen #430

Description

@itlackey

Summary

Introduce `openpalm/services` — a single custom FastAPI container (one port, four OpenAI-compatible endpoint groups) for local AI on a single-user host. Consolidates #431 (image gen). Removes `openpalm/voice` — the voice container code is the starting point for `containers/services/`, not a parallel path.

Full design: `docs/technical/local-ai-unified-container-plan.md`

Milestone scope (0.13.0 — all phases)

GPU variants are the goal. The three phases are sequential implementation steps within this milestone.

Phase Scope
1 — CPU voice + embeddings `containers/services/` from voice foundation; onnxruntime embeddings; `addon.services.cpu` profile; akm wiring
2 — Chat + image gen (CPU baseline) llama-cpp-python (GGUF), diffusers, Connection wiring, `OP_IMAGEGEN_BASE_URL`
3 — GPU variants (all three) CUDA, ROCm, Intel — same Dockerfile targets, matrix CI, compose overlays

Capabilities

Endpoint Library
`POST /v1/audio/speech` Kokoro (from `containers/voice/`)
`POST /v1/audio/transcriptions` faster-whisper
`POST /v1/embeddings` onnxruntime + nomic-embed-text-v1.5 ONNX (768 dims)
`POST /v1/chat/completions` llama-cpp-python (GGUF)
`POST /v1/images/generations` diffusers + torch
`GET /health` per-capability status

What is removed

  • `containers/voice/` — deleted after `containers/services/` is complete
  • `openpalm/voice` addon name, `addon.voice.*` compose profiles
  • `OP_VOICE_PROFILE`, `OP_VOICE_IMAGE_TAG`, `OP_VOICE_PORT_HOST`, `OP_VOICE_BIND_ADDRESS`, `OP_VOICE_WHISPER_MODEL`, `OP_VOICE_KOKORO_VOICE` env vars
  • `publish-voice.yml` + `publish-voice-models.yml` workflows
  • `voice` / `voice-cuda` / `voice-rocm` service blocks from `services.compose.yml`
  • Voice-specific docs (`docs/technical/openpalm-voice-addon.md`, `docs/technical/voice-container-build.md`)

Compose service naming

Compose service name and network alias are both `services`. All in-compose URLs use `http://services:4114/v1\`. The CPU variant uses the service name as its implicit alias; GPU variants add explicit `aliases: [services]` — same pattern as ollama.

Non-goals / explicitly rejected

  • No `OP_SERVICES_ENABLE_*` flags. Missing model file → 503.
  • No in-container supervisor. One uvicorn process.
  • No gateway/routing layer. One FastAPI app; route handlers call model instances directly.
  • No Ollama replacement. Ollama remains the advanced LLM addon.

Engineering changes required

1. `resolveActiveProfiles()` in `compose-args.ts` — replace `voice`/`ollama` if/else with data-driven map, add `services`:

```ts
const HARDWARE_PROFILED_ADDONS = {
ollama: { env: 'OP_OLLAMA_PROFILE', default: 'addon.ollama.cpu' },
services: { env: 'OP_SERVICES_PROFILE', default: 'addon.services.cpu' },
};
```

2. `addons.ts` — replace `'voice'` in `BUILTIN_ADDONS`, update `listEnabledAddonIds()` profile env scan, rename `voiceImageRef()` → `servicesImageRef()`.

3. `addon-env-schemas.ts` — replace `voice` schema entry with `services`.

4. `voice-env.ts` — update `openpalmVoiceBaseURL()` to read `OP_SERVICES_PORT_HOST` / port 4114; rename engine preset `openpalm-voice` → `openpalm-services`.

5. `setup.ts` — rename `voiceProfile` → `servicesProfile`; use addon name `services`.

6. UI routes — `/admin/voice` → `/admin/services`, `/api/setup/voice-profiles` → `/api/setup/services-profiles`.

7. Migration — rename `voice` → `services` in `OP_ENABLED_ADDONS`; rewrite `OP_VOICE_PROFILE` → `OP_SERVICES_PROFILE` (translating variant); rewrite `OP_TTS/STT_BASE_URL` port 8880 → 4114; rename `data/voice/` → `data/services/` (mv, not copy).

Capability wiring

Capability Mechanism URL
TTS/STT `OP_TTS_BASE_URL` / `OP_STT_BASE_URL` (host UI) `http://127.0.0.1:${OP_SERVICES_PORT_HOST:-4114}/v1\`
Embeddings `config/akm/config.json` `http://services:4114/v1\` (compose network alias)
Chat LLM OpenPalm Connection → `auth.json` `http://services:4114/v1\`
Image gen `OP_IMAGEGEN_BASE_URL` (host UI) `http://127.0.0.1:${OP_SERVICES_PORT_HOST:-4114}/v1\`

Acceptance criteria (e2e proof required)

  1. `curl :4114/v1/audio/speech` returns audio.
  2. `curl :4114/v1/audio/transcriptions` returns transcript.
  3. `curl :4114/v1/embeddings` returns `data[].embedding` of length 768.
  4. AKM in the assistant container performs a real memory write via `http://services:4114/v1\`.
  5. `curl :4114/v1/chat/completions` returns a completion from the local GGUF model.
  6. `curl :4114/v1/images/generations` returns a base64 image.
  7. `resolveActiveProfiles` with `services` enabled emits `addon.services.cpu`.
  8. CUDA variant: GPU acceleration verified via `nvidia-smi` inside the container.
  9. Existing installs: migration correctly renames addon, profiles, env vars, and data dir.
  10. `openpalm/voice` addon is absent from the stack — no voice container starts.

Closes #431.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions