结合 RAG 的 AI Agent 核心流程
一、RAG 在 AI Agent 中的核心作用
核心目标:借助动态检索外部知识库,增强 AI Agent 的决策能力和生成质量,突破大模型的知识局限。大模型虽然具备强大的语言处理能力,但对于特定领域知识、实时信息等存在不足,RAG 通过引入外部知识库,为 AI Agent 提供了更丰富的信息来源,从而提升其回答的准确性和实用性。
应用场景:
- 复杂问答:当用户的问题涉及到企业内部政策、最新的行业数据、特定领域的专业知识等外部知识时,AI Agent 可以通过 RAG 从知识库中获取相关信息进行准确回答。例如,在企业客服场景中,用户询问某项业务的具体办理流程,而该流程在企业的内部知识库中有详细记录,此时 RAG 就可以发挥作用。
- 动态任务规划:在任务执行过程中,需要实时获取环境信息来调整任务计划。比如在物流管理中,AI Agent 需要根据实时的库存状态、运输车辆的位置等信息来规划货物的配送路线,RAG 可以帮助 Agent 从相关的数据库中获取这些实时信息。
二、结合 RAG 的 AI Agent 完整流程
步骤详解
- 用户输入
import re
def preprocess_user_input(user_input):
# 导入 re 模块,用于正则表达式操作
# 定义一个函数,用于对用户输入进行预处理
# 使用正则表达式去除用户输入中的特殊字符,只保留字母、数字和空格
user_input = re.sub(r'[^\w\s]', '', user_input)
# 将用户输入转换为小写,使后续处理不区分大小写
user_input = user_input.lower()
# 返回处理后的用户输入
return user_input
# 示例用户输入,包含特殊字符
user_input = "推荐一款适合露营的帐篷!"
# 调用预处理函数对用户输入进行处理
processed_input = preprocess_user_input(user_input)
# 打印处理后的用户输入
print(processed_input)
- 意图识别
import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
# 导入 PyTorch 库,用于深度学习相关操作
# 从 transformers 库导入 AutoTokenizer 和 AutoModelForSequenceClassification
# AutoTokenizer 用于将文本转换为模型可接受的输入格式
# AutoModelForSequenceClassification 用于文本分类任务
# 加载预训练的意图分类模型,需要替换为实际使用的模型名称
model_name = "your_intent_classification_model"
# 使用 AutoTokenizer 从预训练模型中加载分词器
tokenizer = AutoTokenizer.from_pretrained(model_name)
# 使用 AutoModelForSequenceClassification 从预训练模型中加载序列分类模型
model = AutoModelForSequenceClassification.from_pretrained(model_name)
def classify_intent(user_input):
# 定义一个函数,用于对用户输入进行意图分类
# 使用分词器将用户输入转换为 PyTorch 张量,return_tensors="pt" 表示返回 PyTorch 张量
inputs = tokenizer(user_input, return_tensors="pt")
# 使用 torch.no_grad() 上下文管理器,避免在推理过程中计算梯度,节省计算资源
with torch.no_grad():
# 将输入传递给模型,得到模型的输出 logits
logits = model(**inputs).logits
# 找到 logits 中最大值的索引,即预测的类别 ID
predicted_class_id = logits.argmax().item()
# 根据类别 ID 从模型的配置中获取对应的意图标签
intent = model.config.id2label[predicted_class_id]
# 返回预测的意图标签
return intent
# 示例用户输入
user_input = "推荐一款适合露营的帐篷"
# 调用意图分类函数对用户输入进行分类
intent = classify_intent(user_input)
# 根据意图标签判断是否需要使用 RAG 检索
if intent == "product_recommendation":
use_rag = True
else:
use_rag = False
- RAG 检索
import numpy as np
from sentence_transformers import SentenceTransformer
import faiss
# 导入 NumPy 库,用于数值计算
# 从 sentence_transformers 库导入 SentenceTransformer,用于将文本转换为向量表示
# 导入 faiss 库,用于向量数据库的操作
# 加载预训练的嵌入模型,将文本转换为向量
embedding_model = SentenceTransformer('all-MiniLM-L6-v2')
# 初始化一个 Faiss 向量数据库,使用 L2 距离度量,向量维度为 384
# 384 是 all-MiniLM-L6-v2 模型输出的向量维度
vector_db = faiss.IndexFlatL2(384)
# 这里可以添加知识库中的向量数据,示例中为随机生成的 100 个向量
# vectors = np.random.randn(100, 384).astype('float32')
# vector_db.add(vectors)
def search_vector_db(query, top_k=3):
# 定义一个函数,用于在向量数据库中搜索与查询最相似的向量
# 使用嵌入模型将查询文本转换为向量表示
query_embedding = embedding_model.encode(query)
# 将查询向量转换为 NumPy 数组,并指定数据类型为 float32
query_embedding = np.array([query_embedding]).astype('float32')
# 在向量数据库中搜索与查询向量最相似的 top_k 个向量
# distances 存储查询向量与最相似向量的距离
# indices 存储最相似向量在数据库中的索引
distances, indices = vector_db.search(query_embedding, top_k)
# 初始化一个空列表,用于存储检索结果
results = []
# 遍历最相似向量的索引
for idx in indices[0]:
# 这里可以根据 idx 从知识库中获取具体的知识条目
# 示例中简单地将索引作为知识条目返回
result = f"Knowledge item {idx}"
# 将知识条目添加到结果列表中
results.append(result)
# 返回检索结果列表
return results
# 示例查询文本
query = "露营帐篷"
# 调用搜索函数在向量数据库中搜索与查询最相似的向量
results = search_vector_db(query)
# 打印检索结果
print(results)
- 上下文整合
# 示例用户输入
user_input = "推荐一款适合露营的帐篷"
# 将用户输入和检索结果拼接成增强后的上下文
context = f"用户需求:{user_input}\n相关产品信息:{results}"
# 打印增强后的上下文
print(context)
- 任务规划与执行
import requests
def call_api(api_name, **kwargs):
# 导入 requests 库,用于发送 HTTP 请求
# 定义一个函数,用于调用外部 API
if api_name == "get_inventory":
# 如果 API 名称为 "get_inventory"
# 从 kwargs 中获取产品 ID
product_id = kwargs.get("product_id")
# 模拟调用库存接口,发送 GET 请求到指定的 API 地址
response = requests.get(f"https://example.com/api/inventory?product_id={product_id}")
# 解析响应的 JSON 数据,获取库存信息
inventory = response.json().get("inventory")
# 返回库存信息
return inventory
# 可以添加更多的 API 调用逻辑
return None
# 示例产品 ID
product_id = "123"
# 调用 API 函数获取产品的库存信息
inventory = call_api("get_inventory", product_id=product_id)
if inventory > 0:
# 如果库存大于 0
# 假设这里有一个生成推荐的模型
# 示例中简单地定义一个推荐产品
recommendation = "Some recommended product"
# 可以使用上下文和其他信息来生成更准确的推荐
# recommendation = model.generate(context)
# 打印推荐产品
print(recommendation)
- 结果生成与反馈
# 假设这里有一个生成回复的模型
# 结合推荐产品生成最终回复
response = f"推荐产品:{recommendation}"
# 打印最终回复
print(response)
# 将用户反馈信息编码为向量
feedback = "用户反馈:帐篷防水性优秀"
feedback_embedding = embedding_model.encode(feedback)
# 将反馈向量转换为 NumPy 数组,并指定数据类型为 float32
feedback_embedding = np.array([feedback_embedding]).astype('float32')
# 将反馈向量添加到向量数据库中
vector_db.add(feedback_embedding)
三、实战案例:智能电商助手(RAG + AI Agent)
# RAG 检索与函数调用整合
def handle_query(user_input):
# 定义一个函数,用于处理用户查询
# 1. 意图识别
# 调用意图分类函数对用户输入进行分类
intent = classify_intent(user_input)
if intent == "product_query":
# 如果意图为产品查询
# 2. RAG 检索
# 调用搜索函数在向量数据库中搜索与用户输入最相似的向量
results = search_vector_db(user_input)
if results:
# 如果检索到结果
# 假设结果中包含产品 ID,从结果中获取第一个产品的 ID
product_id = results[0].get("id")
# 3. 调用库存接口
# 调用 API 函数获取产品的库存信息
inventory = call_api("get_inventory", product_id=product_id)
if inventory > 0:
# 如果库存大于 0
# 4. 生成推荐
# 从结果中获取第一个产品的名称
recommendation = results[0].get("name")
# 结合推荐产品和库存信息生成回复
response = f"推荐产品:{recommendation}, 库存:{inventory}"
# 返回回复
return response
# 如果没有找到合适的推荐,返回提示信息
return "未找到合适的推荐,请提供更多信息。"
# 示例用户输入
user_input = "帮我推荐一款适合冬季徒步的登山鞋。"
# 调用处理查询函数处理用户输入
response = handle_query(user_input)
# 打印处理结果
print(response)
四、RAG 流程优化建议
-
检索效率:
- 使用分层索引(如 HNSW)加速向量检索。HNSW(Hierarchical Navigable Small World)是一种高效的近似最近邻搜索算法,能够在大规模向量数据中快速找到最相似的向量。
- 缓存高频查询结果(如 Redis)。将经常被查询的问题及其检索结果存储在 Redis 缓存中,当再次收到相同的查询时,直接从缓存中获取结果,避免重复的向量检索操作。
-
知识质量:
- 定期清理过期数据(如下架商品)。随着时间的推移,知识库中的一些数据可能会变得过时,需要定期进行清理,以保证检索结果的准确性。
- 引入人工审核机制(如标注关键知识)。通过人工审核,可以对知识库中的知识进行筛选和标注,提高知识的质量和可靠性。
-
错误处理:
- 重试机制:当 RAG 检索失败时,尝试切换到备用知识库或重新进行检索,以提高系统的稳定性。
- 降级策略:如果多次检索仍然失败,可以直接调用大模型生成兜底回复,避免用户长时间等待或得到无意义的结果。
五、总结
RAG 与 AI Agent 的结合实现了 知识增强的自主决策,关键技术包括动态检索、任务规划和反馈闭环。开发者在实际应用中,需要根据具体的场景权衡 RAG 的实时性与计算成本,避免过度依赖外部知识导致性能瓶颈。同时,要不断优化 RAG 流程,提高检索效率和知识质量,以提升 AI Agent 的整体性能和用户体验。