基于langchain的多轮对话RAG

news2024/9/22 14:40:31

目录

概述

整体架构

代码实现

输出展示

参考


概述

        相比于单轮对话,多轮对话要考虑历史对话记录,大模型需要根据对话上下文去回答用户的问题。在RAG的场景中,通常需要通过问题去召回和问题相关的知识,再将知识和问题交给大模型去润色回复用户。但是有没有想过,如果这个问题指代了历史消息的某个重要对象(通常是问题的核心)时,就不能召回有用的知识,大模型的回答效果不会太好。解决办法是,让大模型基于历史消息对用户最新的问题进行改写,补充指代对象,然后再去进行知识的召回,效果会大大改善。以下将以豆瓣电影《白蛇:浮生》作为大模型的知识补充来进行多轮对话。

整体架构

  • history_aware_retriever将用户的当前输入和历史消息通过大模型来进行改写,从而去进行文档的召回
  • question_answer_chain会基于召回的文档、历史消息、当前输入给到大模型进行润色输出
  • embedding的部分采用BCE模型,embedding+ranking可以达到SOTA水平,本案例只有embedding,后续可以考虑将召回再过一层ranking
  • 向量库采用的是qdrant,在一些数据集和指标上也可以达到SOTA水平,本地部署可以采用内存、持久化到磁盘和docker模式,氪金的话就可以上它的cloud
  • 模型采用的是Qwen/Qwen2-7B-Instruct,采用vllm部署openai接口形式提供服务

代码实现

from typing import List
from langchain_openai.chat_models import ChatOpenAI
from langchain.chains.history_aware_retriever import create_history_aware_retriever
from qdrant_client import QdrantClient
from qdrant_client.models import VectorParams, Distance
from langchain_qdrant import QdrantVectorStore
from langchain.prompts.chat import ChatPromptTemplate
from langchain.prompts import MessagesPlaceholder
from langchain_core.documents import Document
from langchain_huggingface.embeddings import HuggingFaceEmbeddings
from langchain_community.document_loaders import WebBaseLoader
from langchain_community.document_transformers import Html2TextTransformer
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain.chains.retrieval import create_retrieval_chain
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables import RunnableWithMessageHistory
import os
import sys
sys.path.append(os.path.abspath(os.pardir))
from global_config import MODEL_CACHE_DIR


def get_chat_llm():
    chat_model = ChatOpenAI(
        model="Qwen2-7B-Instruct",
        openai_api_key="empty",
        openai_api_base="http://localhost:8000/v1",
        max_tokens=2048,
        temperature=0
    )
    return chat_model


def get_retriever(docs: List[Document]):
    embeddings = HuggingFaceEmbeddings(model_name=os.path.join(MODEL_CACHE_DIR, "maidalun/bce-embedding-base_v1"))
    client = QdrantClient(":memory:")
    # if not exists then create
    if not client.collection_exists("rag_collection"):
        # create collection
        client.create_collection(
            "rag_collection",
            vectors_config=VectorParams(
                size=len(embeddings.embed_query("hello world")),
                distance=Distance.COSINE
            )
        )
    vector_store = QdrantVectorStore(
        client=client, collection_name="rag_collection", embedding=embeddings
    )
    vector_store.add_documents(docs)
    return vector_store.as_retriever(search_kwargs={"k": 5})


def get_contextualize_question_prompt():
    """
    基于历史记录来改写用户问的问题
    :return:
    """
    system_prompt = """\
    请根据聊天历史和最后用户的问题,改写用户最终提出的问题。
    你只需要改写用户最终的问题,请不要回答问题
    没有聊天历史则将用户问题直接返回,有聊天历史则进行改写
    """
    contextualize_question_prompt = ChatPromptTemplate([
        ("system", system_prompt),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}")
    ])
    return contextualize_question_prompt


def get_answer_prompt():
    system_prompt = """\
    你是一个问答任务的助手,请依据以下检索出来的信息去回答问题:
    {context}
    """
    qa_prompt = ChatPromptTemplate([
        ("system", system_prompt),
        MessagesPlaceholder("chat_history"),
        ("human", "{input}")
    ])
    return qa_prompt


def get_session_history(session_id:str) -> ChatMessageHistory:
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]


