Langchain-实战篇-搭建本地问答机器人-01

f146ed0fe16c4b51a17db0a7e247ed3b.png

项目背景

在这个快节奏的职场世界里,我们每个人都可能在某个时刻,化身为一头辛勤的牛或一匹奔腾的马,面对入职签合同时的迷茫,或是离职时的纠纷,心中难免会涌现出各种疑问。比如:

  • "这份合同里的条款,是保护我还是给我挖坑?"
  • "加班费怎么算,难道是按草料的重量来计价的吗?"
  • "离职时的赔偿金,是不是该按马的奔跑速度来计算?"

别担心,就算我们不是法律专家,也能在《中华人民共和国劳动法》的庇护下,找到解决问题的钥匙。现在,让我们用一点幽默来轻松一下,同时开发一款劳动法问答机器人,让它成为我们职场路上的得力助手。

实施方案

简单来讲,我们的计划是将《中华人民共和国劳动法》的内容向量化,并存储到向量化数据库中。在用户提出与劳动法相关的问题时,将问题检索向量数据库,通过提示工程组装交给大模型进行回复,最终得到最终答案。

模型选择:GPT-3.5 Turbo

下面为开发这个项目的流程说明以及详解:

e840f26dcab54438b5d9a965f9fe1ef8.png

1. 数据加载 (Loading)

  • 描述: 将《中华人民共和国劳动法》的法律文档加载到本地系统中。
  • 目的: 使文档变成LangChain能够识别和处理的格式。

2. 文本切割 (Split)

  • 描述: 将大型法律文档切割成指定大小的文档块。
  • 目的: 便于后续的存储和高效检索。

3. 向量化存储 (Storage)

  • 描述: 对切割后的文档块进行向量化处理。
  • 目的: 将文档块转换为LangChain可以索引的向量形式,并存储到向量数据库中。

4. 数据检索 (Retrieval)

  • 描述: 用户提出问题后,在向量数据库中检索相关的文档块。
  • 目的: 快速找到与用户问题最相关的法律条文。

5. 提示工程(Prompt)

  • 描述: 组装用户输入的问题,以及检索后的文档快。
  • 目的: 为LLM提供数据。

在整个项目开发过程中,LangChain平台提供了一系列工具和组件,极大地简化了开发流程,使我们能够轻松实现各项功能。

环境配置

安装python 3.11版本

网上已经有很多教程了,这里就不累赘了

安装langchain以及其它会用到的包

pip install langchain==0.2.6

pip install bs4

pip install langchain_community

pip install langchain_openai

step1 数据处理

1、数据加载  Loading

准备数据,《中华人民共和国劳动法》内容链接:中华人民共和国劳动法

Langchain提供了很多文档加载器,以面对各种类型的文档。本次我们使用的WebBaseLoader

详细使用方法请看我文章中第二小节

03|LangChain | 从入门到实战 -六大组件之Retrival_longcontext-CSDN博客

当然你也可以看官方文档:WebBaseLoader | 🦜️🔗 LangChain

我们来观察一下数据,可以看到所有条目都是位于div class="TRS_PreAppend"

91c762c7d4c045669ace43957524ca60.gif

8ac867390c5c4eb1829be2744dbe6e90.png

加载代码

import bs4
from langchain_community.document_loaders import WebBaseLoader
import os
os.environ["OPENAI_API_KEY"] = 'openAi key'
os.environ["OPENAI_API_BASE"] = "代理"

loader = WebBaseLoader(
    web_path="https://www.mohrss.gov.cn/SYrlzyhshbzb/zcfg/flfg/201601/t20160119_232110.html",
    bs_kwargs=dict(parse_only=bs4.SoupStrainer(
            class_=("TRS_PreAppend")
        ))
)
docs = loader.load()
print()

打上断点可以发现,此时得到了一个 big documents 

Langchain工具中的,WebBaseLoader 将 url网页的代码配合bs4 提取 html数据中 div 标签属性为TRS_PreAppend的数据。

d496e29926374703b016ac5f2ee9fcc6.png

2、切割数据 Split

现在我们有了数据,但是是一个非常大的文本内容。

或许你有疑问,为啥要切割呢?

在我以往的文章中也讲过,LLM对于一次对话的token是有限制的。当然现在也有许多非常优秀的大模型甚至可以做到一次对话128k,但是本次我们使用的模型为 GPT-3.5 Turbo ,所以还是需要切割的。

