Blame view

translation/cache.py 3.61 KB
cd4ce66d   tangwang   trans logs
1
2
3
4
5
6
7
8
  """Shared translation cache utilities."""
  
  from __future__ import annotations
  
  import hashlib
  import logging
  from typing import Mapping, Optional
  
86d8358b   tangwang   config optimize
9
10
11
12
  try:
      import redis
  except ImportError:  # pragma: no cover - runtime fallback for minimal envs
      redis = None  # type: ignore[assignment]
cd4ce66d   tangwang   trans logs
13
  
86d8358b   tangwang   config optimize
14
  from config.loader import get_app_config
cd4ce66d   tangwang   trans logs
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  
  logger = logging.getLogger(__name__)
  
  
  class TranslationCache:
      """Redis-backed cache shared by all translation capabilities."""
  
      def __init__(self, config: Mapping[str, object]) -> None:
          self.ttl_seconds = int(config["ttl_seconds"])
          self.sliding_expiration = bool(config["sliding_expiration"])
          self.redis_client = self._init_redis_client()
  
      @property
      def available(self) -> bool:
          return self.redis_client is not None
  
      def build_key(self, *, model: str, target_lang: str, source_text: str) -> str:
          normalized_model = str(model or "").strip().lower()
          normalized_target_lang = str(target_lang or "").strip().lower()
          text = str(source_text or "")
          text_prefix = text[:4]
          digest = hashlib.sha256(text.encode("utf-8")).hexdigest()
          return f"trans:{normalized_model}:{normalized_target_lang}:{text_prefix}{digest}"
  
      def get(self, *, model: str, target_lang: str, source_text: str) -> Optional[str]:
          if self.redis_client is None:
              return None
          key = self.build_key(model=model, target_lang=target_lang, source_text=source_text)
          try:
              value = self.redis_client.get(key)
              logger.info(
14e67b71   tangwang   分句后的 batching 现在是...
46
                  "Translation cache %s | text_len=%s key=%s",
cd4ce66d   tangwang   trans logs
47
                  "hit" if value is not None else "miss",
cd4ce66d   tangwang   trans logs
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
                  len(str(source_text or "")),
                  key,
              )
              if value and self.sliding_expiration:
                  self.redis_client.expire(key, self.ttl_seconds)
              return value
          except Exception as exc:
              logger.warning("Redis get translation cache failed: %s", exc)
              return None
  
      def set(self, *, model: str, target_lang: str, source_text: str, translated_text: str) -> None:
          if self.redis_client is None:
              return
          key = self.build_key(model=model, target_lang=target_lang, source_text=source_text)
          try:
              self.redis_client.setex(key, self.ttl_seconds, translated_text)
              logger.info(
14e67b71   tangwang   分句后的 batching 现在是...
65
                  "Translation cache write | text_len=%s result_len=%s ttl_seconds=%s key=%s",
cd4ce66d   tangwang   trans logs
66
67
68
69
70
71
72
73
74
75
                  len(str(source_text or "")),
                  len(str(translated_text or "")),
                  self.ttl_seconds,
                  key,
              )
          except Exception as exc:
              logger.warning("Redis set translation cache failed: %s", exc)
  
      @staticmethod
      def _init_redis_client() -> Optional[redis.Redis]:
86d8358b   tangwang   config optimize
76
77
78
79
          if redis is None:
              logger.warning("redis package is not installed; translation cache disabled")
              return None
          redis_config = get_app_config().infrastructure.redis
cd4ce66d   tangwang   trans logs
80
81
          try:
              client = redis.Redis(
86d8358b   tangwang   config optimize
82
83
84
                  host=redis_config.host,
                  port=redis_config.port,
                  password=redis_config.password,
cd4ce66d   tangwang   trans logs
85
                  decode_responses=True,
86d8358b   tangwang   config optimize
86
87
88
                  socket_timeout=redis_config.socket_timeout,
                  socket_connect_timeout=redis_config.socket_connect_timeout,
                  retry_on_timeout=redis_config.retry_on_timeout,
cd4ce66d   tangwang   trans logs
89
90
91
92
93
94
95
                  health_check_interval=10,
              )
              client.ping()
              return client
          except Exception as exc:
              logger.warning("Failed to initialize translation redis cache: %s", exc)
              return None