Skip to content

103. 技能后端、缓存与读取接口

学习目标

这一节开始为 Vibe 系统补齐技能管理的后端能力,让 AI 能先看到技能简介,再按需读取技能详情。

学完后,你应该能理解:

  • 技能为什么要拆成简介和详情;
  • 为什么每轮对话都要把技能简介放进系统提示词;
  • 技能详情为什么要通过工具按需读取;
  • 技能表如何建模;
  • Redis 缓存为什么适合保存技能提示词;
  • 新增、更新、删除技能后为什么要刷新缓存。

技能的作用

技能不是普通文档。

它的作用是约束 AI 按项目规则做事。

例如系统里有几类任务:

  • 编辑模块配置;
  • 编辑前端代码;
  • 编辑后端接口;
  • 生成建表语句;
  • 覆盖默认接口;
  • 调用通用表格组件。

每类任务都有自己的规范。AI 只有先读到这些规范,才知道应该按什么格式输出代码。

这和本地 AGENTS.mdCLAUDE.md 或 Codex 技能文件的思路类似:模型不是凭空知道项目约定,而是通过上下文读取规则。

简介和详情分开

技能表里主要保存两个字段:

  • summary:技能简介;
  • detail:技能详情。

简介会放进系统提示词,让 AI 知道“有哪些技能可以用”。

详情不会每次都全部塞进上下文,而是通过工具按需读取。

这样做有两个好处:

  • 系统提示词不会无限膨胀;
  • AI 可以根据当前任务选择真正需要的技能。

如果每次都把所有技能详情全部发给模型,随着技能越来越多,上下文会变长,成本和出错率都会上升。

技能表建模

课程里为技能建立了独立模型。

它和前面用户、模块等模型类似,都继承基础模型,并声明真实数据表名。

技能表不只按 id 使用。

很多时候系统真正拿到的是技能简介 summary,所以缓存和查询更适合用 summary 作为 key。

这和用户缓存用 username 类似:中间件解析 token 时拿到的是用户名,而不是数据库主键。

缓存单条技能

技能详情会被频繁读取。

例如 AI 判断当前任务需要“前端页面开发规范”,就会调用读取技能详情的工具。这个动作可能在多轮对话中重复出现。

所以单条技能详情适合放进 Redis。

读取流程可以理解成:

  1. 先按技能简介从 Redis 查;
  2. 查不到再访问数据库;
  3. 数据库查到后写回 Redis;
  4. 下次直接从缓存返回。

这样可以减少数据库访问,也能让工具调用更快。

缓存全部技能简介

除了单条技能详情,系统还需要频繁读取“所有技能简介”。

因为每轮大模型对话开始时,系统提示词都要告诉模型:

你可以使用哪些技能。

所以全部技能简介也需要缓存。

课程里为它单独设计缓存 key,并通过 Redis 保存拼接后的简介文本。

如果缓存为空,就从数据库读取所有技能,把每条 summary 用换行拼起来,再写回缓存。

缓存击穿和分布式锁

当缓存失效时,可能有多个请求同时发现缓存为空。

如果它们一起查数据库、一起写缓存,就会造成缓存击穿。

课程里继续使用分布式锁来处理:

  • 先查一次缓存;
  • 如果没有缓存,尝试拿锁;
  • 拿到锁后再查一次缓存;
  • 仍然没有,再访问数据库;
  • 写入缓存后释放锁。

这和前面用户缓存、模块缓存的思路一致。

对 JS 开发者来说,可以把它类比成“多个异步请求同时初始化同一份全局数据”时,需要避免重复初始化。

技能接口

后端提供两类接口:

  • 查询全部技能简介;
  • 按技能简介查询单条技能详情。

前端工具调用时,先把全部简介放进提示词。

当 AI 需要某个技能详情时,再调用工具读取对应 detail

这样技能系统就从“数据库里的文档”变成了“AI 可主动读取的开发规范”。

修改技能后的缓存刷新

技能是可以编辑的。

当新增、更新或删除技能时,缓存必须刷新。

否则数据库里已经改了,AI 仍然读到旧规则。

课程里通过拦截器处理这些变化:

  • 更新单条技能缓存;
  • 刷新全部技能简介缓存;
  • 删除技能时清掉对应缓存;
  • 多个刷新任务可以并发执行。

这让技能管理页面和 AI 对话上下文保持一致。

阶段重点

这一节的核心不是 Redis 语法。

核心是理解技能系统的架构:

简介负责“让 AI 发现能力”,详情负责“让 AI 学会规则”,缓存负责“让读取足够快”。

有了这套后端能力,后面前端聊天组件才能把技能真正接入工具调用流程。

AI Agent 课程学习文档。