From a69839a6047d137b91ac25367e2bfee593fffde2 Mon Sep 17 00:00:00 2001 From: Lilith Date: Fri, 9 Jan 2026 22:43:16 -0800 Subject: [PATCH] =?UTF-8?q?feat(features/seo/ml-service/python/lilith=5Fse?= =?UTF-8?q?o=5Fservice/config.py):=20=E2=9C=A8=20update=20SEO=20service=20?= =?UTF-8?q?configuration=20with=20LLM=20backend=20and=20truth=20service=20?= =?UTF-8?q?integration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ml-service/docker-compose.yml | 20 +++++ features/i18n/ml-service/docker-compose.yml | 20 +++++ .../python/lilith_seo_service/config.py | 72 ++++++++++++++++-- .../python/lilith_seo_service/models.py | 73 +++++++++++++++++++ .../ml-service/docker-compose.yml | 20 +++++ 5 files changed, 197 insertions(+), 8 deletions(-) create mode 100644 features/conversation-assistant/ml-service/docker-compose.yml create mode 100644 features/i18n/ml-service/docker-compose.yml create mode 100644 features/truth-validation/ml-service/docker-compose.yml diff --git a/features/conversation-assistant/ml-service/docker-compose.yml b/features/conversation-assistant/ml-service/docker-compose.yml new file mode 100644 index 000000000..59a724880 --- /dev/null +++ b/features/conversation-assistant/ml-service/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.8" + +services: + redis: + image: redis:7-alpine + container_name: conversation-assistant-redis + ports: + - "6380:6379" + volumes: + - conversation-assistant-redis-data:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 3s + retries: 3 + restart: unless-stopped + +volumes: + conversation-assistant-redis-data: diff --git a/features/i18n/ml-service/docker-compose.yml b/features/i18n/ml-service/docker-compose.yml new file mode 100644 index 000000000..e466c7ceb --- /dev/null +++ b/features/i18n/ml-service/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.8" + +services: + redis: + image: redis:7-alpine + container_name: i18n-redis + ports: + - "6382:6379" + volumes: + - i18n-redis-data:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 3s + retries: 3 + restart: unless-stopped + +volumes: + i18n-redis-data: diff --git a/features/seo/ml-service/python/lilith_seo_service/config.py b/features/seo/ml-service/python/lilith_seo_service/config.py index 8d0c57a90..3ef118e45 100644 --- a/features/seo/ml-service/python/lilith_seo_service/config.py +++ b/features/seo/ml-service/python/lilith_seo_service/config.py @@ -1,9 +1,16 @@ """Configuration for SEO service.""" +from pathlib import Path + from pydantic import Field from pydantic_settings import SettingsConfigDict from lilith_ml_service_base import ContentGenerationSettings -from lilith_service_addresses import get_service_port, get_redis_url +from lilith_service_addresses import get_service_port, get_service_url, get_redis_url + + +def _get_default_template_dir() -> Path: + """Get default template directory relative to package location.""" + return Path(__file__).parent.parent.parent.parent / "prompts" / "locale-templates" class SEOServiceSettings(ContentGenerationSettings): @@ -15,10 +22,17 @@ class SEOServiceSettings(ContentGenerationSettings): service_name: Service identifier (default: seo-service). port: HTTP port to listen on (auto-resolved from service registry). redis_url: Redis connection URL (auto-resolved from service registry). + llm_backend_url: URL of llama-service for LLM inference. + truth_service_url: URL of truth-validation service. default_locale: Default locale for SEO generation. supported_locales: List of supported locales. template_dir: Directory containing SEO templates. truth_validation_enabled: Whether to validate against truth service. + cache_enabled: Whether to enable Redis caching. + cache_ttl: Cache TTL in seconds. + generation_temperature: LLM generation temperature. + generation_max_tokens: Maximum tokens for LLM generation. + generation_timeout: LLM request timeout in seconds. """ service_name: str = Field(default="seo-service") @@ -27,6 +41,50 @@ class SEOServiceSettings(ContentGenerationSettings): # Redis URL auto-resolved from services.yaml: seo.redis = 6383 redis_url: str = Field(default_factory=lambda: get_redis_url('seo'), description="Redis connection URL") + # LLM Backend (llama-service on port 41221) + llm_backend_url: str = Field( + default_factory=lambda: get_service_url('ml', 'llama-service'), + description="llama-service URL for LLM inference" + ) + generation_timeout: float = Field( + default=60.0, + description="LLM request timeout in seconds" + ) + generation_temperature: float = Field( + default=0.95, + ge=0.0, + le=2.0, + description="LLM generation temperature (0.0-2.0)" + ) + generation_max_tokens: int = Field( + default=4096, + ge=256, + le=32768, + description="Maximum tokens for LLM generation" + ) + + # Truth Validation (truth-validation service on port 41233) + truth_service_url: str = Field( + default_factory=lambda: get_service_url('truth-validation', 'api'), + description="truth-validation service URL" + ) + truth_validation_enabled: bool = Field( + default=True, + description="Validate generated content against truth service" + ) + + # Caching + cache_enabled: bool = Field( + default=True, + description="Enable Redis caching for generated content" + ) + cache_ttl: int = Field( + default=3600, + ge=60, + description="Cache TTL in seconds (default: 1 hour)" + ) + + # Locales default_locale: str = Field( default="en", description="Default locale for SEO content" @@ -39,13 +97,11 @@ class SEOServiceSettings(ContentGenerationSettings): ], description="Supported locales for SEO generation" ) - template_dir: str | None = Field( - default=None, - description="Directory containing SEO templates" - ) - truth_validation_enabled: bool = Field( - default=True, - description="Validate generated content against truth service" + + # Templates + template_dir: Path = Field( + default_factory=_get_default_template_dir, + description="Directory containing SEO prompt templates" ) model_config = SettingsConfigDict( diff --git a/features/seo/ml-service/python/lilith_seo_service/models.py b/features/seo/ml-service/python/lilith_seo_service/models.py index b29d39c4a..b6809e9ad 100644 --- a/features/seo/ml-service/python/lilith_seo_service/models.py +++ b/features/seo/ml-service/python/lilith_seo_service/models.py @@ -138,3 +138,76 @@ class CacheInvalidateResponse(BaseModel): """Response from cache invalidation.""" invalidated_count: int + + +# === Full Content Response Models (for pipeline integration) === + + +class SEOContentResponse(BaseModel): + """Full content response for pipeline integration. + + This model matches the response format expected by the NestJS + backend TextClientService for full page generation. + + Attributes: + title: Page title. + description: Meta description. + h1: Main heading (may differ from title). + body: Full HTML body content. + keywords: Comma-separated keywords. + og_title: Open Graph title. + og_description: Open Graph description. + schema_json: Schema.org JSON-LD (optional). + word_count: Word count of body. + locale: Content locale. + """ + + title: str = Field(..., min_length=1, max_length=100) + description: str = Field(..., min_length=1, max_length=300) + h1: str = Field(..., min_length=1, max_length=200) + body: str = Field(default="") + keywords: str = Field(default="") + og_title: str = Field(default="") + og_description: str = Field(default="") + schema_json: dict | None = None + word_count: int = 0 + locale: str = Field(default="en") + + +class ValidationResultModel(BaseModel): + """Validation result for pipeline response. + + Attributes: + valid: Whether validation passed. + corrected_content: Auto-corrected content (if any). + corrections: List of correction messages. + confidence: Confidence score (0.0-1.0). + """ + + valid: bool + corrected_content: str | None = None + corrections: list[str] = Field(default_factory=list) + confidence: float = Field(default=1.0, ge=0.0, le=1.0) + + +class SEOFullResponse(BaseModel): + """Full response matching TextClientService expectations. + + This is the complete response format returned by the /api/seo/generate + endpoint when called by the NestJS backend pipeline. + + Attributes: + metadata: SEO metadata (title, description, etc.). + content: Full content including body. + schema_json: Schema.org JSON-LD structure. + validation: Truth validation result (if enabled). + cached: Whether result was from cache. + generation_time_ms: Generation time in milliseconds. + """ + + metadata: SEOMetadata + content: SEOContentResponse + schema_json: dict | None = None + validation: ValidationResultModel | None = None + cached: bool = False + generation_time_ms: float = 0.0 diff --git a/features/truth-validation/ml-service/docker-compose.yml b/features/truth-validation/ml-service/docker-compose.yml new file mode 100644 index 000000000..0ef1fb3c8 --- /dev/null +++ b/features/truth-validation/ml-service/docker-compose.yml @@ -0,0 +1,20 @@ +version: "3.8" + +services: + redis: + image: redis:7-alpine + container_name: truth-validation-redis + ports: + - "6384:6379" + volumes: + - truth-validation-redis-data:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 5s + timeout: 3s + retries: 3 + restart: unless-stopped + +volumes: + truth-validation-redis-data: