Skip to main content
Mandacode mandacode
塔罗牌:AI塔罗牌解读服务的缓存
·
Caching NestJS OpenAI API Redis TypeScript

塔罗牌:AI塔罗牌解读服务的缓存

在优化OpenAI API费用和响应速度的同时,设计每次都提供新体验的塔罗服务缓存方案

问题意识

AI生成的内容每次都是新的,这是一大优势,但如果每次对相同的输入调用API,费用会迅速累积。塔罗牌服务也是一样。虽然使用OpenAI API进行牌面解读,但由于费用和响应速度问题,不可能对每个请求都调用API。

然而,仅仅将牌面和方向作为键的缓存是不够的。用户即使抽到相同的牌面,也期待每次有不同的解读。为缩小这一差距,我们引入了利用桶系统的缓存策略

桶:多样性与效率的平衡

核心思想很简单。通过组合78张卡牌、正反方向以及10个桶,1560个唯一缓存键,并在每个键下存储AI生成的解读。

78张 × 2方向 × 10桶 = 1560个唯一组合

每当用户请求时,会随机选择这一组合中的一个。缓存键是tarot:read:{card}:{direction}:{bucket}形式,使用相同键的后续请求立即从Valkey返回结果。只有在缓存中无结果时才调用OpenAI API。

此外,还有一个附加装置。服务器每次请求会随机选择4个关键词,与上下文一起传递给AI。因此,即使牌面、方向、桶相同,根据关键词的不同,解读也可能不同。

flowchart LR
    subgraph RandomSelect["随机选择"]
        Card[78张卡牌]
        Dir[正反方向]
        Bucket[桶 1~10]
        Keywords[4个关键词]
    end

    subgraph CacheKey["缓存键"]
        Key["tarot:read:{card}:{dir}:{bucket}"]
    end

    Card --> Key
    Dir --> Key
    Bucket --> Key

    Key --> Valkey[(Valkey)]
    Key -.->|缓存未命中| OpenAI[OpenAI API]
    Keywords -.->|解读方向| OpenAI

整体流程用序列图表示如下。

sequenceDiagram
    autonumber

    actor Client as 客户端
    participant Service as TarotService
    participant Cache as Valkey
    participant AI as OpenAI

    Client->>Service: 塔罗解读请求
    Note over Service: 随机选择牌面/方向/桶

    Service->>Cache: 缓存查询 (`GET`)

    alt 缓存命中
        Cache-->>Service: 返回存储的结果
    else 缓存未命中
        Service->>AI: 调用OpenAI API
        AI-->>Service: 返回解读结果 ({advice})
        Note over Service: 数据组合<br/>(card.name / card.nameKR / keywords)
        Service->>Cache: 保存结果 (`SET`)
    end

    Service-->>Client: 最终解读结果响应

部署

前端通过Vercel,后端在本地Kubernetes集群上运行。

flowchart TD
    subgraph Front["Vercel"]
        Vercel[塔罗牌 Next.js 应用]
    end

    subgraph CICD["CI / CD"]
        GH[GitHub]
        Actions[GitHub Actions]
        Harbor[(Harbor)]
        ArgoCD[ArgoCD]
        S3[(S3)]
    end

    subgraph K8s["本地 K8s 集群"]
        GW[Gateway API]
        Service[塔罗牌服务]
        HPA[HPA: 2~10 副本]
    end

    %% 部署流水线流程
    GH -->|Git 版本标签推送 v*.*.*| Actions
    Actions -->|镜像构建/推送| Harbor
    Harbor -->|镜像存储| S3
    Harbor -->|镜像引用| ArgoCD
    ArgoCD -->|GitOps 部署| Service

    %% 前端流水线流程
    Actions -->|前端构建/部署| Vercel

    %% 流量流向
    Vercel --> |外部流量| GW
    GW -->|路由| Service
    Service -->|自动扩展| HPA

部署流水线在GitHub上新版本标签(v*.*.*)推送时立即自动启动。GitHub Actions基于该标签构建镜像并推送到内部容器仓库Harbor,ArgoCD通过GitOps配置检测变更并自动同步集群状态。此外,前端通过GitHub Actions直接进行Vercel的构建和部署。

后端通过HPA根据流量自动扩展为2至10个副本,外部用户的请求安全地路由到内部Gateway API。

改进空间

目前是一个不用登录即可使用的简单服务,但我们计划添加登录功能,以允许保存用户的解读历史和提供个性化的体验。

结语

塔罗牌服务虽然是一个小项目,但它包含了解决AI生成和缓存平衡的实际问题。利用桶系统的缓存策略在费用和多样性之间提供了实际的妥协方案,并有足够的改进空间。