langchain教程-7.Embedding/文本向量化

前言

该系列教程的代码: https://github.com/shar-pen/Langchain-MiniTutorial

我主要参考 langchain 官方教程, 有选择性的记录了一下学习内容

这是教程清单

  • 1.初试langchain
  • 2.prompt
  • 3.OutputParser/输出解析
  • 4.model/vllm模型部署和langchain调用
  • 5.DocumentLoader/多种文档加载器
  • 6.TextSplitter/文档切分
  • 7.Embedding/文本向量化
  • 8.VectorStore/向量数据库存储和检索
  • 9.Retriever/检索器
  • 10.Reranker/文档重排序
  • 11.RAG管道/多轮对话RAG
  • 12.Agent/工具定义/Agent调用工具/Agentic RAG

OpenAI Embeddings

本教程探讨了在 LangChain 框架中使用 OpenAI 文本嵌入 模型。

展示如何为文本查询和文档生成嵌入,使用 PCA 降维,并将其可视化为 2D 图形以便更好地理解。

通过分析查询与文档之间的 余弦相似度,该教程提供了嵌入如何增强工作流的洞察,包括 文本分析数据可视化

from langchain_openai import OpenAIEmbeddings

# Set desired model
openai_embedding = OpenAIEmbeddings(
	model="bge-m3",
	base_url='http://localhost:9997/v1',
	api_key='cannot be empty',
	# dimensions=1024,
)

query_vector = openai_embedding.embed_query("What is the Open AI's gpt embedding model?")
query = "How does AI improve healthcare?"

# Various embedding models
documents = [
    "AI helps doctors diagnose diseases faster, improving patient outcomes.",
    "AI can analyze medical images to detect conditions like cancer.",
    "Machine learning predicts patient outcomes based on health data.",
    "AI speeds up drug discovery by predicting the effectiveness of compounds.",
    "AI monitors patients remotely, enabling proactive care for chronic diseases.",
    "AI automates administrative tasks, saving time for healthcare workers.",
    "NLP extracts insights from electronic health records for better care.",
    "AI chatbots help with patient assessments and symptom checking.",
    "AI improves drug manufacturing, ensuring better quality and efficiency.",
    "AI optimizes hospital operations and reduces healthcare costs."
]

embed 文本

query_vector = openai_embedding.embed_query(query)
docs_vector = openai_embedding.embed_documents(documents)

print("number of documents: " + str(len(docs_vector)))
print("dimension: " + str(len(docs_vector[0])))

# Part of the sliced ​​vector
print("query: " + str(query_vector[:5]))
print("documents[0]: " + str(docs_vector[0][:5]))
print("documents[1]: " + str(docs_vector[1][:5]))
number of documents: 10
dimension: 1024
query: [-0.008217299357056618, 0.05857884883880615, -0.015418872237205505, 0.02231411822140217, -0.028306419029831886]
documents[0]: [-0.04019297659397125, 0.020847423002123833, -0.019935578107833862, -0.03813512995839119, -0.04728339985013008]
documents[1]: [0.03994722664356232, 0.029537664726376534, -0.027887631207704544, -0.025838112458586693, -0.05827672779560089]

embed_queryembed_documents 没有根本的不同, 前者只是后者的特殊情况

    def embed_query(self, text: str) -> List[float]:
        """Call out to OpenAI's embedding endpoint for embedding query text.

        Args:
            text: The text to embed.

        Returns:
            Embedding for the text.
        """
        return self.embed_documents([text])[0]

相似度计算(余弦相似度)

这段代码通过余弦相似度计算查询与文档之间的相似度。
找出与查询最相似的前 3 个文档最不相似的 3 个文档

from sklearn.metrics.pairwise import cosine_similarity

# Calculate Cosine Similarity
similarity = cosine_similarity([query_vector], docs_vector)

# Sorting by in descending order
sorted_idx = similarity.argsort()[0][::-1]

