用代码杀掉LLM:一个塔罗占卜游戏的程序化解读引擎
起因
我有一个塔罗占卜的小程序,靠 LLM 驱动解读——用户抽牌,把牌面信息发给 LLM,LLM 返回一段解读文字。
能用,但有几个问题:
- 要花钱:每次解读都调 API
- 要等:API 响应要 2-5 秒
- 要联网:没网就用不了
- 不稳定:LLM 有时候太诗意,有时候太敷衍,风格飘忽
今天我决定把它改掉:完全脱离 LLM,纯程序逻辑解读。
思路:三层架构替代 LLM
LLM 在塔罗解读里干三件事:提供塔罗知识、生成解读语言、做牌面推理。我用三层程序化架构分别替代:
LLM 的知识 → 牌数据库(结构化含义查表)
LLM 的生成 → 模板引擎(位置类型选模板填数据)
LLM 的推理 → 规则逻辑(统计/扫描/分析/提取)
第一层:牌数据库替代 LLM 的"知识"
cards-data.js,415 行,包含完整 78 张塔罗牌的数据。每张牌都有正位和逆位的含义、关键词、建议:
{
id: 0, nameCn: "愚者", nameEn: "The Fool", element: "风",
upright: {
keywords: ["新开始", "天真", "自由", "冒险"],
meaning: "代表全新的开始与无限可能,带着天真无畏的心态踏上旅程。",
advice: "保持开放心态,勇敢迈出第一步,不必过度计划。"
},
reversed: {
keywords: ["鲁莽", "轻率", "风险", "未准备"],
meaning: "因鲁莽轻率而陷入风险,缺乏准备就贸然行动。",
advice: "行动前先评估风险,做好基础准备再出发。"
}
}
78 张牌 × 2 种状态 = 156 条结构化含义,全部预置在代码里。LLM 原本"知道"的塔罗知识,现在变成了查表。
第二层:模板引擎替代 LLM 的"语言生成"
interpret-engine.js,334 行,这是替代 LLM 的核心。
解读引擎根据牌阵中每个位置的类型(过去/现在/未来/挑战/建议等),选择不同的句式模板,填入牌的数据:
| 位置类型 | 模板句式 |
|---|---|
| 过去 | “过去因为【牌名】的影响,【含义】” |
| 现在 | “目前呈现【牌名】的状态,【含义】” |
| 未来 | “接下来可能会向【牌名】所示的方向发展” |
| 挑战 | “主要挑战来自【牌名】,意味着【含义】” |
| 建议 | “建议你【牌的 advice 字段】” |
拼接成完整的因果分析段落。不需要 LLM 生成自然语言,模板填充就够了。
第三层:规则逻辑替代 LLM 的"推理"
解读引擎用规则逻辑完成 LLM 原本的"推理"工作:
- 整体基调:统计逆位牌数量 → 0 张积极 / 1-2 张需注意 / 3+ 张挑战多
- 问题识别:扫描逆位牌和传统负面牌(死神、高塔、恶魔),列出实际问题
- 牌面互动:分析相邻牌的元素(火水风土)关系 → 同元素增强、相克冲突
- 建议生成:优先取"建议"位置的牌的 advice,结合逆位牌的应对建议,生成编号列表
8 种牌阵
支持 8 种预定义牌阵,位置含义全部固定,不允许自行发明新位置:
- 单张牌阵(1 张)— 当前最核心的信息
- 三张经典牌阵(3 张)— 过去、现在、未来
- 五张牌阵(5 张)— 当前状况、挑战、过去影响、未来潜力、行动建议
- 凯尔特十字牌阵(10 张)— 经典全分析
- 马蹄牌阵(7 张)— 过去到结果的完整路径
- 关系与情感牌阵(7 张)— 双方感受与关系发展
- 事业与人生方向牌阵(6 张)— 当前阶段到长期指引
- 决策二选一牌阵(8 张)— 两个选项的对比决策
开发过程
整个项目在华为云 CodeArts 沙盒里完成,用 AI 编码助手生成代码,全程约 15 分钟。
项目结构
tarot-game/
├── index.html (66 行) 主页面
├── style.css (391 行) 深色神秘风格样式
├── cards-data.js (415 行) 78 张牌完整数据库
├── spreads-data.js (132 行) 8 种牌阵定义
├── interpret-engine.js (334 行) 解读引擎核心
└── app.js (250 行) 主逻辑(牌阵选择/抽牌/动画/渲染)
总计约 1588 行代码,纯 HTML + CSS + JavaScript,无后端,无依赖,无构建工具。
解读风格
解读风格有严格要求:简单直接,像日常对话,用"因为…所以…“的因果逻辑,不用"能量流动”“高维指引”"灵魂觉醒"等抽象表达。重点说发生了什么、为什么、该怎么做。忠于牌面,不讨好,负面牌就直说问题。
输出格式固定为四段:
- 【牌阵总览】 — 一句话概括核心信息
- 【深度解析】 — 抽牌过程 + 因果分析 + 问题阻碍 + 牌面互动
- 【神谕指引】 — 3-4 条可执行建议
- 【结语】 — 固定免责声明
效果对比
| LLM 方案 | 纯程序方案 | |
|---|---|---|
| 解读质量 | 更灵活自然 | 结构化、一致性好 |
| 运行成本 | 每次调 API | 零成本 |
| 响应速度 | 2-5 秒 | 瞬间 |
| 可离线 | ❌ | ✅ |
| 风格一致 | 可能跑偏 | 严格遵循规则 |
| 代码量 | prompt + API 调用 | 1588 行纯前端 |
纯程序方案的解读质量确实不如 LLM 灵活——没有那些出人意料的联想和隐喻。但它赢在确定性:每次同样的牌面出同样的解读,不会今天诗意明天敷衍。对于塔罗这种有固定含义体系的场景,结构化解读反而更靠谱。
总结
这次开发最有趣的部分不是写代码,而是设计解读引擎的架构——把 LLM 的三个能力(知识、生成、推理)拆开,分别用程序化方案替代。
核心洞察是:塔罗牌的解读体系本身就是高度结构化的。每张牌有固定含义,每个位置有固定作用,解读遵循因果逻辑。这种结构化场景,恰恰是程序化方案比 LLM 更合适的地方。LLM 的优势在于开放性创作,而塔罗解读不需要开放性——它需要的是准确性和一致性。
用 1588 行代码,换掉了一个持续消耗 API 费用的 LLM 调用链。值。
- 点赞
- 收藏
- 关注作者
评论(0)