构建AI智能体:十五、超越关键词搜索:向量数据库如何解锁语义理解新纪元

简介: 向量数据库是专为存储和检索高维向量设计的新型数据库,通过Embedding技术将文本、图像等非结构化数据转化为向量,利用近似最近邻(ANN)算法实现语义级相似性搜索,广泛应用于AI推荐、语义搜索与智能问答,是大模型时代的关键基础设施。

一、前言

       在如今的数字时代,数据的形式正以前所未有的速度变得多样化。文本、图片、音频、视频等非结构化数据占据了数据总量的80%以上。传统数据库(如MySQL)擅长处理“张三的年龄是25岁”这类结构化数据,但对“一张有夕阳、狗和海滩的图片”或“一篇讨论量子计算前景的文章”却无能为力。

       我们可以轻松理解这些内容背后的含义和关联,但计算机需要一种方式来“理解”和“比较”它们。向量数据库(Vector Database) 就是专为解决这一问题而生的新型数据库,它是AI基础设施中至关重要的一环,被誉为AI应用的“长期记忆体”和“检索大脑”。

二、什么是向量数据库

       首先需要回顾一下向量和Embedding的含义,具体可以参考章节《构建AI智能体:十二、给词语绘制地图:Embedding如何构建机器的认知空间

向量:在AI和机器学习领域,向量是一组数字的有序列表,可以表示任何数据对象(如一段文字、一张图片)在高维空间中的位置。

嵌入(Embedding):通过AI模型(如BERT、CNN、CLIP等)将非结构化数据转换为向量的过程,称为“嵌入”。这个转换过程捕获了数据的深层语义特征。

示例:单词“国王”通过模型转换后,可能得到一个包含300个数字的向量。在数学上,这个向量与“男人”、“女王”、“女人”的向量存在某种关系(如“国王” - “男人” + “女人” ≈ “女王”)。

       向量数据库是一种专门用于存储、索引和查询高维向量的数据库。它的核心功能是执行近似最近邻(ANN)搜索,即快速找到与查询向量最相似的向量集合。

三、与传统数据库区别

特性 传统数据库 (SQL/NoSQL) 向量数据库
数据模型 结构化数据(行/列)、文档、键值对 高维向量
查询方式 精确匹配(WHERE age = 25)、范围查询 相似性搜索(找到与这个图片最像的10张图片)
索引技术 B树、哈希索引等 HNSW、IVF-PQ、LSH等专门为高维空间设计的ANN索引
核心能力 事务一致性、完整性 语义理解、相似性检索
适用场景 电商订单、用户信息管理等 AI推荐、语义搜索、图像识别等

四、向量数据库的核心原理

       在高维空间中(维度可达成百上千维),进行精确的最邻近搜索计算量极大,速度极慢。向量数据库使用近似最近邻(ANN)算法,在可接受的精度损失下,极大提升搜索速度。

  • 索引(Indexing):数据库不会暴力比对所有向量,而是预先构建索引,将向量组织成一种易于搜索的结构。
  • HNSW:像构建一个多层的高速公路网络,先从顶层进行粗粒度搜索,再逐层细化,快速逼近目标。
  • IVF-PQ:先将向量空间聚类成多个“单元”,搜索时只找最可能的几个单元。再用产品量化技术压缩向量,减少计算和存储开销。
  • 距离度量(Distance Metric):如何衡量两个向量的相似性?常用方法有:
  • 余弦相似度(Cosine Similarity):衡量向量方向上的差异,忽略其大小。非常适合文本数据。
  • 欧氏距离(Euclidean Distance):衡量向量在空间中的实际距离。
  • 点积(Dot Product):与余弦相似度相关,但也受向量大小影响。