# Display top 3 and bottom 3 documents based on similarity
print("query: ", query)
print("Top 3 most similar document:")
for i in range(0, 3):
    print(
        f"[{i+1}] similarity: {similarity[0][sorted_idx[i]]:.3f} | {documents[sorted_idx[i]]}"
    )

print("\nBottom 3 least similar documents:")
for i in range(1, 4):
    print(
        f"[{i}] similarity: {similarity[0][sorted_idx[-i]]:.3f} | {documents[sorted_idx[-i]]}"
    )
query:  How does AI improve healthcare?
Top 3 most similar document:
[1] similarity: 0.641 | AI monitors patients remotely, enabling proactive care for chronic diseases.
[2] similarity: 0.596 | AI chatbots help with patient assessments and symptom checking.
[3] similarity: 0.592 | AI automates administrative tasks, saving time for healthcare workers.

Bottom 3 least similar documents:
[1] similarity: 0.432 | Machine learning predicts patient outcomes based on health data.
[2] similarity: 0.485 | AI optimizes hospital operations and reduces healthcare costs.
[3] similarity: 0.503 | NLP extracts insights from electronic health records for better care.

使用向量点积进行相似度计算

  • 相似度通过向量的点积来确定。

  • 相似度计算公式:

similarities = q u e r y ⋅ d o c u m e n t s T \text{similarities} = \mathbf{query} \cdot \mathbf{documents}^T similarities=querydocumentsT


📐 向量点积的数学意义

向量点积的定义

两个向量 a \mathbf{a} a b \mathbf{b} b点积,在数学上定义为:

a ⋅ b = ∑ i = 1 n a i b i \mathbf{a} \cdot \mathbf{b} = \sum_{i=1}^{n} a_i b_i ab=i=1naibi


与余弦相似度的关系

点积余弦相似度也有关系,遵循以下性质:

a ⋅ b = ∥ a ∥ ∥ b ∥ cos ⁡ θ \mathbf{a} \cdot \mathbf{b} = \|\mathbf{a}\| \|\mathbf{b}\| \cos \theta ab=a∥∥bcosθ

其中:

  • ∥ a ∥ \|\mathbf{a}\| a ∥ b ∥ \|\mathbf{b}\| b 表示向量 a \mathbf{a} a b \mathbf{b} b模长范数, 特指欧几里得范数)。
  • θ \theta θ 是两向量之间的夹角
  • cos ⁡ θ \cos \theta cosθ 表示两向量之间的余弦相似度

🔍 向量点积在相似度计算中的解释

点积值很大(即一个较大的正值)时:

  • 两个向量的模长 ( ∥ a ∥ \|\mathbf{a}\| a ∥ b ∥ \|\mathbf{b}\| b) 很大。
  • 两个向量之间的夹角 ( θ \theta θ) 很小( cos ⁡ θ \cos \theta cosθ 接近 1)。

这表示两个向量指向相似的方向,并且语义上更为相似,特别是当它们的模长也较大时。


📏 向量的模长(范数)计算

欧几里得范数的定义

对于一个向量 a = [ a 1 , a 2 , … , a n ] \mathbf{a} = [a_1, a_2, \ldots, a_n] a=[a1,a2,,an],其欧几里得范数 ∥ a ∥ \|\mathbf{a}\| a 的计算方式为:

∥ a ∥ = a 1 2 + a 2 2 + ⋯ + a n 2 \|\mathbf{a}\| = \sqrt{a_1^2 + a_2^2 + \cdots + a_n^2} a=a12+a22++an2

这个模长表示向量在多维空间中的长度大小


理解这些数学基础有助于确保精确的相似度计算,进而在语义搜索检索系统推荐引擎等任务中提高性能。 🚀

import numpy as np