if __name__ == '__main__':
    llm = get_chat_llm()

    # loader
    loader = WebBaseLoader(
        web_path=("https://movie.douban.com/subject/36463483/?from=showing",),
        encoding="utf-8"
    )
    docs = loader.load()
    html2test_transformer = Html2TextTransformer()
    docs = html2test_transformer.transform_documents(docs)

    # text split
    text_spliter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=100)
    docs = text_spliter.split_documents(docs)

    # retriever
    retriever = get_retriever(docs)

    # contextualize question
    question_prompt = get_contextualize_question_prompt()
    history_aware_retriever = create_history_aware_retriever(llm, retriever, question_prompt)

    # qa chain
    qa_prompt_template = get_answer_prompt()
    qa_chain = create_stuff_documents_chain(llm, qa_prompt_template)
    rag_chain = create_retrieval_chain(history_aware_retriever, qa_chain)

    # with history
    store = {}
    conversational_rag_chain = RunnableWithMessageHistory(
        rag_chain,
        get_session_history,
        input_messages_key="input",
        history_messages_key="chat_history",
        output_messages_key="answer"
    )

    # 改写用户内容部分
    contextualize_question_chain = RunnableWithMessageHistory(
        question_prompt | llm,
        get_session_history,
        input_messages_key="input",
        history_messages_key="chat_history"
    )

    while(True):
        inputs = input("请输入:")
        if inputs == "end":
            break

        res = contextualize_question_chain.invoke({
            "input": inputs
        }, config={
            "configurable": {"session_id": "test456"}
        })
        print("改写后内容:\n" + res.content)

        res = conversational_rag_chain.invoke({
            "input": inputs
        }, config={
            "configurable": {"session_id": "test123"}
        })
        print("回答:\n" + res["answer"])

输出展示

请输入:介绍一下《白蛇:浮生》这部电影
改写后内容:
请简要概述一下电影《白蛇:浮生》的内容
回答:
《白蛇:浮生》是一部中国大陆制作的动画电影,属于“白蛇”系列的最终章,由陈健喜和李佳锴执导,王微担任编剧。该电影的主演包括张喆、杨天翔、唐小喜、张赫、刘琮、郑小璞、马程、林强和李楠,以及李佳锴。《白蛇:浮生》的类型涵盖了喜剧、爱情、动画和奇幻,讲述的是在南宋临安,白蛇(小白)在五百年后终于找到了许仙(阿宣)的转世,两人在断桥相遇,开始了在人间的平凡生活。然而,杭州城中发生的一系列怪事,金山寺的法海前来除妖,意外揭开了小白和小青(小青)的蛇妖身份,许仙目睹了小白的巨蟒形态,引发了一场生死情劫。

电影的上映日期为2024年8月10日(中国大陆),片长为133分钟。在豆瓣上,该电影的评分是7.1分,基于68261人的评价,其中5星评价占比16.3%,4星评价占比36.0%,3星评价占比37.0%,2星评价占比8.9%,1星评价占比1.8%。该电影被认为在动画片中好于75%,在爱情片中好于84%。

《白蛇:浮生》的剧情简介提到了故事发生在南宋临安,小白与许仙在断桥相遇,开始了平凡的人间生活。然而,随着杭州城中发生的怪事,金山寺的法海前来除妖,意外揭露了小白和小青的蛇妖身份,引发了一场生死情劫。电影探讨了生死、爱情与命运的主题。

在豆瓣上,有700篇关于《白蛇:浮生》的影评,涵盖了从正面到负面的各种观点。影评人杉姐评价说:“我中国人的DNA,都被它唤醒了!”这表明电影在某些方面成功地触动了观众的情感。同时,也有影评人对电影的剧情、角色发展和整体质量提出了批评,认为它在某些方面表现平庸或降智。

