LangChain 构建本地知识库问答应用

news2024/11/16 19:57:52

一、使用本地知识库构建问答应用

上篇文章基于 LangChainPrompts 提示管理构建特定领域模型,如果看过应该可以感觉出来 ChatGPT 还是非常强大的,但是对于一些特有领域的内容让 GPT 回答的话还是有些吃力的,比如让 ChatGPT 介绍下什么是 LangChain

from langchain.llms import OpenAI
import os

openai_api_key=os.environ["OPENAI_API_KEY"]
llm = OpenAI(model_name="gpt-3.5-turbo", openai_api_key=openai_api_key)
my_text = "介绍下 langChain "
print(llm(my_text))

在这里插入图片描述

可以看出回答的貌似不是我们想要的内容,还有在一些特定的场景下的问答,比如学校学生问答系统中,学生提问周一课程是什么?,这种直接让 GPT 回答的话也是有些吃力,那这种情况下怎么解决呢?

现在有了 LangChain 那实现起来就非常简答了:

例如:现有知识内容放在了 data 目录下,有如下内容:

在这里插入图片描述
其中 txt 文件记录了 LangChain 的介绍:

在这里插入图片描述
pdf 介绍了下 langchain 中的 Prompts

在这里插入图片描述
csv 记录的学生课程信息:

在这里插入图片描述

下面首先对知识内容进行载入和向量化。

3.1 文本载入及 Embedding 向量持久化

import os
# 向量数据库
from langchain.vectorstores import Chroma
# 文档加载器
from langchain.document_loaders import TextLoader, CSVLoader, PyPDFLoader
# 文本转换为向量的嵌入引擎
from langchain.embeddings.openai import OpenAIEmbeddings
# 文本拆分
from langchain.text_splitter import RecursiveCharacterTextSplitter

openai_api_key = os.environ["OPENAI_API_KEY"]

knowledge_base_dir = "./data"

doc = []
for item in os.listdir(knowledge_base_dir):
    if item.endswith("txt"):
        loader = TextLoader(file_path=os.path.join(knowledge_base_dir, item), encoding="utf-8")
        doc.append(loader.load())
    elif item.endswith("csv"):
        loader = CSVLoader(file_path=os.path.join(knowledge_base_dir, item), encoding="utf-8")
        doc.append(loader.load())
    elif item.endswith("pdf"):
        loader = PyPDFLoader(file_path=os.path.join(knowledge_base_dir, item))
        doc.append(loader.load())

print("提取文本量:", len(doc))
# 拆分
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=400)
docs = []
for d in doc:
    docs.append(text_splitter.split_documents(d))
    print("拆分文档数:", len(docs))
# 准备嵌入引擎
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
# 向量化
# 会对 OpenAI 进行 API 调用
vectordb = Chroma(embedding_function=embeddings, persist_directory="./cut")
for d in docs:
    vectordb.add_documents(d)
# 持久化
vectordb.persist()

运行后可以在 ./cut 看到持久化的向量内容:

在这里插入图片描述

3.2 构建问答

from langchain import OpenAI
# 向量数据库
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
# 文本转换为向量嵌入引擎
from langchain.embeddings.openai import OpenAIEmbeddings
import os

openai_api_key = os.environ["OPENAI_API_KEY"]
llm = OpenAI(temperature=0, openai_api_key=openai_api_key)

# 准备好你的嵌入引擎
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)

vectordb = Chroma(embedding_function=embeddings, persist_directory="./data/cut")
# 创建您的检索引擎
qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=vectordb.as_retriever())

query = "介绍下什么是 langchain?"
res = qa.run(query)
print('问题:', query, 'LLM回答:', res)

query = "介绍下 langchain 中的 prompts ?"
res = qa.run(query)
print('问题:', query, 'LLM回答:', res)

query = "周一需要上什么课?"
res = qa.run(query)
print('问题:', query, 'LLM回答:', res)

query = "周三上午需要上什么课?"
res = qa.run(query)
print('问题:', query, 'LLM回答:', res)

在这里插入图片描述
可以看出已经精准的做出回答。

正常我们使用 ChatGPT 的时候都是以流的形式进行返回,同样这里我们也可以修改为流的形式:

from langchain import OpenAI
# 向量数据库
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
# 文本转换为向量的嵌入引擎
from langchain.embeddings.openai import OpenAIEmbeddings
# 流式回调
from langchain.callbacks.streaming_stdout import StreamingStdOutCallbackHandler
import os

openai_api_key = os.environ["OPENAI_API_KEY"]
llm = OpenAI(temperature=0, openai_api_key=openai_api_key, streaming=True, callbacks=[StreamingStdOutCallbackHandler()])

# 嵌入引擎
embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)

vectordb = Chroma(embedding_function=embeddings, persist_directory="./data/cut")
# 创建您的检索引擎
qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=vectordb.as_retriever())

query = "介绍下什么是 langchain?"
qa.run(query)

在这里插入图片描述

下面配合 tornado 高性能异步非阻塞web框架,实现接口调用问答。

二、部署 WEB 服务

安装 tornado 框架:

pip install tornado -i https://pypi.tuna.tsinghua.edu.cn/simple