def search_similar_documents(q, docs, hf_embeddings):
    """
    Search for the most relevant documents based on a query using text embeddings.

    Args:
        q (str): The query string for which relevant documents are to be found.
        docs (list of str): A list of document strings to compare against the query.
        hf_embeddings: An embedding model object with `embed_query` and `embed_documents` methods.

    Returns:
        tuple:
            - embedded_query (numpy.ndarray): The embedding vector of the query.
            - embedded_documents (numpy.ndarray): The embedding matrix of the documents.
    """
    # Embed the query and documents using the embedding model
    embedded_query = hf_embeddings.embed_query(q)
    embedded_documents = hf_embeddings.embed_documents(docs)

    # Calculate similarity scores using dot product and normalize with the magnitudes
    query_norm = np.linalg.norm(embedded_query)
    document_norms = np.linalg.norm(embedded_documents, axis=1)

    # Calculate cosine similarity: dot product / (query norm * document norm)
    similarity_scores = (embedded_query @ embedded_documents.T) / (query_norm * document_norms)

    # Sort documents by similarity scores in descending order
    sorted_idx = similarity_scores.argsort()[::-1]

    # Display the results
    print(f"[Query] {q}\n" + "=" * 40)
    for i, idx in enumerate(sorted_idx):
        print(f"[{i}] {docs[idx]}")
        print()

    # Return embeddings for potential further processing or analysis
    return embedded_query, embedded_documents

嵌入可视化(PCA)

为了可视化的目的,减少嵌入的维度。
这段代码使用 主成分分析(PCA) 将高维嵌入向量降至 二维
生成的 二维点 在散点图中显示,每个点都标有对应文档的标签。

高维嵌入向量直接进行解读和分析非常具有挑战性。通过将它们降到二维,我们可以:

  • 可视化探索嵌入之间的关系(例如,聚类、分组)。
  • 识别数据中的模式或异常,这些模式在高维空间中可能不那么显眼。
  • 提高可解释性,使数据更加易于人类分析和决策。
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
import numpy as np

# Combine documents and query for PCA
all_vectors = np.vstack([docs_vector, query_vector])  # Stack query vector with docs
pca = PCA(n_components=2)
reduced_vectors = pca.fit_transform(all_vectors)

# Separate reduced vectors for documents and query
doc_vectors_2d = reduced_vectors[:-1]  # All but the last point (documents)
query_vector_2d = reduced_vectors[-1]  # Last point (query)

# Plot the reduced vectors
plt.scatter(doc_vectors_2d[:, 0], doc_vectors_2d[:, 1], color="blue", label="Documents")
plt.scatter(query_vector_2d[0], query_vector_2d[1], color="red", label="Query", marker="x", s=300,)

# Annotate document points
for i, doc in enumerate(documents):
    plt.text(doc_vectors_2d[i, 0], doc_vectors_2d[i, 1], doc, fontsize=8)

# Add plot details
plt.title("2D Visualization of Embedding Vectors with Query")
plt.xlabel("PCA Dimension 1")
plt.ylabel("PCA Dimension 2")
plt.legend()
plt.show()

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

from langchain_huggingface.embeddings import HuggingFaceEmbeddings

model_name = "../DataCollection/officials/bge-large-zh-v1.5"

hf_embeddings = HuggingFaceEmbeddings(
    model_name=model_name,
    model_kwargs={"device": 'cuda:1'},  # mps, cuda, cpu
    encode_kwargs={"normalize_embeddings": True},
)
vector = hf_embeddings.embed_query("Please tell me more about LangChain.")
print(len(vector))

vector = hf_embeddings.embed_documents([
    "Hi, nice to meet you.",
    "LangChain simplifies the process of building applications with large language models.",
    "The LangChain English tutorial is structured based on LangChain's official documentation, cookbook, and various practical examples to help users utilize LangChain more easily and effectively.",
    "LangChain simplifies the process of building applications with large-scale language models.",
    "Retrieval-Augmented Generation (RAG) is an effective technique for improving AI responses.",
])
print(len(vector))
print([len(item) for item in vector])
1024
5
[1024, 1024, 1024, 1024, 1024]

