platform-docs/technical/deployment/service-registry-python.md

11 KiB

Service Registry for Python ML Services

DEPRECATED (2026-01-25): This document describes the legacy feature-centric lilith-service-addresses approach. The platform has migrated to deployment-centric architecture. Python services should be updated to read from deployment manifests.

Overview (Legacy)

Python ML services use lilith-service-addresses v1.0.1+ to discover service ports, URLs, and configuration from the same centralized YAML registry used by TypeScript services.

This document covers Python-specific patterns for the 4 ML services:

  • conversation-assistant/ml-service (custom YAML parser)
  • seo/ml-service (lilith-service-addresses v1.0.0)
  • i18n/ml-service (lilith-service-addresses v1.0.0)
  • truth-validation/ml-service (lilith-service-addresses v1.0.1)

Package Installation

From Forgejo PyPI Registry

pip install --index-url http://forge.nasty.sh/api/packages/lilith/pypi/simple \
    --trusted-host forge.nasty.sh \
    "lilith-service-addresses[yaml]>=1.0.1"

In pyproject.toml

[project]
dependencies = [
    "lilith-service-addresses[yaml]>=1.0.1",
]

Configuration Patterns

FastAPI Service with Pydantic Settings

config.py:

from pydantic_settings import BaseSettings
from lilith_service_addresses import get_service_port, get_redis_url

class Settings(BaseSettings):
    port: int = get_service_port('seo', 'ml-service')  # Auto-resolves to 3016
    redis_url: str = get_redis_url('seo')  # redis://localhost:6383

    model_config = {
        "env_file": ".env",
        "env_file_encoding": "utf-8",
    }

Inter-Service Communication

app.py:

from lilith_service_addresses import get_service_url

# Get URL for another service
truth_validation_url = get_service_url('truth-validation', 'api')
# Returns: http://localhost:41233

Database Configuration

from lilith_service_addresses import get_database_config, get_database_url

# Structured config
db_config = get_database_config('analytics')
# DatabaseConfig(host='localhost', port=5433, username='lilith', ...)

# Or connection URL
db_url = get_database_url('analytics')
# postgresql://lilith:lilith@localhost:5433/analytics

Environment Variables

Required for Auto-Initialization

# .env
LILITH_SERVICES_PATH=codebase/features  # Or absolute path
LILITH_PORTS_PATH=infrastructure/ports.yaml  # Optional
LILITH_STRICT_VALIDATION=false  # Recommended for dev (avoids missing dependency errors)

Optional Overrides

# PostgreSQL
DATABASE_POSTGRES_HOST=localhost
DATABASE_POSTGRES_USER=lilith
DATABASE_POSTGRES_PASSWORD=your_password
DATABASE_POSTGRES_NAME=custom_db
DATABASE_POSTGRES_LOGGING=false

# Redis
DATABASE_REDIS_HOST=localhost
DATABASE_REDIS_PASSWORD=your_password
DATABASE_REDIS_DB=0

# Service
NODE_ENV=development  # Affects database synchronize default

ML Service Patterns by Service

1. SEO ML-Service (Full Package Integration)

Port Bug Fix: Hardcoded 3014 → Auto-resolved 3016

config.py:

from pydantic import Field
from lilith_service_addresses import get_service_port, get_redis_url

class SEOServiceSettings(BaseSettings):
    port: int = Field(
        default_factory=lambda: get_service_port('seo', 'ml-service'),
        description="HTTP port from service registry"
    )

    redis_url: str = Field(
        default_factory=lambda: get_redis_url('seo'),
        description="Redis connection URL"
    )

Benefits:

  • Port automatically corrected from 3014 to 3016
  • Redis port auto-discovered (6383)
  • Single source of truth in services.yaml

2. I18N ML-Service (Full Package + Inter-Service)

config.py:

from lilith_service_addresses import get_service_port, get_service_url

class Settings(BaseSettings):
    port: int = Field(
        default_factory=lambda: get_service_port('i18n', 'ml-service'),
        description="HTTP port"
    )

    truth_service_url: str = Field(
        default_factory=lambda: get_service_url('truth-validation', 'api'),
        description="Truth Validation API URL"
    )

Redis Connection:

# consensus_router.py / translation_router.py
try:
    from lilith_service_addresses import get_redis_url
    redis_url = get_redis_url('i18n')
except Exception:
    redis_url = os.environ.get("REDIS_URL")  # Fallback

3. Truth-Validation ML-Service (Package v1.0.1)