所以需要需要切割成小块的 chunk documents,以提交给LLM,才能进行问答。

同样的Langchain也提供了非常多的切割方法。

03|LangChain | 从入门到实战 -六大组件之Retrival_longcontext-CSDN博客我在这个小节有介绍常用的

0868f345dc0e4892b170976380e0fa53.png

Langchain官方介绍地址:How-to guides | 🦜️🔗 LangChain

17f284df1c8a4c6fbc40e56ddb9cdff2.png

在这里我们使用一个最基本的切割器:RecursiveCharacterTextSplitter

此文本分割器是推荐用于一般文本的分割器。它由字符列表参数化。它会尝试按顺序分割这些字符,直到块足够小。默认列表是["\n\n", "\n", " ", ""]。这样做的目的是尽量将所有段落(然后是句子,然后是单词)放在一起,因为这些段落在一般情况下似乎是语义上最相关的文本片段。

编写切割代码

from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=1000, 
        chunk_overlap=200
)
splits = text_splitter.split_documents(docs)
  • chunk_size:指定切割的每个块的大小(以字符为单位)
  • chunk_overlap:指定块之间的重叠部分的大小(以字符为单位)

这个是指切割后的每个 document 里包含几个上一个 document 结尾的内容, 主要作用是为了增加每个 document 的上下文关联。

比如,chunk_overlap=0时, 第一个 document 为 aaaaaa,第二个为 bbbbbb;

当 chunk_overlap=2 时, 第一个 document 为 aaaaaa,第二个为 aabbbbbb。

不过,这个也不是绝对的,要看所使用的那个文本分割模型内部的具体算法。

我们来看看切割后的内容,得到11个块

f03b4d8cecc8487299bf682ec58b098b.png

3、向量化存储 Vector

在当前项目中,我们已经成功解析并拆分获得了11个数据块。为了提高检索效率,避免在每次检索时重新进行解析操作,我们将这些数据块存储到数据库中,以便在需要时能够直接从数据库中快速查询。

我们选择使用向量数据库来存储和查询这些数据块。向量数据库的工作原理是将数据项转换成向量形式,这使得它在处理相似性搜索和聚类等任务时表现出色,具有高效率。

设想一下,如果我们有一系列复杂的机械零件,每个零件都有其独特的属性,如耐用性、重量、尺寸和材料类型。向量数据库将这些属性转化为数值向量,例如[(7, 2, 5, 3), (6, 3, 4, 2)],每个元素代表该零件在某个特定属性上的评分或量度。当我们需要找到与给定零件相似的其他零件时,向量数据库会先将该零件的属性转换为向量,然后在数据库中搜索并返回与之最相似的其它零件的向量。

为了将数据块存入向量数据库,我们首先需要对这些数据进行向量化处理,也就是常说的“数据嵌入”。在这个过程中,LangChain 提供了多种嵌入技术,我们选择了 OpenAIEmbeddings。这种嵌入方式利用 OpenAI 的 text-embedding-ada-002 模型来实现数据的向量化。在使用此嵌入方式之前,我们需要设置 OPENAI_API_KEY,这是调用 OpenAI 服务所需的密钥。

通过这种方式,我们不仅优化了数据的存储和检索过程,还为系统增添了强大的语义理解能力,确保了在处理复杂查询时的准确性和效率。

向量数据库有很多,需要了解可以跳转到这个地方查看:Vector stores | 🦜️🔗 LangChain

这里我们选择使用Chroma,更多用法:Chroma | 🦜️🔗 LangChain

安装

pip install langchain-chroma

现在,我们编写一个代码,将前面切割好的文档,存储到向量数据库中

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
db = Chroma.from_documents(
    documents=splits,
    embedding=OpenAIEmbeddings(),
    persist_directory="./chroma_db")
  • documents:上一步切割后的文档块列表。
  • embedding:嵌入函数,这里我们使用 OpenAI 的OpenAIEmbeddings。
  • persist_directory:数据存储的目录。

执行代码后,会在项目目录下自动生成了chroma_db目录,存放着向量化后的数据

7d86cefb61d5448798a7d770a263031e.png

4、数据处理完整代码

到现在,我们完成了从数据获取,到切割,存储到向量数据库的步骤,此刻贴上 etl_datas.py完整代码

