一起做网店17普宁池尾,杭州江干区抖音seo品牌,网站做数据统计,网站开发项目的心得体会LangChain是一个基于大语言模型#xff08;如ChatGPT#xff09;用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口#xff0c;可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互#x…
LangChain是一个基于大语言模型如ChatGPT用于构建端到端语言模型应用的 Python 框架。它提供了一套工具、组件和接口可简化创建由大型语言模型 (LLM) 和聊天模型提供支持的应用程序的过程。LangChain 可以轻松管理与语言模型的交互将多个组件链接在一起以便在不同的应用程序中使用。
今天我们来学习DeepLearning.AI的在线课程:LangChain for LLM Application Development的第五门课Evaluation(评估)所谓评估是指检验LLM回答的问题是否正确的方法在上一篇博客QA over Documents中我们解释了如何通过langchain来实现对文档的问答功能在文档的问答过程中LLM会就用户提出的关于文档内容的相关问题进行回答那么今天我们需要研究的就是如何来检验LLM的回答是否正确
要评估LLM回答问题的准确性大致需要下面几个步骤
需要创建一组关于相关的问答测试集(包含了问题和标准答案)让LLM回答测试集中的所有问题并收集LLM给出的所有答案将LLM的答案与问答测试集中的标准答案做比对并给LLM的表现评分
下面我们就开始来讨论评估LLM表现吧
创建基于文档问答的Q/A应用
首先我们还是要做一些基础性工作比如设置openai的api key,导入一些langchain的基础库
import pandas as pd
from langchain.chains import RetrievalQA
from langchain.chat_models import ChatOpenAI
from langchain.document_loaders import CSVLoader
from langchain.indexes import VectorstoreIndexCreator
from langchain.vectorstores import DocArrayInMemorySearch
import osfrom dotenv import load_dotenv, find_dotenv
_ load_dotenv(find_dotenv()) # read local .env file
接下来我们需要导入一个csv文件该文档主要包含2列name和description,其中name表示商品的名称,description表示该商品的说明信息我们需要对改文档的产品信息进行问答。
dfpd.read_csv(OutdoorClothingCatalog_1000.csv)df 下面我们查看一下其中的某个商品信息
print(df[:1].name.values[0])
print(------------------------)
print(df[:1].description.values[0]) 下面我们将该商品的信息翻译成中文这样便于大家理解 接下来我们要创建一个用于回答文档内容的chain:RetrievalQA, 创建RetrievalQA需要包含以下几个步骤
创建一个文档加载器CSVLoad实例创建向量数据库索引index创建llm创建文档问答chain,RetrievalQA
#1.创建文档加载器
file OutdoorClothingCatalog_1000.csv
loader CSVLoader(file_pathfile)
data loader.load()#2.创建向量数据库索引
index VectorstoreIndexCreator(vectorstore_clsDocArrayInMemorySearch
).from_loaders([loader])#3.创建llm
llm ChatOpenAI(temperature 0.0)#4.创建文档问答chain
qa RetrievalQA.from_chain_type(llmllm, chain_typestuff, retrieverindex.vectorstore.as_retriever(), verboseTrue,chain_type_kwargs {document_separator: }
)
上述代码的主要功能及作用在LangChain大型语言模型(LLM)应用开发(四)QA over Documents这篇博客中都已说明这里不再赘述。
设置测试的数据
下面我们查看一下经过档加载器CSVLoad加载后生成的data内的信息,这里我们抽取data中的第九和第十条数据看看它们的主要内容 手动创建测试集
需要说明的是这里我们的文档是csv文件所以我们使用的是文档加载器是CSVLoaderCSVLoader会对csv文件中的每一行数据进行分割所以这里看到的data[10],data[11]的内容则是csv文件中的第10第11条数据的内容。下面我们根据这两条数据手动设置两条“问答对”每一个“问答对”中包含一个query,一个answer
examples [{query: Do the Cozy Comfort Pullover Set\have side pockets?,answer: Yes},{query: What collection is the Ultra-Lofty \850 Stretch Down Hooded Jacket from?,answer: The DownTek collection}
]
让LLM生成Q/A测试用例
在我以前写的两篇博客中(使用大型语言模(LLM)构建系统(七)评估1与 使用大型语言模(LLM)构建系统(七)评估2)我们使用的方法都是通过手动的方法来构建测试数据集比如说我们可以手动创建10个问题和10个答案然后让LLM回答这10个问题再将LLM给出的答案与我们准备好的答案做比较最后再给LLM打分。评估的流程大概就是这样但是这里有一个问题就是我们需要手动去创建所有的问题集和答案集那会是一个非常耗费人力和时间的成本。那有没有一种可以自动创建大量问题集和答案集的方法呢那当然是有的今天我们就来介绍Langchain提供的方法QAGenerateChain我们可以通过QAGenerateChain来为我们的文档自动创建问答集
from langchain.evaluation.qa import QAGenerateChainexample_gen_chain QAGenerateChain.from_llm(ChatOpenAI())new_examples example_gen_chain.apply([{doc: t} for t in data[:5]])
print(new_examples) 这里我们对上述代码做个简单说明我们创建了一个QAGenerateChain然后我们应用了QAGenerateChain的apply方法对data中的前5条数据创建了5个“问答对”由于创建问答集是由LLM来自动完成的因此会涉及到token成本的问题所以我们这里出于演示的目的只对data中的前5条数据创建问答集。
那QAGenerateChain是如何自动创建问题集的一个简单的apply方法似乎隐藏了很多的细节如果你对这个隐藏的细节感兴趣那我们可以尝试用debug的方式来打开这个潘多拉魔盒
import langchain#打开debug
langchain.debug Truenew_examples example_gen_chain.apply([{doc: t} for t in data[:5]])#关闭debug
langchain.debug False 从上面展现的细节中我们可以看到原来在QAGenerateChain中有一个内置的prompt,在这个内置的prompt的前缀信息中以Human的角色要求LLM对给与它的文档产生一个question和answer。这个prompt的前缀信息大概就长这个样子 QAGenerateChain会在data中的每一条数据中都运用这个prompt模板因此data中的每一条数据都会产生一条“问答对”。有了问答集以后我们还需要对问答集进行解析从中过滤出真正有用的信息不过我们首先需要创建一个解析函数parse_strings
def parse_strings(strings_list):parsed_list []for s in strings_list:s s.replace(\n\n,\n)split_s s.split(\n)# Ensure there are 2 parts in the split stringif len(split_s) ! 2:continuequestion_part, answer_part split_s# Ensure each part has the correct prefixif not question_part.startswith(QUESTION: ) or not answer_part.startswith(ANSWER: ):continue# Remove the prefixes and strip leading/trailing whitespacequestion question_part.replace(QUESTION: , ).strip()answer answer_part.replace(ANSWER: , ).strip()parsed_list.append({query: question, answer: answer})return parsed_list#对问答集进行解析
new_examples parse_strings([t[text] for t in new_examples])
print(new_examples) 这里经过解析以后我们的new_examples 中只包含了5个query和5个answer,没有其他多余的信息这正是我们想要的测试集。
组合测试集
还记得我们前面手动创建的两个问答集吗现在我们需要将之前手动创建的问答集合并到QAGenerateChain创建的问答集中这样在答集中既有手动创建的例子又有llm自动创建的例子这会使我们的测试集更加完善
examples new_examplesexamples 这里我们看到examples 的前两条数据就是我们先前手动创建的接下来我们就需要让之前创建的文档问答chain来回答这个测试集里的问题来看看LLM是怎么回答的吧
qa.run(examples[0][query]) 这里我们看到qa回答了第0个问题“Yes, the Cozy Comfort Pullover Set does have side pockets.” 这里的第0个问题就是先前我们手动创建的第一个问题并且我们手动创建的answer是 :Yes, 这里我们发现问答chain qa回答的也是“Yes”,只是它比我们的答案还多了一段说明“the Cozy Comfort Pullover Set does have side pockets.”。
你想知道问答chain qa是怎么找到问题的答案的吗魔鬼往往隐藏在细节中下面让我们打开debug,看看问答chain qa是如何找到问题的答案
langchain.debug Trueqa.run(examples[0][query])langchain.debug False 这里我们稍微对问答chain qa寻找答案的过程进行一些说明首先qa拿到问题然后根据问题去向量数据库中搜索和问题相关的产品信息(会在全部产品中搜索)由于向量数据库中可能会存在多条产品信息和问题相关因此这里会用“”来分隔搜索到的多个产品信息这里所谓的搜索是指向量间的相似度计算和比较首先将问题转换成向量再计算问题向量和数据库中每个向量的相似度获取相似度最高的n条向量然后再将这些相似的向量再转换成对应的文本即可。当这些步骤完成以后我们就看到了上述的结果其中罗列了question和contentquestion是我们提出的问题而“content”则是搜索到的多个相关产品信息它们被用“”分隔。这里需要加入一个我的个人判断在搜索相关文档的时候应该是没有llm参与的因此不会产生token成本的问题。在有了问题和相关产品信息后接下来就需要LLM登场了这里就会有一个prompt在这个prompt中有一个System前缀信息,它告诉llm需要做什么紧接着前缀信息的是多个产品信息它们被用进行分隔最后是我们的问题这里用Human来标识我们的问题。 下面是输出部分LLM会根据给它的prompt输出一个内容较多的json格式的结果其中包含了问题的答案 最后经过过滤得到了最终的答案 前面我们让问答chain qa回答了测试集中的一个问题下面我们要做的是让qa来回答测试集中的所有问题
predictions qa.apply(examples) 基于LLM的自我评估
让我们来理一下思路首先我们让LLM自动创建了问答测试集接着我们又让LLM回答了测试集中所有的问题并得到了所有问题的回复信息。接下来我们要做的就是将这些问题的回复信息与测试集里的答案进行比对更其妙的是这个比对过程也将是由LLM自己来完成也就是说我们的LLM既当球员又当裁判最后再由“裁判”给出比对的结果不过我需要指出的这里既当球员又当裁判的LLM并非是同一个chain构成的它们来自于不同的chain,也就是说这些chain的职能是不同的
from langchain.evaluation.qa import QAEvalChain#创建LLM
llm ChatOpenAI(temperature0)#创建评估chain
eval_chain QAEvalChain.from_llm(llm)#生成评估结果
graded_outputs eval_chain.evaluate(examples, predictions)#统计评估结果
for i, eg in enumerate(examples):print(fExample {i}:)print(Question: predictions[i][query])print(Real Answer: predictions[i][answer])print(Predicted Answer: predictions[i][result])print(Predicted Grade: graded_outputs[i][text])print() 从上面的返回结果中我们看到每一个问题中都包含了QuestionReal Answer,Predicted Anser和Predicted Grade 四组内容其中Real Answer是有先前的QAGenerateChain创建的问答测试集中的答案而Predicted Answer则是由我们的问答chain qa回答的问题最后的Predicted Grade则是由上面代码中的QAEvalChain回答的。
总结
今天我们学习了如何利用Langchain来评估LLM的表现和以前评估openai模型的方法不同的是这里我们使用的是全自动方式即全自动方式生成测试集然后全自动的给出问题的预测结果最好全自动的评估预测结果的准确性通过这种全自动的方式解放了我们的双手使我们不需要因为没有测试数据集而苦恼大大提高了生产率。
参考资料
QA Generation | ️ Langchain
Question Answering | ️ Langchain