扩展:通俗的介绍ANN算法

       想象一下,你是一个图书管理员,管理着一个有100万本书的图书馆。一个顾客问你:“请帮我找一本和《三体》最相似的书。”

  • 愚蠢但精确的方法(暴力搜索):你拿起《三体》,然后一页一页地和其他999,999本书逐字逐句地对比。这绝对能找到最相似的那本,但你找到的时候,顾客可能已经老了。这就像计算机中的精确最近邻搜索,结果完美,但速度慢到无法接受。
  • 聪明但近似的方法(ANN算法):你是一个聪明的管理员。你事先做了功课:你给书分了类(建立了索引):科幻区、文学区、历史区……你知道《三体》是科幻小说。你还给书贴了标签:有“外星人”、“物理学”、“悬疑”标签的书大概率在科幻区。当顾客提出同样的问题时,你不会去检查所有100万本书。你直接冲向科幻区,然后只在这个区的几千本书里快速寻找和《三体》最像的。你甚至可能只看了有“外星人”标签的那个书架。
  • 结果就是:你极快地找到了一本非常相似的书(比如《银河帝国》),但它是不是100万本中绝对最相似的那本?不一定。可能历史区有一本讲科学史的书某个角度也很像,但你忽略了它。

       这个“聪明的办法”就是 ANN 算法的核心思想:ANN(Approximate Nearest Neighbor),近似最近邻。它的精髓就是:用极高的效率(速度)和可接受的内存占用,换来一个“差不多”的、非常接近正确的搜索结果。它不保证找到的是绝对最近的,但能保证找到的是非常近的。

       为什么需要它? 因为在处理高维数据(比如图片、文本的1024维向量)时,暴力搜索的计算量是灾难性的,ANN 是唯一可行的解决方案。

五、常见的向量数据库

  1. Pinecone:全托管的云端向量数据库,以易用性、高性能和强大的API著称,是快速构建原型和应用的理想选择。
  2. Chroma:轻量级、开源,特别专注于AI原生应用和LLM(大语言模型)生态,易于集成和本地部署。
  3. Weaviate:开源向量搜索引擎,不仅支持向量搜索,还具备GraphQL接口,可以像图数据库一样处理数据对象之间的关系。
  4. Milvus / Zilliz Cloud:Milvus是开源领域功能最全面、最受欢迎的向量数据库之一,专为海量向量数据设计。Zilliz是其背后的商业公司,提供全托管云服务。
  5. Qdrant:一个用Rust编写的高性能、开源向量数据库和搜索引擎,提供丰富的API和云服务。
  6. FAISS:核心算法库,非数据库。由Meta AI开发。提供最广泛、最前沿的ANN索引算法。支持CPU和GPU。在内存中进行裸向量检索时速度极快,尤其是GPU版本,是衡量其他数据库性能的基准。

注意:FAISS是一个极其高效的向量相似性搜索库(Library),而不是一个完整的、功能齐备的数据库(Database)。FAISS 是 Facebook AI 团队开源的一个用于高效相似性搜索和密集向量聚类的库。它提供了大量的算法,针对不同的数据集大小和精度要求,可以组合出最优的索引和搜索方式。

六、向量数据库的运用

1. 将数据导入到向量数据库

  • 第一步:数据清洗与准备

确保原始数据(如文本文档、图片)的质量,进行必要的预处理。

  • 第二步:数据向量化(Embedding)

使用预训练的Embedding Model将原始数据转换成向量。

  • 文本:可使用bge-m, Qwen3-Embedding, Jina-Embedding 等模型。
  • 图片:可使用CLIP, ResNet等模型。

选择合适的模型至关重要,它直接决定了向量的质量和后续检索的效果。

  • 第三步:数据与元数据一同导入

将生成的向量及与其关联的元数据(Metadata)一同存入向量数据库。

  • 向量(Vector):生成的Embedding数字数组。
  • 唯一ID(ID):用于唯一标识每个数据点,方便后续的更新或删除。
  • 元数据(Metadata):描述向量的附加信息,是实现高级检索的关键。例如:文本来源的文件名、章节、URL、商品的类别、品牌、价格等

示例:指定模型将数据向量化

