对于给定的文档, 比如从PDF、网页、公司主页中提取构建的内部文档集合,我们可以使用大语言模型来回答关于这些文档内容的问题,以帮助用户更有效地获取和使用他们所需要的信息。这种方式非常有效且灵活地适用于实际应用场景,因为它不仅仅利用大语言模型已有的训练集数据信息,它还能使用外部信息。
这个过程会涉及LongChain中的其他组件,比如:表征模型(Embedding Models)和向量储存(Vector Stores)
一、设置API Key
import os
from zhipuai import ZhipuAI
from dotenv import load_dotenv, find_dotenv# 读取本地/项目的环境变量。# find_dotenv()寻找并定位.env文件的路径
# load_dotenv()读取该.env文件,并将其中的环境变量加载到当前的运行环境中
# 如果你设置的是全局的环境变量,这行代码则没有任何作用。
_ = load_dotenv(find_dotenv())# 获取环境变量 OPENAI_API_KEY
key = "f5cd91f2528fed334b9dfd75015791c3.GuLdvM9tXWrGQnAg"
client = ZhipuAI(api_key = key)
二、 结合表征模型和向量存储
解决长文档问答的方法:利用向量表征(Embeddings)和向量存储(Vector Store)技术处理长文档,使语言模型能够回答涉及全部内容的问题。
文本表征将文本转换为语义向量,相似内容的向量在空间中也相近。这种特性便于在向量空间中进行文本相似性比较。
将文档分割为较小的文本块(chunks),获取每个块的文本表征并存入向量数据库。这种处理方式称为创建索引(index),目的是解决语言模型单次处理文本长度的限制。
为查询生成向量表征后,与向量数据库中的向量进行相似性比对,选出最相关的n个文本块。将这些文本块构建为提示输入语言模型,最终生成答案。
2.1 导入数据
from langchain.chains.retrieval_qa.base import RetrievalQA #检索QA链,在文档上进行检索
from langchain_community.chat_models.zhipuai import ChatZhipuAI #openai模型
from langchain.document_loaders import CSVLoader #文档加载器,采用csv格式存储
from langchain.vectorstores import DocArrayInMemorySearch #向量存储
from IPython.display import display, Markdown #在jupyter显示信息的工具
#创建一个文档加载器,通过csv格式加载
file = 'data/OutdoorClothingCatalog_1000.csv'
loader = CSVLoader(file_path=file,encoding="utf-8")
docs = loader.load()
docs = docs[:20]
2.2 文本向量表征模型
#使用OpenAIEmbedding类
from langchain_community.embeddings.zhipuai import ZhipuAIEmbeddings# 使用智谱 AI 嵌入模型
embeddings = ZhipuAIEmbeddings(model="embedding-2", # 智谱 AI 的嵌入模型名称api_key=key # 替换为你的智谱 AI API Key
)
#因为文档比较短了,所以这里不需要进行任何分块,可以直接进行向量表征
#使用初始化OpenAIEmbedding实例上的查询方法embed_query为文本创建向量表征
embed = embeddings.embed_query("Hi my name is Harrison")#查看得到向量表征的长度
print(len(embed))
2.3 基于向量表征创建向量存储
# 将刚才创建文本向量表征(embeddings)存储在向量存储(vector store)中
# 使用DocArrayInMemorySearch类的from_documents方法来实现
# 该方法接受文档列表以及向量表征模型作为输入
#docs过长会报调用参数有误,现取前20条
db = DocArrayInMemorySearch.from_documents(docs, embeddings)
import langchain
langchain.__version__
2.4 查询创建的向量存储
query = "Please suggest a shirt with sunblocking"#使用上面的向量存储来查找与传入查询类似的文本,得到一个相似文档列表
docs = db.similarity_search(query)
2.5 使用向量储存回答文档的相关问题
#基于向量储存,创建检索器
retriever = db.as_retriever()
#导入大语言模型, 这里使用默认模型gpt-3.5-turbo会出现504服务器超时,因此使用gpt-3.5-turbo-0301
llm = ChatZhipuAI(model_name="glm-3-turbo",temperature = 0.0, zhipuai_api_key=key)
#合并获得的相似文档内容
qdocs = "".join([docs[i].page_content for i in range(len(docs))])
#将合并的相似文档内容后加上问题(question)输入到 `llm.call_as_llm`中
#这里问题是:以Markdown表格的方式列出所有具有防晒功能的衬衫并总结
response = llm.call_as_llm(f"{qdocs} Question: Please list all your \
shirts with sun protection in a table in markdown and summarize each one.")
display(Markdown(response))
'''
通过LangChain链封装起来
创建一个检索QA链,对检索到的文档进行问题回答,要创建这样的链,我们将传入几个不同的东西
1、语言模型,在最后进行文本生成
2、传入链类型,这里使用stuff,将所有文档塞入上下文并对语言模型进行一次调用
3、传入一个检索器
'''qa_stuff = RetrievalQA.from_chain_type(llm=llm, chain_type="stuff", retriever=retriever, verbose=True
)
query = "Please list all your shirts with sun protection in a table \
in markdown and summarize each one."#创建一个查询并在此查询上运行链
response = qa_stuff.run(query)
display(Markdown(response))#使用 display 和 markdown 显示它