从零学RAG0x01之向量化

0 阅读4分钟

RAG回顾

image.png

回顾一下上次的RAG原理图,上次讲了RAG是怎么分分块的。分块之后存储之前还有重要的一步就是向量化。

向量化

  • 向量检索:根据用户的输入,与向量数据库中存放的文本向量进行相似度计算匹配,并检索返回最为相似的内容。

  • 向量化:文档分块后,每一个块都会被向量化为文档块向量

  • 向量模型:将现实世界中的非结构化数据(如文本、图像、音频)转化为机器能够理解和计算的、高维空间中的“数学点”(即向量)的技术框架和算法集合。它要解决的根本问题是弥合人类语义与计算机数值计算之间的鸿沟。

简单地讲,RAG技术需要将分块后文档块进行向量化,转换为机器可识别和理解的格式。这里可以结合之前Transformer里input环境的Embedding环节,这里目的可能不完全一样,但是手段原理有相同之处。

在线向量模型

每一个LLM厂商都有对应的Embedding模型,以通义千问为例:

image.png

这里我们做AI开发使用的LLM模型和Embedding模型必须是匹配的同一套,就是使用千问的LLM,RAG就必须使用千问的Embedding模型,而不是豆包的Embedding模型。

LLM模型很多集成了Embedding功能,我们直接调API即可。废话少说上代码。

# 创建 client: 默认通义千问
# 通义千问
client_qwen = OpenAI(api_key=os.getenv(ALI_TONGYI_API_KEY_OS_VAR_NAME),
                     base_url=ALI_TONGYI_URL)

# 嵌入模型
def get_embeddings(texts, model, dimensions=1024):
    #  texts: 是一个包含要获取嵌入表示的文本的列表,
    #  model: 则是用来指定要使用的模型的名称
    #  生成文本的嵌入表示。结果存储在data中。
    data = client_qwen.embeddings.create(input=texts, model=model, dimensions=dimensions).data
    print(data)
    print("-" * 100)

    # 返回了一个包含所有嵌入表示的列表
    return [x.embedding for x in data]

# 调用向量化函数返回向量数组
vec = get_embeddings(test_query, model=ALI_TONGYI_EMBEDDING_V4)

我们可以简单看下打印的结果:

image.png

一个模块被向量化为一个1024的向量数组,每个位置的值共同决定了这个文档块在机器世界的语义。是不是有点熟悉?像不像之前LLM对Token的向量化?

本地向量模型

Ollama

Ollama 是一个专为在本地快速部署和运行各种开源大型语言模型(LLM)而设计的工具。它的核心逻辑是“开箱即用”。简单地讲Ollama就好比LLM领域的”Docker“。

image.png

image.png

Ollama 安装后,模型下载渠道:

  • Ollama-Models 下载
  • 命令行下载:ollama pull qwen3-embedding:0.6b

📢:更多ollama用法可以在命令行使用 ollama help 查看

安装模型后,使用 ollama list 展示已经下载好的model:

image.png

本地部署

我们依然以通义千问的的Embedding模型为例,这里我们选择比较小的一个:qwen3-embedding:0.6b

image.png

  1. 本地创建一个Ollama客户端
# 创建Ollama客户端实例,本机服务
client = Client(host="http://127.0.0.1:11434")
# 或者更简单地使用默认值
client = Client() # 默认就是连接 http://127.0.0.1:11434

# 获取模型列表并打印端口和访问链接
models = client.list()

2. 调用Ollama客户端的embed函数

def get_embedding(text, model_name="qwen3-embedding:0.6b"):
    # 使用ollama库获取嵌入向量
    response = client.embed(model_name, text)
    embedding = response['embeddings']
    return embedding
    
vec = get_embedding(test_query) 

3. embed函数的另一种调用:直接使用Ollama类方法

# 使用ollama库获取嵌入向量
response = ollama.embed(model_name, text)

向量相似度

前面已经将文档转换为机器语义存储在机器里,那么当用户发起一个query,RAG是怎么将这个query和存储的文档向量关联起来呢?

这就需要用到向量相似度。query向量和某几个文档块向量越相似时,其相关性越大,那么这些文档块对query的贡献度也将更高。那么怎么计算向量相似度呢?目前有三种主流的方式。

  1. 余弦相似度Cosine:基于两个向量夹角的余弦值来衡量相似度。精度高,速度慢、消耗大(全量计算);适用小规模、高精度场景;越大越接近

  2. 欧式距离L2:通过计算向量之间的欧几里得距离来衡量相似度。直观,但高维度下易失效;越小越接近

  3. 点积:计算两个向量的点积,适合归一化后的向量。计算最快,但若向量未归一化处理,容易片偏离语义

image.png

至此,关于RAG的基础就基本差不多了。后续学习下向量数据库,就可以基本上手搞一个基于RAG的LLM项目了。