import bs4
from langchain_community.document_loaders import WebBaseLoader

# 配置OpenAi密匙
import os
os.environ["OPENAI_API_KEY"] = 'openai key'
os.environ["OPENAI_API_BASE"] = "代理地址"

# 构建加载器,加载URL数据
loader = WebBaseLoader(
    web_path="https://www.mohrss.gov.cn/SYrlzyhshbzb/zcfg/flfg/201601/t20160119_232110.html",
    bs_kwargs=dict(parse_only=bs4.SoupStrainer(
        class_=("TRS_PreAppend")
    ))
)
docs = loader.load()

# 切割文档
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)

# 向量化数据
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
db = Chroma.from_documents(
    documents=splits,
    embedding=OpenAIEmbeddings(),
    persist_directory="./chroma_db")

step2 创建问答机器人

a48009aefc9347ccba19aeb43d09cb3c.png

现在我们要开始构建第二步,创建问答机器人。

这里运用Langchain当中的模块清单:

  1. Retrieval 检索器,Langchain集成了与向量数据库 增删改查的封装

  2. Chain  我在文章当中有详细介绍 04|LangChain | 从入门到实战 -六大组件之chain-CSDN博客b41a090847ae4657b160f57b78b34420.png

  3. Prompt  提示模版工程,让LLM获悉外部的数据,以解决某些任务,得到具体结果行为
  4.  LangServe  LangServe帮助开发人员将可运行LangChain 对象和链部署 为 REST API。更多内容参考:GitHub - langchain-ai/langserve: LangServe 🦜️🏓

总的来说,Chain 帮助我们串联整个流程,并且利用 LangServe,快速构建交互API,配合web网页进行操作。

1、创建提示 Prompt

你可以理解 Prompt是与LLM沟通的方式,Prompt编写的好坏决定了最后的效果,关于Prompt也有

提示词是一门大学问,可以阅读一下这个地址:🟢 AI 简介

这里我们运用RAG工程

RAG(Retrieval Augmented Generation)检索增强生成,通过检索增强大模型的生成能力。

079ea8b26a2646f794365165d7b6c100.png

参考论文:https://arxiv.org/abs/2005.11401

假设一位你需要从繁杂的《中华人民共和国劳动法》中找到相关的法律条文来协助处理劳动争议或合同问题,那么他有三种方式可以使用:

  • 最原始的方法:他可以直接翻阅纸质版的《中华人民共和国劳动法》,或者查询其电子版,然后仔细阅读以掌握具体的法律条文和操作方法。如果他遇到的劳动问题较为复杂,就需要综合多个章节的内容,自行分析和理解法律条文的适用。

  • 借助问答机器人:他也可以向问答机器人(chatbot)咨询,机器人能够提供相关的法律知识。但这种方法可能存在两个问题:一是机器人可能只能提供类似常见问题解答(FAQ)式的服务,需要用户自己整合答案;二是机器人需要大量的预训练和知识库的构建,这通常需要专业法律人员的大量工作,逐条输入法律条目及其相似问法,这在大规模推广时可能不太实用。

  • 使用RAG技术:第三种方式是将《中华人民共和国劳动法》的电子版上传到RAG(Retrieval-Augmented Generation)系统中,系统能在几分钟内创建索引,供专员进行咨询。RAG系统不仅能提供综合了整个法律文本的多个知识点的答案,还能以专家的口吻给出建议:“要解决这个问题,你需要先确认两个前提条件,并有三种可能的解决途径。下面我们逐步分析具体的操作步骤…”。

通过RAG技术,你可以能够快速获得全面、综合的法律建议,极大地提高了工作效率和解决问题的准确性。这种方法不仅减少了查找和分析法律条文的时间,还为用户提供了一种更为智能和高效的法律咨询服务。

下面我们使用Langchain提供的一个最基本的RAG 提示

"""
You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.

Question: {question} 

Context: {context} 

Answer:
"""
 

翻译成中文

你是问答任务的助手。使用以下检索到的上下文来回答问题。如果你不知道答案,就说你不知道。最多使用三个句子并保持答案简洁。
问题: {question}
上下文: {context}
答案:

这里我们使用Langhcain最基础的模版 PromptTemplate ,可以看到下面有2个参数

  1. {question}  将用户传入的问题进行填充
  2. {context}  向量数据库检索出来的数据