# 导入必要的库
import os  # 用于访问操作系统环境变量
from openai import OpenAI  # 导入OpenAI客户端库
# 初始化OpenAI客户端,配置为连接阿里云百炼服务
client = OpenAI(
    # 从环境变量DASHSCOPE_API_KEY获取API密钥,用于身份验证
    # 如果没有设置环境变量,可以在此直接替换为您的API密钥字符串(但不建议在代码中硬编码密钥)
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 指定API的基础URL,这里指向阿里云百炼服务的兼容模式端点
    # 这使得可以使用OpenAI库的标准格式调用阿里云的API服务
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)
# 创建文本嵌入向量
completion = client.embeddings.create(
    model="text-embedding-v4",  # 指定使用的嵌入模型版本
    input='我想知道迪士尼的退票政策',  # 输入需要转换为向量的文本内容
    # 指定生成的向量维度(长度),1024维是常见的选择
    # 此参数仅text-embedding-v3及更高版本支持
    dimensions=1024,
    # 指定向量值的编码格式为浮点数(float)
    # 这是最常用的格式,提供高精度表示
    encoding_format="float"
)
# 将API响应结果转换为JSON格式字符串并打印输出
# model_dump_json()方法将返回的对象序列化为JSON字符串
print(completion.model_dump_json())

执行步骤:

1. 导入必要的库:os 和 openai(需要安装openai库,如果使用百炼,需要确保版本支持)

2. 创建OpenAI客户端,指定api_key和base_url

3. 调用embeddings.create方法,传入模型名、输入文本、向量维度和编码格式

4. 将返回的嵌入对象转换为JSON字符串并打印

注意:

       这里我们使用 embeddings 模型 "text-embedding-v4",并指定维度为1024。 同时,我们打印出返回的JSON字符串。

返回结果:

{"data":[{"embedding":[0.0026341788470745087,-0.03762197867035866,-0.024403059855103493,-0.010764381848275661,0.01541021279990673,0.0007359159062616527,0.018554862588644028,-0.02278093248605728,-0.05350175499916077,0.023905038833618164,-0.02632400020956993,-0.009014192037284374,0.001929833902977407,0.0883917286992073,0.003021924290806055,0.015310607850551605,0.05139583349227905,-0.04928991198539734,-0.053074877709150314,
中间省略部分....
-0.004830809775739908,-0.0026359574403613806,-0.021955639123916626,0.01802838407456875,0.0019369485089555383,0.0010609639575704932,-0.01535329595208168,0.018014153465628624,-0.04493578150868416,0.0027284470852464437,-0.05347329378128052,-0.047639328986406326,-0.03625597432255745],"index":0,"object":"embedding"}],"model":"text-embedding-v4","object":"list","usage":{"prompt_tokens":8,"total_tokens":8},"id":"4f3c37d0-1b7b-99bb-ba7d-878b0e73a153"}

2. 将Embedding 和元数据一起存储在FAISS

  • FAISS 适合探索和实验,适合于数据不需要频繁更新的场景,同时拥有极致的向量搜索速度,且不需要复杂的元数据过滤;
  • FAISS 本身只存储和检索向量,不存储元数据,我们需要在FAISS 之外维护一个元数据的“查找表”,并通过向量在FAISS 中的唯一ID将两者关联起来。
  • 最直接有效的方法是使用FAISS 的IndexIDMap,允许我们为每个向量指定一个自定义的、唯一的64位整数ID。然后,可以用这个ID作为元数据存储的键。

示例:构建一个迪士尼政策权限相关的检索系统

  • 第一步:准备数据,创建示例文本和对应的元数据。
  • 第二步:生成向量,基于百炼text-embedding-v4 生成每个文本的向量。
  • 第三步:创建元数据存储,使用一个简单的Python 列表来存储元数据。列表的索引将作为每个数据点的唯一ID。
  • 第四步:构建FAISS 索引:
  • 使用faiss.IndexFlatL2 创建一个基础的索引,这里使用L2距离(欧氏距离)进行精确搜索。
  • 用faiss.IndexIDMap将基础索引包装起来,这样就可以添加带有自定义ID的向量了。
  • 第五步:添加数据到索引:将生成的向量和对应的ID(即元数据列表的索引)添加到IndexIDMap中。
  • 第六步:执行搜索:
  • 对一个新的查询文本生成向量。
  • 在FAISS 索引中搜索最相似的向量。
  • FAISS 会返回最相似向量的ID。
  • 第七步:检索元数据,使用返回的ID,从元数据存储中查找到原始文本和元数据。
import os
import numpy as np
import faiss
from openai import OpenAI
# Step1. 初始化 API 客户端
try:
    client = OpenAI(
        api_key=os.getenv("DASHSCOPE_API_KEY"),
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
    )
