当前位置: 首页 > news >正文

本地大模型编程实战(34)使用faiss实现语义检索

FAISS(Facebook AI Similarity Search)是 Facebook AI 研究院开发的一款高效的向量相似性搜索库,专门用于优化大规模高维向量的近邻搜索任务,广泛应用于语义检索、图像检索、推荐系统等场景。
本文将详细介绍如何使用 FAISS 实现语义检索。具体内容包括:

  • 将内容矢量化并保存为索引
  • 在保存索引的同时,保存每条信息的相关信息metadata
  • 通过矢量库进行语义检索

语义检索是一种基于内容含义(语义)而非表面关键词的信息检索技术,核心目标是让计算机 “理解” 用户查询的真实意图,从而返回含义相关的结果,而非仅匹配字面关键词的内容。
传统检索(如早期搜索引擎)依赖关键词匹配,例如用户搜索 “如何缓解头痛”,仅会返回包含 “缓解”“头痛” 等字面词汇的内容,若某篇文章写 “应对偏头痛的方法”(未出现 “缓解”“头痛”),则会被遗漏。
语义检索则通过语义嵌入(Embedding) 技术解决这一问题:

  • 将文本转化为 “语义向量”:用 AI 模型(如 BERT、BGE-M3 等)把用户的查询、待检索的文档(句子 / 段落)都转化为高维向量(类似 “数字指纹”),向量的相似度直接对应内容语义的相似度。
  • 通过向量相似度匹配结果:计算 “查询向量” 与 “文档向量” 的相似度(如余弦相似度),排序后返回相似度最高的内容,实现 “含义相关即匹配”。

数据结构设计

数据项中包含metadata,可以存储任何重要内容。

documents = [{"text": "人工智能是计算机科学的一个分支,研究如何使机器具有智能","metadata": {"id": "doc_001","category": "人工智能基础","source": "教科书","publish_date": "2023-01-15"}},{"text": "机器学习是人工智能的核心技术,让计算机能从数据中学习","metadata": {"id": "doc_002","category": "机器学习","source": "技术博客","publish_date": "2023-03-20"}},{"text": "深度学习是机器学习的一个子领域,基于人工神经网络","metadata": {"id": "doc_003","category": "深度学习","source": "论文","publish_date": "2023-02-10"}},{"text": "自然语言处理专注于让计算机理解和生成人类语言","metadata": {"id": "doc_004","category": "自然语言处理","source": "技术文档","publish_date": "2023-04-05"}},{"text": "计算机视觉是人工智能的一个重要方向,处理图像和视频","metadata": {"id": "doc_005","category": "计算机视觉","source": "教程","publish_date": "2023-01-28"}}
]

初始化模型和存储路径

model = SentenceTransformer('BAAI/bge-m3',cache_folder=Path("./model")    # 模型会下载到这个目录,第一次执行会下载模型,比较慢。
)
prefix = "为这个句子生成表示以用于检索相关句子:" # 定义存储路径
data_folder_path = Path("./data")
if not data_folder_path.exists():data_folder_path.mkdir(parents=True, exist_ok=True)
index_path = data_folder_path / "faiss_index_with_metadata.index"
metadata_path = data_folder_path / "metadata.json"

上面代码中有两个要点:
使用bge-m3 :因为在 中文检索/相似度匹配 场景中,bge-m3 远超 all-MiniLM-L6-v2
使用前缀 prefix
文本嵌入(Embedding)过程中添加特定前缀是指令微调(Instruction Tuning) 思想在嵌入模型中的应用,主要作用是引导模型生成更符合特定任务需求的向量表示,从而提升下游任务(如语义检索)的效果。
当一个模型需要同时支持多种任务时,前缀可以作为 “任务标识符”:

  • 检索任务:用"为检索生成表示:…"
  • 聚类任务:用"为聚类生成表示:…"
  • 问答匹配:用"为匹配问题和答案生成表示:…"