from langchain.prompts.prompt import PromptTemplate

prompt_template_str = """
You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.

Question: {question} 

Context: {context} 

Answer:
"""
prompt_template = PromptTemplate.from_template(prompt_template_str)

我在我的文章中有详细介绍:02|LangChain | 从入门到实战 -六大组件之Models IO_langchain编程:从入门到实践-CSDN博客

c3ddfa6b171644e8a57fd7496f7f8838.png

2、检索向量数据库

Langchain集成了与向量数据库 增删改查的封装,开箱即用。

前面我们将数据存储在本地db中,现在,我们利用Langchain查询一下DB,看看效果。

# 配置OpenAi密匙
import os

os.environ["OPENAI_API_KEY"] = ''
os.environ["OPENAI_API_BASE"] = ""

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings

# 链接本地向量数据库
vectorstore = Chroma(
    persist_directory="./chroma_db",
    embedding_function=OpenAIEmbeddings()
)

# 构建检索器
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 4}
)

# 查询
docs = retriever.invoke("劳动者解除劳动合同需要提前多久告诉人事?")

print()

在上面代码中使用的是 OpenAIEmbeddings() 向量模型

并且利用检索器的相似度算法,去查询检索出4条可能相关的知识,并且我们看第一个检索出来的数据,可以看到答案就在这里

72706f3488a5405f9f98af321ae9cee2.png

3、创建Chain

现在我们已经得到了 检索出来的知识,现在我们要将前面流程通过Langchain提供的Chain串联起来。

在此之前,我们先安装一个包,用于后面生成Chain的图

pip install grandalf

其中这个包会比较麻烦

pip install pygraphviz

如果在你安装 pygraphviz 这个包报错了,请参考我另外一个方法

GitHub - Pomurnik/pygraphviz-windows-whl: Wheels for pygraphviz Python libary with Graphviz 3.0 version.

3e26089a56df45b287f3e50247733984.png

因为我们是python3.11 环境,所以选择这个,点击下载

82f39f95ffb240b59df3db30b864c6f9.png

下载好的文件复制到工程下,进入到这个目录执行安装即可

pip install .\pygraphviz-1.12-cp311-cp311-win_amd64.whl

a55cbd4ced93438e975f30273cceb4b5.png

现在运行我这个代码

# 配置OpenAi密匙
import os

os.environ["OPENAI_API_KEY"] = ''
os.environ["OPENAI_API_BASE"] = ""

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings

# 链接本地向量数据库
vectorstore = Chroma(
    persist_directory="./chroma_db",
    embedding_function=OpenAIEmbeddings()
)

# 构建检索器
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 4}
)

# 查询
# docs = retriever.invoke("劳动者解除劳动合同需要提前多久告诉人事?")


# 将前面查询出来的结果,提取成一个大的文本
def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

# 构建RAG链
from langchain.prompts.prompt import PromptTemplate

prompt_template_str = """
You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.

Question: {question} 

Context: {context} 

Answer:
"""
prompt_template = PromptTemplate.from_template(prompt_template_str)

from langchain_core.runnables import RunnablePassthrough
from langchain_community.chat_models import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI()
rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()} # 组装用户问题跟检索后的知识
    | prompt_template # 提示模版
    | llm # 大模型
    | StrOutputParser() # 结构化输出
)
# 生成Chain的调用图
rag_chain.get_graph().draw_png("rag-chain.png")

我们在目录下会得到一幅图,这个过程为链的调用过程,可能看起来有点抽象。

8bd1657be7d94043beae0cf7949b0d2f.png

现在我将图简化一下说明

518edab319234264844c298daf736b30.png

我们配合代码片段看

首先我们来说代码,这种写法为langchain的 LCEL 编码格式,LangChain Expression Language (LCEL) 翻译过来叫做langchain expression语言,详细内容参考

Conceptual guide | 🦜️🔗 LangChain

4eb541ede5974d0e9276a8eecf54fec8.png

       在构建劳动法问答机器人的过程中,Retriever组件扮演着至关重要的角色,它是整个信息检索流程的起点。用户输入的问题将首先被传递给Retriever,它负责在向量数据库中查询并筛选出相关的法律文档列表。以下是对您提供的段落进行优化后的描述:

