Skip to main content

逐对字符串比较

通常,您会希望比较LLM、Chain或Agent对于给定输入的预测。StringComparison评估器可以帮助您回答以下问题:

  • 对于给定的问题,哪个LLM或提示生成了首选输出?
  • 对于少样本示例选择,应该包括哪些示例?
  • 包含哪个输出进行微调更好?

选择给定输入的首选预测的最简单且通常最可靠的自动化方法是使用pairwise_string评估器。

请查看参考文档以获取有关PairwiseStringEvalChain的更多信息。

from langchain.evaluation import load_evaluator

evaluator = load_evaluator("labeled_pairwise_string")

API参考:

evaluator.evaluate_string_pairs(
prediction="there are three dogs",
prediction_b="4",
input="how many dogs are in the park?",
reference="four",
)
{
'reasoning': '两个回答都与所问问题相关,因为它们都提供了关于公园里有多少只狗的问题的数字答案。然而,根据参考答案,回答A是不正确的,参考答案指出公园里有四只狗。另一方面,回答B是正确的,因为它与参考答案相匹配。两个回答都没有展示出深入思考,因为它们只是提供了一个数字答案,没有提供任何额外的信息或上下文。\n\n基于这些标准,回答B是更好的回答。\n',
'value': 'B',
'score': 0
}

方法

可以使用evaluate_string_pairs(或异步的aevaluate_string_pairs)方法调用逐对字符串评估器,这些方法接受以下参数:

  • prediction (str) – 第一个模型、链或提示的预测响应。
  • prediction_b (str) – 第二个模型、链或提示的预测响应。
  • input (str) – 输入问题、提示或其他文本。
  • reference (str) – (仅适用于labeled_pairwise_string变体)参考响应。

它们返回一个包含以下值的字典:

  • value: 'A'或'B',分别表示首选的predictionprediction_b
  • score: 从'value'映射的整数0或1,其中得分为1表示首选第一个prediction,得分为0表示首选prediction_b
  • reasoning: 在创建得分之前由LLM生成的“思路链”

没有参考

当没有参考时,您仍然可以预测首选的响应。结果将反映评估模型的偏好,这种偏好可能不太可靠,并可能导致事实上不正确的偏好。

from langchain.evaluation import load_evaluator

evaluator = load_evaluator("pairwise_string")

API参考:

evaluator.evaluate_string_pairs(
prediction="Addition is a mathematical operation.",
prediction_b="Addition is a mathematical operation that adds two numbers to create a third number, the 'sum'.",
input="What is addition?",
)
{
'reasoning': '两个回答都是正确的,并且与问题相关。然而,回答B更有帮助和深入,因为它提供了关于加法是什么的更详细的解释。回答A是正确的,但缺乏深度,因为它没有解释加法的操作内容。\n\n最终决定:[[B]]',
'value': 'B',
'score': 0
}

定义标准

默认情况下,LLM被指示根据有用性、相关性、正确性和思考深度选择“首选”响应。您可以通过传递criteria参数来自定义标准,其中标准可以采用以下任何形式:

  • Criteria枚举或其字符串值 - 使用默认标准及其描述之一
  • 宪法原则 - 使用langchain中定义的任何宪法原则
  • 字典:自定义标准的列表,其中键是标准的名称,值是描述。
  • 标准或宪法原则的列表 - 将多个标准组合在一起。

以下是根据自定义风格确定首选写作响应的示例。

custom_criteria = {
"simplicity": "语言是否简单直接?",
"clarity": "句子是否清晰易懂?",
"precision": "写作是否精确,没有不必要的词语或细节?",
"truthfulness": "写作是否感觉真实和真诚?",
"subtext": "写作是否暗示更深层次的意义或主题?",
}
evaluator = load_evaluator("pairwise_string", criteria=custom_criteria)
evaluator.evaluate_string_pairs(
prediction="Every cheerful household shares a similar rhythm of joy; but sorrow, in each household, plays a unique, haunting melody.",
prediction_b="Where one finds a symphony of joy, every domicile of happiness resounds in harmonious, identical notes; yet, every abode of despair conducts a dissonant orchestra, each playing an elegy of grief that is peculiar and profound to its own existence.",
input="Write some prose about families.",
)
{
'reasoning': '回答A简单、清晰、精确。它使用简单直接的语言传达了关于家庭的深刻和真诚的信息。将喜悦和悲伤比作音乐的隐喻是有效且易于理解的。\n\n另一方面,回答B更复杂,不太清晰。语言更加炫耀,使用了“住所”、“回响”、“居所”、“不和谐”和“挽歌”等词语。虽然它传达了与回答A类似的信息,但方式更加复杂。由于使用了不必要的词语和细节,精确性也有所不足。\n\n两个回答都暗示了关于家庭中共享的喜悦和独特的悲伤的更深层次的意义或主题。然而,回答A以更有效和易于理解的方式暗示了这一点。\n\n因此,更好的回答是[[A]]。',
'value': 'A',
'score': 1
}