前缀的本质是通过自然语言指令引导模型聚焦任务需求,这是基于大语言模型时代的典型优化手段。对于 BGE-M3 这类支持指令微调的模型,使用官方推荐的前缀能显著提升检索效果;而对于早期不支持指令的模型(如原始 BERT),前缀可能无效甚至产生干扰。

生成数据库

下面使用 FAISS 生成嵌入数据库,并将其保存在本地文件夹中。

def process_documents(docs):# 提取文本并添加前缀texts = [prefix + doc["text"] for doc in docs]# 生成向量embeddings = model.encode(texts,normalize_embeddings=True).astype(np.float32)# 提取metadata列表(保持与向量顺序一致)metadatas = [doc["metadata"] for doc in docs]return embeddings, metadatasdef create_db():"""生成矢量库并保存"""if index_path.exists():print("数据库已创建")return# 处理文档生成向量和metadataembeddings, metadatas = process_documents(documents)print(f"向量形状: {embeddings.shape}")print(f"metadata数量: {len(metadatas)}")# 创建内积索引index = faiss.IndexFlatIP(embeddings.shape[1])index.add(embeddings)print(f"索引向量数量: {index.ntotal}")# 保存FAISS索引faiss.write_index(index, str(index_path))# 保存metadata(使用JSON格式)with open(metadata_path, "w", encoding="utf-8") as f:json.dump(metadatas, f, ensure_ascii=False, indent=2)print("\n数据保存完成:")print(f" - 索引: {index_path}")print(f" - Metadata: {metadata_path}")create_db()

保存json格式的metadata时,其顺序要与与向量顺序一致,这样在语义检索的时候,可以根据检索出来的矢量位置找到对应的 metadata 。

加载矢量库

与 metadata 一同加载。

def load_data():# 加载索引index = faiss.read_index(str(index_path))# 加载metadatawith open(metadata_path, "r", encoding="utf-8") as f:metadatas = json.load(f)print("\n数据加载完成:")print(f" - 索引向量数量: {index.ntotal}")print(f" - Metadata数量: {len(metadatas)}")return index, metadatasindex, metadatas = load_data()

语义检索

下面实现 FAISS语义检索 功能,在检索到最匹配文本的同时,也会找到关联的 metadata 。

def search_with_metadata(query, top_k=2):# 处理查询query_text = prefix + queryquery_embedding = model.encode([query_text],normalize_embeddings=True).astype(np.float32)# 搜索相似向量scores, indices = index.search(query_embedding, top_k)# 关联metadata并返回结果results = []for i in range(top_k):idx = indices[0][i]results.append({"score": float(scores[0][i]),"metadata": metadatas[idx],"text": documents[idx]["text"]  # 也可以从metadata中存储text})return results

我们用下面的代码做一下语义检索测试:

if __name__ == '__main__':    query = "什么是深度学习"results = search_with_metadata(query, top_k=2)print(f"\n查询: {query}")print("检索结果:")for i, result in enumerate(results, 1):print(f"\n结果 {i}:")print(f"相似度得分: {result['score']:.4f}")print(f"文本内容: {result['text']}")print(f"Metadata: {json.dumps(result['metadata'], ensure_ascii=False, indent=2)}")

执行上述代码后,将按照相似度高低返回两个结果:

结果 1:  
相似度得分: 0.8673
文本内容: 深度学习是机器学习的一个子领域,基于人工神经网络
Metadata: {"id": "doc_003","category": "深度学习","source": "论文","publish_date": "2023-02-10"
}结果 2:
相似度得分: 0.7643
文本内容: 机器学习是人工智能的核心技术,让计算机能从数据中学习
Metadata: {"id": "doc_002","category": "机器学习","source": "技术博客","publish_date": "2023-03-20"
}

靠谱,哈哈:)

总结

通过上面的演示,我们发现使用 FAISS 实现 语义检索 并不复杂,在 CPU 中运行速度也很快。


代码