在劳动法问答机器人的工作流程中,Retriever 是接收用户查询的第一站。用户提出的每一个问题,无论是关于劳动合同的细节还是劳动争议的解决,都会被自动送入Retriever进行处理。

Retriever的核心任务是从向量数据库中检索与用户问题最相关的法律文档。这一步骤完成后,检索到的文档列表将被传递给Format_docs组件。Format_docs的作用是将文档列表转换成适合LLM(大型语言模型)处理的字符串格式,确保信息的流畅性和可读性,并将转换后的字符串赋值给context变量,为下一步的LLM处理提供上下文。

在这一过程中,RunnablePassthrough作为一个直通组件,确保了从RetrieverFormat_docs的数据流转。由于我们处于整个链的第一环节,RunnablePassthrough()将捕获用户原始的问题,并将其作为问题变量question进行传递。

随着**contextquestion两个关键变量的准备就绪,我们便可以利用它们与预先定义的提示词模板结合,构建最终的prompt。这个prompt将引导LLM生成精准的答案。

LLM在接收到prompt后,将运用其语言理解与生成能力,提供一个经过深思熟虑的答案。生成的答案随后被送入**StrOutputParser**——一个专门的输出解析器,它负责对答案进行格式化处理,确保输出结果的准确性和可读性。

最终,经过StrOutputParser处理的答案将以一种易于理解且专业的形式呈现给用户,完成整个问答过程。

4、部署应用

我们现在都是代码级别,需要一个web页面及其后端接口才能更好的进行交互。

LangServe 帮我们解决了这个问题

LangServe GitHub - langchain-ai/langserve: LangServe 🦜️🏓

c94faf00f39d41b3a97db2e44b62f7c7.png

详细内容见:langchain/templates/README.md at master · langchain-ai/langchain · GitHub

安装包

pip install langserve

pip install sse_starlette

编写服务代码 app.py

cad7474d867e430395a1169ff878f2fb.png

# 配置OpenAi密匙
import os

os.environ["OPENAI_API_KEY"] = ''
os.environ["OPENAI_API_BASE"] = ""

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings

# 链接本地向量数据库
vectorstore = Chroma(
    persist_directory="./chroma_db",
    embedding_function=OpenAIEmbeddings()
)

# 构建检索器
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 4}
)

# 查询
# docs = retriever.invoke("劳动者解除劳动合同需要提前多久告诉人事?")


# 将前面查询出来的结果,提取成一个大的文本
def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

# 构建RAG链
from langchain.prompts.prompt import PromptTemplate

prompt_template_str = """
You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.

Question: {question} 

Context: {context} 

Answer:
"""
prompt_template = PromptTemplate.from_template(prompt_template_str)

from langchain_core.runnables import RunnablePassthrough
from langchain_community.chat_models import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI()
rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()} # 组装用户问题跟检索后的知识
    | prompt_template # 提示模版
    | llm # 大模型
    | StrOutputParser() # 结构化输出
)
# 生成Chain的调用图
# rag_chain.get_graph().draw_png("rag-chain.png")

from fastapi import FastAPI
from langserve import add_routes
app = FastAPI(
  title="劳动法智能助手",
  version="1.0",
)
# 3. Adding chain route
add_routes(
    app,
    rag_chain,
    path="/low_ai",
)
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="localhost", port=7777)

现在咱们运行脚本

e84b960ce0a742e993f7d1737e9fc40d.png

访问 http://localhost:7777/low_ai/playground/

现在,输入你的问题!进行测试吧!

cd550283dac54c9d8559da25f62c13c6.gif

完整代码

数据处理:数据加载+数据切割+存储向量数据库

etl_datas.py

import bs4
from langchain_community.document_loaders import WebBaseLoader

# 配置OpenAi密匙
import os
os.environ["OPENAI_API_KEY"] = 'openai key'
os.environ["OPENAI_API_BASE"] = "代理地址"

# 构建加载器,加载URL数据
loader = WebBaseLoader(
    web_path="https://www.mohrss.gov.cn/SYrlzyhshbzb/zcfg/flfg/201601/t20160119_232110.html",
    bs_kwargs=dict(parse_only=bs4.SoupStrainer(
        class_=("TRS_PreAppend")
    ))
)
docs = loader.load()

# 切割文档
from langchain.text_splitter import RecursiveCharacterTextSplitter
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=200)
splits = text_splitter.split_documents(docs)