自定义LLM

默认情况下,加载器在评估链中使用gpt-4。您可以在加载时自定义此项。

from langchain.chat_models import ChatAnthropic

llm = ChatAnthropic(temperature=0)
evaluator = load_evaluator("labeled_pairwise_string", llm=llm)

API参考:

evaluator.evaluate_string_pairs(
prediction="there are three dogs",
prediction_b="4",
input="how many dogs are in the park?",
reference="four",
)
{
'reasoning': '这是我的评估:\n\n回答B比回答A更有帮助、见解更深入、准确性更高。回答B只是简单地陈述“4”,直接回答了问题,提供了参考答案中提到的狗的确切数量。相比之下,回答A陈述了“公园里有三只狗”,这与参考答案不符。\n\n就有用性而言,回答B给出了精确的数字,而回答A提供了一个不准确的猜测。对于相关性,两者都涉及到了问题中的公园里的狗。然而,根据参考答案,回答B更正确和准确。回答A显示了一些推理的尝试,但最终是不正确的。回答B需要更少的思考深度,只需简单陈述事实上的数字。\n\n总之,回答B在有用性、相关性、正确性和深度方面都更优秀。我的最终决定是:[[B]]\n',
'value': 'B',
'score': 0
}

自定义评估提示

您可以使用自定义的评估提示添加更多特定任务的说明,或指示评估器对输出进行评分。

*注意:如果您使用的提示期望以唯一格式生成结果,则还必须传入自定义输出解析器(output_parser=your_parser()),而不是默认的PairwiseStringResultOutputParser

from langchain.prompts import PromptTemplate

prompt_template = PromptTemplate.from_template(
"""Given the input context, which do you prefer: A or B?
Evaluate based on the following criteria:
{criteria}
Reason step by step and finally, respond with either [[A]] or [[B]] on its own line.

DATA
----
input: {input}
reference: {reference}
A: {prediction}
B: {prediction_b}
---
Reasoning:

"""
)
evaluator = load_evaluator(
"labeled_pairwise_string", prompt=prompt_template
)

API参考:

# 将提示分配给评估器
print(evaluator.prompt)
input_variables=['prediction', 'reference', 'prediction_b', 'input'] output_parser=None partial_variables={'criteria': 'helpfulness: Is the submission helpful, insightful, and appropriate?\nrelevance: Is the submission referring to a real quote from the text?\ncorrectness: Is the submission correct, accurate, and factual?\ndepth: Does the submission demonstrate depth of thought?'} template='Given the input context, which do you prefer: A or B?\nEvaluate based on the following criteria:\n{criteria}\nReason step by step and finally, respond with either [[A]] or [[B]] on its own line.\n\nDATA\n----\ninput: {input}\nreference: {reference}\nA: {prediction}\nB: {prediction_b}\n---\nReasoning:\n\n' template_format='f-string' validate_template=True
evaluator.evaluate_string_pairs(
prediction="The dog that ate the ice cream was named fido.",
prediction_b="The dog's name is spot",
input="What is the name of the dog that ate the ice cream?",
reference="The dog's name is fido",
)
{
'reasoning': 'Helpfulness: Both A and B are helpful as they provide a direct answer to the question.\nRelevance: A is relevant as it refers to the correct name of the dog from the text. B is not relevant as it provides a different name.\nCorrectness: A is correct as it accurately states the name of the dog. B is incorrect as it provides a different name.\nDepth: Both A and B demonstrate a similar level of depth as they both provide a straightforward answer to the question.\n\nGiven these evaluations, the preferred response is:\n',
'value': 'A',
'score': 1
}