gRPC结合FAISS构建AI助手语义缓存模块(一):设计

一、背景简介

原AI聊天助手项目中,每次提问(Prompt)都需要调用公有LLM API来获取大模型的回答(Answer),然而,有些时候用户会向聊天助手询问同样的问题,我们将KV存储集成到聊天助手当中,初步实现了一个Prompt对应一个Answer的缓存功能。

但是有时候,用户向聊天助手询问的问题并不是一字不差,同样的语义,由于prompt字面的不同,原先的缓存功能就失效,现在的问题是如何实现语义级别的缓存功能

二、组件依赖

2.1 高性能中间件 - 自研KV存储

Github - KVstore

支持命令

命令 语法 说明
SET SET 写入键值对,key 已存在则覆盖
GET GET 读取键值,不存在返回 $-1
DEL DEL 删除键,返回删除数量
EXISTS EXISTS 检查键是否存在,返回 0 / 1
MOD MOD 仅当键存在时更新值
SAVE SAVE 手动触发 RDB 快照保存
PING PING message 连通性探测,返回 PONG 或回显 message

2.2 高效向量搜索 - FAISS

语义级别的识别,首先想到的方案是结合FAISS来做,(Facebook AI Similarity Search),这是由 Meta(原 Facebook)开源的一个高效向量搜索库。

FAISS向量搜索具体的内部实现是一个比较复杂的问题,这里只粗浅介绍一下:

原始的prompt,比如"我饿了"、"我想吃饭",被模型编码成为高维向量:

复制代码
文本输入                    高维向量空间
"我饿了"    → 模型编码 → [0.12, -0.34, 0.56, ..., 0.78]  (768维)
"我想吃饭"  → 模型编码 → [0.11, -0.32, 0.55, ..., 0.79]  (768维)
                           ↑ 两个向量方向几乎相同 ↑

内存结构:

隐式ID 向量数据 (768个float32) 对应的文本
0 [0.0123, -0.0456, 0.0789, ...] "我饿了"
1 [0.0115, -0.0412, 0.0765, ...] "我想吃饭"
2 [-0.0891, 0.1234, -0.0056, ...] "今天天气不错"
  • FAISS 只存数字,不知道prompt的文本是什么
  • ID 自动生成(从0开始,每次调用add自增)
  • prompt文本存在KV存储里,用 ID 关联

检索时暴力遍历,通过余弦相似度衡量向量方向的相似性,给定阈值,判断是否命中。当然了,检索算法有内置的优化实现。

我们faiss模块中使用到的核心接口如下:

分类 接口 一句话作用
创建索引 IndexFlatIP 建一个用内积算相似度的索引
写入 add 把向量存进索引
检索 search 找最相似的 Top-K 个向量
保存 write_index 把内存索引存成文件
加载 read_index 从文件恢复索引到内存
取数量 ntotal 看索引里存了多少条
取维度 d 看向量是几维的

2.3 通信底座 - gRPC

gRPC(Google Remote Procedure Call)是由谷歌公司开发的远程调用框架。什么叫远程调用?

如下图所示,这是一个多语言多平台的系统,不同语言和平台之间的对象本不能直接相互调用,gRPC就是为了解决这个问题出现的:

通过Protobuf 协议(一种语言无关、平台无关且便于传输的序列化协议),server端对需要共享的对象进行序列化,接收端进行反序列化,并且client端通过stub封装从而实现直接调用 (无需关系底层实现),这篇博客介绍了你所需要的Protobuf相关内容

三、模块架构

Go后端作为gRPC的client,通过stub收发proto消息,由Python实现的faiss语义层为gRPCserver,他们之间的通信消息和服务由Proto文件给定,proto文件中定义三个接口函数:

伪代码 复制代码
GetCache(prompt)
PutCache(prompt)
DeleteCache(prompt)

prompt进faiss层被编码为相似度+ID,ID与KV中的answer绑定,faiss层通过GET ID、SET ID Answer等命令与KV存储交互。

整体模块架构总结如下:

复制代码
┌────────────────────────────────────────────────────────┐
│               业务客户端层 (Go Web 后端)               │
└───────────────────────────┬────────────────────────────┘
                            │ gRPC 通信 (50051)
┌───────────────────────────▼────────────────────────────┐
│ 1. 网关层 (main.py) - 流量拦截与服务生命周期管理        │
└───────────────────────────┬────────────────────────────┘
                            │ 本地方法调度
┌───────────────────────────▼────────────────────────────┐
│ 2. 核心算法层 (engine.py)                              │
│    ├── [模块 A] 语义编码 (SentenceTransformer)          │
│    ├── [模块 B] 几何正规化 ($L_2$ Normalization)       │
│    └── [模块 C] 容错自愈 (维度探测器)                   │
└───────────────────────────┬────────────────────────────┘
                            │ 双向读写
┌───────────────────────────▼────────────────────────────┐
│ 3. 存储与索引层 (持久化)                                │
│    ├── [模块 D] 内存阵列检索 (FAISS) ──> 负责"控门"   │
│    └── [模块 E] KV缓存 (自研KV)  ──> 负责"管账"   │
└────────────────────────────────────────────────────────┘
相关推荐
unique1 小时前
AI Coding 工具使用监控 — 市场竞品调研报告
人工智能·ai编程
环球科讯1 小时前
爱征信 惠民生 促发展——建行江西省新余市分行开展征信知识进商户宣讲活动
人工智能
Dick5071 小时前
ROS2 常用命令表
人工智能·学习·算法·机器人
云烟成雨TD1 小时前
Agent Scope Java 2.x 系列【19】Harness:从零搭建 MySQL 文件系统
java·人工智能·agent
keyanbanyungong1 小时前
AI绘图行业乱象:科学失真、素材侵权,MedPeer如何重构科研可视化行业
人工智能
咕咕AI学堂2 小时前
并发编程模式:从生产者-消费者到 Actor 的工程实践
人工智能
指掀涛澜天下惊2 小时前
AI 基础知识十九 强化学习前言
人工智能·机器学习·强化学习
X54先生(人文科技)2 小时前
《元创力》纪实录·卷宗2.2 会议室的裂缝:当“真实高于完美”第一次被写在会议纪要里
人工智能·开源·ai写作·零知识证明
武子康2 小时前
调查研究-178 Google 官方 Agent Skills 仓库解读:AI Agent 时代,知识正在从「提示词」变成「可安装能力包」
人工智能·openai