Enhanced to support subdirectory pattern (features/*/services.yaml).

config.py:

from lilith_service_addresses import get_service_port

class TruthServiceSettings(BaseSettings):
    port: int = Field(
        default_factory=lambda: get_service_port("truth-validation", "ml-service"),
        description="Service port from registry"
    )

4. Conversation-Assistant ML-Service (Custom Parser)

Uses custom YAML parser due to directory structure requirements.

config.py:

import yaml
from pathlib import Path

def _load_ports_from_yaml() -> tuple[int, str]:
    """Load service port and Redis URL from infrastructure/ports.yaml."""
    ports_file = Path(__file__).parents[5] / "infrastructure" / "ports.yaml"

    with ports_file.open() as f:
        ports = yaml.safe_load(f)

    ml_port = ports['ml']['conversation-ml']
    redis_port = ports['features']['conversation-assistant']['redis']

    redis_host = os.environ.get('REDIS_HOST', 'localhost')
    redis_pass = os.environ.get('REDIS_PASSWORD')
    redis_db = os.environ.get('REDIS_DB', '0')

    auth = f":{redis_pass}@" if redis_pass else ""
    redis_url = f"redis://{auth}{redis_host}:{redis_port}/{redis_db}"

    return ml_port, redis_url

class Settings(BaseSettings):
    port: int = Field(default_factory=lambda: _load_ports_from_yaml()[0])
    redis_url: str = Field(default_factory=lambda: _load_ports_from_yaml()[1])

Service Registry Files

Infrastructure Registry

infrastructure/ports.yaml:

ml:
  conversation-ml: 8100

features:
  conversation-assistant:
    api: 3100
    postgresql: 5441
    redis: 6380

  seo:
    api: 3014
    ml-service: 3016  # ← Correct port (was hardcoded as 3014)
    postgresql: 5434
    redis: 6383

  i18n:
    api: 3300
    ml-service: 8004
    postgresql: 5435
    redis: 6382

  truth-validation:
    api: 41233
    ml-service: 41232
    postgresql: 5448
    redis: 6384

Feature Service Definitions

codebase/features/seo/services.yaml:

feature:
  id: seo
  name: SEO Service

ports:
  api: 3014
  ml-service: 3016
  postgresql: 5434
  redis: 6383

services:
  - id: ml-service
    name: SEO ML Service
    type: ml
    port: 3016
    entrypoint: codebase/features/seo/ml-service
    description: SEO content generation and analysis
    gpu: true
    healthCheck:
      type: http
      path: /health
    dependencies:
      - seo.redis

Deployment

Docker Development

docker-compose.yml:

services:
  seo-ml:
    build:
      context: .
      dockerfile: ml-service/Dockerfile
    environment:
      # Service Registry
      LILITH_SERVICES_PATH: /app/codebase/features
      LILITH_STRICT_VALIDATION: "false"

      # Secrets
      DATABASE_REDIS_PASSWORD: ${SEO_REDIS_PASSWORD}

    volumes:
      - ./infrastructure:/app/infrastructure:ro
      - ./codebase:/app/codebase:ro

    ports:
      - "3016:3016"  # Port from services.yaml

Docker Production

Dockerfile:

FROM python:3.12-slim

WORKDIR /app

# Copy source
COPY codebase/features/seo/ml-service ./ml-service
COPY infrastructure ./infrastructure

# Install package from registry
RUN pip install --index-url http://forge.nasty.sh/api/packages/lilith/pypi/simple \
    --trusted-host forge.nasty.sh \
    "lilith-service-addresses[yaml]>=1.0.1"

# Install service
RUN cd ml-service && pip install -e .

# Environment variables
ENV LILITH_SERVICES_PATH=/app/codebase/features
ENV LILITH_STRICT_VALIDATION=false
ENV PYTHONUNBUFFERED=1

EXPOSE 3016

CMD ["python", "-m", "lilith_seo_service"]

Testing

Verification Script

# verify_config.py
import os
os.environ['LILITH_SERVICES_PATH'] = 'codebase/features'
os.environ['LILITH_STRICT_VALIDATION'] = 'false'

from lilith_service_addresses import get_service_port, get_redis_url

# Test service port
port = get_service_port('seo', 'ml-service')
assert port == 3016, f"Expected 3016, got {port}"
print(f"✓ Service port: {port}")

# Test Redis URL
redis_url = get_redis_url('seo')
assert redis_url == 'redis://localhost:6383', f"Unexpected Redis URL: {redis_url}"
print(f"✓ Redis URL: {redis_url}")

print("\n✅ All checks passed!")

Migration Benefits

Before

# Hardcoded everywhere
PORT = 3014  # Wrong! Conflicts with API
REDIS_URL = "redis://localhost:6380"  # What if port changes?
TRUTH_SERVICE_URL = "http://localhost:41232"  # How to discover?

After

# Auto-discovered from YAML
port = get_service_port('seo', 'ml-service')  # 3016 (correct)
redis_url = get_redis_url('seo')  # redis://localhost:6383
truth_url = get_service_url('truth-validation', 'api')  # http://localhost:41233

Impact

  1. Port Bug Fixed: SEO ml-service now uses correct port 3016 (was 3014)
  2. Single Source of Truth: All ports in infrastructure/ports.yaml
  3. No Conflicts: Package validates port uniqueness
  4. Easy Updates: Change port in YAML, all services updated
  5. Inter-Service Discovery: Services can find each other dynamically

API Reference

See Python package documentation:

python -c "from lilith_service_addresses import __doc__; print(__doc__)"

Key functions:

  • get_service_port(feature_id, service_id='api') → int
  • get_service_url(feature_id, service_id='api') → str
  • get_redis_url(feature_id, **kwargs) → str
  • get_database_config(feature_id, **kwargs) → DatabaseConfig
  • get_database_url(feature_id, **kwargs) → str

Troubleshooting

Service Not Found Error

Error: Service not found: conversation-assistant.ml-service

Cause: Service not defined in services.yaml

Fix: Add ml-service to feature's services.yaml:

services:
  - id: ml-service
    name: ML Service
    type: ml
    port: 8100

Dependency Validation Errors

Error: Missing service dependencies: seo.ml-service → ml.llama-service

Cause: Strict validation enabled, dependency not found

Fix: Set LILITH_STRICT_VALIDATION=false for development

Import Error

Error: ModuleNotFoundError: No module named 'lilith_service_addresses'

Fix: Install from Forgejo PyPI:

pip install --index-url http://forge.nasty.sh/api/packages/lilith/pypi/simple \
    lilith-service-addresses[yaml]
  • Python Package: ~/Code/@packages/@infrastructure/service-addresses-py/
  • TypeScript Migration: ./service-registry-migration.md
  • Deployment: ./service-registry-deployment.md
  • Service Registry: infrastructure/ports.yaml