# 向量化数据
from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings
db = Chroma.from_documents(
    documents=splits,
    embedding=OpenAIEmbeddings(),
    persist_directory="./chroma_db")

应用构建:创建 llm ,创建prompt,检索数据库,构建 web 服务

app.py

# 配置OpenAi密匙
import os

os.environ["OPENAI_API_KEY"] = 'openai key'
os.environ["OPENAI_API_BASE"] = "代理地址"

from langchain_community.vectorstores import Chroma
from langchain_openai import OpenAIEmbeddings

# 链接本地向量数据库
vectorstore = Chroma(
    persist_directory="./chroma_db",
    embedding_function=OpenAIEmbeddings()
)

# 构建检索器
retriever = vectorstore.as_retriever(
    search_type="similarity",
    search_kwargs={"k": 4}
)

# 查询
# docs = retriever.invoke("劳动者解除劳动合同需要提前多久告诉人事?")


# 将前面查询出来的结果,提取成一个大的文本
def format_docs(docs):
    return "\n\n".join(doc.page_content for doc in docs)

# 构建RAG链
from langchain.prompts.prompt import PromptTemplate

prompt_template_str = """
You are an assistant for question-answering tasks. Use the following pieces of retrieved context to answer the question. If you don't know the answer, just say that you don't know. Use three sentences maximum and keep the answer concise.

Question: {question} 

Context: {context} 

Answer:
"""
prompt_template = PromptTemplate.from_template(prompt_template_str)

from langchain_core.runnables import RunnablePassthrough
from langchain_community.chat_models import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
llm = ChatOpenAI()
rag_chain = (
    {"context": retriever | format_docs, "question": RunnablePassthrough()} # 组装用户问题跟检索后的知识
    | prompt_template # 提示模版
    | llm # 大模型
    | StrOutputParser() # 结构化输出
)
# 生成Chain的调用图
# rag_chain.get_graph().draw_png("rag-chain.png")

from fastapi import FastAPI
from langserve import add_routes
app = FastAPI(
  title="劳动法智能助手",
  version="1.0",
)
# 3. Adding chain route
add_routes(
    app,
    rag_chain,
    path="/low_ai",
)
if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="localhost", port=7777)

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

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

相关文章

Mongodb集群中的分布式读写

学习mongodb,体会mongodb的每一个使用细节,欢迎阅读威赞的文章。这是威赞发布的第81篇mongodb技术文章,欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题,欢迎在文章下面点个赞,或者关…

百元蓝牙耳机推荐2024,百元蓝牙耳机排行榜盘点

在2024年面对琳琅满目的蓝牙耳机选项,消费者往往难以抉择,特别是在预算有限的情况下,如何在众多产品中挑选出既满足质量又符合预算的耳机成为了一个不小的挑战。 为了帮助大家在繁多的选择中找到真正物有所值的百元蓝牙耳机,我们…

vue响应式原理细节分享

在讲解之前,我们先了解一下数据响应式是什么?所谓数据响应式就是建立响应式数据与依赖(调用了响应式数据的操作)之间的关系,当响应式数据发生变化时,可以通知那些使用了这些响应式数据的依赖操作进行相关更…

【JavaEE】JVM

