做网站图片教程,贾汪网站开发,做的网站怎么查看点击率,被公司优化掉是什么意思⭐ 使用大语言模型构建一个能够回答关于给定文档和文档集合的问答系统是一种非常实用和有效的应用场景。与仅依赖模型预训练知识不同#xff0c;这种方法可以进一步整合用户自有数据#xff0c;实现更加个性化和专业的问答服务。 例如,我们可以收集某公司的内部文档、产品说明…⭐ 使用大语言模型构建一个能够回答关于给定文档和文档集合的问答系统是一种非常实用和有效的应用场景。与仅依赖模型预训练知识不同这种方法可以进一步整合用户自有数据实现更加个性化和专业的问答服务。 例如,我们可以收集某公司的内部文档、产品说明书等文字资料导入问答系统中。然后用户针对这些文档提出问题时系统可以先在文档中检索相关信息再提供给语言模型生成答案。
这样语言模型不仅利用了自己的通用知识还可以充分运用外部输入文档的专业信息来回答用户问题显著提升答案的质量和适用性。构建这类基于外部文档的问答系统可以让语言模型更好地服务于具体场景而不是停留在通用层面。这种灵活应用语言模型的方法值得在实际使用中推广。
基于文档问答的这个过程我们会涉及 LangChain 中的其他组件比如嵌入模型Embedding Models)和向量储存(Vector Stores)等 文章目录 01、给LLM引入外部知识库的流程02、初始化openai环境03、本章内容采用以下两种方式实现一、方式1直接使用向量存储查询1.1 导入数据1.2 基于文档加载器创建向量存储1.3 查询创建的向量存储 二、 方式2结合表征模型和向量存储2.1 导入数据2.2 文本向量表征模型2.3 基于向量表征创建并查询向量存储2.4 使用查询结果构造提示来回答问题2.5 使用检索问答链 RetrievalQA 来回答问题 Reference 01、给LLM引入外部知识库的流程
引入外部知识的主要流程如下(引用 LangChain-Chatchat (原 Langchain-ChatGLM) 项目的图)
1加载文件2读取文本3文本分割4文本向量化5问句向量化6在文本向量中匹配出与问句向量最相似的 top k个7匹配出的文本作为上下文和问题一起添加到 prompt中8提交给 LLM生成回答。
匹配出的文本作为上下文和问题一起添加到 prompt中。从文档处理角度来看实现流程如图所示。核心技术主要是向量 embedding将用户知识库内容经过 embedding 存入向量知识库然后用户每一次提问也会经过 embedding利用向量相关性算法例如余弦算法找到最匹配的几个知识库片段将这些知识库片段作为上下文与用户问题一起作为 prompt 提交给 LLM 回答。
02、初始化openai环境
from langchain.chat_models import ChatOpenAI
import os
import openai
# 运行此API配置需要将目录中的.env中api_key替换为自己的
from dotenv import load_dotenv, find_dotenv
_ load_dotenv(find_dotenv()) # read local .env file
openai.api_key os.environ[OPENAI_API_KEY]03、本章内容采用以下两种方式实现 疑问点 我们可以看到章节1中的index.query()的结果和第2章节中用检索问答链RetrievalQA的方法实现的结果是一样的也许有读者会问既然index.query()可以只用一行代码就完成了文档问答功能又何必要舍近求远搞一个RetrievalQA这样的对象来实现并且增加很多繁琐的步骤(有5个步骤)来实现同样的效果呢Langchain框架的作者Harrison Chase在课件视频中是这么解释的通过index来进行文档问答只需一行代码但是这其中其实隐藏了很多的实现细节如果我们使用的是RetrievalQA对象来实现文档问答功能那么我们就可以了解其中的细节比如Embeddings向量数据库等内容反正各有各的好处吧。
一、方式1直接使用向量存储查询
1.1 导入数据
from langchain.chains import RetrievalQA #检索QA链在文档上进行检索
from langchain.chat_models import ChatOpenAI #openai模型
from langchain.document_loaders import CSVLoader #文档加载器采用csv格式存储
from langchain.vectorstores import DocArrayInMemorySearch #向量存储
from IPython.display import display, Markdown #在jupyter显示信息的工具
import pandas as pd# 某平台电商数据库
file ./data/kg.csv# 使用pandas导入数据用以查看
data pd.read_csv(file, encodinggbk)
data.head()1.2 基于文档加载器创建向量存储
# 使用langchain文档加载器对数据进行导入
loader CSVLoader(file_pathfile)创建了文档加载器loder以后我们需要创建一个用于检索文档内容的索引器这里我们需要指定指定一个向量数据库我们使用DocArrayInMemorySearch作为向量数据库DocArrayInMemorySearch是由Docarray提供的文档索引它将会整个文档以向量的形式存储在内存中对于小型数据集来说使用DocArrayInMemorySearch会非常方便接下来我们还要指定一个数据源loder。 这里我们需要说明的是当加载文档后将执行三个主要步骤
1、将文档分割成块2、为每个文档创建embeddings3、将文档和embeddings存储到向量数据库中
#导入向量存储索引创建器
from langchain.indexes import VectorstoreIndexCreator # 创建指定向量存储类, 创建完成后从加载器中调用, 通过文档加载器列表加载
# VectorstoreIndexCreator可以设置embedding参数指定embedding的方式
index VectorstoreIndexCreator(vectorstore_clsDocArrayInMemorySearch).from_loaders([loader])1.3 查询创建的向量存储
query 请用markdown表格的方式列出所有手机品牌并对其描述进行总结。#使用索引查询创建一个响应并传入这个查询
response index.query(query)
# \n\n| 手机品牌 | 描述 |\n| -------- | ---- |\n| 小米14pro | 超乎你想象 |\n| 华为mate60pro | 遥遥领先 |#查看查询返回的内容
display(Markdown(response))二、 方式2结合表征模型和向量存储
这种方式主要为了方便学习其内部细节组成
2.1 导入数据
由于语言模型的上下文长度限制直接处理长文档具有困难。为实现对长文档的问答我们可以引入向量嵌入(Embeddings)和向量存储(Vector Store)等技术
首先使用文本嵌入(Embeddings)算法对文档进行向量化使语义相似的文本片段具有接近的向量表示。其次将向量化的文档切分为小块存入向量数据库这个流程正是创建索引(index)的过程。向量数据库对各文档片段进行索引支持快速检索。这样当用户提出问题时可以先将问题转换为向量在数据库中快速找到语义最相关的文档片段。然后将这些文档片段与问题一起传递给语言模型生成回答。
通过嵌入向量化和索引技术我们实现了对长文档的切片检索和问答。这种流程克服了语言模型的上下文限制可以构建处理大规模文档的问答系统。
#创建一个文档加载器通过csv格式加载
file ./data/kg.csv
loader CSVLoader(file_pathfile)
docs loader.load()#查看单个文档每个文档对应于CSV中的一行数据
docs[Document(page_contentname: 耐克跑鞋\ndescription: 男子运动鞋为鞋款匠心融入经典设计打造复古潮鞋佳选。, metadata{source: ./data/kg.csv, row: 0}),Document(page_contentname: chanel 可可小姐香水\ndescription: 清新感性的东方香调清新活力的柑橘瞬间唤醒感官。, metadata{source: ./data/kg.csv, row: 1}),Document(page_contentname: 安踏运动跑鞋鞋\ndescription: 安踏星云轻质慢跑鞋精心调教的中底材料搭配四大设计亮点轻松解锁解锁软弹脚感。, metadata{source: ./data/kg.csv, row: 2}),Document(page_contentname: 华为mate60pro手机\ndescription: 遥遥领先的华为手机。, metadata{source: ./data/kg.csv, row: 3}),Document(page_contentname: 小罐茶彩多泡特级茉莉花茶\ndescription: 一口茶汤落喉间茉莉开馥郁的花香扑鼻而来像是沐浴在夏日的茉莉花田瞬间感到清新凉爽。, metadata{source: ./data/kg.csv, row: 4}),Document(page_contentname: 小米14pro手机\ndescription: 小米14手机超乎你想象。, metadata{source: ./data/kg.csv, row: 5})]2.2 文本向量表征模型
看一看embedding向量的样子
# 使用OpenAIEmbedding类
from langchain.embeddings import OpenAIEmbeddings embeddings OpenAIEmbeddings() #因为文档比较短了所以这里不需要进行任何分块,可以直接进行向量表征
#使用初始化OpenAIEmbedding实例上的查询方法embed_query为文本创建向量表征
embed embeddings.embed_query(你好呀我的名字叫小可爱)#查看得到向量表征的长度
print(\n\033[32m向量表征的长度: \033[0m \n, len(embed))#每个元素都是不同的数字值组合起来就是文本的向量表征
print(\n\033[32m向量表征前5个元素: \033[0m \n, embed[:5])向量表征的长度: 1536向量表征前5个元素: [-0.01954011514905696, -0.006576854850604859, -0.007268821433052672, -0.024199778786441622, -0.02676449759650871]2.3 基于向量表征创建并查询向量存储
# 将刚才创建文本向量表征(embeddings)存储在向量存储(vector store)中
# 使用DocArrayInMemorySearch类的from_documents方法来实现
# 该方法接受文档列表以及向量表征模型作为输入
db DocArrayInMemorySearch.from_documents(docs, embeddings)query 请推荐一部华为手机
#使用上面的向量存储来查找与传入查询类似的文本得到一个相似文档列表
docs db.similarity_search(query, k3)
print(\n\033[32m返回文档的个数: \033[0m \n, len(docs))
print(\n\033[32m第一个文档: \033[0m \n, docs[0])返回文档的个数: 4第一个文档: page_contentname: 华为mate60pro手机\ndescription: 遥遥领先的华为手机。 metadata{source: ./data/kg.csv, row: 3}2.4 使用查询结果构造提示来回答问题 llm ChatOpenAI(temperature 0.0) #合并获得的相似文档内容
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} 问题请用markdown表格的方式列出所有手机并对每种手机的描述进行总结。) display(Markdown(response))2.5 使用检索问答链 RetrievalQA 来回答问题
通过LangChain创建一个检索问答链对检索到的文档进行问题回答。检索问答链的输入包含以下
1、llm: 语言模型进行文本生成。 2、chain_type: 传入链类型这里使用stuff将所有查询得到的文档组合成一个文档传入下一步。其他的方式包括
Map Reduce 将所有块与问题一起传递给语言模型获取回复使用另一个语言模型调用将所有单独的回复总结成最终答案它可以在任意数量的文档上运行。可以并行处理单个问题同时也需要更多的调用。它将所有文档视为独立的Refine 用于循环许多文档际上是迭代的建立在先前文档的答案之上非常适合前后因果信息并随时间逐步构建答案依赖于先前调用的结果。它通常需要更长的时间并且基本上需要与Map Reduce一样多的调用Map Re-rank 对每个文档进行单个语言模型调用要求它返回一个分数选择最高分这依赖于语言模型知道分数应该是什么需要告诉它如果它与文档相关则应该是高分并在那里精细调整说明可以批量处理它们相对较快但是更加昂贵。
3、retriever: 检索器 # 以下方法和上面方法一样这里一步到位了检索出来后组合在一起和query一起输入llm。
# 基于向量储存创建检索器
retriever db.as_retriever() qa_stuff RetrievalQA.from_chain_type(llmllm, chain_typestuff, retrieverretriever, verboseTrue
)#创建一个查询并在此查询上运行链
query 请用markdown表格的方式列出所有手机并对每种手机的描述进行总结。response qa_stuff.run(query)display(Markdown(response)) Reference
[1] 吴恩达老师的教程[2] DataWhale组织