"""用于解析字符串的评估器。"""
import json
from operator import eq
from typing import Any, Callable, Optional, Union, cast
from langchain_core.utils.json import parse_json_markdown
from langchain.evaluation.schema import StringEvaluator
[docs]class JsonValidityEvaluator(StringEvaluator):
"""评估预测是否为有效的JSON。
此评估器检查预测是否为有效的JSON字符串。不需要任何输入或参考。
属性:
requires_input (bool): 此评估器是否需要输入字符串。始终为False。
requires_reference (bool): 此评估器是否需要参考字符串。始终为False。
evaluation_name (str): 评估指标的名称。始终为"json"。
示例:
>>> evaluator = JsonValidityEvaluator()
>>> prediction = '{"name": "John", "age": 30, "city": "New York"}'
>>> evaluator.evaluate(prediction)
{'score': 1}
>>> prediction = '{"name": "John", "age": 30, "city": "New York",}'
>>> evaluator.evaluate(prediction)
{'score': 0, 'reasoning': 'Expecting property name enclosed in double quotes'}"""
[docs] def __init__(self, **kwargs: Any) -> None:
super().__init__()
@property
def requires_input(self) -> bool:
return False
@property
def requires_reference(self) -> bool:
return False
@property
def evaluation_name(self) -> str:
return "json_validity"
def _evaluate_strings(
self,
prediction: str,
input: Optional[str] = None,
reference: Optional[str] = None,
**kwargs: Any,
) -> dict:
"""评估预测字符串。
参数:
prediction (str): 要评估的预测字符串。
input (str, optional): 在此评估器中未使用。默认为None。
reference (str, optional): 在此评估器中未使用。默认为None。
返回:
dict: 包含评估分数的字典。如果预测是有效的JSON,则分数为1,否则为0。
如果预测不是有效的JSON,则字典还包含一个带有错误消息的“reasoning”字段。
"""
try:
parse_json_markdown(prediction, parser=json.loads)
return {"score": 1}
except Exception as e:
return {"score": 0, "reasoning": str(e)}
[docs]class JsonEqualityEvaluator(StringEvaluator):
"""评估是否在将预测和参考解析为JSON之后相等。
此评估器检查预测是否在解析为JSON后等于参考,
参考也被解析为JSON。它不需要输入字符串。
属性:
requires_input (bool): 此评估器是否需要输入字符串。始终为False。
requires_reference (bool): 此评估器是否需要参考字符串。始终为True。
evaluation_name (str): 评估指标的名称。始终为"parsed_equality"。
示例:
>>> evaluator = JsonEqualityEvaluator()
>>> evaluator.evaluate_strings('{"a": 1}', reference='{"a": 1}')
{'score': True}
>>> evaluator.evaluate_strings('{"a": 1}', reference='{"a": 2}')
{'score': False}
>>> evaluator = JsonEqualityEvaluator(operator=lambda x, y: x['a'] == y['a'])
>>> evaluator.evaluate_strings('{"a": 1}', reference='{"a": 1}')
{'score': True}
>>> evaluator.evaluate_strings('{"a": 1}', reference='{"a": 2}')
{'score': False}"""
[docs] def __init__(self, operator: Optional[Callable] = None, **kwargs: Any) -> None:
super().__init__()
self.operator = operator or eq
@property
def requires_input(self) -> bool:
return False
@property
def requires_reference(self) -> bool:
return True
@property
def evaluation_name(self) -> str:
return "json_equality"
def _parse_json(
self,
string: Any,
) -> Union[dict, list, None, float, bool, int, str]:
if isinstance(string, str):
return parse_json_markdown(string)
return string
def _evaluate_strings(
self,
prediction: str,
input: Optional[str] = None,
reference: Optional[str] = None,
**kwargs: Any,
) -> dict:
"""评估预测字符串。
参数:
prediction (str): 需要评估的预测字符串。
input (str, optional): 在此评估器中未使用。
reference (str): 用于比较的参考字符串。
返回:
dict: 包含评估分数的字典。
"""
parsed = self._parse_json(prediction)
label = self._parse_json(cast(str, reference))
if isinstance(label, list):
if not isinstance(parsed, list):
return {"score": 0}
parsed = sorted(parsed, key=lambda x: str(x))
label = sorted(label, key=lambda x: str(x))
return {"score": self.operator(parsed, label)}