Spaces:
Running on Zero
Running on Zero
GitHub Actions
fix: 0 test failures; FileService; real RagService; emergency probe; chat return
4aaae80 | """TranslationService β registers trans.text@1.0 on the bus.""" | |
| from __future__ import annotations | |
| from typing import Any | |
| from hearthnet.constants import TRANSLATION_MAX_CHARS | |
| class TranslationService: | |
| name = "translation" | |
| version = "1.0" | |
| def __init__( | |
| self, | |
| backends: list[Any] | None = None, | |
| bus: Any = None, | |
| ) -> None: | |
| if backends is not None: | |
| self._backends = backends | |
| else: | |
| self._backends = self._discover_backends() | |
| if bus is not None: | |
| self.register(bus) | |
| # ββ Backend discovery βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _discover_backends(self) -> list[Any]: | |
| backends: list[Any] = [] | |
| try: | |
| from hearthnet.services.translation.backends.nllb import NllbBackend | |
| b = NllbBackend() | |
| if b.health().get("status") == "ok": | |
| backends.append(b) | |
| except Exception: | |
| pass | |
| return backends | |
| def _select_backend( | |
| self, | |
| from_lang: str, | |
| to_lang: str, | |
| preferred: str | None = None, | |
| ) -> Any | None: | |
| for backend in self._backends: | |
| if preferred and backend.name != preferred: | |
| continue | |
| if backend.health().get("status") != "ok": | |
| continue | |
| pairs = backend.supported_pairs | |
| if from_lang == "auto" or (from_lang, to_lang) in pairs: | |
| return backend | |
| # Any healthy backend as fallback | |
| for backend in self._backends: | |
| if backend.health().get("status") == "ok": | |
| return backend | |
| return None | |
| # ββ Capability registration βββββββββββββββββββββββββββββββββββββββββββββββ | |
| def register(self, bus: Any) -> None: | |
| from hearthnet.bus.capability import CapabilityDescriptor | |
| desc = CapabilityDescriptor( | |
| name="trans.text", | |
| version=(1, 0), | |
| stability="stable", | |
| params={ | |
| "backends": [b.name for b in self._backends], | |
| "max_chars": TRANSLATION_MAX_CHARS, | |
| }, | |
| max_concurrent=4, | |
| trust_required="member", | |
| timeout_seconds=30, | |
| idempotent=True, | |
| ) | |
| bus.register_capability(desc, self._handle_translate, self.params_compatible) | |
| def params_compatible(self, offered: dict, requested: dict) -> bool: | |
| req_backend = requested.get("backend") | |
| if not req_backend: | |
| return True | |
| return req_backend in offered.get("backends", []) | |
| # ββ Handler βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| async def _handle_translate(self, req: Any) -> dict: | |
| body = req.body if hasattr(req, "body") else req | |
| inp = body.get("input", body) | |
| text: str = inp.get("text", "") | |
| from_lang: str = inp.get("from_lang", "auto") | |
| to_lang: str | None = inp.get("to_lang") | |
| domain: str | None = inp.get("domain") | |
| preferred: str | None = inp.get("backend") | |
| if not to_lang: | |
| return {"error": "bad_request", "reason": "to_lang is required"} | |
| if len(text) > TRANSLATION_MAX_CHARS: | |
| return { | |
| "error": "bad_request", | |
| "reason": f"Text too long: {len(text)} > {TRANSLATION_MAX_CHARS} chars", | |
| } | |
| backend = self._select_backend(from_lang, to_lang, preferred) | |
| if backend is None: | |
| return { | |
| "error": "backend_unavailable", | |
| "reason": "No healthy translation backend available", | |
| } | |
| try: | |
| result = await backend.translate( | |
| text, from_lang=from_lang, to_lang=to_lang, domain=domain | |
| ) | |
| except Exception as exc: | |
| return {"error": "internal_error", "reason": str(exc)} | |
| return { | |
| "text": result.text, | |
| "from_lang": result.from_lang, | |
| "to_lang": result.to_lang, | |
| "backend": result.backend, | |
| "ms": result.ms, | |
| } | |