文章目录 一、JVM 简介二、JVM 运行流程三、JVM 运行时数据区1、堆(线程共享)2、Java虚拟机栈(线程私有)3、本地方法栈(线程私有)4、程序计数器(线程私有)5、方法区(线程…

# 音频处理4_傅里叶变换

1.离散傅里叶变换 对于离散时域信号 x[n]使用离散傅里叶变换(Discrete Fourier Transform, DFT)进行频域分析。 DFT 将离散信号 x[n] 变换为其频谱表示 X[k],定义如下: X [ k ] ∑ n 0 N − 1 x [ n ] e − j 2 π k n N X[k]…

.NET 漏洞情报 | 某整合管理平台SQL注入

01阅读须知 此文所提供的信息只为网络安全人员对自己所负责的网站、服务器等(包括但不限于)进行检测或维护参考,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵操作。利用此文所提供的信息而造成的直接或间接后果和损失&#xf…

揭秘Wish自养号秘诀:新手卖家如何快速出单?

对于卖家来说,如果想要提升店铺的转化率和销量,有几个关键策略是必不可少的: 一、精心挑选热销产品 成功的第一步在于选品。选择热销产品如同掌握了成功的钥匙。卖家需要深入分析平台用户群体,了解他们的需求和偏好。例如&#…

Tampermonkey 油猴脚本使用教程

Tampermonkey 油猴脚本使用教程 一、Tampermonkey 油猴脚本简介 Tampermonkey 是一款流行的浏览器扩展,它允许用户通过用户脚本增强网页功能或改变网页的外观。它支持包括 Chrome、Microsoft Edge、Safari、Opera Next 和 Firefox 在内的多种浏览器。Tampermonkey…

【C++ 初阶路】--- C++内存管理

目录 一、C/C内存分布二、C内存管理方式2.1 new/delete操作内置类型2.2 new和delete操作自定义类型 三、operator new与operator delete函数四、new和delete的实现原理4.1 内置类型4.2 自定义类型 一、C/C内存分布 int globalVar 1; static int staticGlobalVar 1; void Tes…

大模型+多模态合规分析平台,筑牢金融服务安全屏障

随着金融市场的快速发展,金融产品和服务日趋多样化,消费者面临的风险也逐渐增加。 为保护消费者权益,促进金融市场长期健康稳定发展,国家监管机构不断加强金融监管,出台了一系列法律法规和政策文件。对于金融从业机构…

代码托管服务:GitHub、GitLab、Gitee

目录 引言GitHub:全球最大的代码托管平台概述功能特点适用场景 GitLab:一体化的开发平台概述功能特点适用场景 Gitee(码云):中国本土化的代码托管服务概述功能特点适用场景 功能对比结论 引言 在现代软件开发中&#…

Pickle, SafeTensor, GGML和GGUF

如今,大型语言模型的使用方式有以下几种: 作为 OpenAI、Anthropic 或主要云提供商托管的专有模型的 API 端点作为从 HuggingFace 的模型中心下载的模型工件和/或使用 HuggingFace 库进行训练/微调并托管在本地存储中作为针对本地推理优化的格式的模型工…

机器学习 中数据是如何处理的?

数据处理是将数据从给定形式转换为更可用和更理想的形式的任务,即使其更有意义、信息更丰富。使用机器学习算法、数学建模和统计知识,整个过程可以自动化。这个完整过程的输出可以是任何所需的形式,如图形、视频、图表、表格、图像等等&#…

Linux基础篇——目录结构

基本介绍 Linux的文件系统是采用级层式的树状目录结构,在此结构中的最上层是根目录"/",然后在根目录下再创建其他的目录 在Linux中,有一句经典的话:在Linux世界里,一切皆文件 Linux中根目录下的目录 具体的…

PHP留守儿童关爱之家网站-计算机毕业设计源码11079

目录 1 绪论 1.1 研究背景 1.2研究意义 1.3 论文结构与章节安排 2 留守儿童关爱之家网站系统分析 2.1 可行性分析 2.2 系统功能分析 2.3 系统用例分析 2.4 系统流程和逻辑 2.5本章小结 3 留守儿童关爱之家网站总体设计 3.1系统结构设计 3.2系统功能模块设计 3.2 数…

基于SSM网上拍卖系统

设计技术: 开发语言:Java数据库:MySQL技术:SpringMybatisSpringMvc 工具:IDEA、Maven、Navicat 主要功能 管理员功能有个人中心,用户管理,卖家管理,商品类型管理,拍卖…

EDA 虚拟机 Synopsys Sentaurus TCAD 2017.09 下载

下载地址(制作不易,下载使用需付费,不能接受的请勿下载): 链接:https://pan.baidu.com/s/1327I58gvV1usWSqSrG7KXw?pwdo03i 提取码:o03i

AI网络爬虫001:用kimichat自动批量提取网页内容

文章目录 一、准备工作二、输入内容三、输出内容一、准备工作 在网页中按下F12键,查看定位网页元素 二、输入内容 在kimi中输入提示词: 你是一个Python编程专家,要完成一个爬取网页内容的Python脚本,具体步骤如下:在F盘新建一个Excel文件:提示词.xlsx打开网页:https:…

http.cookiejar.LoadError: Cookies file must be Netscape formatted,not JSON.解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

【Linux】线程周边002之线程安全

👀樊梓慕:个人主页 🎥个人专栏:《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》《C》《Linux》《算法》 🌝每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.Linux线程互斥 1…