创建问答服务接口 server.py

from tornado.concurrent import run_on_executor
from tornado.web import RequestHandler
import tornado.gen
import utils_response
from langchain import OpenAI
# 向量数据库
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
# 文本转换为向量的嵌入引擎
from langchain.embeddings.openai import OpenAIEmbeddings
import os

class QA(RequestHandler):
    # 准备模型
    openai_api_key = os.environ["OPENAI_API_KEY"]
    llm = OpenAI(temperature=0, openai_api_key=openai_api_key)
    # 准备好你的嵌入引擎
    embeddings = OpenAIEmbeddings(openai_api_key=openai_api_key)
    vectordb = Chroma(embedding_function=embeddings, persist_directory="./cut")
    # 检索引擎
    qa = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=vectordb.as_retriever())
    print("检索引擎已加载!")

    def prepare(self):
        self.executor = self.application.pool

    @tornado.gen.coroutine
    def get(self):
        questions = self.get_query_argument('questions')
        if not questions or questions == '':
            return utils_response.fail(message='问题为空')
        result = yield self.detection(questions)
        self.write(result)

    @run_on_executor
    def detection(self, questions):
        # 开始检测
        res = self.qa.run(questions)
        return utils_response.ok(res)

路由配置,并启动服务 app.py

import tornado.web
import tornado.ioloop
import tornado.httpserver
import os
from concurrent.futures.thread import ThreadPoolExecutor
from server import QA

## 配置
class Config():
    port = 8081
    base_path = os.path.dirname(__file__)
    settings = {
        # "debug":True,
        # "autore load":True,
        "static_path": os.path.join(base_path, "resources/static"),
        "template_path": os.path.join(base_path, "resources/templates"),
        "autoescape": None
    }

# 路由
class Application(tornado.web.Application):
    def __init__(self):
        handlers = [
            ("/qa", QA),
            ("/(.*)$", tornado.web.StaticFileHandler, {
                "path": os.path.join(Config.base_path, "resources/static"),
                "default_filename": "index.html"
            })
        ]
        super(Application, self).__init__(handlers, **Config.settings)
        self.pool = ThreadPoolExecutor(10)


if __name__ == '__main__':
    app = Application()

    httpserver = tornado.httpserver.HTTPServer(app)

    httpserver.listen(Config.port)

    print("start success", "prot = ", Config.port)

    print("http://localhost:" + str(Config.port) + "/")

    tornado.ioloop.IOLoop.current().start()

在这里插入图片描述
下面使用 PostMan 进行测试:

在这里插入图片描述
已经成功获取到答案。

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

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

相关文章

地下水数值模拟软件有哪些??GMS、Visual MODFLOW Flex、FEFLOW、MODFLOW

目录 ①全流程GMS地下水数值模拟技能培养及溶质运移反应问题深度解析 ②Visual modflow Flex地下水数值模拟及参数优化、抽水实验设计与处理、复杂的饱和/非饱和地下水流分析 ③全流程各工程类型地下水环境影响评价【一级】方法与MODFLOW Flex建模 ④地下水热耦合模拟FEFLO…

亚马逊云科技通过“逆向工作法”,为客户解决数据库问题

最近,数据库领域发生了一个大事件,可以称得上是一座里程碑。全球最具权威的IT研究公司Gartner最近发布了一个消息:在2022年的全球DBMS市场份额中,亚马逊云科技的数据库超越微软,登顶第一。 亚马逊云科技、微软、Oracle这三巨头近几年一直排名前三,占据了全球DBMS超过三分之二的…

8.7 实现TCP通讯

目录 socket函数 与 通信域 套接字类型与协议 bind函数 与 通信结构体 domain通信地址族 与 通信结构体 IPv4地址族结构体 通用地址族结构体 示例&#xff1a;为套接字fd绑定通信结构体addr listen函数 与 accept函数 socket函数 与 通信域 #include <sys/types.h&g…

网络初识知识小结

目录 IP地址 端口号 协议 协议分层 TCP/IP 五层模型 传输过程 接收过程 IP地址 IP地址主要用于标识网络主机、其他网络设备&#xff08;如路由器&#xff09;的网络地址 换句话说 IP是网络中主机的身份证,可以通过IP地址定位该主机在网络中的地址 端口号 在网络通信中…

子项目中程序报:java.lang.NoClassDefFoundError

1.项目结构 NoClassDefFoundError 的 java类是在父项目中导入的 &#xff0c;子项目继承了父项目&#xff0c;在子项目中新建的main 程序中使用了该java类 大家可以看下scope 是否是 provided&#xff0c;大家选上下图的设置就可以了&#xff0c;不同版本idea 可能有差距然后重…

中移链链账户、合约与资源关系介绍

中移链链账户是在中移链区块链上注册的用户标识&#xff0c;每个账户可以持有一定数量的资源。CPU资源是账户用于执行智能合约的计算能力配额&#xff0c;决定了账户可以使用的CPU计算时间。NET资源是账户的带宽配额&#xff0c;用于处理事务的传输和网络通信。RAM资源用于存储…

【SSO】单点登录方案

