「LangChain大模型应用开发」 系列文章目录:

  1. LangChain大模型应用开发:模型,提示和输出解释器

  2. LangChain大模型应用开发:储存(Memory)

  3. LangChain大模型应用开发:模型链(Chains)

  4. LangChain大模型应用开发:基于文档的问答

  5. LangChain大模型应用开发:评估

  6. LangChain大模型应用开发:代理 (Agent) 

目录

1. 创建LLM应用

1.1 手动编测试的数据做评估

1.2 通过LLM生成测试的数据做评估

1.3 整合测试集

2. 人工评估

3. 通过LLM进行评估实例


评估是检验语言模型问答质量的关键环节。评估可以检验语言模型在不同文档上的问答效果,找出其弱点。还可以通过比较不同模型,选择最佳系统。此外,定期评估也可以检查模型质量的衰减。评估通常有两个目的:

  • 检验LLM应用是否达到了验收标准
  • 分析改动对于LLM应用性能的影响

基本的思路就是利用语言模型本身和链本身,来辅助评估其他的语言模型、链和应用程序。我们还是以上一章节的文档问答应用为例,在本章节中讨论如何在 LangChain 中处理和考虑评估的内容。

1. 创建LLM应用

首先,按照 langchain 链的方式构建一个 LLM 的文档问答应用。

PS:数据来源:llm-cookbook/content/必修三-LangChain for LLM Application Development/data at main · datawhalechina/llm-cookbook

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    api_key="你的API key",
    base_url="https://qianfan.baidubce.com/v2",
    model="ernie-3.5-8k",
    temperature=0
)

from langchain.document_loaders import CSVLoader
file = 'data/product_data.csv'
loader = CSVLoader(file_path=file)
docs = loader.load()

#查看数据
import pandas as pd
test_data = pd.read_csv(file,skiprows=0)
display(test_data.head())

from langchain_huggingface import HuggingFaceEmbeddings
#因为文档比较短了,所以这里不需要进行任何分块,可以直接进行向量嵌入
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")


from langchain.vectorstores import DocArrayInMemorySearch
db = DocArrayInMemorySearch.from_documents(docs, embeddings)


from langchain.chains import RetrievalQA #检索QA链,在文档上进行检索

qa = RetrievalQA.from_chain_type(
    llm=llm, 
    chain_type="stuff", 
    retriever=db.as_retriever(), 
    verbose=True,
    chain_type_kwargs = {
        "document_separator": "<<<<>>>>>"
    }
)

以上代码与上一章基于文档的回答一致,如需详细说明请参考:「LangChain 学习笔记」LangChain大模型应用开发:基于文档的问答-CSDN博客

1.1 手动编测试的数据做评估

需要说明的是这里我们的文档是 csv 文件,所以我们使用的是文档加载器是 CSVLoader ,CSVLoader 会对 csv 文件中的每一行数据进行分割。下面我们手动设置两条“问答对”,每一个“问答对”中包含一个 query (测试问题),一个 answer(预期的答案) :

examples = [
    {
        "query": "高清电视机怎么进行护理?",
        "answer": "使用干布清洁。"
    },
    {
        "query": "旅行背包有内外袋吗?",
        "answer": "有。"
    }
]

1.2 通过LLM生成测试的数据做评估

在前面的内容中,我们使用的方法都是通过手动的方法来构建测试数据集,比如说我们手动创建10个问题和10个答案,然后让 LLM 回答这10个问题,再将 LLM 给出的答案与我们准备好的答案做比较,最后再给 LLM 打分,评估的流程大概就是这样。但是这里有一个问题,就是我们需要手动去创建所有的问题集和答案集,那会是一个非常耗费时间和人力的成本。那有没有一种可以自动创建大量问答测试集的方法呢?那当然是有的,今天我们就来介绍 Langchain 提供的方法:QAGenerateChain,我们可以通过QAGenerateChain来为我们的文档自动创建问答集:

由于QAGenerateChain类中使用的PROMPT是英文,故我们继承QAGenerateChain类,将PROMPT加上“请使用中文输出”。下面是generate_chain.py文件中的QAGenerateChain类的源码:

from langchain.evaluation.qa import QAGenerateChain #导入QA生成链,它将接收文档,并从每个文档中创建一个问题答案对

#下面是langchain.evaluation.qa.generate_prompt中的源码,在template的最后加上“请使用中文输出”
from langchain.output_parsers.regex import RegexParser
from langchain.prompts import PromptTemplate
from langchain.base_language import BaseLanguageModel
from typing import Any