except Exception as e:
    print("初始化OpenAI客户端失败,请检查环境变量'DASHSCOPE_API_KEY'是否已设置。")
    print(f"错误信息: {e}")
    exit()
# Step2. 准备示例文本和元数据
# 在实际应用中,这些数据可能来自数据库、文件等
documents = [
    {
        "id": "doc1",
        "text": "迪士尼乐园的门票一经售出,原则上不予退换。但在特殊情况下,如恶劣天气导致园区关闭,可在官方指引下进行改期或退款。",
        "metadata": {"source": "official_faq_v1.pdf", "category": "退票政策", "author": "Admin"}
    },
    {
        "id": "doc2",
        "text": "购买“奇妙年卡”的用户,可以享受一年内多次入园的特权,并且在餐饮和购物时有折扣。",
        "metadata": {"source": "annual_pass_rules.docx", "category": "会员权益", "author": "MarketingDept"}
    },
    {
        "id": "doc3",
        "text": "对于在线购买的迪士尼门票,如果需要退票,必须在票面日期前48小时通过原购买渠道提交申请,并可能收取手续费。",
        "metadata": {"source": "online_policy.html", "category": "退票政策", "author": "E-commerceTeam"}
    },
    {
        "id": "doc4",
        "text": "园区内的“加勒比海盗”项目因年度维护,将于下周暂停开放。",
        "metadata": {"source": "maintenance_notice.txt", "category": "园区公告", "author": "OpsDept"}
    }
]
# Step3. 创建元数据存储和向量列表
# 我们使用一个简单的列表来存储元数据。列表的索引将作为FAISS的ID。
# 这种方式简单直接,适用于中小型数据集。
# 对于大型数据集,可以考虑使用字典或数据库(如Redis, SQLite)
metadata_store = []
vectors_list = []
vector_ids = []
print("正在为文档生成向量...")
for i, doc in enumerate(documents):
    try:
        # 调用API生成向量
        completion = client.embeddings.create(
            model="text-embedding-v4",
            input=doc["text"],
            dimensions=1024,
            encoding_format="float"
        )
        # 获取向量
        vector = completion.data[0].embedding
        vectors_list.append(vector)
        # 存储元数据,并使用列表索引作为唯一ID
        metadata_store.append(doc)
        vector_ids.append(i) # 自定义ID与列表索引一致
        print(f"  - 已处理文档 {i+1}/{len(documents)}")
    except Exception as e:
        print(f"处理文档 '{doc['id']}' 时出错: {e}")
        continue
# 将向量列表转换为NumPy数组,FAISS需要这种格式
vectors_np = np.array(vectors_list).astype('float32')
vector_ids_np = np.array(vector_ids)
# Step4. 构建并填充 FAISS 索引
dimension = 1024  # 向量维度
k = 3             # 查找最近的3个邻居
# 创建一个基础的L2距离索引
index_flat_l2 = faiss.IndexFlatL2(dimension)
# 使用IndexIDMap来包装基础索引,能够映射我们自定义的ID
# 这就是关联向量和元数据的关键!
index = faiss.IndexIDMap(index_flat_l2)
# 将向量和它们对应的ID添加到索引中
index.add_with_ids(vectors_np, vector_ids_np)
print(f"\nFAISS 索引已成功创建,共包含 {index.ntotal} 个向量。")
# Step5. 执行搜索并检索元数据
query_text = "我想了解一下迪士尼门票的退款流程"
print(f"\n正在为查询文本生成向量: '{query_text}'")
try:
    # 为查询文本生成向量
    query_completion = client.embeddings.create(
        model="text-embedding-v4",
        input=query_text,
        dimensions=1024,
        encoding_format="float"
    )
    query_vector = np.array([query_completion.data[0].embedding]).astype('float32')
    # 在FAISS索引中执行搜索
    # search方法返回两个NumPy数组:
    # D: 距离 (distances)
    # I: 索引/ID (indices/IDs)
    distances, retrieved_ids = index.search(query_vector, k)
    # Step6. 展示结果
    print("\n--- 搜索结果 ---")
    # `retrieved_ids[0]` 包含与查询最相似的k个向量的ID
    for i in range(k):
        doc_id = retrieved_ids[0][i]
        # 检查ID是否有效
        if doc_id == -1:
            print(f"\n排名 {i+1}: 未找到更多结果。")
            continue
        # 使用ID从我们的元数据存储中检索信息
        retrieved_doc = metadata_store[doc_id]
        print(f"\n--- 排名 {i+1} (相似度得分/距离: {distances[0][i]:.4f}) ---")
        print(f"ID: {doc_id}")
        print(f"原始文本: {retrieved_doc['text']}")
        print(f"元数据: {retrieved_doc['metadata']}")