《白蛇:浮生》的视频和图片部分包含了预告片和电影截图,供观众预览和欣赏。此外,还有其他与“白蛇”系列相关的电影推荐,如《聊斋:兰若寺》、《白蛇2:青蛇劫起》、《新神榜:杨戬》、《长安三万里》、《落凡尘》、《穿过月亮的旅行》、《八戒之天蓬下界》、《雄狮少年2》、《大雨》和《我想活出怎样的人生》等。
===================================================
请输入:这部电影是白蛇系列的第几部
改写后内容:
白蛇系列电影中,《白蛇:浮生》是哪一部作品
回答:
《白蛇:浮生》是“白蛇”系列的最终章,标志着该系列的完结。在时间顺序上,它应该被视为三部曲的“正传”,前有《白蛇:缘起》作为“前传”,后有《白蛇2:青蛇劫起》作为“后传”。因此,《白蛇:浮生》是“白蛇”系列的第三部电影。
====================================================
请输入:这个电影好看吗
改写后内容:
您觉得电影《白蛇:浮生》是否值得一看呢
回答:
《白蛇:浮生》在豆瓣上获得了7.1的评分,基于68261人的评价,这表明它在动画片中好于75%,在爱情片中好于84%。从这个评分来看,大部分观众对这部电影持正面评价。

然而,电影的评价存在一定的主观性,不同观众可能会有不同的看法。一些影评人对电影的剧情、角色发展和整体质量提出了批评,认为它在某些方面表现平庸或降智。例如,有影评人提到电影中“爱让我接受最真实的你”,这可能意味着电影在情感表达和角色塑造上得到了认可,但也有人批评电影的剧情走向和角色处理。

总的来说,《白蛇:浮生》在动画和爱情片类别中获得了相对较高的评价,但是否“好看”还需根据个人的观影喜好和期待来判断。建议在观看前,可以参考更多的影评和评分,以及查看预告片,以更好地了解电影的内容和风格,从而决定是否符合自己的观影需求。

参考

Conversational RAG | 🦜️🔗 LangChain

Qdrant | 🦜️🔗 LangChain

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

江大白 | 大模型时代,CV目标检测任务,会走向何方?

本文来源公众号“江大白”,仅用于学术分享,侵权删,干货满满。 原文链接:大模型时代,CV目标检测任务,会走向何方? 以下文章来源于知乎:深度眸 作者:深度眸 编辑&#…

华为手机永久关闭自动亮度 | 使用智慧场景

问题 使用华为手机时,无法在设置中永久性关闭自动亮度,因为每次手机重启后都会自动打开自动亮度。此问题目前无法通过设置去解决,但可以通过华为的智慧场景解决,下文介绍解决方案。 解决方案 智慧场景 打开智慧生活APP&#xf…

JavaScript 作用链

JavaScript 作用链是指在 JavaScript 中查找变量时所遵循的规则和路径。它描述了当前执行上下文及其父级上下文之间的关系。作用链用于解析变量,当在一个作用域中查找变量时,如果当前作用域中没有找到,则会沿着作用链向上查找,直到…

华为OD机试真题 - 查找充电设备组合 - 子集和问题(Java/Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Java/Python/JS/C/C++)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX…

51单片机——LED点阵屏

1、点阵屏简介 LED点阵屏由若干个独立的LED组成,LED以矩阵的形式排列,以灯珠亮灭来显示文字、图片、视频等。LED点阵屏广泛应用于各种公共场合,如汽车报站器、广告屏以及公告牌等 LED点阵屏分类 按颜色:单色、双色、全彩 …

多目标应用:基于SPEA2的移动机器人路径规划研究(提供MATLAB代码)

一、机器人路径规划介绍 移动机器人(Mobile robot,MR)的路径规划是 移动机器人研究的重要分支之,是对其进行控制的基础。根据环境信息的已知程度不同,路径规划分为基于环境信息已知的全局路径规划和基于环境信息未知或…

【网络安全】命令执行漏洞—远程代码执行及远程系统命令

命令执行漏洞是指Web应用程序中由于对用户输入的验证不足,导致恶意用户能够构造并传递一些预期之外的命令给服务器,从而在服务器上执行任意命令。这种漏洞可能允许攻击者获取敏感信息、破坏服务、访问系统文件,甚至获得服务器的控制权。 一、…

minio文件存储+ckplayer视频播放(minio分片上传合并视频播放)