CacheBackedEmbeddings

嵌入值可以存储或临时缓存,以避免重新计算。

缓存嵌入值可以使用 CacheBackedEmbeddings 来完成。缓存支持的嵌入器是对嵌入器的包装,它将嵌入存储在一个键值存储中。文本被哈希处理,哈希值作为缓存中的键。

import os

os.makedirs("./cache/", exist_ok=True)
print(os.path.exists("./cache/"))  # Check if the directory exists
print(os.access("./cache/", os.W_OK))  # Check if the directory is writable
True
True

使用嵌入与本地文件存储(持久化存储)

初始化 CacheBackedEmbeddings 的主要支持方法是 from_bytes_store

它接受以下参数:

  • underlying_embeddings: 用于生成嵌入的嵌入器。
  • document_embedding_cache: 用于缓存文档嵌入的 ByteStore 实现之一。
  • namespace: (可选,默认值为 "")命名空间用于文档缓存。这样可以避免与其他缓存发生冲突。例如,可以将其设置为正在使用的嵌入模型的名称。

注意:设置 namespace 参数非常重要,以避免在使用不同的嵌入模型对相同文本进行嵌入时发生冲突。

首先,让我们看一个使用本地文件系统存储嵌入,并使用 FAISS 向量存储进行检索的例子。

from langchain.storage import LocalFileStore
from langchain_openai import OpenAIEmbeddings
from langchain.embeddings import CacheBackedEmbeddings
from langchain_community.vectorstores.faiss import FAISS

# Configure basic embeddings using OpenAI embeddings
underlying_embeddings = OpenAIEmbeddings(
	model="bge-m3",
	base_url='http://localhost:9997/v1',
	api_key='cannot be empty',
	# dimensions=1024,
)

# Set up a local file storage
store = LocalFileStore("./cache/")

# Create embeddings with caching support
cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings=underlying_embeddings, 
    document_embedding_cache=store, 
    namespace=underlying_embeddings.model, # Create a cache-backed embedder using the base embedding and storage
)

在 embedding 之前 cache 是空的

list(store.yield_keys())
[]

加载文档,将其拆分为多个块,对每个块进行嵌入,并将嵌入加载到向量存储中。

from langchain.document_loaders import TextLoader
from langchain_text_splitters import CharacterTextSplitter

raw_documents = TextLoader("./data/appendix-keywords.txt", encoding="utf-8").load()
text_splitter = CharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
documents = text_splitter.split_documents(raw_documents)

从文档创建 FAISS 数据库。

%time db = FAISS.from_documents(documents, cached_embedder)
CPU times: user 375 ms, sys: 43 ms, total: 418 ms
Wall time: 809 ms

如果我们尝试再次创建向量存储,它会更快,因为无需重新计算任何嵌入。

%time db2 = FAISS.from_documents(documents, cached_embedder)
CPU times: user 13.7 ms, sys: 1.04 ms, total: 14.7 ms
Wall time: 13.8 ms
list(store.yield_keys())[:5]
['bge-m34b802135-9b69-54ac-835f-f31f0a8f73cf',
 'bge-m34fd4987e-f5b6-52f8-91e2-886802754643',
 'bge-m3229c1600-8452-5938-b611-45db25315327',
 'bge-m3fed9c955-3b6d-5ce9-b7d2-235f35d18610',
 'bge-m39668cb63-4ad2-528c-9bf2-aecbfa54e1cd']

使用 InMemoryByteStore(非持久化)

要使用不同的 ByteStore,只需在创建 CacheBackedEmbeddings 时指定所需的 ByteStore

以下是使用非持久化的 InMemoryByteStore 创建相同缓存嵌入对象的示例。

from langchain.embeddings import CacheBackedEmbeddings
from langchain.storage import InMemoryByteStore

# Create an in-memory byte store
store = InMemoryByteStore()

underlying_embeddings = OpenAIEmbeddings(
	model="bge-m3",
	base_url='http://localhost:9997/v1',
	api_key='cannot be empty',
	# dimensions=1024,
)

cached_embedder = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings, store, namespace=underlying_embeddings.model
)
%time db = FAISS.from_documents(documents, cached_embedder)  
list(store.yield_keys())[:5]
CPU times: user 6.92 ms, sys: 905 μs, total: 7.82 ms
Wall time: 7.34 ms





['bge-m34b802135-9b69-54ac-835f-f31f0a8f73cf',
 'bge-m34fd4987e-f5b6-52f8-91e2-886802754643',
 'bge-m3229c1600-8452-5938-b611-45db25315327',
 'bge-m3fed9c955-3b6d-5ce9-b7d2-235f35d18610',
 'bge-m39668cb63-4ad2-528c-9bf2-aecbfa54e1cd']

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/965448.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Mac下使用brew安装go 以及遇到的问题

首先按照网上找到的命令进行安装 brew install go 打开终端输入go version,查看安装的go版本 go version 配置环境变量 查看go的环境变量配置: go env 事实上安装好后的go已经可以使用了。 在home/go下新建src/hello目录,在该目录中新建…

Ubuntu部署Deepseek-R1模型(8b)

安装ubuntu系统 本机电脑系统ubuntu-20.04 #升级软件 sudo apt-get update#安装curl sudo apt-get install curl通过以上两条指令,完成了curl命令的安装。 安装ollama 打开Ollama官网 选择Linux, 给出如上图方框所示的一条指令 curl -fsSL https:…

【ROS视频推流】使用web_video_server完成视频推流

🚀 本文简要介绍一下使用web_video_server功能包完成实时视频推流的方法。 假设有A,B两个设备,它们之间可以ping通。我们需要将A设备上的实时摄像头图像推流并在B设备的浏览器上显示。 🌔01准备工作 # A设备 # 下载视频推流功能包 #&#xff…

[LVGL] 在VC_MFC中移植LVGL

前言: 0. 在MFC中开发LVGL的优点是可以用多个Window界面做辅助扩展 1.本文基于VC2022-MFC单文档框架移植lvgl8 2. gitee上下载lvgl8.3 源码,并将其文件夹改名为lvgl lvgl: LVGL 是一个开源图形库,提供您创建具有易于使用的图形元素、漂亮…

Java----线程池

什么是线程池呢,先举一个情景: 一个火锅店开业了,早上人比较少,大家进店后不需要预约,直接付款在店里的桌子上吃饭,慢慢的人多了,店里的桌子不够用了,没座位的人可以先预约&#xf…

安卓开发,底部导航栏

1、创建导航栏图标 使用系统自带的矢量图库文件,鼠标右键点击res->New->Vector Asset 修改 Name , Clip art 和 Color 再创建一个 同样的方法再创建四个按钮 2、添加百分比布局依赖 app\build.gradle.kts 中添加百分比布局依赖,并点击Sync Now …

每日Attention学习22——Inverted Residual RWKV

模块出处 [arXiv 25] [link] [code] RWKV-UNet: Improving UNet with Long-Range Cooperation for Effective Medical Image Segmentation 模块名称 Inverted Residual RWKV (IR-RWKV) 模块作用 用于vision的RWKV结构 模块结构 模块代码 注:cpp扩展请参考作者原…

Git--使用教程

Git的框架讲解 Git 是一个分布式版本控制系统,其架构设计旨在高效地管理代码版本,支持分布式协作,并确保数据的完整性和安全性。 Git 的核心组件: 工作区(Working Directory): 工作区是你在本…

智慧停车系统:不同规模停车场的应用差异与YunCitys解决方案

在智慧停车领域,不同规模停车场因自身特点,对智慧停车系统的需求和应用效果存在显著差异。云创智城凭借丰富的经验和先进的技术,为各类规模停车场打造了贴合需求的智慧停车系统,下面为您详细剖析。 小型停车场:精准高…