except Exception as e:
    print(f"执行搜索时发生错误: {e}")

执行结果:

正在为文档生成向量...
-已处理文档1/4
-已处理文档2/4
-已处理文档3/4
-已处理文档4/4
FAISS 索引已成功创建,共包含4 个向量。
正在为查询文本生成向量: '我想了解一下迪士尼门票的退款流程'
---搜索结果---
---排名1 (相似度得分/距离: 0.3222) ---
ID: 2
原始文本: 对于在线购买的迪士尼门票,如果需要退票,必须在票面日期前48小时通过原购买渠道提交申请,并可能收取手续费。
元数据: {'source': 'online_policy.html', 'category': '退票政策', 'author': 'E-commerceTeam'}
---排名2 (相似度得分/距离: 0.3312) ---
ID: 0
原始文本: 迪士尼乐园的门票一经售出,原则上不予退换。但在特殊情况下,如恶劣天气导致园区关闭,可在官方指引下进行改期或退款。
元数据: {'source': 'official_faq_v1.pdf', 'category': '退票政策', 'author': 'Admin'}
---排名3 (相似度得分/距离: 1.0135) ---
ID: 1
原始文本: 购买“奇妙年卡”的用户,可以享受一年内多次入园的特权,并且在餐饮和购物时有折扣。
元数据: {'source': 'annual_pass_rules.docx', 'category': '会员权益', 'author': 'MarketingDept'}

距离越小表示越相近,越大表示越不相关;

七、总结

       向量数据库并非要取代传统数据库,而是对其能力的重要补充。它将数据从简单的字符和数字提升到了富含语义的数学表示,使计算机能够真正地“理解”和“联想”非结构化数据。随着生成式AI和大语言模型的爆发,向量数据库作为其记忆和知识检索的核心组件,正在成为现代AI技术栈中不可或缺的基础设施。

