Skip to content

翻译内容哈希缓存 #3

@Arcadia822

Description

@Arcadia822

背景

当前 IntelligenceService._to_chinese() 通过 Google Translate 免费 API 进行实时翻译,每次 digest 生成都会重新翻译所有非中文内容。存在问题:

  1. 重复翻译:同一事件在多次 digest run 中(如跨天未更新的源)会被重复翻译。
  2. API 无保障:Google Translate 免费 API 无 SLA,高频调用可能被限流。
  3. 无翻译历史:翻译结果不持久化,agent 无法回溯或校对历史翻译。

参考实现

OpenTrends (nexmoe/opentrends) 的翻译系统:

  1. 内容哈希校验:对原文 (title, description) 计算 SHA-256 哈希,作为翻译缓存的 key。翻译结果存入 source_item_translation 表,包含 textHashtitledescriptionmodelcreatedAt 字段。下次翻译同一内容时,先比对哈希——命中则直接返回缓存。
  2. 递归批次拆分:批量翻译失败时自动将 batch size 减半重试,逐层降级到单条翻译。
  3. 超时感知:翻译有严格的超时控制,超时后降级返回原文。

提案

IntelligenceService 中增加翻译缓存层:

1. 缓存存储

<skrya-data-root>/cache/
  translations/
    <lang>/
      <content-hash>.json

缓存条目结构:

{
  "source_text": "OpenAI launches ChatGPT agent browser",
  "translated_text": "OpenAI 推出 ChatGPT 代理浏览器",
  "content_hash": "a1b2c3...",
  "lang": "zh-CN",
  "model": "google-translate",
  "created_at": "2026-05-17T10:00:00+08:00"
}

2. 哈希策略

import hashlib

def content_hash(text: str) -> str:
    normalized = " ".join(text.strip().split())
    return hashlib.sha256(normalized.encode()).hexdigest()[:16]
  • 归一化空白后计算 SHA-256,取前 16 位作为 key
  • 同一原文哈希相同,不同原文碰撞概率极低

3. 翻译流程改造

def _to_chinese(self, text: str) -> str:
    if is_chinese(text):
        return text
    
    # 1. 查缓存
    h = content_hash(text)
    cached = self._translation_cache.get("zh-CN", h)
    if cached:
        return cached
    
    # 2. 调翻译 API
    translated = self._translator(text)
    if not translated:
        return text
    
    # 3. 写缓存
    self._translation_cache.put("zh-CN", h, text, translated)
    return translated

4. 缓存生命周期

  • 缓存不过期(同一原文的翻译不会变)
  • 提供 --clear-translation-cache CLI 命令用于手动清理
  • 翻译模型/提供商变更时建议清理缓存

收益

  • 减少 API 调用:跨 run 的重复事件直接命中缓存
  • 提升 digest 速度:缓存命中时跳过网络请求(每次 digest 可能节省 5-20 秒)
  • 翻译可追溯:缓存文件可用于 agent 事后校对翻译质量

优先级

— 性能优化,不影响功能正确性,但对 agent 响应速度有明显改善。

备注

来源:agent=牛马AI, model=mimo-v2.5-pro, reference=opentrends

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions