DLAI-提示词压缩和优化笔记-全-
DLAI 提示词压缩和优化笔记(全)
001:课程介绍 🎯
在本节课中,我们将学习如何结合传统数据库的强大功能与向量搜索技术,以降低大型RAG(检索增强生成)应用程序的运营成本,并提升其效率。
课程概述
本课程由MongoDB合作构建,并由开发者倡导者Richmond Alake主讲。Richmond拥有丰富的机器学习架构师经验,并长期从事人工智能与机器学习的教学工作。课程将展示如何将成熟的数据库功能与向量搜索相结合,为构建高效、经济的RAG应用提供解决方案。
假设您正在构建一个帮助用户选择租赁房产的对话式RAG应用程序。用户可能会输入诸如“寻找位于安静街道上的一居室公寓”的查询。您可以使用语义搜索,通过将用户查询转化为向量嵌入,并在向量数据库中搜索与之最匹配的房源描述来找到相关结果。
然而,用户通常还会有明确的硬性要求,例如需要三间卧室、两间浴室,或者明确不要带游泳池的房产。这类精确的筛选条件更适合通过传统的数据库查询来处理,即根据数据库中明确存储的字段(如卧室数量、浴室数量)进行筛选。
在本课程中,您将学习如何同时利用这两个领域的优势:即结合了向量索引的传统数据库。在RAG应用中,检索到的结果会提供给大型语言模型进行最终处理。如果检索到的上下文信息非常冗长,会导致提示词过长,从而显著增加处理成本。
例如,如果每次检索返回约10,000个标记(tokens),而您的租赁比较网站每天需要处理一百万个查询,且大型语言模型输入标记的成本为每百万标记10美元,那么您每年的成本可能会超过3600万美元。因此,为了帮助您降低成本,本课程还将涵盖如何使检索结果尽可能精简且高度相关的方法。
核心技术简介
以下是您将在本课程中学到的一些关键技术。让我们继续以租赁应用程序为例进行说明。
预过滤与后过滤
根据卧室或浴室数量进行筛选,可以通过预过滤或后过滤来实现。
- 预过滤:在数据库索引创建阶段完成,效率更高。例如,如果您预知会频繁收到关于特定卧室数量房源的查询,可以预先构建包含“卧室数量”字段的索引。
- 后过滤:先执行向量搜索查询,得到初步结果后,再对这个结果集应用过滤器,筛选出符合硬性条件的子集。大规模应用程序可能会同时使用这两种技术。
字段投影
这是一种最小化返回数据大小的技术,它允许您选择从查询中返回的字段子集。
例如,一个房源可能包含15个字段,但您的应用可能只需要其中的三个:名称、卧室数量和价格。通过投影,您可以只请求这三个字段,减少不必要的数据传输和处理。
结果重排序
在利用房源描述的文本嵌入完成语义搜索后,您可以根据其他数据字段对结果进行重新排序。
例如,您可以结合平均星级或评价数量等字段,将更受欢迎或质量更高的结果排在列表前面,从而为大型语言模型生成更优质的上下文。

提示词压缩
如果检索到的信息非常冗长,将所有上下文都放入大型语言模型提示中会导致提示过长、处理成本高昂。
为了降低此成本,您可以在将最终提示发送给主大型语言模型之前,使用一个更小型、低成本的、经过微调的语言模型对提示进行压缩,只保留最核心的信息。
课程总结与致谢
综上所述,本课程提供了多种提高RAG应用相关性和节省成本的机会。在接下来的课程中,您将从实施一个基础的向量搜索开始,逐步学习并实践上述所有技术,最终以实施提示词压缩作为结束。
本课程的诞生离不开许多人的共同努力。特别感谢来自MongoDB的Apova Joshi、Pavel Dikovny、Prakul Agrawal、Jesse Hall、Rita Rodriguez、Henry Weller和Shupon Ranjan,以及来自dblend.ai的Eshmel Gargari所做出的贡献。

希望您能享受这门课程的学习过程!
002:基础向量搜索 🔍
在本节课中,我们将学习向量搜索的基础知识,并动手构建一个完整的检索增强生成(RAG)系统。我们将使用MongoDB作为向量数据库,Pydantic进行数据验证,并基于Airbnb房源数据集创建一个推荐系统。

概述:从关键词匹配到语义搜索
互联网上存在海量数据。比较数据点之间相似性或接近程度有多种方法。一种常见方法是文本搜索,即将查询关键词与数据点内容的部分进行匹配以计算匹配度。

这本质上是信息检索:输入一个关键词或搜索词,与多个数据点进行匹配,并检测关键词是否在内容中。现在,我们将学习如何根据数据的上下文或意义来检索数据。
向量搜索基础

数据向量化
第一步是收集数据。数据可以是结构化数据,如在具有定义列的表格或电子表格中组织的数据;也可以是非结构化数据,如音频和图像数据。

下一步涉及将数据作为输入传递给嵌入模型。嵌入模型的输出是一个向量。此时,原始数据已经被向量化,留下了捕捉数据上下文和语义的数字表示。这被称为向量嵌入。
在一个高维空间(称为向量空间)中,可以比较两个或更多嵌入向量之间的距离,以获得它们在语义或上下文方面的接近程度的指示。

向量搜索与传统搜索
到目前为止,我们理解了向量搜索是一种使用数据的数字表示(称为向量嵌入)来搜索和检索信息的信息检索技术。我们也明白,传统上,信息检索依赖于关键词匹配,即搜索查询文本与数据集中文本之间的直接匹配。
然而,向量搜索利用这些嵌入来实现高级功能,例如:
- 语义搜索:理解查询的上下文。
- 推荐系统:预测用户偏好。
- 检索增强生成(RAG):为大型语言模型输入提供额外上下文。

这些能力使向量搜索在各种人工智能应用中成为强大的工具。
向量数据库与索引

一旦收集了结构化和非结构化的数据并将其编码为向量嵌入,就需要将向量化的数据存储到一个专门的数据存储中,称为向量数据库。

在向量数据库中,为了确保基于向量搜索查询高效检索向量数据,最佳实践是对向量数据进行索引。向量搜索索引是一种专门的结构,它优化了向量嵌入的存储和检索,允许进行高效的相似性搜索。
因此,当执行向量搜索操作时,该索引有助于查询向量与数据集的高效匹配,减少找到最相似向量所需的时间。这就引出了检索增强生成系统中的向量搜索。
检索增强生成(RAG)简介

检索增强生成(RAG)是一种系统设计模式,它利用信息检索技术(包括向量搜索)和基础模型,为用户查询提供准确和相关的响应。
RAG通过检索语义相似的数据来为用户查询补充额外上下文,然后将检索到的信息与原始查询结合,作为输入传递给大型语言模型来实现这一点。
例如,使用聊天界面的一个典型过程是:输入聊天内容,然后从大型语言模型获得回应。这不是理想的过程,因为这没有使用任何相关数据。

理想的过程应该是:在向大型语言模型输入时,添加相关的特定领域数据,这样大型语言模型就可以为查询提供相关且有上下文感知的回应。

RAG的优势
现在我们已经了解了检索增强生成,让我们概述一下RAG设计模式对大型语言模型应用的关键好处。
构建利用RAG系统设计模式的人工智能应用提供了许多好处:
- 减少幻觉:将大型语言模型的回应建立在相关和最新的信息基础上,减少模型提供错误或不相关信息的机会。
- 减少输入量:通过RAG,可以减少作为输入传递给大型语言模型的信息量,从而减少传递到上下文窗口的上下文。
- 避免微调:在某些情况下,不再需要微调大型语言模型。
- 利用私有数据:使用RAG,可以利用自己的私有数据或特定领域数据来确保大型语言模型的回应满足特定的要求和需求。

MongoDB:作为向量数据库

现在我们知道,当补充相关上下文时,大型语言模型会给出更好的答案。你可能会想知道在哪里以及如何存储这些数据,以及如何实现信息检索的向量搜索。这就是MongoDB发挥作用的地方。

MongoDB是一个开发者数据平台,提供具有向量搜索功能的NoSQL数据库。在人工智能应用中,MongoDB可以作为向量数据的存储解决方案,充当向量数据库。MongoDB还提供了更多功能,可作为操作和事务数据的数据存储,使其成为LLM和AI应用(包括RAG和智能系统)的强大内存提供者。
文档数据模型

你可能熟悉传统的关系型数据库。让我们用房子的数据存储来举例说明关系型数据库是如何工作的。在典型的关系型数据库中,可能会在一个表上存储房子的房间数和浴室数等信息,而在另一个表上存储房子的地址信息。


在文档模型中,根据应用程序上发生的交互来建模数据,而不是相反。

什么是文档?
在MongoDB中,文档是类似于JSON的基本数据单元。每个文档是一组键值对,这在MongoDB中相当于关系型数据库中的一行。

以房子为例,我们把房子的所有属性都分配在一个文档中,包括它的地址。这是MongoDB中的一个文档示例。文档是动态的,这意味着它们可以在同一集合中包含不同的字段和结构。非关系型数据库中的集合类似于关系型数据库中的表。


文档模型使用JSON模式,这是技术栈各层的核心数据模型。例如,JSON有助于在应用层的网站部分和REST API之间传输数据,并在实现智能体时用于模型层的函数调用和工具定义。MongoDB能够实现灵活的字段和值数据存储,并能够存储不同的数据类型。


数据建模与聚合管道
为确保文档结构合理,应考虑数据建模。数据建模涉及设计文档和集合的结构,以有效表示和组织数据。这关乎规划如何在文档间存储和链接数据,以优化性能、可扩展性以及应用程序的特定数据访问模式。


有时,应用程序的组件布局由数据库中数据的结构和格式决定。这表示根据数据层中的信息实现应用层。但理想情况下,应首先从应用程序需求开始,而不是数据本身。必须问:“我将如何访问我的数据?”而这应该决定将如何建模数据结构。

MongoDB能够使用对“管道”的熟悉理解,这在数据处理或机器学习概念中存在。可以将管道概念应用于数据库层内的想法。使用MongoDB进行查询时,构建一个聚合管道。
可以将聚合管道视为一系列数据处理阶段,其中每个阶段在数据通过时对其进行转换。这个过程允许在MongoDB中进行复杂的查询组合,因为在管道内有各种数据转换阶段。


聚合管道示例:
假设正在管理来自社交媒体应用程序的数据,其中有一系列用户帖子。想找到2021年1月根据点赞数定义的最热门帖子。也许对按类别汇总每个帖子的平均评论数和点赞数感兴趣。

这个聚合管道会:
- 过滤出2021年1月的帖子。
- 按类别进行分组。
- 计算平均点赞数和评论数。
- 按平均点赞数降序排列结果。


通过使用聚合管道,可以利用对机器学习和人工智能管道中顺序操作的理解,并将类似逻辑应用于在MongoDB中管理和分析数据,使复杂查询变得相当容易理解和管理。
Pydantic:数据验证与管理


在人工智能应用中,需要进行数据验证并确保数据符合特定模型。这降低了生产系统中出现错误的可能性。Pydantic是一个用于数据验证、建模和管理的Python库。

Pydantic提供的功能允许创建包含对象及其属性定义的数据模式。Pydantic还确保数据符合定义的模式、数据类型、格式和约束。如果数据模式不符合验证标准,Pydantic通过引发详细说明具体验证问题的异常来处理错误。

实战:构建Airbnb RAG推荐系统


在我们深入编码之前,让我们回顾一下数据集。它由托管在Hugging Face上的5000个Airbnb房源组成,包含地址、描述、交通、评论和意见等细节。

对于本课程,将使用它基于RAG技术构建一个Airbnb房源推荐系统。每条记录或数据点包括列表照片的图像嵌入和来自空间属性内容的文本嵌入。空间属性中的信息已由OpenAI text-embedding-ada-002 模型处理。

项目步骤概述

以下是我们在本节课的编码部分要采取的步骤:
- 从Hugging Face加载数据。
- 建立数据库连接以访问数据库和集合。
- 向集合插入数据(数据摄取)。
- 使用查询嵌入和集合内的嵌入进行向量搜索查询。
- 处理用户查询并可视化响应。

系统预期输出

在本节课中,将构建一个使用向量搜索从向量数据库中提取相关结果,并将其作为额外上下文添加到大型语言模型的RAG推荐系统。
系统将展示:
- 向量搜索查询的执行时间。
- 用户问题和系统响应(来自LLM的响应,包含推荐列表及原因)。
- 一个属性表格,显示作为额外上下文传递给LLM的数据(包括名称、可容纳人数、地址等),针对所有从向量搜索查询中检索到的信息。

代码实现

1. 环境设置与库导入

import os
from datasets import load_dataset
import pandas as pd
from pydantic import BaseModel, Field
from datetime import datetime
from pymongo import MongoClient
from pymongo.operations import SearchIndexModel
from openai import OpenAI
import time
2. 加载数据集

# 从Hugging Face加载Airbnb嵌入数据集
dataset = load_dataset("abidlabs/airbnb-embeddings", split="train", streaming=True)
# 取5000个数据点并转换为Pandas DataFrame
dataset = dataset.take(5000)
df = pd.DataFrame(dataset)
# 查看前5个数据点
print(df.head())

3. 使用Pydantic进行数据建模

# 定义数据模型
class Host(BaseModel):
host_id: str
host_name: str
host_location: str | None
host_response_time: str | None
class Location(BaseModel):
type: str = "Point"
coordinates: list[float]

class Address(BaseModel):
street: str
suburb: str
government_area: str
market: str
country: str
country_code: str
location: Location
class Review(BaseModel):
_id: str
date: datetime
listing_id: str
reviewer_id: str
reviewer_name: str
comments: str | None
class Listing(BaseModel):
_id: str
listing_url: str
name: str
summary: str | None
space: str | None
description: str | None
neighborhood_overview: str | None
notes: str | None
transit: str | None
access: str | None
interaction: str | None
house_rules: str | None
property_type: str
room_type: str
bed_type: str
minimum_nights: str
maximum_nights: str
cancellation_policy: str
last_scraped: datetime
calendar_last_scraped: datetime
first_review: datetime | None
last_review: datetime | None
accommodates: int
bedrooms: int | None
beds: int | None
number_of_reviews: int
bathrooms: float | None
amenities: list[str]
price: float
security_deposit: float | None
cleaning_fee: float | None
extra_people: float
guests_included: int
images: dict
host: Host
address: Address
availability: dict
review_scores: dict
reviews: list[Review]
text_embeddings: list[float]

# 将数据转换为Listing对象列表
records = df.to_dict('records')
listings = [Listing(**record).dict() for record in records]
print(listings[0]) # 查看第一个房源

4. 连接MongoDB数据库


# 设置数据库和集合名称
DATABASE_NAME = "airbnb_dataset"
COLLECTION_NAME = "listings_reviews"

def get_mongo_client(mongo_uri):
"""创建并返回MongoDB客户端"""
return MongoClient(mongo_uri, appname="rag-course")

# 从环境变量获取URI并连接
MONGO_URI = os.getenv("MONGODB_URI")
client = get_mongo_client(MONGO_URI)
db = client[DATABASE_NAME]
collection = db[COLLECTION_NAME]
# 清理现有集合(首次运行可跳过)
collection.delete_many({})

5. 数据摄取

# 将数据插入MongoDB集合
result = collection.insert_many(listings)
print(f"插入了 {len(result.inserted_ids)} 个文档")
6. 创建向量搜索索引

# 定义向量搜索索引
text_embedding_field_name = "text_embeddings"
vector_search_index_name_text = "vector_index_text"
vector_search_model = SearchIndexModel(
definition={
"fields": [
{
"type": "vector",
"path": text_embedding_field_name,
"numDimensions": 1536, # OpenAI ada-002的维度
"similarity": "cosine",
}
]
},
name=vector_search_index_name_text,
)

# 创建索引
collection.create_search_index(vector_search_model)
print("向量搜索索引创建成功。等待索引初始化...")
time.sleep(60) # 等待索引就绪


7. 定义嵌入生成函数


# 初始化OpenAI客户端
openai_client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

def get_embedding(text):
"""使用OpenAI生成文本嵌入"""
if not isinstance(text, str):
raise ValueError("输入必须是字符串")
response = openai_client.embeddings.create(
model="text-embedding-ada-002",
input=text
)
return response.data[0].embedding

8. 构建向量搜索函数
def vector_search(query, db, collection, vector_index_name="vector_index_text"):
"""执行向量搜索"""
# 将查询转换为嵌入
query_embedding = get_embedding(query)
# 定义向量搜索阶段
vector_search_stage = {
"$vectorSearch": {
"index": vector_index_name,
"queryVector": query_embedding,
"path": text_embedding_field_name,
"numCandidates": 100,
"limit": 20
}
}
# 构建聚合管道
pipeline = [vector_search_stage]
# 执行搜索
start_time = time.time()
results = list(collection.aggregate(pipeline))
search_time = (time.time() - start_time) * 1000 # 转换为毫秒
print(f"向量搜索耗时: {search_time:.2f} 毫秒")
return results

9. 处理用户查询与RAG集成
# 定义搜索结果模型
class SearchResultItem(BaseModel):
name: str
accommodates: int
address: dict
summary: str | None
price: float
property_type: str

def handle_user_query(query, db, collection):
"""处理用户查询:RAG全流程"""
# 1. 向量搜索获取相关知识
knowledge = vector_search(query, db, collection)
if not knowledge:
return "未找到相关房源信息。"
# 2. 格式化搜索结果
search_results = [SearchResultItem(**doc) for doc in knowledge]
results_df = pd.DataFrame([item.dict() for item in search_results])
# 3. 构建LLM提示词
context = results_df.to_string()
prompt = f"""
你是一个Airbnb房源推荐系统。根据以下房源信息,回答用户的问题。
用户查询: {query}
相关房源信息:
{context}
请推荐最符合用户需求的房源,并说明推荐理由。
如果信息不足,请如实告知。
"""
# 4. 调用LLM生成回复
response = openai_client.chat.completions.create(
model="gpt-3.5-turbo",
messages=[
{"role": "system", "content": "你是一个专业的Airbnb旅行顾问。"},
{"role": "user", "content": prompt}
],
temperature=0.7
)
system_response = response.choices[0].message.content
# 5. 打印结果
print("="*50)
print(f"用户查询: {query}")
print(f"系统响应: {system_response}")
print("="*50)
print("\n用于生成回复的房源信息:")
print(results_df[['name', 'accommodates', 'property_type', 'price']].to_string())
return system_response

10. 运行系统
# 测试查询
query = "推荐一个温暖友好、离餐馆不太远的Airbnb房源"
response = handle_user_query(query, db, collection)

总结

在本节课中,我们一起学习了:
- 向量搜索原理:理解了如何将数据转换为向量嵌入,并通过计算向量间距离实现语义搜索。
- RAG系统架构:掌握了检索增强生成如何结合向量搜索与大型语言模型,提供基于上下文的精准回答。
- MongoDB向量数据库:学会了使用MongoDB存储和索引向量数据,并执行高效的向量搜索查询。
- Pydantic数据验证:使用Pydantic库确保数据质量,为AI应用提供可靠的数据基础。
- 实战项目:构建了一个完整的Airbnb房源RAG推荐系统,实现了从数据加载、向量搜索到LLM集成的全流程。

通过本节课,你已经掌握了构建基础RAG系统的核心技能。在下一节课中,我们将探索如何在向量搜索操作中添加过滤(包括前置过滤和后置过滤),使推荐系统更加精准和高效。
003:使用元数据进行过滤 🎯

在本节课中,我们将学习如何使用元数据来优化MongoDB的向量搜索查询。我们将构建一个多阶段的聚合管道,通过后过滤和前过滤技术,利用元数据来细化和限制搜索结果,从而提高检索的效率和相关性。

概述

元数据是关于数据的额外信息,它为关键数据点提供了更多上下文。在大型语言模型应用和检索增强生成(RAG)模式中,元数据可以增强嵌入数据的上下文,并通过过滤和排序来提高向量搜索查询的相关性。

什么是元数据?
元数据旨在补充一个关键数据点并提供更多上下文。例如,蒙娜丽莎的图像是关键数据,其向量嵌入可以代表图像本身。而标题、艺术家姓名、位置等信息则可以作为元数据添加到图像嵌入中。

关键数据 + 元数据 = 单个MongoDB文档

通过将向量嵌入与元数据配对,整体数据变得更具信息量和有用性。

元数据如何提升搜索?
在RAG设计模式中,元数据主要有两个作用:
- 为嵌入数据添加额外上下文,以提高模型对内容的理解和相关性判断。
- 通过基于数据属性(即元数据)进行过滤和排序,来缩小向量搜索的范围或优化其结果。
为了简化操作并提高结果的相关性,我们将在MongoDB的聚合管道中,将过滤阶段与向量搜索阶段组合使用。聚合管道使得创建和实现复杂的可组合查询变得更加容易。

过滤技术:后过滤与前过滤

上一节我们介绍了元数据的概念,本节中我们来看看两种核心的过滤技术。
以下是两种主要的过滤方法:
后过滤
在后过滤中,我们先对完整数据集执行向量搜索,以获得与用户查询语义相似的结果。然后,在向量搜索阶段之后应用一个过滤阶段,根据指定的元数据标准(如位置、容量)进一步减少返回的结果。
流程:完整数据集 → 向量搜索 → 过滤 → 最终结果

前过滤
在前过滤中,流程则相反。我们首先对数据集应用过滤操作,去除不符合元数据标准的结果。然后,仅对这个过滤后的数据子集进行向量搜索。
流程:完整数据集 → 过滤 → 向量搜索 → 最终结果
关键区别:前过滤在进行向量搜索之前就缩小了数据集,这可能会提高搜索效率,但也存在风险:一些在语义上与查询相似但不符合过滤条件的文档,将完全不会被纳入搜索范围,从而导致潜在的相关信息丢失。

实践:构建带过滤的RAG管道


了解了理论之后,现在让我们动手编写代码,实际构建一个结合过滤功能的RAG管道。

1. 准备环境与数据
首先,我们需要导入必要的模块并加载数据。我们使用一个自定义工具模块来简化流程。


# 导入自定义工具模块
from utils import process_records, connectToDatabase, setupVectorSearchIndex

# 加载并处理数据集
data_points = process_records(loaded_dataset) # 返回符合数据模型的Python列表


# 连接数据库
db, collection = connectToDatabase()

# 清空集合(为实验做准备)
delete_result = collection.delete_many({})
print(f"已删除 {delete_result.deleted_count} 个文档。")


# 将数据插入集合
collection.insert_many(data_points)
print("数据摄入完成。")

2. 创建向量搜索索引
接下来,我们需要为集合创建向量搜索索引,这是进行语义搜索的基础。
# 设置向量搜索索引
index_name = setupVectorSearchIndex(collection)
3. 基础向量搜索查询
我们定义一个基础的向量搜索函数,它将用户查询转换为向量,并在数据库中执行搜索。

def vector_search(user_query, db, collection, index_name):
# 将用户查询转换为嵌入向量
query_embedding = get_embedding(user_query)
# 构建聚合管道
pipeline = [
{
"$vectorSearch": {
"index": index_name,
"path": "embedding_field",
"queryVector": query_embedding,
"numCandidates": 150,
"limit": 20
}
}
]
# 执行搜索并计时
start_time = time.time()
results = list(collection.aggregate(pipeline))
elapsed_time = time.time() - start_time
print(f"向量搜索耗时: {elapsed_time:.4f} 秒")
return results

4. 处理后过滤查询
现在,我们来实现后过滤。在向量搜索之后,添加一个$match阶段来过滤结果。
以下是后过滤的实现步骤:

- 定义过滤路径:指定要基于哪个元数据字段进行过滤(例如,
address.country)。 - 创建匹配阶段:使用
$match操作符定义过滤条件(例如,国家为“美国”,容纳人数在1到5人之间)。 - 修改管道:在向量搜索阶段后添加这个
$match阶段。


# 定义过滤路径和条件
search_path = "address.country"
filter_criteria = {
search_path: "United States",
"accommodates": {"$gt": 1, "$lt": 5}
}

# 创建额外的匹配阶段(后过滤)
additional_stage = {"$match": filter_criteria}
# 修改向量搜索函数以支持后过滤
def vector_search_with_postfilter(user_query, db, collection, index_name, extra_stage=None):
query_embedding = get_embedding(user_query)
pipeline = [
{
"$vectorSearch": {
"index": index_name,
"path": "embedding_field",
"queryVector": query_embedding,
"numCandidates": 150,
"limit": 20
}
}
]
if extra_stage:
pipeline.append(extra_stage) # 添加后过滤阶段
results = list(collection.aggregate(pipeline))
return results
# 执行带后过滤的查询
user_query = “寻找一个温暖、友好且离餐厅不远的地方。”
postfilter_results = vector_search_with_postfilter(user_query, db, collection, index_name, additional_stage)
执行后,返回的文档将仅限于来自美国且容纳人数在1-5之间的房源。

5. 实现前过滤查询
最后,我们来实现前过滤。这需要在向量搜索阶段内部定义过滤条件,以便在搜索执行前就应用过滤。
以下是前过滤的实现步骤:

- 创建支持过滤的索引:为了高效执行,可以为过滤字段创建复合索引(可选,但推荐)。
- 修改向量搜索阶段:在
$vectorSearch参数中直接加入filter条件。 - 定义新的搜索函数:该函数在搜索前就通过
filter字段限制数据集。

# 首先,创建一个新的支持过滤的向量搜索索引(可选)
filtered_index_name = “vector_index_with_filter”
# ... 创建索引的代码 ...

# 定义带前过滤的向量搜索函数
def vector_search_with_prefilter(user_query, db, collection, index_name):
query_embedding = get_embedding(user_query)
pipeline = [
{
"$vectorSearch": {
"index": index_name,
"path": "embedding_field",
"queryVector": query_embedding,
"numCandidates": 150,
"limit": 20,
"filter": { # 前过滤在此发生
"$and": [
{"accommodates": {"$gt": 1, "$lt": 5}},
{"bedrooms": {"$lte": 7}}
]
}
}
}
]
results = list(collection.aggregate(pipeline))
return results

# 执行带前过滤的查询
prefilter_results = vector_search_with_prefilter(user_query, db, collection, filtered_index_name)
使用前过滤后,向量搜索仅处理那些满足容纳人数和卧室数量条件的文档子集,返回的结果也会严格符合这些条件。

结果对比与总结

本节课中,我们一起学习了如何利用元数据对向量搜索进行过滤优化。


- 后过滤:先进行广泛的语义搜索,再过滤结果。可能丢失那些语义相关但不符合过滤条件的文档。在我们的例子中,请求20个文档,但过滤后只返回了4个。
- 前过滤:先根据元数据严格筛选数据集,再进行语义搜索。搜索效率更高,结果始终符合过滤条件,但可能无法发现过滤条件之外的潜在相关项。它返回了我们请求的20个文档。

总结:选择后过滤还是前过滤,取决于你的应用场景。如果确保结果完全符合硬性约束(如法规、价格范围)至关重要,则前过滤更合适。如果你想先最大化语义相关性,再根据次要属性进行筛选,则后过滤是更好的选择。通过将元数据与MongoDB强大的聚合管道结合,你可以构建出既高效又精准的智能搜索系统。

在下一节课中,我们将探讨如何进一步减少从数据库返回的数据量,以优化性能。
004:L3 投影 - 在聚合管道中精简数据 🎯

概述
在本节课中,我们将学习如何通过向 MongoDB 聚合管道添加投影阶段,来简化数据库操作的输出。这将有效减少返回的数据量,从而优化性能与数据处理效率。

从应用层过滤到数据库层投影
在上一节课中,我们使用 Pydantic 模型来指定并修改向量搜索后返回文档中的字段。这种方法将过滤不需要字段的任务留给了应用层,可能导致网络流量增加和处理时间延长,因为不必要的数据仍需传输。

为了更高效地处理数据,MongoDB 允许我们将字段的包含或排除作为聚合管道的一个独立阶段。这项技术称为投影,它能输出与前一阶段数量相同的文档,但每个文档中返回的字段数量会减少。

什么是投影?
MongoDB 中的投影技术通过指定最终文档中需要包含或排除的字段来工作。例如,我们可以将一幅画作(如蒙娜丽莎)的文档表示,通过投影操作精简到仅包含几个选定的字段。


投影操作的核心语法是一个包含字段名和值的文档。值为 1 表示包含该字段,值为 0 表示排除该字段(_id 字段除外,它可以被显式排除)。

投影阶段示例代码:
projection_stage = {
"$project": {
"_id": 0, # 排除 _id 字段
"name": 1, # 包含 name 字段
"summary": 1, # 包含 summary 字段
"score": {"$meta": "vectorSearchScore"} # 包含向量搜索相似度分数
}
}

投影的优势
以下是使用投影技术的主要优点:

- 减少内存使用:由于从数据库传递到应用层的结果数据变少,整体内存消耗降低。
- 提升查询性能:更少的数据传输和处理有助于缩短查询执行时间。
- 增强安全与隐私:在数据库层就过滤掉敏感信息(如个人财务数据),能为下游流程提供更好的安全保障。

实践:在 RAG 系统中实现投影
现在,我们将通过编码实践,在一个检索增强生成(RAG)系统中实现投影。步骤与上节课类似,但会增加一个投影阶段。



首先,我们导入必要的模块并加载数据集。

# 导入自定义模块并加载数据
from custom_materials import setupVectorSearchIndexWithFilter
from datasets import load_dataset
# ... 其他导入和初始化代码


接着,我们连接到数据库,清空并重新插入数据,同时设置好带过滤器的向量搜索索引。

然后,我们定义搜索结果的数据模型。这次模型包含了一些新属性,如 score。

from pydantic import BaseModel
class SearchResultItem(BaseModel):
name: str
summary: str
space: str
score: float # 用于存储相似度分数
# ... 其他字段

现在,我们来实现处理用户查询的函数。关键变化在于添加了投影阶段。

def handle_user_query(user_query: str, extra_stages: list):
# 构建聚合管道,包含向量搜索、过滤和投影阶段
pipeline = [
{"$vectorSearch": {...}}, # 向量搜索阶段
{"$match": {...}}, # 过滤阶段
*extra_stages # 包含投影等其他阶段
]
# 执行查询并处理结果
# ...


在定义投影阶段时,我们明确列出需要包含的字段,并排除 _id 字段。同时,我们使用 $meta 操作符将向量搜索的相似度分数也包含在返回文档中。


# 定义投影阶段
projection_stage = {
"$project": {
"_id": 0,
"name": 1,
"summary": 1,
"space": 1,
"score": {"$meta": "vectorSearchScore"}, # 注入相似度分数
# ... 包含其他需要的字段
}
}
extra_stages = [projection_stage] # 将投影阶段放入列表


运行查询后,我们可以看到返回的文档只包含我们在投影中指定的字段,并且包含了向量搜索的相似度分数,查询速度也得到了优化。


重要注意事项
进行投影时,必须保持模式一致:
- 如果使用包含模式(字段值为
1),则所有需要出现的字段都应设为1。未提及的字段会被自动排除。 - 如果使用排除模式(字段值为
0),则所有需要排除的字段都应设为0。 - 唯一例外是
_id字段,在包含模式中,可以单独将其设为0来排除它。 - 不能混用模式。例如,在同一个投影文档中,不能既有字段值为
1(包含),又有其他字段值为0(排除,_id除外),否则会导致操作失败。

总结
本节课中,我们一起学习了如何为 RAG 系统设置向量搜索索引和数据摄取流程。我们掌握的新技能是:创建并向聚合管道添加了一个投影阶段,以此来限制查询返回的字段,从而提升效率、安全性和性能。在下一节课中,我们将探索如何通过“提升”技术,利用定性和定量数据来进一步优化返回文档的相关性。
005:L4 提升 - 使用元数据优化搜索结果排序 🚀
概述
在本节课中,我们将学习如何通过“提升”技术,在向量搜索结果的基础上,结合文档的元数据(如评分、评论数量)来优化文档的最终排序。这种方法能确保返回的结果不仅语义相关,而且在质量和受欢迎程度上也满足用户的期望。
上一节我们介绍了基础的向量搜索,本节中我们来看看如何通过额外的元数据来增强排序逻辑。
提升的概念与价值
在某些情况下,一个文档可以包含其他影响其在搜索结果中位置的字段。以爱彼迎的房源列表为例,其中有评分和评论数量字段。这些字段表示定性和定量的衡量标准,它们可以对文档相对于用户查询和搜索标准的相关性做出贡献。
考虑这些字段的值以影响文档在返回的搜索结果列表中的位置,这被称为提升。
为什么需要提升?
以下是使用提升技术的几个关键原因:
- 补充向量搜索的不足:向量搜索是一种根据语义相似性对文档进行排名的有效方法。尽管向量搜索得分和排名是有效的,但元数据值可以对文档相关性做出贡献,从而影响搜索结果中的排序。
- 增加结果可信度:使用额外的定性和定量衡量标准对文档进行排名,可确保数据库操作结果对用户查询及其搜索标准是可信和相关的。
- 引入个性化:提升也可用于确保结果满足用户特定要求,从而在搜索结果中引入个性化。
实践:在RAG管道中实现提升
在编码部分,你将经历一些熟悉的步骤。首先是设置一个 RAG 管道,你将添加相关阶段。然后你将添加一个提升逻辑,它将使用 MongoDB 数据库中可用的一些数学运算符。和往常一样,你将处理用户查询并可视化结果。
1. 环境与数据准备
首先像在之前的课程中那样导入你自定义的工具模块。接着像之前的课程中那样加载数据。你也可以花些时间查看每个数据点的属性。
接着进行文档建模,将列表加载到符合模型中。这与你在之前课程中执行的过程类似。
下一步是获取你的数据库对象和集合。然后通过在集合记录上调用删除菜单来开始一个干净的集合。这与之前课程中执行的过程类似。
完成数据摄取过程,接着进行向量搜索索引定义过程,都与之前的课程类似。
2. 定义结果模型
现在,你将为本课中显示的结果定义一个搜索结果项模型。每个结果的属性需要包含综合得分、评价数量和平均评价得分。这个新属性稍后会解释。
再次,就像在之前的课程中一样,你有完全相同代码的处理用户查询函数。
3. 实现提升逻辑
现在,我们可以进入本课的主要方面。你将实现一个增强逻辑并将其添加到在应用程序管道上进行的向量搜索操作中。在这里,你将其分配给一个名为 reviewAverageStage 的变量。
在这个单元格中,正在发生的是我们正在向从数据库操作返回的每个文档添加两个新字段。
以下是添加新字段的两个步骤:
-
添加平均评价得分(定性度量):平均评价得分将遍历文档的每个评价组件并取评价组件总和的平均值。所以在每个文档中,我们可以看到准确性、清洁度、登记以及列表的其他属性。获取分数,使用
$add运算符进行加法运算,我们可以得到所有评价组件的总和。然后我们将其除以评价组件的数量,在这种情况下,对于我们数据集中的列表,是 6。这让我们了解一个列表的平均评级是多少。这就解释了我们添加到每个文档中的新字段,称为平均评价分数。# 伪代码示例:计算平均评分 average_review_score = $divide( $add(accuracy, cleanliness, checkin, ...), 6 ) -
添加评价数量提升(定量度量):添加到每个文档的第二个字段是评价数量提升。这是一个定量测量,这个字段将取每个文档中评价属性的数量值。这就是你如何使用
$运算符和字段名称将一个字段的值传递到一个新字段。
要将这个新字段添加到数据库操作中的每个文档,你可以将此过程添加为一个新阶段,特别是添加字段阶段。这就完成了添加定性测量和定量测量。
4. 加权与排序
在下一步,你需要添加权重并确定定性测量和定量测量的每个组件在向量搜索操作后应如何影响文档的排名。这是通过向我们的管道添加一个新阶段来完成的。这是加权阶段。
现在,加权阶段紧跟在评价平均阶段之后。所以加权阶段将随后具有在评价平均阶段添加到每个文档中的平均评价分数和评价数量提升的参考。这就是你如何从文档中参考这些字段的值。
要实现加权逻辑,你将使用 MongoDB 数据库启用的几个操作符来进行数学运算:加法操作符和乘法操作符。
- 对于乘法操作符,你将平均评价分数的值(这是定性度量),乘以一个权重。我使用 0 到 1 之间的数字来分配权重。
- 然后,对评价数量提升也做同样的操作。这是一个将在向量搜索操作后用于对文档进行排序的定量度量。
- 然后你将使用加法操作符来组合不同乘法运算的两个结果,将这个新的附加值分配给组合分数字段。组合分数是两个相乘值的组合,我们可以通过使用添加字段操作符在数据库操作中为每个文档添加组合分数。
这是加权阶段。
要完成这个过程还有一个阶段。最后阶段是排序阶段。排序阶段非常简单。使用 $sort 操作符,我们实际上可以根据它们的组合分数或某个字段重新对文档进行排序。在这种情况下,你使用组合分数,并且以降序对其进行重新排序。所以这由 -1 表示。升序将由 1 表示。
5. 整合阶段并执行
现在你已经实现了所有要添加到向量搜索操作的附加阶段。你可以创建一个名为 additionalStages 的新变量,它接受所有已定义阶段的列表。
- 第一个是评价阶段,在那里我们进行数学运算以获得定性和定量度量,并在向量搜索操作后将其作为新字段添加到文档中。
- 然后有一个加权阶段。
- 然后有一个排序阶段。
所有阶段在向量搜索操作之后按顺序执行。记住,我们在这节课中使用的向量搜索操作是一种类似于你在之前课程中创建的预过滤向量搜索。
观察提升效果
现在,是时候让你看看提升逻辑的结果了。使用与之前课程相同的查询以及相同的来自之前课程的函数,即处理用户查询函数,你正在传递额外的阶段并做笔记,以使用带有过滤器的向量索引。在这里,你可以观察到向量搜索操作阶段在一毫秒的一小部分时间内进行。
现在,让我们观察从这个操作返回的文档,其中包括多个阶段的组合以模拟我们的提升逻辑。在这里,你可以看到包括多个阶段的数据库操作的结果。平均评价分数与评价数量和综合评分一起包括在内。记住,综合评分包括权重考虑。
现在,显示的文档是按综合评分排序的。你可以在这里暂停视频并观察其他文档的综合评分。
要注意的一件事是,由于我们添加的加权逻辑,你会观察到,尽管这个文档有很高的评分,但与上面的其他文档相比,它的排名较低,因为它的评价数量较少。这就是为你的提升逻辑所考虑的组件添加权重的影响。
调整权重
还有一件事,你可以调整权重并调整数字以查看它如何影响结果。要做到这一点,只需回到加权阶段并调整权重。
现在,我给评论数量赋予更高的权重,给平均评论赋予较低的权重。一旦你改变了权重,你可以再次观察结果。正如你从结果中可以观察到的,因为你给评论数量增加了更多的权重,与具有高评分数量的文档相比,具有高评论数量的文档排名更高。在此处暂停视频以观察结果。

总结
在这节课中,你已经学习了如何实现一个典型的 RAG 系统,进行向量搜索,但现在你已经在聚合管道中添加了多个阶段来模拟一个增强逻辑,该逻辑在数据库操作后为你的文档排名增加了更多的相关性和上下文。

在下一节课中,你将学习如何利用提示压缩来减少发送给大型语言模型的提示,以降低运营成本。
006:L5 提示压缩 🧠
在本节课中,我们将学习并实施提示压缩的成本节约策略。这对于像RAG(检索增强生成)和智能体系统这样的大型语言模型应用特别有价值。我们将直观地了解提示压缩是什么、如何使用它,以及它为大型语言模型应用带来的操作优势。
概述:什么是提示压缩?
在最近几年,出现了许多提示策略,例如上下文学习、思维链和反应式提示。从大型语言模型获得合适和高质量的响应是一种艺术形式,这些提示策略中的大多数都涉及向大型语言模型编写大量文本作为输入。
具有大上下文窗口的大型语言模型正成为新的常态。现在常见的是可以接受超过10万个标记,甚至在某些情况下100万个标记输入的大型语言模型。这相当于在一次推理调用中向大型语言模型传递一整部小说。
尽管在某些情况下有用,但在通过REST API调用访问大型语言模型时,利用完整的上下文窗口可能会变得非常昂贵。具有大上下文窗口的大型语言模型在现实世界应用中有其位置,但这些模型的操作成本可能会飙升。
例如,支付每100万个标记10美元,像爱彼迎这样每天有几百万用户的应用,仅从交互量来看就会有巨大的运营费用。更不用说,随着模型必须处理更多输入以提取适当信息来响应用户查询,响应中的延迟会增加。
当你继续学习和构建使用大型语言模型的人工智能应用时,你会遇到提示压缩的概念,有时也称为标记压缩。你可能认为在人工智能应用的初始开发阶段不会有那么大的量,但构建强大的人工智能应用需要提前考虑可扩展性,并解决可能成为瓶颈的问题。


在本节课的代码部分,我们将实施提示词压缩技术,并直接观察实施提示词压缩与现有RAG管道一起是多么容易。
提示压缩的核心概念
所以,提示词压缩是减少标记数量的过程。

但让我们看看在一个例子中这是什么样子。在屏幕上,你可以观察到一个跨越三个长句子的原始未压缩提示词。通过使用你将在本节课编码部分使用的LLMlingua包,我们能够将未压缩的句子减少到跨越两个自由行的两个句子。这就是提示词压缩的力量,你将在编码部分直接看到。
我在幻灯片上的链接中保留了介绍提示词压缩技术的论文的链接。在本节课之后可以随意观察和阅读这篇研究论文。

几分钟后,你将把一个几千个标记的广泛提示词压缩到几百个标记。有了提示词压缩,将输入传递到提示词压缩技术非常直接。想象一下有一个50,000个标记的未压缩提示词。只需传递未压缩提示词并使用提示词压缩库LLMlingua,指定几个参数,就可以将未压缩提示词减少到10,000个标记。这是五倍的减少。然后你可以像使用未压缩提示词一样直接将输入传递到大型语言模型中,并获得与最初提供时相同质量的输出。
你即将在代码中看到这个。

代码实施:构建RAG管道并集成压缩

在本课程的编码部分,你将经历一些熟悉的步骤,包括建立正确的管道,添加相关的MongoDB阶段,然后实现压缩逻辑。和往常一样,你将处理用户查询并观察结果。

让我们开始编码。

首先导入自定义零售模块。就像你在之前的课程中所做的那样,你继续加载你的数据集,在那里你可以观察到与之前课程相似的属性。
接下来的步骤在之前的课程中已经涵盖,在那里你对你的文档进行建模,连接到你的数据库,为你的数据库和你的集合提取对象,删除集合内的现有记录,摄取新数据,最后,创建你的向量搜索索引。


就像在之前的课程中一样,你将处理用户查询。你首先创建一个搜索结果项模型,它将指定你希望从数据库操作返回的文档中获得的属性。对于这种情况,你有名字、地址和其他相应的属性。
就像在之前的课程中一样,你添加额外的提升阶段。你将有平均评价阶段、加权阶段和排序阶段。然后你将所有额外的阶段添加到一个称为额外阶段的变量中。所有这些都是你在之前课程中采取的步骤。

现在,我们在本课程的主要部分。这里有一个你在之前课程中看到的类似的处理用户查询,但你正在打印出关于压缩提示以供观察。这在这两个新的打印语句中指定。


现在,你有与上节课相同的用户查询,也有相同的处理用户查询函数,但这节课的不同之处在于打印语句,在这里我们可以看到压缩提示词。

从输出中,你可以观察到向量搜索操作执行所花费的时间,这只是一毫秒的一部分。你也可以观察到压缩提示词。在这里,你可以看到压缩提示词很广泛,请注意它已被截断,以确保能在屏幕上全部显示。
你也可以通过查看表格中列出的向量搜索操作返回的文档,来查看提示词的全部内容。在此暂停视频,以了解传递给大型语言模型的共享大小。

你还会注意到系统推荐了五星新公寓的温馨房间。

记住这节课。


实施提示压缩技术
现在,这是有趣的部分。我们将研究一种技术,该技术允许我们减少你之前观察到的广泛提示词,并减少几百个标记。
你首先从LLM Lingua库中导入提示词压缩器构造函数。使用提示词压缩器构造函数,你可以指定一个较小的大型语言模型,该模型已针对提示词压缩进行了微调以进行压缩。你还将通过将true指定为参数use LLM Lingua 2的值,来指定利用最新的LLM Lingua提示词压缩逻辑。你还指定将提示词压缩模块使用CPU,以确保你在设备上使用CPU。
现在我们已经专门设置了提示词压缩器,设置了一个较小的语言模型来进行提示词压缩,我们可以继续定义压缩提示词函数。

现在,你可以定义压缩查询提示函数,该函数将压缩后的提示作为函数的查询接收。提示压缩模块要求输入以特定方式结构化。也就是具有基于组件的结构,其中具体有示例、指令和问题字段。我将详细说明这意味着什么。
以下是压缩查询提示函数的核心结构:
def compress_query_prompt(query_info):
# 结构示例
example = query_info['example'] # 从数据库返回的上下文文档
instruction = query_info['instruction'] # 压缩指令
question = query_info['question'] # 用户查询
# 调用压缩器
compressed_prompt = compressor.compress_prompt(
contexts=[example],
instruction=instruction,
question=question,
target_token=512, # 目标标记数
condition_compare=True,
condition_in_question='after',
rank_method='longllmlingua',
context_budget="+100",
reorder_context="sort",
dynamic_context_compression_ratio=0.4,
)
return compressed_prompt
- 示例将保存用作与用户查询一起传递给大型语言模型的额外信息的上下文。这实质上是从数据库操作返回的文档。
- 指令将保存告诉较小的大型语言模型如何压缩提示的具体指令。
- 问题就是具体的用户查询本身。
现在,你实际上可以在我们之前初始化的大型语言模型Lingua上调用压缩提示方法。我将解释每个参数的作用。
- 第一个参数指定如何具体地按新行拆分每个上下文。
- 第二个参数接收指令,然后是问题。
- 接下来,我们指定希望压缩后的提示要压缩到的目标标记。
- 接下来,有要使用的压缩算法的说明。你将使用来自大型语言模型Lingua的最新压缩算法,特别是Long LLM Lingua。
- 接下来,我们将指定上下文预算,但允许预算超支100个标记。
- 最后,我们将指定压缩比。该比率表明压缩逻辑如何将标记分配给上下文(即示例),以及整体指令和问题。
- 最后,我们启用压缩器使用排序算法重新排列上下文。
这就是压缩提示方法的所有参数。压缩查询提示函数的结果是压缩提示的JSON表示,它将包括诸如标记(即压缩提示上的原始标记)和压缩提示标记等信息。稍后你将看到实际操作。


集成压缩逻辑到查询流程
现在你已经指定了一种压缩提示的方法,你将开始指定使用压缩处理用户查询,它将接收用户查询并执行之前定义的压缩。
这个使用压缩处理用户查询与之前课程中的之前处理用户查询函数类似。但关键区别在于这个函数中有一个新的输入到大型语言模型,指定为查询信息。这个查询信息遵循我们的压缩逻辑结构,有演示、指令和问题。
记住,演示只是数据库操作的一个结果。指令告诉压缩模块我们希望压缩如何执行。而用户查询或问题,它仅仅是用户查询。

这就是通过调用之前定义的函数并传入查询信息,然后将结果赋给一个名为压缩提示的变量的结构。为了可视化结果,你将以结构化的方式打印出压缩提示。最后,使用压缩处理用户查询返回搜索结果和压缩提示本身。

你在这节课中将实现的最后一个方法是处理系统响应。处理系统响应将查询和压缩提示作为输入传递到大型语言模型。为了可视化,你将打印出查询和系统响应。

运行并观察压缩效果
现在,您可以使用之前定义的压缩方法处理用户查询,通过传递查询、数据库对象、集合对象、附加阶段,并指定您在本课程中使用的向量搜索索引。

执行单元格。由于您正在使用较小的语言模型来压缩提示,该单元格的执行可能需要几分钟。尽管我们的延迟增加了,但总体运营成本将会降低。
这是提示压缩技术的结果。在这里,我们有一个压缩提示字段,其中包含所有提示。如您所见,这比我们之前看到的提示要短得多。但更重要的是,我们有未压缩提示的原始标记,其长度为4284个标记。而新的压缩标记仅为512个。这是8倍压缩的比率。
还有一个使用此提示压缩技术并将压缩提示作为输入传递给GPT-4模型时您节省的成本因素的指示。在这种情况下,对于这个特定的调用,我们节省了0.2美元。如果您考虑在像爱彼迎这样的大规模应用中,其中对API进行了数百万次推理调用,这可能会节省数十万美元。

验证压缩后的输出质量

本课程的最后一步是将压缩提示和用户查询传递给大型语言模型以实际获得系统响应。确认您有压缩提示,然后将压缩提示和查询传递到handleSystemResponse函数中。
在这里,我们可以观察到结果。这个压缩提示的结果为我们提供了一个非常接近用户查询的推荐。具体来说,它在一个温暖、友好的街区,这包含在列表的空间中,而且它紧挨着餐馆,这是用户查询中指定的。

我们节省了RAG管道的运营成本并获得了高质量的输出,这个输出与未压缩提示词的输出不同,但质量相似,并且满足用户查询中指定的要求。

未压缩提示词(它为我们提供了这个推荐)的结果和压缩提示词(它为我们提供了这个推荐)的结果之间的差异非常小,这意味着在标记数量较低的情况下,您可以从大型语言模型中获得质量方面类似的输出。
总结

在本节课中,我们一起学习了如何创建一个RAG管道、进行向量搜索,还进行了提示词压缩以获得与未压缩提示词相同质量的输出。我们看到了如何通过LLMlingua库显著减少输入标记数量(例如从4284个减少到512个),从而大幅降低运营成本,同时保持响应的相关性。这是构建可扩展且经济高效的大型语言模型应用的关键技术之一。
007:总结 🎯
在本课程中,我们学习了如何通过向量搜索、元数据过滤与提示压缩等技术,来优化检索增强生成系统的性能与成本效益。
恭喜你完成了这门课程。在这门课程中,你实施了向量搜索。你通过使用元数据和一个 MongoDB 聚合管道来优化检索系统,以提高系统效率和输出相关性。最后,你学会了如何通过使用提示压缩来降低大型语言模型应用的运营成本。
我期待看到你自己会构建什么。这里有一些额外的资源,我建议你在完成这节课后看一看。
以下是推荐的后续学习资源:
- MongoDB 开发者中心:它包含了教程、文章和视频,涵盖了与人工智能相关的各种主题。
- 生成式人工智能展示库:这里包含不同的代码,是一个展示 RAG 和智能体系统不同用例的资源库。
- 深度学习人工智能论坛:在那里你可以就这门课程提出问题并进行讨论。


在本节课中,我们一起学习了向量搜索的实施、利用元数据与聚合管道优化检索系统,以及通过提示压缩降低应用成本的核心方法。希望这些知识能帮助你构建更高效、更经济的AI应用。

浙公网安备 33010602011771号