template = """You are a teacher coming up with questions to ask on a quiz. 
Given the following document, please generate a question and answer based on that document.

Example Format:
<Begin Document>
...
<End Document>
QUESTION: question here
ANSWER: answer here

These questions should be detailed and be based explicitly on information in the document. Begin!

<Begin Document>
{doc}
<End Document>
请使用中文输出
"""

PROMPT = PromptTemplate(
    input_variables=["doc"], template=template
)


# 继承QAGenerateChain
class ChineseQAGenerateChain(QAGenerateChain):
    """LLM Chain specifically for generating examples for question answering."""

    @classmethod
    def from_llm(cls, llm: BaseLanguageModel, **kwargs: Any) -> QAGenerateChain:
        """Load QA Generate Chain from LLM."""
        return cls(llm=llm, prompt=PROMPT, **kwargs)



example_gen_chain = ChineseQAGenerateChain.from_llm(llm)#通过传递llm语言模型来创建这个链
new_examples = example_gen_chain.apply([{"doc": t} for t in docs[:5]]) 


#查看用例数据
print(len(new_examples))
print(new_examples)

5
[{'qa_pairs': {'query': '这款全自动咖啡机是由什么材质制成的?', 'answer': '这款全自动咖啡机是由高品质不锈钢制成的。'}}, {'qa_pairs': {'query': '该电动牙刷是由哪些材料制成的?', 'answer': '该电动牙刷是由食品级塑料和尼龙刷毛制成的。'}}, {'qa_pairs': {'query': '该橙味维生素C泡腾片的主要成分是什么?', 'answer': '该橙味维生素C泡腾片的主要成分为维生素C和柠檬酸钠。'}}, {'qa_pairs': {'query': '这款无线蓝牙耳机的电池续航力是多久?', 'answer': '这款无线蓝牙耳机的电池续航力长达8小时。'}}, {'qa_pairs': {'query': '这款瑜伽垫的尺寸是多少?', 'answer': "这款瑜伽垫的尺寸是24'' x 68''。"}}]

在上面的代码中,我们创建了一个QAGenerateChain,然后我们应用了QAGenerateChain apply 方法docs (最开始使用CSVLoader 读取到的数据)中的前5条数据创建了5个“问答对”,由于创建问答集是由 LLM 来自动完成的,因此会涉及到 token 成本的问题,所以我们这里出于演示的目的,只对 data 中的前5条数据创建问答集。

1.3 整合测试集

现在我们需要将之前手动创建的问答集合并QAGenerateChain创建的问答集中,这样在答集中既有手动创建的例子又有 llm 自动创建的例子,这会使我们的测试集更加完善。

examples += [ v for item in new_examples for k,v in item.items()]

print(len(examples))
examples

可以看到我们已经将测试集整合到一块(手动2个+LLM5个)。

qa.invoke(examples[0]["query"])

这里我们看到qa回答了第0个问题:"高清电视机怎么进行护理?" ,这里的第0个问题就是先前我们手动创建的第一个问题,并且我们手动创建的 answer 是:"使用干布清洁。" " 这里我们发现问答链qa回答的也是“使用干布清洁高清电视机。”。

2. 人工评估

你想知道qa是怎么找到问题的答案的吗?下面让我们打开debug,看看qa是如何找到问题的答案!

import langchain
langchain.debug = True

