构建LangChain应用程序的示例代码:47、使用MongoDB和LangChain为RAG应用添加语义缓存和记忆功能

在此示例中,我们将了解如何在 RAG 应用程序中使用新的 MongoDBCache 和 MongoDBChatMessageHistory。

步骤1: 安装所需库

  • datasets: 用于访问Hugging Face Hub上可用数据集的Python库
  • langchain: LangChain的Python工具包
  • langchain-mongodb: 在LangChain中使用MongoDB作为向量存储、语义缓存、聊天历史存储等的Python包
  • langchain-openai: 在LangChain中使用OpenAI模型的Python包
  • pymongo: MongoDB的Python工具包
  • pandas: 用于数据分析、探索和操作的Python库
! pip install -qU datasets langchain langchain-mongodb langchain-openai pymongo pandas

步骤2: 设置先决条件

  • 设置MongoDB连接字符串。按照这里的步骤从Atlas UI获取连接字符串。

  • 设置OpenAI API密钥。获取API密钥的步骤在这里

import getpass

# 导入getpass模块用于安全输入密码

MONGODB_URI = getpass.getpass("输入你的MongoDB连接字符串:")
# 安全地输入MongoDB连接字符串

OPENAI_API_KEY = getpass.getpass("输入你的OpenAI API密钥:")
# 安全地输入OpenAI API密钥

# 可选 -- 如果你想启用Langsmith -- 对调试很有帮助
import os

os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = getpass.getpass()
# 设置Langsmith环境变量

步骤3: 下载数据集

我们将使用MongoDB的embedded_movies数据集

import pandas as pd
from datasets import load_dataset

# 导入pandas和datasets库

# 确保你的开发环境中有HF_TOKEN:
# 访问令牌可以在Hugging Face平台上创建或复制 (https://huggingface.co/docs/hub/en/security-tokens)

# 从Hugging Face加载MongoDB的embedded_movies数据集
# https://huggingface.co/datasets/MongoDB/airbnb_embeddings

data = load_dataset("MongoDB/embedded_movies")
# 加载数据集

df = pd.DataFrame(data["train"])
# 将数据集转换为pandas DataFrame

步骤4: 数据分析

确保数据集长度符合预期,删除空值等。

# 预览数据内容
df.head(1)

# 只保留fullplot字段不为空的记录
df = df[df["fullplot"].notna()]

# 将嵌入字段重命名为"embedding" -- LangChain要求
df.rename(columns={"plot_embedding": "embedding"}, inplace=True)

步骤5: 使用MongoDB作为向量存储创建简单的RAG链

from langchain_mongodb import MongoDBAtlasVectorSearch
from pymongo import MongoClient

# 初始化MongoDB Python客户端
client = MongoClient(MONGODB_URI, appname="devrel.content.python")

DB_NAME = "langchain_chatbot"
COLLECTION_NAME = "data"
ATLAS_VECTOR_SEARCH_INDEX_NAME = "vector_index"
collection = client[DB_NAME][COLLECTION_NAME]

# 删除集合中任何现有记录
collection.delete_many({})

# 数据导入
records = df.to_dict("records")
collection.insert_many(records)

print("数据导入MongoDB完成")

from langchain_openai import OpenAIEmbeddings

# 使用text-embedding-ada-002,因为这是用于创建电影数据集中的嵌入的模型
embeddings = OpenAIEmbeddings(
    openai_api_key=OPENAI_API_KEY, model="text-embedding-ada-002"
)

# 创建向量存储
vector_store = MongoDBAtlasVectorSearch.from_connection_string(
    connection_string=MONGODB_URI,
    namespace=DB_NAME + "." + COLLECTION_NAME,
    embedding=embeddings,
    index_name=ATLAS_VECTOR_SEARCH_INDEX_NAME,
    text_key="fullplot",
)

# 在RAG链中使用MongoDB向量存储作为检索器
retriever = vector_store.as_retriever(search_type="similarity", search_kwargs={"k": 5})

from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.runnables import RunnablePassthrough
from langchain_openai import ChatOpenAI

# 使用检索器生成上下文,并传递用户问题
retrieve = {
    "context": retriever | (lambda docs: "\n\n".join([d.page_content for d in docs])),
    "question": RunnablePassthrough(),
}
template = """仅根据以下上下文回答问题: \
{context}

问题: {question}
"""
# 定义聊天提示
prompt = ChatPromptTemplate.from_template(template)
# 定义用于聊天完成的模型
model = ChatOpenAI(temperature=0, openai_api_key=OPENAI_API_KEY)
# 将输出解析为字符串
parse_output = StrOutputParser()