本文涉及的所有代码以及相关资源都已经共享,参见:

  • github
  • gitee

为便于找到代码,程序文件名称最前面的编号与本系列文章的文档编号相同。

🪐感谢您观看,祝好运🪐


文章转载自:

http://4D9oRC0S.tmxfn.cn
http://AWLTALCl.tmxfn.cn
http://cTD5x0e8.tmxfn.cn
http://borK7NCt.tmxfn.cn
http://3Y6gKibK.tmxfn.cn
http://jDFaR40P.tmxfn.cn
http://PbIOwne3.tmxfn.cn
http://aVARNwM8.tmxfn.cn
http://jgSy2tf6.tmxfn.cn
http://01815Wgd.tmxfn.cn
http://kVKbLpJq.tmxfn.cn
http://YdAxDFBN.tmxfn.cn
http://7DJQ51kL.tmxfn.cn
http://wOq4obHe.tmxfn.cn
http://fzEeSGgh.tmxfn.cn
http://4w5zsoPg.tmxfn.cn
http://pjVxaaeq.tmxfn.cn
http://X6cSfxs1.tmxfn.cn
http://twGgzxDd.tmxfn.cn
http://Qxkcuww1.tmxfn.cn
http://BVFkP2Uj.tmxfn.cn
http://Y8WW7o46.tmxfn.cn
http://s8hQUiVY.tmxfn.cn
http://QDe2fJLX.tmxfn.cn
http://Wihrk7zz.tmxfn.cn
http://D7Egqt6i.tmxfn.cn
http://A2ZN8eHS.tmxfn.cn
http://9H6O4dAm.tmxfn.cn
http://vZ6Ms6ej.tmxfn.cn
http://2gL0Y7jg.tmxfn.cn
http://www.dtcms.com/a/388669.html

相关文章:

  • Linux:线程池
  • 告别依赖混乱:Spring IoC 容器与 DI 依赖注入入门精讲
  • Python爬虫实战——使用NetNut网页解锁器获取亚马逊电商数据的高级策略与实践
  • 黑马JavaWeb+AI笔记 Day11 Web后端实战(登录模块)
  • Nocobase如何优雅的设置动态的自定义存储路径
  • 线性回归与 Softmax 回归:深度学习基础模型及训练逻辑解析
  • 第四章:职业初印象:打造你的个人品牌(3)
  • 大模型学习:什么是FastText模型架构
  • 【人工智能通识专栏】第十八讲:作业辅导提升
  • Python Matplotlib 布局
  • PHP自动计算文件大小,如:KB、MB、TB等
  • K近邻:从理论到实践
  • 微服务高可用流程讲解
  • 云HIS系统,HIS源码,基于云计算技术的医院信息管理平台,采用B/S架构和微服务技术开发,支持SaaS应用模式。
  • 【卷积神经网络详解与实例】10——经典CNN之GoogLeNet
  • C# 委托和事件详解,委托 vs 方法封装解析
  • MariaDB源码编译安装
  • 多智能体编排之王:深度解析微软Semantic Kernel的AgentOrchestration架构革命
  • AI工具推荐之ezremove.ai
  • 关于Address Editor中修改基地址和地址空间的指南
  • 【Linux 系统探幽:从入门到内核・系统编程开篇】基础指令与权限精讲,筑牢系统开发根基
  • 【STL库】哈希封装 unordered_map/unordered_set
  • 【AI编程】Qoder AI 编程工具从部署到深度使用实战详解
  • 网络原理——数据链路层
  • 大语言模型的 “幻觉” 难题:技术成因、解决方案与应用风险规避
  • 状态保留功耗门控 SRPG (State Retention Power Gating)
  • Elman神经网络多输入多输出回归预测+SHAP可解释分析+新数据预测(MATLAB源码)
  • 408 王道数据结构的学习记录
  • 使用内存映射读取文件和写入文件,并进行性能测试
  • SQL的UNION用法大全介绍