如何基于LangChain快速构建自己的知识库

57 阅读8分钟

什么是langchain

LangChain(python.langchain.com/en/latest/i…

•读取数据。提供多种文档加载器

•调用模型api。对接了很多的三方模型接口

•结果处理。提供多种向量数据处理方式

如果你做过java开发,那么可以理解成它是ai界的spring框架。

接下来我们将通过一个具体的小例子来体验一把.

背景需求

由于ChatGPT的训练数据库仅更新至2021年,因此对于2022年的发生的事情如果不做训练,那么它肯定是不知道的,如果对它提问2022年世界杯冠军是谁,肯定回答不出来。通过playground测试一把

发送下面的问题到playground

2022年世界杯冠军是谁

得到回复是

作为AI语言模型,我没有预测未来的能力,也无法预测2022年世界杯的冠军。
预测体育比赛结果需要考虑很多因素,包括球队实力、球员状态、比赛场地和气候等等,
这些因素都是非常难以预测的。最终的结果只能由比赛的实际情况决定。

那下面我们就结合langchain来训练openai模型

准备训练数据

到网上找一段2022年世界杯的新闻

在卡塔尔当地时间2022年12月18日,梅西带领阿根廷男足在2022年世界杯决赛中通过点球大战以7-5击败法国男足,为阿根廷队夺得队史的第三座世界杯冠军奖杯,这也是阿根廷队时隔36年再度捧起世界杯冠军奖杯。夺冠后梅西深情亲吻大力神杯,尽情宣泄心中的激动和喜悦。值得一提的是,阿根廷夺得2022世界杯冠军之后,梅西等阿根廷球员纷纷在个人社交媒体发表了对于夺冠的喜悦之情。对于梅西而言,个人足球职业生涯再无遗憾,而对于年轻的阿根廷小将们则意味着职业生涯奠定了一个非常好的开端。而对于梅西的老帮手迪马利亚来说,他改变了自己从阿根廷国家队退役的决定,希望能够以冠军身份继续为潘帕斯雄鹰效力。阿根廷队本来是准备在首都布宜诺斯艾利斯的市中心共和国广场进行庆祝,但是由于球迷实在过于热情,最终庆祝仪式被迫提前结束,球员们改为直升飞机绕城飞行庆祝,但这也依然不能熄灭球迷的火热激情。所有看到阿根廷夺冠球员的球迷都激动万分,有的球迷更是兴奋的直接泣不成声,场面十分令人动容。梅西在夺得2022世界杯冠军之后也是情绪激动,以世界杯冠军结束自己的世界杯旅程,对于梅西而言毫无疑问是最完美的结局,而梅西的家人们也在比赛现场见证了梅西的巅峰时刻,一家人的幸福合影令人羡慕。

把上面的内容保存到一个txt文件,名为2022世界杯.txt

准备langchain环境

安装python环境

python的安装不在本文内容范畴,可自行进行搜索安装

langchain相关依赖包

通过pip安装
pip install langchain
pip install openai
# 向量数据库
pip install chromadb
# 中文分词
pip install jieba
# 处理非结构化数据
pip install unstructured
导入依赖
import jieba as jb
from langchain.llms import OpenAI


from langchain.document_loaders import DirectoryLoader, PyPDFLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.text_splitter import TokenTextSplitter
from langchain.vectorstores import Chroma
from langchain.chains import ConversationalRetrievalChain, ChatVectorDBChain
from langchain.chat_models import ChatOpenAI

开始读取本地训练数据并分词处理

本地的txt文件内是中文,需要使用jieba对中文进行分词处理

    file='2022世界杯.txt'
    my_file = f"./data/{file}"
    # 从本地读取文件
    with open(my_file, "r", encoding='utf-8') as f:
        data = f.read()
        # 对内容按空格进行分词处理
        cut_data = " ".join(w for w in list(jb.cut(data)))
        # 保存分词后的内容
        cut_file = f"./data/cut/cut_{file}"
        with open(cut_file, 'w') as f:
            f.write(cut_data)
            f.close()
    print("写入文件完成")

分词后的内容长这样,是用空格分隔

 卡塔尔 当地 时间 2022  12  18   梅西 带领 阿根廷 男足  2022  世界杯 决赛  通过 点球 大战  7 - 5 击败 法国 男足   阿根廷队 夺得 队史  第三座 世界杯 冠军 奖杯     阿根廷队 时隔 36  再度 捧起 世界杯 冠军 奖杯 。夺冠 后梅西 深情 亲吻 大力神杯  尽情 宣泄 心中  激动  喜悦 
 值得一提的是  阿根廷 夺得 2022 世界杯 冠军 之后  梅西  阿根廷 球员 纷纷  个人 社交 媒体 发表  对于 夺冠  喜悦之情 。对于 梅西 而言  个人 足球 职业生涯   遗憾   对于 年轻  阿根廷 小将   意味着 职业生涯 奠定  一个 非常   开端 。而 对于 梅西   帮手  马利亚 来说   改变  自己  阿根廷 国家队 退役  决定  希望 能够  冠军 身份 继续  潘帕斯 雄鹰 效力 
 阿根廷队 本来  准备  首都 布宜诺斯艾利斯  市中心 共和国 广场 进行 庆祝  但是 囿于 球迷 实在 过于 热情  最终 庆祝 仪式 被迫 提前结束  球员  改为 直升飞机 绕城 飞行 庆祝     依然 不能 熄灭 球迷  火热 激情 。所有 看到 阿根廷 夺冠 球员  球迷  激动 万分    球迷 更是 兴奋  直接 泣不成声  场面 十分 令人 动容 
 梅西  夺得 2022 世界杯 冠军 之后   情绪 激动   世界杯 冠军 结束 自己  世界杯 旅程  对于 梅西 而言 毫无疑问   完美  结局  而梅西   人们   比赛 现场 见证  梅西  巅峰 时刻  一家人  幸福 合影 令人羡慕 

通过openai的Embeddings训练

DirectoryLoader是由langchain提供的目录加载器。langchain提供了很多种不同文档加载器,根据资源来源不同,使用对应的加载器。

TokenTextSplitter是由langchain提供的文本分割器,它也提供一系列其它的splitter。这里需要自行设定要分块的大小

# 通过目录加载器读取分词数据
loader = DirectoryLoader('./data/cut', glob='**/*.txt')
docs = loader.load()
# 这里要进行分块处理,因为openai的接口是有限制的,chunk_size表示块大小,chunk_overlap表示块重叠部分多少
text_splitter = TokenTextSplitter(chunk_size=1000, chunk_overlap=0)
doc_texts = text_splitter.split_documents(docs)
print(doc_texts)

通过调用openai的embeddings接口,去训练数据,训练以后,接口会返回一组向量数据。

langchain也提供封装了很多种向量数据库。网上很多是用Pinecone来保存,这个是一个三方的服务商来着,要申请。这里通过Chroma保存向量数据。Chroma是一款开源的向量数据库,可以来替换Pinecone。通过chroma把向量数据储存在本地目录

# 调用openai的embeddings接口,然后保存返回的向量数据
os.environ["OPENAI_API_KEY"] = "这里替换成自己在openai申请的api key"
embeddings = OpenAIEmbeddings(openai_api_key=os.environ["OPENAI_API_KEY"])
# 指定保存目录
vectordb = Chroma.from_documents(doc_texts, embeddings, persist_directory="./data/cut")
vectordb.persist()

它会在./data/cut目录下生成

chroma-collections.parquet文件

chroma-embeddings.parquet文件

./data/cut/index/目录下生成相关索引

到此,数据模型训练完毕。

接入聊天api

模型训练完了,现在可以再次向chatgpt发起提问2022年世界杯冠军

//创建聊天对象
chain = ChatVectorDBChain.from_llm(OpenAI(temperature=0, 
          model_name="gpt-3.5-turbo"), vectordb,
                 return_source_documents=True)
          

question = '2022年世界杯冠军是谁?'
print(get_answer(question))
          

# 聊天对话,获取回复
def get_answer(question):
    chat_history=[]
    result=chain({
        "question":question,
        "chat_history":chat_history
    })
    return result["answer"]
          

输出
question = '2022年世界杯冠军是谁?'
answer = 阿根廷男足。
question = ‘谁带阿根廷男足赢了2022年世界杯?’
answer = 梅西带领阿根廷男足赢得了2022年世界杯。

总结

本文只是简单的体验了一把Langchain开发ai应用是多便捷,根据上面的例子,扩展场景可以对一本Pdf的内容进行训练,然后对该pdf的内容进行ai问答。它还提供很多其它的组件,和每个组件的示例,这个就需要自行去阅读官网文档了。