qa.invoke(examples[0]["query"])
[chain/start] [chain:RetrievalQA] Entering Chain run with input:
{
  "query": "高清电视机怎么进行护理?"
}
[chain/start] [chain:RetrievalQA > chain:StuffDocumentsChain] Entering Chain run with input:
[inputs]
[chain/start] [chain:RetrievalQA > chain:StuffDocumentsChain > chain:LLMChain] Entering Chain run with input:
{
  "question": "高清电视机怎么进行护理?",
  "context": "product_name: 高清电视机\ndescription: 规格:\n尺寸:50''。\n\n为什么我们热爱它:\n我们的高清电视机拥有出色的画质和强大的音效,带来沉浸式的观看体验。\n\n材质与护理:\n使用干布清洁。\n\n构造:\n由塑料、金属和电子元件制成。\n\n其他特性:\n支持网络连接,可以在线观看视频。\n配备遥控器。\n在韩国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。<<<<>>>>>product_name: 旅行背包\ndescription: 规格:\n尺寸:18'' x 12'' x 6''。\n\n为什么我们热爱它:\n我们的旅行背包拥有多个实用的内外袋,轻松装下您的必需品,是短途旅行的理想选择。\n\n材质与护理:\n可以手洗,自然晾干。\n\n构造:\n由防水尼龙制成。\n\n其他特性:\n附带可调节背带和安全锁。\n在中国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。<<<<>>>>>product_name: 太阳能庭院灯\ndescription: 规格:\n高度:18''。\n\n为什么我们热爱它:\n我们的太阳能庭院灯无需电源,只需将其放在阳光下即可充电。到了晚上,它会自动点亮,为您的庭院增添温馨的氛围。\n\n材质与护理:\n可以用湿布清洁。\n\n构造:\n由塑料和太阳能板制成。\n\n其他特性:\n自动感应,日落后自动点亮。\n在中国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。<<<<>>>>>product_name: 迷你无线蓝牙音箱\ndescription: 规格:\n直径:3'',高度:2''。\n\n为什么我们热爱它:\n我们的迷你无线蓝牙音箱体积小巧,音质出色,可以轻松带给您音乐的享受。\n\n材质与护理:\n使用湿布擦拭清洁。\n\n构造:\n由塑料和金属构成。\n\n其他特性:\n内置可充电电池,充满后可播放5小时。\n在中国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。"
}
[llm/start] [chain:RetrievalQA > chain:StuffDocumentsChain > chain:LLMChain > llm:ChatOpenAI] Entering LLM run with input:
{
  "prompts": [
    "System: Use the following pieces of context to answer the user's question.\nIf you don't know the answer, just say that you don't know, don't try to make up an answer.\n----------------\nproduct_name: 高清电视机\ndescription: 规格:\n尺寸:50''。\n\n为什么我们热爱它:\n我们的高清电视机拥有出色的画质和强大的音效,带来沉浸式的观看体验。\n\n材质与护理:\n使用干布清洁。\n\n构造:\n由塑料、金属和电子元件制成。\n\n其他特性:\n支持网络连接,可以在线观看视频。\n配备遥控器。\n在韩国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。<<<<>>>>>product_name: 旅行背包\ndescription: 规格:\n尺寸:18'' x 12'' x 6''。\n\n为什么我们热爱它:\n我们的旅行背包拥有多个实用的内外袋,轻松装下您的必需品,是短途旅行的理想选择。\n\n材质与护理:\n可以手洗,自然晾干。\n\n构造:\n由防水尼龙制成。\n\n其他特性:\n附带可调节背带和安全锁。\n在中国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。<<<<>>>>>product_name: 太阳能庭院灯\ndescription: 规格:\n高度:18''。\n\n为什么我们热爱它:\n我们的太阳能庭院灯无需电源,只需将其放在阳光下即可充电。到了晚上,它会自动点亮,为您的庭院增添温馨的氛围。\n\n材质与护理:\n可以用湿布清洁。\n\n构造:\n由塑料和太阳能板制成。\n\n其他特性:\n自动感应,日落后自动点亮。\n在中国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。<<<<>>>>>product_name: 迷你无线蓝牙音箱\ndescription: 规格:\n直径:3'',高度:2''。\n\n为什么我们热爱它:\n我们的迷你无线蓝牙音箱体积小巧,音质出色,可以轻松带给您音乐的享受。\n\n材质与护理:\n使用湿布擦拭清洁。\n\n构造:\n由塑料和金属构成。\n\n其他特性:\n内置可充电电池,充满后可播放5小时。\n在中国制造。\n\n有问题?请随时联系我们的客户服务团队,他们会解答您的所有问题。\nHuman: 高清电视机怎么进行护理?"
  ]
}
[llm/end] [chain:RetrievalQA > chain:StuffDocumentsChain > chain:LLMChain > llm:ChatOpenAI] [2.22s] Exiting LLM run with output:
{
  "generations": [
    [
      {
        "text": "使用干布清洁高清电视机。",
        "generation_info": {
          "finish_reason": "stop",
...
[chain/end] [chain:RetrievalQA] [2.26s] Exiting Chain run with output:
{
  "result": "使用干布清洁高清电视机。"
}
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...

我们可以看到它首先深入到检索 QA 链中,然后它进入了一些文档链。如上所述,我们正在使用 stuff 方法,现在我们正在传递这个上下文,可以看到,这个上下文是由我们检索到的不同文档创建的。因此,在进行问答时,当返回错误结果时,通常不是语言模型本身出错了,实际上是检索步骤出错了,仔细查看问题的确切内容和上下文可以帮助调试出错的原因。

3. 通过LLM进行评估实例

来简要梳理一下问答评估的流程:

  • 首先,我们使用 LLM 自动构建了问答测试集,包含问题及标准答案。

  • 然后,同一 LLM 试图回答测试集中的所有问题,得到响应。

  • 下一步,需要评估语言模型的回答是否正确。这里奇妙的是,我们再使用另一个 LLM 链进行判断,所以 LLM 既是“球员”,又是“裁判”。

具体来说,第一个语言模型负责回答问题。第二个语言模型链用来进行答案判定。最后我们可以收集判断结果,得到语言模型在这一任务上的效果分数。需要注意的是,回答问题的语言模型链和答案判断链是分开的,职责不同。这避免了同一个模型对自己结果的主观判断。

总之,语言模型可以自动完成构建测试集、回答问题和判定答案等全流程,使评估过程更加智能化和自动化。我们只需要提供文档并解析最终结果即可。

langchain.debug = False

#为所有不同的示例创建预测
predictions = qa.batch(examples) 

# 对预测的结果进行评估,导入QA问题回答,评估链,通过语言模型创建此链
from langchain.evaluation.qa import QAEvalChain #导入QA问题回答,评估链


eval_chain = QAEvalChain.from_llm(llm)

#在此链上调用evaluate,进行评估
graded_outputs = eval_chain.evaluate(examples, predictions)
print(len(graded_outputs))
print(graded_outputs)
> Entering new RetrievalQA chain...


> Entering new RetrievalQA chain...


> Entering new RetrievalQA chain...


> Entering new RetrievalQA chain...


> Entering new RetrievalQA chain...


> Entering new RetrievalQA chain...


> Entering new RetrievalQA chain...

> Finished chain.

> Finished chain.
...

> Finished chain.
7
[{'results': 'CORRECT'}, {'results': 'CORRECT'}, {'results': 'INCORRECT'}, {'results': 'INCORRECT'}, {'results': 'CORRECT'}, {'results': 'CORRECT'}, {'results': 'INCORRECT'}]
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
#我们将传入示例和预测,得到一堆分级输出,循环遍历它们打印答案
for i, eg in enumerate(examples):
    print(f"Example {i}:")
    print("Question: " + predictions[i]['query'])
    print("Real Answer: " + predictions[i]['answer'])
    print("Predicted Answer: " + predictions[i]['result'])
    print("Predicted Grade: " + graded_outputs[i]['results'])
    print()
Example 0:
Question: 高清电视机怎么进行护理?
Real Answer: 使用干布清洁。
Predicted Answer: 使用干布清洁高清电视机。
Predicted Grade: CORRECT

Example 1:
Question: 旅行背包有内外袋吗?
Real Answer: 有。
Predicted Answer: 是的,旅行背包拥有多个实用的内外袋。
Predicted Grade: CORRECT

Example 2:
Question: 这款全自动咖啡机是由什么材质制成的?
Real Answer: 这款全自动咖啡机是由高品质不锈钢制成的。
Predicted Answer: 不知道。
Predicted Grade: INCORRECT

Example 3:
Question: 该电动牙刷是由哪些材料制成的?
Real Answer: 该电动牙刷是由食品级塑料和尼龙刷毛制成的。
Predicted Answer: 不知道。
Predicted Grade: INCORRECT

Example 4:
Question: 该橙味维生素C泡腾片的主要成分是什么?
Real Answer: 该橙味维生素C泡腾片的主要成分为维生素C和柠檬酸钠。
Predicted Answer: 该橙味维生素C泡腾片的主要成分为维生素C和柠檬酸钠。
Predicted Grade: CORRECT

Example 5:
Question: 这款无线蓝牙耳机的电池续航力是多久?
Real Answer: 这款无线蓝牙耳机的电池续航力长达8小时。
Predicted Answer: 这款无线蓝牙耳机的电池续航力长达8小时。
Predicted Grade: CORRECT

Example 6:
Question: 这款瑜伽垫的尺寸是多少?
Real Answer: 这款瑜伽垫的尺寸是24'' x 68''。
Predicted Answer: 不知道。
Predicted Grade: INCORRECT

从上面的返回结果中我们可以看到,在评估结果中每一个问题中都包含了Question,Real Answer,Predicted Answer和Predicted Grade 四组内容,

其中Real Answer是有先前的QAGenerateChain创建的问答测试集中的答案,

而Predicted Answer则是由我们的qa链给出的答案,

最后的Predicted Grade则是由上面代码中的QAEvalChain回答的。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