文章目录 参考简述效果启动minio代码配置类RedisConfigWebConfigMinioClientAutoConfigurationOSSPropertiesapplication.yml 实体类MinioObjectResultStatusCodeOssFileOssPolicy 工具类FileTypeUtilMd5UtilMediaTypeMinioTemplate 文件分片上传与合并MinioFileControllerMini…

JVM堆内存空间(heap)

在Java程序运行时,系统运行过程中产生的大部分实例对象以及数组对象都会被放到堆中存储。 默认情况下,如果不通过参数强制指定堆空间大小,那么JVM会根据当前所在的平台进行自适应调整,起始大小默认为当前物理机器内存的1/64&…

我的第一个QT程序_创建项目_全程图解

创建项目 1.打开QT开发工具 2.点【创建项目】 在弹出的窗口的项目列表中选择【Application(Qt)】中间列选择 第一项 如上图。 3.输入项目名称和项目保存的路径 4.Build system下拉列表中有三个选项,虽然Qt6主推CMake,所以可以默认,直接下一步…

【用Java学习数据结构系列】震惊,二叉树原来是要这么学习的(二)

看到这句话的时候证明:此刻你我都在努力 加油陌生人 个人主页:Gu Gu Study 专栏:用Java学习数据结构系列 喜欢的一句话: 常常会回顾努力的自己,所以要为自己的努力留下足迹 喜欢的话可以点个赞谢谢了。 作者&#xff…

基于yolov8的玉米病害检测系统python源码+onnx模型+评估指标曲线+精美GUI界面

【算法介绍】 基于YOLOv8的玉米病害检测系统是一款利用前沿深度学习技术开发的智能农业工具。该系统以YOLOv8为核心算法,通过大量玉米病害图片的训练,能够精准识别玉米害虫病害。 该系统具备高效、准确的检测能力,支持图片、批量图片、视频…

7.整数反转

7.整数反转 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。 假设环境不允许存储 64 位整数(有符号或无符号)。 示例 1&#x…

Linux主机网络参数的设置—IP地址的作用和类型

网络参数管理 一.网络参数 主机名,IP地址,子网掩码,网关,DNS服务器地址 1.配置主机名 hostname命令来查看当前系统的主机名, hosnamectl set-hostname 修改centos7的主机名, 建议以FQDN的&#xff…

顶级 USB 恢复工具探讨:2024 -2025 年最佳 USB 数据恢复

在数字数据与物理文档一样重要的时代,丢失 USB 驱动器中的数据可能是一种令人恐慌的经历。无论是重要的工作文件、珍贵的照片还是重要文档,数据丢失都会以难以想象的方式让您倒退。值得庆幸的是,一些 USB 恢复工具旨在帮助您度过这些可怕的时…

【Delphi】一种生成透明 Icon 图标方法、原理

在程序开发中,我们会遇到制作程序的主图标,windows下程序的图标给是要求是ico格式,也就是常说的Icon。本文介绍一种Delphi利用windos API生成icon的方法。 在制作ico图标的时候,我们需要两幅bitmap图片,一幅我们称作掩…

单片机中的定时器:精确时间的掌控者

在单片机的世界里,定时器就像是一个精确的时间守护者,默默地为各种任务提供准确的时间基准。从简单的定时功能到复杂的实时控制系统,定时器都发挥着至关重要的作用。本文将深入探讨单片机中的定时器,包括其工作原理、应用场景以及…

华为OD机试真题 - 高效货运 - 暴力搜索(Java/Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中,刷题点这里 专栏导读 本专栏收录于《华为OD机试真题(Java/Python/JS/C/C++)》。 刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX…

JAVA开源项目 加油站管理系统 计算机毕业设计

本文项目编号 T 003 ,文末自助获取源码 \color{red}{T003,文末自助获取源码} T003,文末自助获取源码 目录 一、系统介绍二、演示录屏三、启动教程四、功能截图五、文案资料5.1 选题背景5.2 国内外研究现状5.3 可行性分析 六、核心代码6.1 查…

CTFHub技能树-备份文件下载-网站源码

目录 法一:使用自动化工具扫描 方法二:使用dirsearch目录扫描器扫描 法一:使用自动化工具扫描 import requestsurl1 http://challenge-0e8fe706d11de65e.sandbox.ctfhub.com:10800/ # url为被扫描地址,后不加‘/’# 常见的网…