snort的学习记录

一、what is snort?什么是snort? Snort 是一款开源的 网络入侵检测系统(NIDS) 和 网络入侵防御系统(NIPS),能够实时监控网络流量,检测恶意行为(如端口扫描、SQL注入、DDoS攻击等&a…

PHP-trim

[题目信息]: 题目名称题目难度PHP-trim1 [题目考点]: trim() 函数移除字符串两侧的空白字符或其他预定义字符。[Flag格式]: SangFor{dl9hFiITmhQNAJysCgigAskyCZ6kQaDc}[环境部署]: docker-compose.yml文件或者docker tar原始文件。 ht…

maven如何不把依赖的jar打包到同一个jar?

spring boot项目打jar包部署: 经过以下步骤, 最终会形成maven依赖的多个jar(包括lib下添加的)、 我们编写的程序代码打成一个jar,将程序jar与 依赖jar分开,便于管理: success: 最终…

【ArcGIS Pro 简介1】

ArcGIS Pro 是由 Esri (Environmental Systems Research Institute)公司开发的下一代桌面地理信息系统(GIS)软件,是传统 ArcMap 的现代化替代产品。它结合了强大的空间分析能力、直观的用户界面和先进的三维可视化技术…

DeepSeek 部署过程中的问题

文章目录 DeepSeek 部署过程中的问题一、部署扩展:docker 部署 DS1.1 部署1.2 可视化 二、问题三、GPU 设置3.1 ollama GPU 的支持情况3.2 更新 GPU 驱动3.3 安装 cuda3.4 下载 cuDNN3.5 配置环境变量 四、测试 DeepSeek 部署过程中的问题 Windows 中 利用 ollama 来…

Elasticsearch基本使用详解

文章目录 Elasticsearch基本使用详解一、引言二、环境搭建1、安装 Elasticsearch2、安装 Kibana(可选) 三、索引操作1、创建索引2、查看索引3、删除索引 四、数据操作1、插入数据2、查询数据(1)简单查询(2)…

点(线)集最小包围外轮廓效果赏析

“ 图像、点集、线集合最小外轮廓计算应用较为广泛,如抠图、神奇选择、LOD、碰撞检查等领域,提高场景效率” 1.前言 作者基于递归迭代求解实现点集的最小外轮廓计算,在CGLib库中实现,已集成于CGViewer,可联系作者试用&…

IOPS与吞吐量、读写块大小及延迟之间的关系

IOPS(每秒输入/输出操作次数)、吞吐量、读写块大小及延迟是衡量存储系统性能的四个关键指标,它们之间存在密切的关系。以下从多个方面详细说明这些指标之间的关系: 1. IOPS与吞吐量的关系 公式关系:吞吐量&#xff0…

FPGA与ASIC:到底选哪个好?

不少人想转行FPGA,但在ASIC和FPGA之间犹豫不决。要做出选择,首先需要清楚两者的区别和各自特点。 FPGA (Field Programmable Gate Array) 是一种现场可编程门阵列芯片,本质上它是一种半定制的芯片,可以根据需要重新编程&#xff…

LLMs之data:synthetic-data-generator的简介、安装和使用方法、案例应用之详细攻略

LLMs之data:synthetic-data-generator的简介、安装和使用方法、案例应用之详细攻略 目录 synthetic-data-generator的简介 1、核心功能和优势 2、特点 synthetic-data-generator的安装和使用方法 1、安装 pip安装 安装依赖项 运行应用 2、使用方法 快速入…

第二天:系统从BIOS/UEFI到GRUB/bootloader的启动过程

目录 **一、BIOS/UEFI初始化阶段****二、引导加载程序(GRUB)的启动过程****1. BIOS模式下的GRUB分阶段加载****2. UEFI模式下的GRUB加载** **三、操作系统内核加载与初始化****四、关键组件与配置文件****五、故障排查与恢复****总结**常见问题如何在UEF…