引言
ChatGPT是一种功能强大的自然语言处理模型,可以用于生成自然语言文本、回答问题、翻译语言等多种场景。
然而,在搭建智能机器人方面,ChatGPT也存在明显的局限:
- ChatGPT的回答是基于已有的语言数据生成的。资料显示,目前ChatGPT训练的数据截至2021年的,因此该时间点之后产生的数据,它很可能无法回答(或者无法准确地回答)。
- 无法跟自身业务需求做更深度的结合。原因简单来说就是没有用自身的业务数据去训练它。
因此,本文简单介绍一下使用LangChain来搭建可以跟自身业务需求相结合的智能机器人。
这里会使用最近的新闻数据作为示例。
希望能帮助到大家。
环境准备
假设大家已经熟悉Python开发环境的搭建,以及各种依赖项的安装。
为了让内容更聚焦,这里就忽略前期的Python环境搭建方面的内容。
使用conda创建一个新的虚拟环境
# 创建新的虚拟环境,并指定Python版本
conda create --name envLangChain python==3.8
# 激活虚拟环境,后面的操作也都在这个虚拟环境下
conda activate envLangChain
安装LangChain
# 方法一:
pip install langchain
# 或者使用方法而:
conda install langchain -c conda-forge
安装openai 库
后面会调用它的一些接口,用于做Embedding
pip install openai
数据准备
新闻数据的爬取,以及正文内容的提取,不在本文阐述范围之内。
请读者自行准备。
我这里爬取了3000篇新闻,提取出的正文文本内容保存在3000个.txt文件中。
# 假设3000个.txt新闻数据存到到这里了
source_documents_dir = "/data/source_documents/news"
灌入数据
将下面的代码保存为ingest_news.py
# 导入各种必要的库
from langchain.text_splitter import CharacterTextSplitter
from langchain.document_loaders import DirectoryLoader
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.vectorstores import Chroma
import time
import os
# 设置openai 的key,在后续的Embedding阶段会用到该key调用oepnai的API
# openai Key的生成(或查看)入口如下
# https://platform.openai.com/account/api-keys
os.environ["OPENAI_API_KEY"] = "sk-XXXXXXXX"
# 待灌入的新闻数据全部在这个目录,里面有3000个.txt文件
source_documents_dir = "/data/source_documents/news"
# 持久化存储目录,用于存储计算出来的向量信息
persist_directory = "/data/embeddings_db/news"
# 加载文件夹中的所有txt类型的文件
loader = DirectoryLoader(source_documents_dir, glob="*.txt")
documents = loader.load()
print(f"Load documents done, count: {len(documents)}")
# 初始化文本分割器
text_splitter = CharacterTextSplitter(chunk_size=100, chunk_overlap=0)
split_docs = text_splitter.split_documents(documents)
print(f"Split documents done, split_docs.count: {len(split_docs)}")
# 初始化 openai 的 embeddings 对象
# 备注1:这里应该也可以使用其它模型来做Embedding,这里先直接使用openai的接口
# 备注2:这里会消耗openai Key的使用额度。如果额度有限会影响程序执行。如果对额度比较在意的,请谨慎使用
embeddings = OpenAIEmbeddings()
# 对新闻数据进行embedding,并将结果持久化到指定目录,方便后续机器人复用
docsearch = Chroma.from_documents(split_docs, embeddings, persist_directory=persist_directory)
docsearch.persist()
执行程序。我自己的机器上大概花了100秒时。
python ingest_news.py
程序执行完毕后,可以切换到 /data/embeddings_db/news
目录查看结果数据,大概长这样:
.
├── chroma-collections.parquet
├── chroma-embeddings.parquet
└── index
├── id_to_uuid_11dd9ae9-79bc-4359-b0ff-86acc062b467.pkl
├── index_11dd9ae9-79bc-4359-b0ff-86acc062b467.bin
├── index_metadata_11dd9ae9-79bc-4359-b0ff-86acc062b467.pkl
└── uuid_to_id_11dd9ae9-79bc-4359-b0ff-86acc062b467.pkl
后面,就可以加载这些数据,并使用LangChain搭建智能问答了。
智能问答
将下面的程序保存为query.py
# 导入各种依赖
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain import OpenAI
from langchain.vectorstores import Chroma
from langchain.chains import RetrievalQA
import os
# 设置openai 的key,在后续的Embedding阶段会用到该key调用oepnai的API
# openai Key的生成(或查看)入口如下
# https://platform.openai.com/account/api-keys
os.environ["OPENAI_API_KEY"] = "sk-XXXXXXXX"
# 持久化存储目录,用于存储计算出来的向量信息(上一步生成的)
persist_directory = "/data/embeddings_db/news"
# 初始化 openai 的 embeddings 对象
embeddings = OpenAIEmbeddings()
# 直接从本地加载已经计算好的向量信息
docsearch = Chroma(persist_directory=persist_directory, embedding_function=embeddings)
# 创建问答对象
qa = RetrievalQA.from_chain_type(llm=OpenAI(), chain_type="stuff", retriever=docsearch.as_retriever())
# 循环输入问题,直到输入 exit 退出
while True:
try:
query = input("请输入问题:")
if not query:
print("问题为空,请重新输入:")
continue
if query == "exit":
print("退出程序")
break
# 判断query是否UTF-8编码(本地测试的时候有时会异常,所以加上这个判断)
query = query.encode("utf-8").decode("utf-8")
result = qa.run(query)
except UnicodeDecodeError as e:
print("UnicodeDecodeError: ", e)
continue
print(result)
执行程序python query.py
。
结果如下图所示:
写在后面
这里只简单演示了通过 LangChain + openai API
来基于近期的新闻数据
搭建智能聊天机器人的例子。
各位朋友可以结合自己的需要,把更多的数据(如.pdf,.doc,.csv等等)灌进去并按需调优。
也可以搭建在线服务
,或者增加web UI
便于使用。
限于篇幅,这些先不详细展开。
后面有机会再继续。