相关文章
|
23天前
|
存储 机器学习/深度学习 人工智能
构建AI智能体:十六、构建本地化AI应用:基于ModelScope与向量数据库的文本向量化
本文介绍了如何利用本地化部署的轻量级文本嵌入模型实现语义搜索。重点讲解了两种高效模型paraphrase-MiniLM-L6-v2和all-MiniLM-L6-v2的特点,它们通过知识蒸馏技术实现高质量语义表示,且体积小、速度快。文章详细演示了从ModelScope下载模型到本地、使用sentence-transformers库生成文本向量、构建FAISS索引进行相似性搜索的完整流程。通过Python代码示例展示了如何实现文档添加、查询处理和索引持久化功能,为构建本地化的语义搜索系统提供了实用解决方案。
255 0
构建AI智能体:十六、构建本地化AI应用:基于ModelScope与向量数据库的文本向量化
|
22天前
|
存储 人工智能 自然语言处理
构建AI智能体:十七、大模型的幻觉难题:RAG 解决AI才华横溢却胡言乱语的弊病
RAG(检索增强生成)是一种结合信息检索与大型语言模型的技术,旨在解决LLM的幻觉问题。其核心流程包括:离线处理阶段(知识库构建)和在线处理阶段(用户查询应答)。通过将外部知识源转换为向量存入数据库,当用户提问时,系统会检索相关内容并增强提示,再由LLM生成准确答案。RAG技术显著提升了AI在专业领域的可靠性,适用于智能客服、企业知识管理、内容创作等场景。尽管面临检索精度、多模态处理等挑战,RAG仍是AI实用化的重要突破方向。
231 2
|
25天前
|
机器学习/深度学习 人工智能 供应链
构建AI智能体:十四、从“计算”到“洞察”:AI大模型如何让时间序列数据“开口说话”
时间序列模型是分析和预测时序数据的核心工具,广泛应用于销量预测、趋势分析和异常检测。本文深入浅出地讲解其基本概念、组成成分(趋势、季节性、残差)、平稳性处理及主流模型如Holt-Winters和ARIMA,并结合代码实例展示建模全过程,帮助读者掌握从数据预处理到预测可视化的关键技能,实现数据驱动的科学决策。
352 6
|
21天前
|
存储 人工智能 自然语言处理
构建AI智能体:十八、解密LangChain中的RAG架构:让AI模型突破局限学会“翻书”答题
本文深入探讨了如何利用LangChain框架实现RAG(检索增强生成)架构,构建智能问答系统。文章首先介绍了RAG技术解决大模型知识更新和准确性问题的原理,以及LangChain作为开发框架提供的模块化组件。详细解析了LangChain的核心模块(模型、提示、索引、链等)和四种ChainType(stuff、map_reduce、refine、map_rerank)的特点与适用场景。通过一个完整的代码示例,展示了如何结合DeepSeek模型和FAISS向量数据库处理PDF文档,实现本地知识库问答功能
274 9
|
26天前
|
机器学习/深度学习 人工智能 自然语言处理
构建AI智能体:十三、大数据下的“搭积木”:N-Gram 如何实现更智能的语义搜索
N-gram是一种基于上下文的统计语言模型,通过前N-1个词预测当前词的概率,广泛应用于文本生成、输入法预测、语音识别等领域,具有简单高效、可解释性强的优点,是自然语言处理的基础技术之一。
268 10
|
27天前
|
机器学习/深度学习 人工智能 自然语言处理
构建AI智能体:十二、给词语绘制地图:Embedding如何构建机器的认知空间
Embedding是一种将词语、图像等信息转化为低维稠密向量的技术,使计算机能捕捉语义关系。不同于传统One-Hot编码,Embedding通过空间距离表达语义相似性,如“国王-男人+女人≈王后”,广泛应用于NLP、推荐系统与大模型中,是AI理解世界的基石。
407 13
|
2月前
|
人工智能 自然语言处理 前端开发
构建AI智能体:六、体验Trae指定Qwen-Turbo模型自动生成问答系统
本文介绍如何使用字节跳动的AI编程工具Trae与阿里通义千问Qwen-Turbo模型,快速生成一个智能问答系统。通过图文结合方式,演示从环境搭建、指令生成到界面优化的全过程,涵盖前后端代码自动生成、模型调用封装及交互优化技巧,展现AI辅助开发的高效与趣味,助力开发者提升生产力。
486 12
|
24天前
|
存储 人工智能 算法
AI时代数字营销的底层重构:于磊老师深度解析Geo未来发展趋势展望
随着AI技术重塑数字营销,生成式引擎优化(GEO)正取代传统SEO。本文结合15年经验专家于磊的洞察,探讨GEO未来发展趋势:以E-E-A-T构建内容权威,倡导人性化表达与生态规范化,反对黑帽行为,推动AI时代可持续、有温度的营销新范式。
212 8
|
20天前
|
存储 人工智能 JSON
构建AI智能体:十九、优化 RAG 检索精度:深入解析 RAG 中的五种高级切片策略
本文详细介绍了RAG(检索增强生成)系统中的文本切片策略。RAG切片是将长文档分割为语义完整的小块,以便AI模型高效检索和使用知识。文章分析了五种切片方法:改进固定长度切片(平衡效率与语义)、语义切片(基于嵌入相似度)、LLM语义切片(利用大模型智能分割)、层次切片(多粒度结构)和滑动窗口切片(高重叠上下文)。作者建议根据文档类型和需求选择策略,如通用文档用固定切片,长文档用层次切片,高精度场景用语义切片。切片质量直接影响RAG系统的检索效果和生成答案的准确性。
289 11
|
2月前
|
人工智能 测试技术 API
构建AI智能体:二、DeepSeek的Ollama部署FastAPI封装调用
本文介绍如何通过Ollama本地部署DeepSeek大模型,结合FastAPI实现API接口调用。涵盖Ollama安装、路径迁移、模型下载运行及REST API封装全过程,助力快速构建可扩展的AI应用服务。
605 6

热门文章

最新文章