一、单点登录问题 由于Http请求是无状态的请求&#xff0c;服务器无法确认登录信息。当用户登录时&#xff0c;将用户信息存储到Session中&#xff0c;Session将认证的用户信息以Cookie方式返回给客户端。每次用户请求不同的业务系统&#xff0c;都会携带Cookie去请求。保证了…

CloudCompare

零、安装 软件包直接安装 帮助文档&#xff1a;http://www.cloudcompare.org/doc 官网&#xff1a;http://www.danielgm.net/cc/ 一、操作&#xff1a;分割、删除点 1、打开文件File–>Open 支持的格式&#xff1a; 2、旋转和移动点云 鼠标左键可以旋转、右键可以移动 定轴…

Yolov8改进---注意力机制:ICASSP2023 EMA基于跨空间学习的高效多尺度注意力、效果优于ECA、CBAM、CA | 小目标涨点明显

1.EMA介绍 论文:https://arxiv.org/abs/2305.13563v1 录用:ICASSP2023 通过通道降维来建模跨通道关系可能会给提取深度视觉表示带来副作用。本文提出了一种新的高效的多尺度注意力(EMA)模块。以保留每个通道上的信息和降低计算开销为目标,将部分通道重塑为批量维度,并将…

【Linux】ubuntu20.04上使用xrdp控制输入密码之后一直停顿不动,进不去桌面环境

一、问题背景 如下图所示&#xff0c;每次登录桌面一段时间&#xff0c;就会因为自动锁定机制而锁定账户。 重新去激活账户时&#xff0c;输入正确的密码&#xff0c;回车确定&#xff0c;之后就停留在上面那个界面了。 二、 解决方案 2.1 重启xrdp服务 这个方法&#xff…

支付宝沙箱支付详细教程(IDEA版)—2023最新版

&#x1f607;作者介绍&#xff1a;一个有梦想、有理想、有目标的&#xff0c;且渴望能够学有所成的追梦人。 &#x1f386;学习格言&#xff1a;不读书的人,思想就会停止。——狄德罗 ⛪️个人主页&#xff1a;进入博主主页 &#x1f5fc;专栏系列&#xff1a;无 &#x1f33c…

leetcode数据库题第七弹

leetcode数据库题第七弹 1581. 进店却未进行过交易的顾客1587. 银行账户概要 II1633. 各赛事的用户注册率1661. 每台机器的进程平均运行时间1667. 修复表中的名字1683. 无效的推文1693. 每天的领导和合伙人1729. 求关注者的数量1731. 每位经理的下属员工数量1741. 查找每个员工…

软件性能测试流程指南

1 编写目的 规范Performance Tesing性能测试过程中的活动&#xff0c;明确测试活动流程和过程中各组织、角色的职责&#xff1b;使性能测试工作有章可循&#xff0c;控制测试活动按照计划有效的进行&#xff0c;用于指导性能测试项目的实施&#xff0c;从流程和规范性上保证测…

详细讲解~接口测试实践

目录 前言&#xff1a; 接口测试 为什么介绍接口测试&#xff1f; 模块接口测试 web接口测试 前言&#xff1a; 接口测试是软件测试中的重要环节&#xff0c;它涉及对系统的API&#xff08;Application Programming Int…

中间件解析漏洞

服务器解析漏洞算是历史比较悠久了&#xff0c;但如今依然广泛存在。在此记录汇总一些常见服务器&#xff08;WEB server&#xff09;的解析漏洞&#xff0c;比如IIS6.0、IIS7.5、apache、nginx等 2|0 二、IIS5.x-6.x解析漏洞&#xff08;针对asa/asp/cer&#xff09; 2|11、打…

仿造 elementUI 实现一个下拉选择器

前言&#xff1a; 近期在项目中遇到了一个设计需求&#xff0c;在 UI 给我提供的原图中有一个和 element UI 选择器功能基本一致的样式&#xff0c;但是由于我们是有自己的主体颜色和一些细节上的样式设计的&#xff0c;无法直接复用 element 组件库。所以需要自己动手实现一个…

Linux3.权限

1.外壳程序(shell):通常情况下用户不直接与操作系统进行交互&#xff0c;而是通过外壳程序&#xff0c;在windows下叫做图形化界面&#xff0c;在Linux下叫做指令。 centos7使用的外壳程序是bash。 作用 :a.是用户和操作系统交互的中间软件层。b可以在一定程度起到保护操作系统…

HackTheBox - 学院【CPTS】复习3 - XSS、文件包含、文件上传、命令注入

XSS 登录表单 document.write(<h3>Please login to continue</h3><form actionhttp://OUR_IP><input type"username" name"username" placeholder"Username"><input type"password" name"password&…

动态规划:积木画

积木画 问题描述 小明最近迷上了积木画, 有这么两种类型的积木, 分别为 I I I 型&#xff08;大小为 2 个单位面积) 和 L L L 型 (大小为 3 个单位面积): 同时, 小明有一块面积大小为 2 N 2 \times N 2N 的画布, 画布由 2 N 2 \times N 2N 个 1 1 1 \times 1 11 区域…

如何解读 Java 的继承和多态特性?

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言继承类的继承继承的…