# 简单的RAG链
naive_rag_chain = retrieve | prompt | model | parse_output

naive_rag_chain.invoke("当伤心时看什么电影最好?")

步骤6: 创建带有聊天历史的RAG链

from langchain_core.prompts import MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory

def get_session_history(session_id: str) -> MongoDBChatMessageHistory:
    return MongoDBChatMessageHistory(
        MONGODB_URI, session_id, database_name=DB_NAME, collection_name="history"
    )

# 给定一个后续问题和历史记录,创建一个独立的问题
standalone_system_prompt = """
给定聊天历史和后续问题,将后续问题重新表述为一个独立的问题。\
不要回答问题,只需在需要时重新表述,否则按原样返回。\
只返回最终的独立问题。\
"""
standalone_question_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", standalone_system_prompt),
        MessagesPlaceholder(variable_name="history"),
        ("human", "{question}"),
    ]
)

question_chain = standalone_question_prompt | model | parse_output

# 通过将question_chain的输出(即独立问题)传递给检索器来生成上下文
retriever_chain = RunnablePassthrough.assign(
    context=question_chain
    | retriever
    | (lambda docs: "\n\n".join([d.page_content for d in docs]))
)

# 创建一个包含上下文、历史记录和后续问题的提示
rag_system_prompt = """仅根据以下上下文回答问题: \
{context}
"""
rag_prompt = ChatPromptTemplate.from_messages(
    [
        ("system", rag_system_prompt),
        MessagesPlaceholder(variable_name="history"),
        ("human", "{question}"),
    ]
)

# RAG链
rag_chain = retriever_chain | rag_prompt | model | parse_output

# 带有历史记录的RAG链
with_message_history = RunnableWithMessageHistory(
    rag_chain,
    get_session_history,
    input_messages_key="question",
    history_messages_key="history",
)
with_message_history.invoke(
    {"question": "当伤心时看什么电影最好?"},
    {"configurable": {"session_id": "1"}},
)

with_message_history.invoke(
    {
        "question": "嗯...我不想看那个。你能推荐其他的吗?"
    },
    {"configurable": {"session_id": "1"}},
)

with_message_history.invoke(
    {"question": "有更轻松一点的吗?"},
    {"configurable": {"session_id": "1"}},
)

步骤7: 使用语义缓存获得更快的响应

注意: 语义缓存只缓存LLM的输入。在检索链中使用时,请记住检索到的文档可能在运行之间发生变化,导致语义相似的查询出现缓存未命中。

from langchain_core.globals import set_llm_cache
from langchain_mongodb.cache import MongoDBAtlasSemanticCache

set_llm_cache(
    MongoDBAtlasSemanticCache(
        connection_string=MONGODB_URI,
        embedding=embeddings,
        collection_name="semantic_cache",
        database_name=DB_NAME,
        index_name=ATLAS_VECTOR_SEARCH_INDEX_NAME,
        wait_until_ready=True,  # 可选,等待缓存准备就绪后再使用
    )
)

%%time
naive_rag_chain.invoke("当伤心时看什么电影最好?")

%%time
naive_rag_chain.invoke("当伤心时看什么电影最好?")

%%time
naive_rag_chain.invoke("伤心的时候我应该看什么电影?")

总结

本文介绍了如何在RAG(检索增强生成)应用中使用MongoDB的新功能MongoDBCache和MongoDBChatMessageHistory。文章详细说明了安装必要库、设置先决条件、下载并分析数据集、创建简单的RAG链、添加聊天历史功能,以及使用语义缓存来加速响应等步骤。这些技术可以显著提高RAG应用的性能和用户体验。

扩展知识

  1. RAG (检索增强生成) 是一种结合了检索系统和生成模型的技术,可以提高大语言模型回答问题的准确性和相关性。

  2. 语义缓存是一种高级缓存技术,它不仅基于精确匹配来缓存结果,还可以识别语义相似的查询,从而提高缓存命中率。

  3. MongoDB Atlas Vector Search 是一个强大的工具,可以高效地执行向量相似性搜索,这在实现RAG系统时非常有用。

  4. LangChain 是一个用于开发以语言模型为中心的应用程序的框架,它提供了许多工具和抽象,使得构建复杂的AI应用变得更加简单。

  5. 在实际应用中,合理使用缓存和历史记录可以显著提高系统的响应速度和用户体验,同时也可以减少API调用成本。

  • 23
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hugo_Hoo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值