MetricType
基类: Enum
Ragas 中指标类型的枚举。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
SINGLE_TURN |
str |
表示单轮指标类型。 |
MULTI_TURN |
str |
表示多轮指标类型。 |
Metric
Metric(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '')
基类: ABC
Ragas 中指标的抽象基类。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
name |
str |
指标名称。 |
required_columns |
Dict[str, Set[str]] |
将指标类型名映射到所需列名集合的字典。这是一个属性;若列不在 VALID_COLUMNS 中会抛出 ValueError。 |
init
init(run_config: RunConfig) -> None
用给定运行配置初始化指标。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
run_config |
RunConfig |
指标运行配置,包括超时及其他设置。 | required |
源代码位于 src/ragas/metrics/base.py
@abstractmethod
def init(self, run_config: RunConfig) -> None:
"""
Initialize the metric with the given run configuration.
Parameters
----------
run_config : RunConfig
Configuration for the metric run including timeouts and other settings.
"""
...
MetricWithLLM
MetricWithLLM(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '', llm: Optional[BaseRagasLLM] = None, output_type: Optional[MetricOutputType] = None)
基类: Metric, PromptMixin
使用语言模型进行评测的指标类。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
llm |
Optional[BaseRagasLLM] |
用于该指标的语言模型。运行时通过 duck typing 同时接受 BaseRagasLLM 和 InstructorBaseRagasLLM(二者方法兼容)。 |
init
init(run_config: RunConfig) -> None
用运行配置初始化指标,并校验 LLM 是否存在。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
run_config |
RunConfig |
指标运行配置。 | required |
抛出:
| 类型 | 说明 |
|---|---|
ValueError |
若未向指标提供 LLM。 |
源代码位于 src/ragas/metrics/base.py
def init(self, run_config: RunConfig) -> None:
"""
Initialize the metric with run configuration and validate LLM is present.
Parameters
----------
run_config : RunConfig
Configuration for the metric run.
Raises
------
ValueError
If no LLM is provided to the metric.
"""
if self.llm is None:
raise ValueError(
f"Metric '{self.name}' has no valid LLM provided (self.llm is None). Please instantiate the metric with an LLM to run."
)
# Only BaseRagasLLM has set_run_config method, not InstructorBaseRagasLLM
if isinstance(self.llm, BaseRagasLLM):
self.llm.set_run_config(run_config)
train
train(path: str, demonstration_config: Optional[DemonstrationConfig] = None, instruction_config: Optional[InstructionConfig] = None, callbacks: Optional[Callbacks] = None, run_config: Optional[RunConfig] = None, batch_size: Optional[int] = None, with_debugging_logs=False, raise_exceptions: bool = True) -> None
使用本地 JSON 数据训练指标
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
path |
str |
本地 JSON 训练数据文件路径 | required |
demonstration_config |
DemonstrationConfig |
示例优化的配置 | None |
instruction_config |
InstructionConfig |
指令优化的配置 | None |
callbacks |
Callbacks |
回调函数列表 | None |
run_config |
RunConfig |
运行配置 | None |
batch_size |
int |
训练批次大小 | None |
with_debugging_logs |
bool |
启用调试日志 | False |
raise_exceptions |
bool |
训练期间是否抛出异常 | True |
抛出:
| 类型 | 说明 |
|---|---|
ValueError |
若未提供 path 或不是 JSON 文件 |
源代码位于 src/ragas/metrics/base.py
def train(
self,
path: str,
demonstration_config: t.Optional[DemonstrationConfig] = None,
instruction_config: t.Optional[InstructionConfig] = None,
callbacks: t.Optional[Callbacks] = None,
run_config: t.Optional[RunConfig] = None,
batch_size: t.Optional[int] = None,
with_debugging_logs=False,
raise_exceptions: bool = True,
) -> None:
"""
Train the metric using local JSON data
Parameters
----------
path : str
Path to local JSON training data file
demonstration_config : DemonstrationConfig, optional
Configuration for demonstration optimization
instruction_config : InstructionConfig, optional
Configuration for instruction optimization
callbacks : Callbacks, optional
List of callback functions
run_config : RunConfig, optional
Run configuration
batch_size : int, optional
Batch size for training
with_debugging_logs : bool, default=False
Enable debugging logs
raise_exceptions : bool, default=True
Whether to raise exceptions during training
Raises
------
ValueError
If path is not provided or not a JSON file
"""
# Validate input parameters
if not path:
raise ValueError("Path to training data file must be provided")
if not path.endswith(".json"):
raise ValueError("Train data must be in json format")
run_config = run_config or RunConfig()
callbacks = callbacks or []
# Load the dataset from JSON file
dataset = MetricAnnotation.from_json(path, metric_name=self.name)
# only optimize the instruction if instruction_config is provided
if instruction_config is not None:
self._optimize_instruction(
instruction_config=instruction_config,
dataset=dataset,
callbacks=callbacks,
run_config=run_config,
batch_size=batch_size,
with_debugging_logs=with_debugging_logs,
raise_exceptions=raise_exceptions,
)
# if demonstration_config is provided, optimize the demonstrations
if demonstration_config is not None:
self._optimize_demonstration(
demonstration_config=demonstration_config,
dataset=dataset,
)
SingleTurnMetric
SingleTurnMetric(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '')
基类: Metric
用于评测单轮交互的指标类。
该类提供同步和异步为单轮样本打分的方法。
single_turn_score
single_turn_score(sample: SingleTurnSample, callbacks: Callbacks = None) -> float
同步为单轮样本打分。
若在类 Jupyter 环境中未安装 nest_asyncio,可能抛出 ImportError。
源代码位于 src/ragas/metrics/base.py
def single_turn_score(
self,
sample: SingleTurnSample,
callbacks: Callbacks = None,
) -> float:
"""
Synchronously score a single-turn sample.
May raise ImportError if nest_asyncio is not installed in a Jupyter-like environment.
"""
callbacks = callbacks or []
# only get the required columns
sample = self._only_required_columns_single_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
async def _async_wrapper():
try:
result = await self._single_turn_ascore(
sample=sample, callbacks=group_cm
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": result})
return result
apply_nest_asyncio()
score = run(_async_wrapper)
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
single_turn_ascore
single_turn_ascore(sample: SingleTurnSample, callbacks: Callbacks = None, timeout: Optional[float] = None) -> float
异步为单轮样本打分,可设超时。
若打分过程超过指定超时,可能抛出 asyncio.TimeoutError。
源代码位于 src/ragas/metrics/base.py
async def single_turn_ascore(
self,
sample: SingleTurnSample,
callbacks: Callbacks = None,
timeout: t.Optional[float] = None,
) -> float:
"""
Asynchronously score a single-turn sample with an optional timeout.
May raise asyncio.TimeoutError if the scoring process exceeds the specified timeout.
"""
callbacks = callbacks or []
# only get the required columns
sample = self._only_required_columns_single_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
try:
score = await asyncio.wait_for(
self._single_turn_ascore(sample=sample, callbacks=group_cm),
timeout=timeout,
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": score})
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
MultiTurnMetric
MultiTurnMetric(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '')
基类: Metric
用于评测多轮对话的指标类。
该类扩展基础 Metric 类,提供为多轮对话样本打分的功能。
multi_turn_score
multi_turn_score(sample: MultiTurnSample, callbacks: Callbacks = None) -> float
同步为多轮对话样本打分。
若在类 Jupyter 环境中未安装 nest_asyncio,可能抛出 ImportError。
源代码位于 src/ragas/metrics/base.py
def multi_turn_score(
self,
sample: MultiTurnSample,
callbacks: Callbacks = None,
) -> float:
"""
Score a multi-turn conversation sample synchronously.
May raise ImportError if nest_asyncio is not installed in Jupyter-like environments.
"""
callbacks = callbacks or []
sample = self._only_required_columns_multi_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
async def _async_wrapper():
try:
result = await self._multi_turn_ascore(
sample=sample, callbacks=group_cm
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": result})
return result
apply_nest_asyncio()
score = run(_async_wrapper)
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
multi_turn_ascore
multi_turn_ascore(sample: MultiTurnSample, callbacks: Callbacks = None, timeout: Optional[float] = None) -> float
异步为多轮对话样本打分。
若打分过程超过指定超时,可能抛出 asyncio.TimeoutError。
源代码位于 src/ragas/metrics/base.py
async def multi_turn_ascore(
self,
sample: MultiTurnSample,
callbacks: Callbacks = None,
timeout: t.Optional[float] = None,
) -> float:
"""
Score a multi-turn conversation sample asynchronously.
May raise asyncio.TimeoutError if the scoring process exceeds the specified timeout.
"""
callbacks = callbacks or []
sample = self._only_required_columns_multi_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
try:
score = await asyncio.wait_for(
self._multi_turn_ascore(sample=sample, callbacks=group_cm),
timeout=timeout,
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": score})
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
Ensember
将同一输入的多个 llm 输出(n>1)合并为单个输出
from_discrete
from_discrete(inputs: list[list[Dict]], attribute: str) -> List[Dict]
对二元值做简单多数投票,即 [0,0,1] -> 0;inputs:字典列表的列表,每个包含单条输入的判定
源代码位于 src/ragas/metrics/base.py
def from_discrete(
self, inputs: list[list[t.Dict]], attribute: str
) -> t.List[t.Dict]:
"""
Simple majority voting for binary values, ie [0,0,1] -> 0
inputs: list of list of dicts each containing verdict for a single input
"""
if not isinstance(inputs, list):
inputs = [inputs]
if not all(len(item) == len(inputs[0]) for item in inputs):
logger.warning("All inputs must have the same length")
return inputs[0]
if not all(attribute in item for input in inputs for item in input):
logger.warning(f"All inputs must have {attribute} attribute")
return inputs[0]
if len(inputs) == 1:
return inputs[0]
verdict_agg = []
for i in range(len(inputs[0])):
item = inputs[0][i]
verdicts = [inputs[k][i][attribute] for k in range(len(inputs))]
verdict_counts = dict(Counter(verdicts).most_common())
item[attribute] = list(verdict_counts.keys())[0]
verdict_agg.append(item)
return verdict_agg
SimpleBaseMetric
SimpleBaseMetric(name: str, allowed_values: AllowedValuesType = (lambda: ['pass', 'fail'])())
基类: ABC
返回 MetricResult 对象的简单指标基类。
该类为评测输入并返回包含分数和推理的结构化 MetricResult 对象的指标提供基础。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
name |
str |
指标名称。 |
allowed_values |
AllowedValuesType |
指标输出的允许值。离散指标可为字符串列表,数值指标可为浮点元组,排序指标可为整数。 |
示例:
>>> from ragas.metrics import discrete_metric
>>>
>>> @discrete_metric(name="sentiment", allowed_values=["positive", "negative"])
>>> def sentiment_metric(user_input: str, response: str) -> str:
... return "positive" if "good" in response else "negative"
>>>
>>> result = sentiment_metric(user_input="How are you?", response="I'm good!")
>>> print(result.value) # "positive"
score
score(**kwargs) -> 'MetricResult'
同步计算指标分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
**kwargs |
dict |
特定指标实现所需的输入参数。 | {} |
返回:
| 类型 | 说明 |
|---|---|
MetricResult |
包含分数和推理的评测结果。 |
源代码位于 src/ragas/metrics/base.py
@abstractmethod
def score(self, **kwargs) -> "MetricResult":
"""
Synchronously calculate the metric score.
Parameters
----------
**kwargs : dict
Input parameters required by the specific metric implementation.
Returns
-------
MetricResult
The evaluation result containing the score and reasoning.
"""
pass
ascore
ascore(**kwargs) -> 'MetricResult'
异步计算指标分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
**kwargs |
dict |
特定指标实现所需的输入参数。 | {} |
返回:
| 类型 | 说明 |
|---|---|
MetricResult |
包含分数和推理的评测结果。 |
源代码位于 src/ragas/metrics/base.py
@abstractmethod
async def ascore(self, **kwargs) -> "MetricResult":
"""
Asynchronously calculate the metric score.
Parameters
----------
**kwargs : dict
Input parameters required by the specific metric implementation.
Returns
-------
MetricResult
The evaluation result containing the score and reasoning.
"""
pass
batch_score
batch_score(inputs: List[Dict[str, Any]]) -> List['MetricResult']
同步计算一批输入的分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
inputs |
List[Dict[str, Any]] |
输入字典列表,每个包含该指标的参数。 | required |
返回:
| 类型 | 说明 |
|---|---|
List[MetricResult] |
评测结果列表,每个输入一个。 |
源代码位于 src/ragas/metrics/base.py
def batch_score(
self,
inputs: t.List[t.Dict[str, t.Any]],
) -> t.List["MetricResult"]:
"""
Synchronously calculate scores for a batch of inputs.
Parameters
----------
inputs : List[Dict[str, Any]]
List of input dictionaries, each containing parameters for the metric.
Returns
-------
List[MetricResult]
List of evaluation results, one for each input.
"""
return [self.score(**input_dict) for input_dict in inputs]
abatch_score
abatch_score(inputs: List[Dict[str, Any]]) -> List['MetricResult']
并行异步计算一批输入的分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
inputs |
List[Dict[str, Any]] |
输入字典列表,每个包含该指标的参数。 | required |
返回:
| 类型 | 说明 |
|---|---|
List[MetricResult] |
评测结果列表,每个输入一个。 |
源代码位于 src/ragas/metrics/base.py
async def abatch_score(
self,
inputs: t.List[t.Dict[str, t.Any]],
) -> t.List["MetricResult"]:
"""
Asynchronously calculate scores for a batch of inputs in parallel.
Parameters
----------
inputs : List[Dict[str, Any]]
List of input dictionaries, each containing parameters for the metric.
Returns
-------
List[MetricResult]
List of evaluation results, one for each input.
"""
async_tasks = []
for input_dict in inputs:
# Process input asynchronously
async_tasks.append(self.ascore(**input_dict))
# Run all tasks concurrently and return results
return await asyncio.gather(*async_tasks)
SimpleLLMMetric
SimpleLLMMetric(name: str, allowed_values: AllowedValuesType = (lambda: ['pass', 'fail'])(), prompt: Optional[Union[str, 'Prompt']] = None)
基类: SimpleBaseMetric
使用 prompt 生成结构化响应的基于 LLM 的指标。
save
save(path: Optional[str] = None) -> None
将指标配置保存到 JSON 文件。
参数:
path : str, 可选 要保存到的文件路径。若未提供,保存为 "./{metric.name}.json"。使用 .gz 扩展名可压缩。
Note:
若指标有 response_model,其 schema 会保存以供参考,但模型本身无法序列化。加载时你需要提供它。
示例:
以下均可:
metric.save() # → ./response_quality.json metric.save("custom.json") # → ./custom.json metric.save("/path/to/metrics/") # → /path/to/metrics/response_quality.json metric.save("no_extension") # → ./no_extension.json metric.save("compressed.json.gz") # → ./compressed.json.gz (compressed)
源代码位于 src/ragas/metrics/base.py
def save(self, path: t.Optional[str] = None) -> None:
"""
Save the metric configuration to a JSON file.
Parameters:
-----------
path : str, optional
File path to save to. If not provided, saves to "./{metric.name}.json"
Use .gz extension for compression.
Note:
-----
If the metric has a response_model, its schema will be saved for reference
but the model itself cannot be serialized. You'll need to provide it when loading.
Examples:
---------
All these work:
>>> metric.save() # → ./response_quality.json
>>> metric.save("custom.json") # → ./custom.json
>>> metric.save("/path/to/metrics/") # → /path/to/metrics/response_quality.json
>>> metric.save("no_extension") # → ./no_extension.json
>>> metric.save("compressed.json.gz") # → ./compressed.json.gz (compressed)
"""
import gzip
import json
import warnings
from pathlib import Path
# Handle default path
if path is None:
# Default to current directory with metric name as filename
file_path = Path(f"./{self.name}.json")
else:
file_path = Path(path)
# If path is a directory, append the metric name as filename
if file_path.is_dir():
file_path = file_path / f"{self.name}.json"
# If path has no extension, add .json
elif not file_path.suffix:
file_path = file_path.with_suffix(".json")
# Collect warning messages for data loss
warning_messages = []
if hasattr(self, "_response_model") and self._response_model:
# Only warn for custom response models, not auto-generated ones
if not getattr(self._response_model, "__ragas_auto_generated__", False):
warning_messages.append(
"- Custom response_model will be lost (set it manually after loading)"
)
# Serialize the prompt (may add embedding_model warning)
prompt_data = self._serialize_prompt(warning_messages)
# Determine the metric type
metric_type = self.__class__.__name__
# Get metric-specific config
config = self._get_metric_config()
# Emit consolidated warning if there's data loss
if warning_messages:
warnings.warn(
"Some metric components cannot be saved and will be lost:\n"
+ "\n".join(warning_messages)
+ "\n\nYou'll need to provide these when loading the metric."
)
data = {
"format_version": "1.0",
"metric_type": metric_type,
"name": self.name,
"prompt": prompt_data,
"config": config,
"response_model_info": self._serialize_response_model_info(),
}
try:
if file_path.suffix == ".gz":
with gzip.open(file_path, "wt", encoding="utf-8") as f:
json.dump(data, f, indent=2)
else:
with open(file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
except (OSError, IOError) as e:
raise ValueError(f"Cannot save metric to {file_path}: {e}")
load
load(path: str, response_model: Optional[Type['BaseModel']] = None, embedding_model: Optional['EmbeddingModelType'] = None) -> 'SimpleLLMMetric'
从 JSON 文件加载指标。
参数:
path : str 要加载的文件路径。支持 .gz 压缩文件。response_model : Optional[Type[BaseModel]] 用于响应校验的 Pydantic 模型。自定义 SimpleLLMMetrics 时必需。embedding_model : Optional[Any] DynamicFewShotPrompt 的嵌入模型。若原始指标使用了嵌入模型则必需。
返回:
SimpleLLMMetric 已加载的指标实例
抛出:
ValueError:若文件无法加载、无效,或缺少所需模型
源代码位于 src/ragas/metrics/base.py
@classmethod
def load(
cls,
path: str,
response_model: t.Optional[t.Type["BaseModel"]] = None,
embedding_model: t.Optional["EmbeddingModelType"] = None,
) -> "SimpleLLMMetric":
"""
Load a metric from a JSON file.
Parameters:
-----------
path : str
File path to load from. Supports .gz compressed files.
response_model : Optional[Type[BaseModel]]
Pydantic model to use for response validation. Required for custom SimpleLLMMetrics.
embedding_model : Optional[Any]
Embedding model for DynamicFewShotPrompt. Required if the original used one.
Returns:
--------
SimpleLLMMetric
Loaded metric instance
Raises:
-------
ValueError
If file cannot be loaded, is invalid, or missing required models
"""
import gzip
import json
from pathlib import Path
file_path = Path(path)
# Load JSON data
try:
if file_path.suffix == ".gz":
with gzip.open(file_path, "rt", encoding="utf-8") as f:
data = json.load(f)
else:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError, OSError) as e:
raise ValueError(f"Cannot load metric from {path}: {e}")
# Validate format
if data.get("format_version") != "1.0":
import warnings
warnings.warn(
f"Loading metric with format version {data.get('format_version')}, expected 1.0"
)
# Reconstruct the prompt
prompt = cls._deserialize_prompt(data["prompt"], embedding_model)
# Get config
config = data.get("config", {})
# Create the metric instance
metric = cls(name=data["name"], prompt=prompt, **config)
# Set response model if provided
if response_model:
metric._response_model = response_model
return metric
get_correlation
get_correlation(gold_labels: List[str], predictions: List[str]) -> float
计算黄金分数与预测分数之间的相关性。这是占位方法,应根据具体指标实现。
源代码位于 src/ragas/metrics/base.py
@abstractmethod
def get_correlation(
self, gold_labels: t.List[str], predictions: t.List[str]
) -> float:
"""
Calculate the correlation between gold scores and predicted scores.
This is a placeholder method and should be implemented based on the specific metric.
"""
pass
align_and_validate
align_and_validate(dataset: 'Dataset', embedding_model: 'EmbeddingModelType', llm: 'BaseRagasLLM', test_size: float = 0.2, random_state: int = 42, **kwargs: Dict[str, Any])
参数: dataset: 用于对齐指标的实验。 embedding_model: 用于动态 few-shot prompting 的嵌入模型。 llm: 用于打分的 LLM 实例。
将指标与指定实验对齐,并对照黄金标准实验做校验。该方法把对齐和校验合并为一步。
源代码位于 src/ragas/metrics/base.py
def align_and_validate(
self,
dataset: "Dataset",
embedding_model: "EmbeddingModelType",
llm: "BaseRagasLLM",
test_size: float = 0.2,
random_state: int = 42,
**kwargs: t.Dict[str, t.Any],
):
"""
Args:
dataset: experiment to align the metric with.
embedding_model: The embedding model used for dynamic few-shot prompting.
llm: The LLM instance to use for scoring.
Align the metric with the specified experiments and validate it against a gold standard experiment.
This method combines alignment and validation into a single step.
"""
train_dataset, test_dataset = dataset.train_test_split(
test_size=test_size, random_state=random_state
)
self.align(train_dataset, embedding_model, **kwargs) # type: ignore
return self.validate_alignment(llm, test_dataset) # type: ignore
align
align(train_dataset: 'Dataset', embedding_model: 'EmbeddingModelType', **kwargs: Dict[str, Any])
参数: train_dataset: 用于对齐指标的 train_dataset。 embedding_model: 用于动态 few-shot prompting 的嵌入模型。
通过不同优化方法将指标与指定实验对齐。
源代码位于 src/ragas/metrics/base.py
def align(
self,
train_dataset: "Dataset",
embedding_model: "EmbeddingModelType",
**kwargs: t.Dict[str, t.Any],
):
"""
Args:
train_dataset: train_dataset to align the metric with.
embedding_model: The embedding model used for dynamic few-shot prompting.
Align the metric with the specified experiments by different optimization methods.
"""
# get prompt
if not self.prompt:
raise Exception("prompt not passed")
from ragas.prompt.simple_prompt import Prompt
self.prompt = (
self.prompt if isinstance(self.prompt, Prompt) else Prompt(self.prompt)
)
# Extract specific parameters for from_prompt method
max_similar_examples_val = kwargs.get("max_similar_examples", 3)
similarity_threshold_val = kwargs.get("similarity_threshold", 0.7)
max_similar_examples = (
int(max_similar_examples_val)
if isinstance(max_similar_examples_val, (int, str))
else 3
)
similarity_threshold = (
float(similarity_threshold_val)
if isinstance(similarity_threshold_val, (int, float, str))
else 0.7
)
# Convert BaseRagasEmbeddings to BaseRagasEmbedding if needed
if hasattr(embedding_model, "embed_query"):
# For legacy BaseRagasEmbeddings, we need to wrap it
# Create a wrapper that implements BaseRagasEmbedding interface
class EmbeddingWrapper:
def __init__(self, legacy_embedding):
self.legacy_embedding = legacy_embedding
def embed_text(self, text: str, **kwargs) -> t.List[float]:
return self.legacy_embedding.embed_query(text)
async def aembed_text(self, text: str, **kwargs) -> t.List[float]:
return await self.legacy_embedding.aembed_query(text)
actual_embedding_model = EmbeddingWrapper(embedding_model)
else:
# Already BaseRagasEmbedding
actual_embedding_model = embedding_model
from ragas.prompt.dynamic_few_shot import DynamicFewShotPrompt
self.prompt = DynamicFewShotPrompt.from_prompt(
self.prompt,
actual_embedding_model, # type: ignore[arg-type]
max_similar_examples,
similarity_threshold,
)
train_dataset.reload()
total_items = len(train_dataset)
input_vars = self.get_variables()
output_vars = [self.name, f"{self.name}_reason"]
from rich.progress import Progress
with Progress() as progress:
task = progress.add_task("Processing examples", total=total_items)
for row in train_dataset:
inputs = {
var: train_dataset.get_row_value(row, var) for var in input_vars
}
inputs = {k: v for k, v in inputs.items() if v is not None}
output = {
var: train_dataset.get_row_value(row, var) for var in output_vars
}
output = {k: v for k, v in output.items() if v is not None}
if output:
self.prompt.add_example(inputs, output)
progress.update(task, advance=1)
validate_alignment
validate_alignment(llm: 'BaseRagasLLM', test_dataset: 'Dataset', mapping: Dict[str, str] = {})
参数: llm: 用于打分的 LLM 实例。 test_dataset: 包含黄金标准分数的 Dataset 实例。 mapping: A dictionary mapping variable names expected by metrics to their corresponding names in the gold experiment.
通过将分数与黄金标准实验比较,校验指标对齐情况。该方法计算黄金标准分数与指标预测分数之间的 Cohen's Kappa 分数和一致率。
源代码位于 src/ragas/metrics/base.py
def validate_alignment(
self,
llm: "BaseRagasLLM",
test_dataset: "Dataset",
mapping: t.Dict[str, str] = {},
):
"""
Args:
llm: The LLM instance to use for scoring.
test_dataset: An Dataset instance containing the gold standard scores.
mapping: A dictionary mapping variable names expected by metrics to their corresponding names in the gold experiment.
Validate the alignment of the metric by comparing the scores against a gold standard experiment.
This method computes the Cohen's Kappa score and agreement rate between the gold standard scores and
the predicted scores from the metric.
"""
test_dataset.reload()
gold_scores_raw = [
test_dataset.get_row_value(row, self.name) for row in test_dataset
]
pred_scores = []
for row in test_dataset:
values = {
v: (
test_dataset.get_row_value(row, v)
if v not in mapping
else test_dataset.get_row_value(row, mapping.get(v, v))
)
for v in self.get_variables()
}
score = self.score(llm=llm, **values)
pred_scores.append(score.value)
# Convert to strings for correlation calculation, filtering out None values
gold_scores = [str(score) for score in gold_scores_raw if score is not None]
pred_scores_str = [str(score) for score in pred_scores if score is not None]
df = test_dataset.to_pandas()
df[f"{self.name}_pred"] = pred_scores
correlation = self.get_correlation(gold_scores, pred_scores_str)
agreement_rate = sum(
x == y for x, y in zip(gold_scores, pred_scores_str)
) / len(gold_scores)
return {
"correlation": correlation,
"agreement_rate": agreement_rate,
"df": df,
}
create_auto_response_model
create_auto_response_model(name: str, **fields) -> Type['BaseModel']
创建响应模型并标记为 Ragas 自动生成。
该函数使用 create_model 创建 Pydantic 模型,并标记特殊属性以表明它是自动生成的。这样 save() 就能区分自动生成的模型(加载时会重建)和用户自定义模型。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
name |
str |
模型类名称 | required |
**fields |
create_model 格式的字段定义。每个字段指定为:field_name=(type, default_or_field_info) | {} |
返回:
| 类型 | 说明 |
|---|---|
Type[BaseModel] |
标记为自动生成的 Pydantic 模型类 |
示例:
>>> from pydantic import Field
>>> # Simple model with required fields
>>> ResponseModel = create_auto_response_model(
... "ResponseModel",
... value=(str, ...),
... reason=(str, ...)
... )
>>>
>>> # Model with Field validators and descriptions
>>> ResponseModel = create_auto_response_model(
... "ResponseModel",
... value=(str, Field(..., description="The predicted value")),
... reason=(str, Field(..., description="Reasoning for the prediction"))
... )
源代码位于 src/ragas/metrics/base.py
def create_auto_response_model(name: str, **fields) -> t.Type["BaseModel"]:
"""
Create a response model and mark it as auto-generated by Ragas.
This function creates a Pydantic model using create_model and marks it
with a special attribute to indicate it was auto-generated. This allows
the save() method to distinguish between auto-generated models (which
are recreated on load) and custom user models.
Parameters
----------
name : str
Name for the model class
**fields
Field definitions in create_model format.
Each field is specified as: field_name=(type, default_or_field_info)
Returns
-------
Type[BaseModel]
Pydantic model class marked as auto-generated
Examples
--------
>>> from pydantic import Field
>>> # Simple model with required fields
>>> ResponseModel = create_auto_response_model(
... "ResponseModel",
... value=(str, ...),
... reason=(str, ...)
... )
>>>
>>> # Model with Field validators and descriptions
>>> ResponseModel = create_auto_response_model(
... "ResponseModel",
... value=(str, Field(..., description="The predicted value")),
... reason=(str, Field(..., description="Reasoning for the prediction"))
... )
"""
from pydantic import create_model
model = create_model(name, **fields)
setattr(model, "__ragas_auto_generated__", True) # type: ignore[attr-defined]
return model
Metric
Metric(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '')
基类: ABC
Ragas 中指标的抽象基类。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
name |
str |
指标名称。 |
required_columns |
Dict[str, Set[str]] |
将指标类型名映射到所需列名集合的字典。这是一个属性;若列不在 VALID_COLUMNS 中会抛出 ValueError。 |
init
init(run_config: RunConfig) -> None
用给定运行配置初始化指标。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
run_config |
RunConfig |
指标运行配置,包括超时及其他设置。 | required |
源代码位于 src/ragas/metrics/base.py
@abstractmethod
def init(self, run_config: RunConfig) -> None:
"""
Initialize the metric with the given run configuration.
Parameters
----------
run_config : RunConfig
Configuration for the metric run including timeouts and other settings.
"""
...
MetricType
基类: Enum
Ragas 中指标类型的枚举。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
SINGLE_TURN |
str |
表示单轮指标类型。 |
MULTI_TURN |
str |
表示多轮指标类型。 |
MetricWithLLM
MetricWithLLM(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '', llm: Optional[BaseRagasLLM] = None, output_type: Optional[MetricOutputType] = None)
基类: Metric, PromptMixin
使用语言模型进行评测的指标类。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
llm |
Optional[BaseRagasLLM] |
用于该指标的语言模型。运行时通过 duck typing 同时接受 BaseRagasLLM 和 InstructorBaseRagasLLM(二者方法兼容)。 |
init
init(run_config: RunConfig) -> None
用运行配置初始化指标,并校验 LLM 是否存在。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
run_config |
RunConfig |
指标运行配置。 | required |
抛出:
| 类型 | 说明 |
|---|---|
ValueError |
若未向指标提供 LLM。 |
源代码位于 src/ragas/metrics/base.py
def init(self, run_config: RunConfig) -> None:
"""
Initialize the metric with run configuration and validate LLM is present.
Parameters
----------
run_config : RunConfig
Configuration for the metric run.
Raises
------
ValueError
If no LLM is provided to the metric.
"""
if self.llm is None:
raise ValueError(
f"Metric '{self.name}' has no valid LLM provided (self.llm is None). Please instantiate the metric with an LLM to run."
)
# Only BaseRagasLLM has set_run_config method, not InstructorBaseRagasLLM
if isinstance(self.llm, BaseRagasLLM):
self.llm.set_run_config(run_config)
train
train(path: str, demonstration_config: Optional[DemonstrationConfig] = None, instruction_config: Optional[InstructionConfig] = None, callbacks: Optional[Callbacks] = None, run_config: Optional[RunConfig] = None, batch_size: Optional[int] = None, with_debugging_logs=False, raise_exceptions: bool = True) -> None
使用本地 JSON 数据训练指标
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
path |
str |
本地 JSON 训练数据文件路径 | required |
demonstration_config |
DemonstrationConfig |
示例优化的配置 | None |
instruction_config |
InstructionConfig |
指令优化的配置 | None |
callbacks |
Callbacks |
回调函数列表 | None |
run_config |
RunConfig |
运行配置 | None |
batch_size |
int |
训练批次大小 | None |
with_debugging_logs |
bool |
启用调试日志 | False |
raise_exceptions |
bool |
训练期间是否抛出异常 | True |
抛出:
| 类型 | 说明 |
|---|---|
ValueError |
若未提供 path 或不是 JSON 文件 |
源代码位于 src/ragas/metrics/base.py
def train(
self,
path: str,
demonstration_config: t.Optional[DemonstrationConfig] = None,
instruction_config: t.Optional[InstructionConfig] = None,
callbacks: t.Optional[Callbacks] = None,
run_config: t.Optional[RunConfig] = None,
batch_size: t.Optional[int] = None,
with_debugging_logs=False,
raise_exceptions: bool = True,
) -> None:
"""
Train the metric using local JSON data
Parameters
----------
path : str
Path to local JSON training data file
demonstration_config : DemonstrationConfig, optional
Configuration for demonstration optimization
instruction_config : InstructionConfig, optional
Configuration for instruction optimization
callbacks : Callbacks, optional
List of callback functions
run_config : RunConfig, optional
Run configuration
batch_size : int, optional
Batch size for training
with_debugging_logs : bool, default=False
Enable debugging logs
raise_exceptions : bool, default=True
Whether to raise exceptions during training
Raises
------
ValueError
If path is not provided or not a JSON file
"""
# Validate input parameters
if not path:
raise ValueError("Path to training data file must be provided")
if not path.endswith(".json"):
raise ValueError("Train data must be in json format")
run_config = run_config or RunConfig()
callbacks = callbacks or []
# Load the dataset from JSON file
dataset = MetricAnnotation.from_json(path, metric_name=self.name)
# only optimize the instruction if instruction_config is provided
if instruction_config is not None:
self._optimize_instruction(
instruction_config=instruction_config,
dataset=dataset,
callbacks=callbacks,
run_config=run_config,
batch_size=batch_size,
with_debugging_logs=with_debugging_logs,
raise_exceptions=raise_exceptions,
)
# if demonstration_config is provided, optimize the demonstrations
if demonstration_config is not None:
self._optimize_demonstration(
demonstration_config=demonstration_config,
dataset=dataset,
)
MultiTurnMetric
MultiTurnMetric(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '')
基类: Metric
用于评测多轮对话的指标类。
该类扩展基础 Metric 类,提供为多轮对话样本打分的功能。
multi_turn_score
multi_turn_score(sample: MultiTurnSample, callbacks: Callbacks = None) -> float
同步为多轮对话样本打分。
若在类 Jupyter 环境中未安装 nest_asyncio,可能抛出 ImportError。
源代码位于 src/ragas/metrics/base.py
def multi_turn_score(
self,
sample: MultiTurnSample,
callbacks: Callbacks = None,
) -> float:
"""
Score a multi-turn conversation sample synchronously.
May raise ImportError if nest_asyncio is not installed in Jupyter-like environments.
"""
callbacks = callbacks or []
sample = self._only_required_columns_multi_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
async def _async_wrapper():
try:
result = await self._multi_turn_ascore(
sample=sample, callbacks=group_cm
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": result})
return result
apply_nest_asyncio()
score = run(_async_wrapper)
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
multi_turn_ascore
multi_turn_ascore(sample: MultiTurnSample, callbacks: Callbacks = None, timeout: Optional[float] = None) -> float
异步为多轮对话样本打分。
若打分过程超过指定超时,可能抛出 asyncio.TimeoutError。
源代码位于 src/ragas/metrics/base.py
async def multi_turn_ascore(
self,
sample: MultiTurnSample,
callbacks: Callbacks = None,
timeout: t.Optional[float] = None,
) -> float:
"""
Score a multi-turn conversation sample asynchronously.
May raise asyncio.TimeoutError if the scoring process exceeds the specified timeout.
"""
callbacks = callbacks or []
sample = self._only_required_columns_multi_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
try:
score = await asyncio.wait_for(
self._multi_turn_ascore(sample=sample, callbacks=group_cm),
timeout=timeout,
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": score})
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
BaseMetric
BaseMetric(name: str, allowed_values: AllowedValuesType = (lambda: ['pass', 'fail'])())
基类: ABC
返回 MetricResult 对象的简单指标基类。
该类为评测输入并返回包含分数和推理的结构化 MetricResult 对象的指标提供基础。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
name |
str |
指标名称。 |
allowed_values |
AllowedValuesType |
指标输出的允许值。离散指标可为字符串列表,数值指标可为浮点元组,排序指标可为整数。 |
示例:
>>> from ragas.metrics import discrete_metric
>>>
>>> @discrete_metric(name="sentiment", allowed_values=["positive", "negative"])
>>> def sentiment_metric(user_input: str, response: str) -> str:
... return "positive" if "good" in response else "negative"
>>>
>>> result = sentiment_metric(user_input="How are you?", response="I'm good!")
>>> print(result.value) # "positive"
score
score(**kwargs) -> 'MetricResult'
同步计算指标分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
**kwargs |
dict |
特定指标实现所需的输入参数。 | {} |
返回:
| 类型 | 说明 |
|---|---|
MetricResult |
包含分数和推理的评测结果。 |
源代码位于 src/ragas/metrics/base.py
@abstractmethod
def score(self, **kwargs) -> "MetricResult":
"""
Synchronously calculate the metric score.
Parameters
----------
**kwargs : dict
Input parameters required by the specific metric implementation.
Returns
-------
MetricResult
The evaluation result containing the score and reasoning.
"""
pass
ascore
ascore(**kwargs) -> 'MetricResult'
异步计算指标分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
**kwargs |
dict |
特定指标实现所需的输入参数。 | {} |
返回:
| 类型 | 说明 |
|---|---|
MetricResult |
包含分数和推理的评测结果。 |
源代码位于 src/ragas/metrics/base.py
@abstractmethod
async def ascore(self, **kwargs) -> "MetricResult":
"""
Asynchronously calculate the metric score.
Parameters
----------
**kwargs : dict
Input parameters required by the specific metric implementation.
Returns
-------
MetricResult
The evaluation result containing the score and reasoning.
"""
pass
batch_score
batch_score(inputs: List[Dict[str, Any]]) -> List['MetricResult']
同步计算一批输入的分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
inputs |
List[Dict[str, Any]] |
输入字典列表,每个包含该指标的参数。 | required |
返回:
| 类型 | 说明 |
|---|---|
List[MetricResult] |
评测结果列表,每个输入一个。 |
源代码位于 src/ragas/metrics/base.py
def batch_score(
self,
inputs: t.List[t.Dict[str, t.Any]],
) -> t.List["MetricResult"]:
"""
Synchronously calculate scores for a batch of inputs.
Parameters
----------
inputs : List[Dict[str, Any]]
List of input dictionaries, each containing parameters for the metric.
Returns
-------
List[MetricResult]
List of evaluation results, one for each input.
"""
return [self.score(**input_dict) for input_dict in inputs]
abatch_score
abatch_score(inputs: List[Dict[str, Any]]) -> List['MetricResult']
并行异步计算一批输入的分数。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
inputs |
List[Dict[str, Any]] |
输入字典列表,每个包含该指标的参数。 | required |
返回:
| 类型 | 说明 |
|---|---|
List[MetricResult] |
评测结果列表,每个输入一个。 |
源代码位于 src/ragas/metrics/base.py
async def abatch_score(
self,
inputs: t.List[t.Dict[str, t.Any]],
) -> t.List["MetricResult"]:
"""
Asynchronously calculate scores for a batch of inputs in parallel.
Parameters
----------
inputs : List[Dict[str, Any]]
List of input dictionaries, each containing parameters for the metric.
Returns
-------
List[MetricResult]
List of evaluation results, one for each input.
"""
async_tasks = []
for input_dict in inputs:
# Process input asynchronously
async_tasks.append(self.ascore(**input_dict))
# Run all tasks concurrently and return results
return await asyncio.gather(*async_tasks)
LLMMetric
LLMMetric(name: str, allowed_values: AllowedValuesType = (lambda: ['pass', 'fail'])(), prompt: Optional[Union[str, 'Prompt']] = None)
基类: SimpleBaseMetric
使用 prompt 生成结构化响应的基于 LLM 的指标。
save
save(path: Optional[str] = None) -> None
将指标配置保存到 JSON 文件。
参数:
path : str, 可选 要保存到的文件路径。若未提供,保存为 "./{metric.name}.json"。使用 .gz 扩展名可压缩。
Note:
若指标有 response_model,其 schema 会保存以供参考,但模型本身无法序列化。加载时你需要提供它。
示例:
以下均可:
metric.save() # → ./response_quality.json metric.save("custom.json") # → ./custom.json metric.save("/path/to/metrics/") # → /path/to/metrics/response_quality.json metric.save("no_extension") # → ./no_extension.json metric.save("compressed.json.gz") # → ./compressed.json.gz (compressed)
源代码位于 src/ragas/metrics/base.py
def save(self, path: t.Optional[str] = None) -> None:
"""
Save the metric configuration to a JSON file.
Parameters:
-----------
path : str, optional
File path to save to. If not provided, saves to "./{metric.name}.json"
Use .gz extension for compression.
Note:
-----
If the metric has a response_model, its schema will be saved for reference
but the model itself cannot be serialized. You'll need to provide it when loading.
Examples:
---------
All these work:
>>> metric.save() # → ./response_quality.json
>>> metric.save("custom.json") # → ./custom.json
>>> metric.save("/path/to/metrics/") # → /path/to/metrics/response_quality.json
>>> metric.save("no_extension") # → ./no_extension.json
>>> metric.save("compressed.json.gz") # → ./compressed.json.gz (compressed)
"""
import gzip
import json
import warnings
from pathlib import Path
# Handle default path
if path is None:
# Default to current directory with metric name as filename
file_path = Path(f"./{self.name}.json")
else:
file_path = Path(path)
# If path is a directory, append the metric name as filename
if file_path.is_dir():
file_path = file_path / f"{self.name}.json"
# If path has no extension, add .json
elif not file_path.suffix:
file_path = file_path.with_suffix(".json")
# Collect warning messages for data loss
warning_messages = []
if hasattr(self, "_response_model") and self._response_model:
# Only warn for custom response models, not auto-generated ones
if not getattr(self._response_model, "__ragas_auto_generated__", False):
warning_messages.append(
"- Custom response_model will be lost (set it manually after loading)"
)
# Serialize the prompt (may add embedding_model warning)
prompt_data = self._serialize_prompt(warning_messages)
# Determine the metric type
metric_type = self.__class__.__name__
# Get metric-specific config
config = self._get_metric_config()
# Emit consolidated warning if there's data loss
if warning_messages:
warnings.warn(
"Some metric components cannot be saved and will be lost:\n"
+ "\n".join(warning_messages)
+ "\n\nYou'll need to provide these when loading the metric."
)
data = {
"format_version": "1.0",
"metric_type": metric_type,
"name": self.name,
"prompt": prompt_data,
"config": config,
"response_model_info": self._serialize_response_model_info(),
}
try:
if file_path.suffix == ".gz":
with gzip.open(file_path, "wt", encoding="utf-8") as f:
json.dump(data, f, indent=2)
else:
with open(file_path, "w", encoding="utf-8") as f:
json.dump(data, f, indent=2)
except (OSError, IOError) as e:
raise ValueError(f"Cannot save metric to {file_path}: {e}")
load
load(path: str, response_model: Optional[Type['BaseModel']] = None, embedding_model: Optional['EmbeddingModelType'] = None) -> 'SimpleLLMMetric'
从 JSON 文件加载指标。
参数:
path : str 要加载的文件路径。支持 .gz 压缩文件。response_model : Optional[Type[BaseModel]] 用于响应校验的 Pydantic 模型。自定义 SimpleLLMMetrics 时必需。embedding_model : Optional[Any] DynamicFewShotPrompt 的嵌入模型。若原始指标使用了嵌入模型则必需。
返回:
SimpleLLMMetric 已加载的指标实例
抛出:
ValueError:若文件无法加载、无效,或缺少所需模型
源代码位于 src/ragas/metrics/base.py
@classmethod
def load(
cls,
path: str,
response_model: t.Optional[t.Type["BaseModel"]] = None,
embedding_model: t.Optional["EmbeddingModelType"] = None,
) -> "SimpleLLMMetric":
"""
Load a metric from a JSON file.
Parameters:
-----------
path : str
File path to load from. Supports .gz compressed files.
response_model : Optional[Type[BaseModel]]
Pydantic model to use for response validation. Required for custom SimpleLLMMetrics.
embedding_model : Optional[Any]
Embedding model for DynamicFewShotPrompt. Required if the original used one.
Returns:
--------
SimpleLLMMetric
Loaded metric instance
Raises:
-------
ValueError
If file cannot be loaded, is invalid, or missing required models
"""
import gzip
import json
from pathlib import Path
file_path = Path(path)
# Load JSON data
try:
if file_path.suffix == ".gz":
with gzip.open(file_path, "rt", encoding="utf-8") as f:
data = json.load(f)
else:
with open(file_path, "r", encoding="utf-8") as f:
data = json.load(f)
except (FileNotFoundError, json.JSONDecodeError, OSError) as e:
raise ValueError(f"Cannot load metric from {path}: {e}")
# Validate format
if data.get("format_version") != "1.0":
import warnings
warnings.warn(
f"Loading metric with format version {data.get('format_version')}, expected 1.0"
)
# Reconstruct the prompt
prompt = cls._deserialize_prompt(data["prompt"], embedding_model)
# Get config
config = data.get("config", {})
# Create the metric instance
metric = cls(name=data["name"], prompt=prompt, **config)
# Set response model if provided
if response_model:
metric._response_model = response_model
return metric
get_correlation
get_correlation(gold_labels: List[str], predictions: List[str]) -> float
计算黄金分数与预测分数之间的相关性。这是占位方法,应根据具体指标实现。
源代码位于 src/ragas/metrics/base.py
@abstractmethod
def get_correlation(
self, gold_labels: t.List[str], predictions: t.List[str]
) -> float:
"""
Calculate the correlation between gold scores and predicted scores.
This is a placeholder method and should be implemented based on the specific metric.
"""
pass
align_and_validate
align_and_validate(dataset: 'Dataset', embedding_model: 'EmbeddingModelType', llm: 'BaseRagasLLM', test_size: float = 0.2, random_state: int = 42, **kwargs: Dict[str, Any])
参数: dataset: 用于对齐指标的实验。 embedding_model: 用于动态 few-shot prompting 的嵌入模型。 llm: 用于打分的 LLM 实例。
将指标与指定实验对齐,并对照黄金标准实验做校验。该方法把对齐和校验合并为一步。
源代码位于 src/ragas/metrics/base.py
def align_and_validate(
self,
dataset: "Dataset",
embedding_model: "EmbeddingModelType",
llm: "BaseRagasLLM",
test_size: float = 0.2,
random_state: int = 42,
**kwargs: t.Dict[str, t.Any],
):
"""
Args:
dataset: experiment to align the metric with.
embedding_model: The embedding model used for dynamic few-shot prompting.
llm: The LLM instance to use for scoring.
Align the metric with the specified experiments and validate it against a gold standard experiment.
This method combines alignment and validation into a single step.
"""
train_dataset, test_dataset = dataset.train_test_split(
test_size=test_size, random_state=random_state
)
self.align(train_dataset, embedding_model, **kwargs) # type: ignore
return self.validate_alignment(llm, test_dataset) # type: ignore
align
align(train_dataset: 'Dataset', embedding_model: 'EmbeddingModelType', **kwargs: Dict[str, Any])
参数: train_dataset: 用于对齐指标的 train_dataset。 embedding_model: 用于动态 few-shot prompting 的嵌入模型。
通过不同优化方法将指标与指定实验对齐。
源代码位于 src/ragas/metrics/base.py
def align(
self,
train_dataset: "Dataset",
embedding_model: "EmbeddingModelType",
**kwargs: t.Dict[str, t.Any],
):
"""
Args:
train_dataset: train_dataset to align the metric with.
embedding_model: The embedding model used for dynamic few-shot prompting.
Align the metric with the specified experiments by different optimization methods.
"""
# get prompt
if not self.prompt:
raise Exception("prompt not passed")
from ragas.prompt.simple_prompt import Prompt
self.prompt = (
self.prompt if isinstance(self.prompt, Prompt) else Prompt(self.prompt)
)
# Extract specific parameters for from_prompt method
max_similar_examples_val = kwargs.get("max_similar_examples", 3)
similarity_threshold_val = kwargs.get("similarity_threshold", 0.7)
max_similar_examples = (
int(max_similar_examples_val)
if isinstance(max_similar_examples_val, (int, str))
else 3
)
similarity_threshold = (
float(similarity_threshold_val)
if isinstance(similarity_threshold_val, (int, float, str))
else 0.7
)
# Convert BaseRagasEmbeddings to BaseRagasEmbedding if needed
if hasattr(embedding_model, "embed_query"):
# For legacy BaseRagasEmbeddings, we need to wrap it
# Create a wrapper that implements BaseRagasEmbedding interface
class EmbeddingWrapper:
def __init__(self, legacy_embedding):
self.legacy_embedding = legacy_embedding
def embed_text(self, text: str, **kwargs) -> t.List[float]:
return self.legacy_embedding.embed_query(text)
async def aembed_text(self, text: str, **kwargs) -> t.List[float]:
return await self.legacy_embedding.aembed_query(text)
actual_embedding_model = EmbeddingWrapper(embedding_model)
else:
# Already BaseRagasEmbedding
actual_embedding_model = embedding_model
from ragas.prompt.dynamic_few_shot import DynamicFewShotPrompt
self.prompt = DynamicFewShotPrompt.from_prompt(
self.prompt,
actual_embedding_model, # type: ignore[arg-type]
max_similar_examples,
similarity_threshold,
)
train_dataset.reload()
total_items = len(train_dataset)
input_vars = self.get_variables()
output_vars = [self.name, f"{self.name}_reason"]
from rich.progress import Progress
with Progress() as progress:
task = progress.add_task("Processing examples", total=total_items)
for row in train_dataset:
inputs = {
var: train_dataset.get_row_value(row, var) for var in input_vars
}
inputs = {k: v for k, v in inputs.items() if v is not None}
output = {
var: train_dataset.get_row_value(row, var) for var in output_vars
}
output = {k: v for k, v in output.items() if v is not None}
if output:
self.prompt.add_example(inputs, output)
progress.update(task, advance=1)
validate_alignment
validate_alignment(llm: 'BaseRagasLLM', test_dataset: 'Dataset', mapping: Dict[str, str] = {})
参数: llm: 用于打分的 LLM 实例。 test_dataset: 包含黄金标准分数的 Dataset 实例。 mapping: A dictionary mapping variable names expected by metrics to their corresponding names in the gold experiment.
通过将分数与黄金标准实验比较,校验指标对齐情况。该方法计算黄金标准分数与指标预测分数之间的 Cohen's Kappa 分数和一致率。
源代码位于 src/ragas/metrics/base.py
def validate_alignment(
self,
llm: "BaseRagasLLM",
test_dataset: "Dataset",
mapping: t.Dict[str, str] = {},
):
"""
Args:
llm: The LLM instance to use for scoring.
test_dataset: An Dataset instance containing the gold standard scores.
mapping: A dictionary mapping variable names expected by metrics to their corresponding names in the gold experiment.
Validate the alignment of the metric by comparing the scores against a gold standard experiment.
This method computes the Cohen's Kappa score and agreement rate between the gold standard scores and
the predicted scores from the metric.
"""
test_dataset.reload()
gold_scores_raw = [
test_dataset.get_row_value(row, self.name) for row in test_dataset
]
pred_scores = []
for row in test_dataset:
values = {
v: (
test_dataset.get_row_value(row, v)
if v not in mapping
else test_dataset.get_row_value(row, mapping.get(v, v))
)
for v in self.get_variables()
}
score = self.score(llm=llm, **values)
pred_scores.append(score.value)
# Convert to strings for correlation calculation, filtering out None values
gold_scores = [str(score) for score in gold_scores_raw if score is not None]
pred_scores_str = [str(score) for score in pred_scores if score is not None]
df = test_dataset.to_pandas()
df[f"{self.name}_pred"] = pred_scores
correlation = self.get_correlation(gold_scores, pred_scores_str)
agreement_rate = sum(
x == y for x, y in zip(gold_scores, pred_scores_str)
) / len(gold_scores)
return {
"correlation": correlation,
"agreement_rate": agreement_rate,
"df": df,
}
SingleTurnMetric
SingleTurnMetric(_required_columns: Dict[MetricType, Set[str]] = dict(), name: str = '')
基类: Metric
用于评测单轮交互的指标类。
该类提供同步和异步为单轮样本打分的方法。
single_turn_score
single_turn_score(sample: SingleTurnSample, callbacks: Callbacks = None) -> float
同步为单轮样本打分。
若在类 Jupyter 环境中未安装 nest_asyncio,可能抛出 ImportError。
源代码位于 src/ragas/metrics/base.py
def single_turn_score(
self,
sample: SingleTurnSample,
callbacks: Callbacks = None,
) -> float:
"""
Synchronously score a single-turn sample.
May raise ImportError if nest_asyncio is not installed in a Jupyter-like environment.
"""
callbacks = callbacks or []
# only get the required columns
sample = self._only_required_columns_single_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
async def _async_wrapper():
try:
result = await self._single_turn_ascore(
sample=sample, callbacks=group_cm
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": result})
return result
apply_nest_asyncio()
score = run(_async_wrapper)
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
single_turn_ascore
single_turn_ascore(sample: SingleTurnSample, callbacks: Callbacks = None, timeout: Optional[float] = None) -> float
异步为单轮样本打分,可设超时。
若打分过程超过指定超时,可能抛出 asyncio.TimeoutError。
源代码位于 src/ragas/metrics/base.py
async def single_turn_ascore(
self,
sample: SingleTurnSample,
callbacks: Callbacks = None,
timeout: t.Optional[float] = None,
) -> float:
"""
Asynchronously score a single-turn sample with an optional timeout.
May raise asyncio.TimeoutError if the scoring process exceeds the specified timeout.
"""
callbacks = callbacks or []
# only get the required columns
sample = self._only_required_columns_single_turn(sample)
rm, group_cm = new_group(
self.name,
inputs=sample.to_dict(),
callbacks=callbacks,
metadata={"type": ChainType.METRIC},
)
try:
score = await asyncio.wait_for(
self._single_turn_ascore(sample=sample, callbacks=group_cm),
timeout=timeout,
)
except Exception as e:
if not group_cm.ended:
rm.on_chain_error(e)
raise e
else:
if not group_cm.ended:
rm.on_chain_end({"output": score})
# track the evaluation event
_analytics_batcher.add_evaluation(
EvaluationEvent(
metrics=[self.name],
num_rows=1,
evaluation_type=MetricType.SINGLE_TURN.name,
language=get_metric_language(self),
)
)
return score
DiscreteMetric
DiscreteMetric(name: str, allowed_values: List[str] = (lambda: ['pass', 'fail'])(), prompt: Optional[Union[str, 'Prompt']] = None)
基类: SimpleLLMMetric, DiscreteValidator
带预定义允许值的类别/离散评测指标。
该类用于输出类别值的指标,例如 "pass/fail"、"good/bad/excellent" 或自定义离散类别。使用 instructor 库获得结构化 LLM 输出。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
allowed_values |
List[str] |
指标可输出的允许类别值列表。默认为 ["pass", "fail"]。 |
prompt |
Optional[Union[str, Prompt]] |
指标的 prompt 模板。应包含将在运行时格式化的评测输入占位符。 |
示例:
>>> from ragas.metrics import DiscreteMetric
>>> from ragas.llms import llm_factory
>>> from openai import OpenAI
>>>
>>> # Create an LLM instance
>>> client = OpenAI(api_key="your-api-key")
>>> llm = llm_factory("gpt-4o-mini", client=client)
>>>
>>> # Create a custom discrete metric
>>> metric = DiscreteMetric(
... name="quality_check",
... prompt="Check the quality of the response: {response}. Return 'excellent', 'good', or 'poor'.",
... allowed_values=["excellent", "good", "poor"]
... )
>>>
>>> # Score with the metric
>>> result = metric.score(
... llm=llm,
... response="This is a great response!"
... )
>>> print(result.value) # Output: "excellent" or similar
get_correlation
get_correlation(gold_labels: List[str], predictions: List[str]) -> float
计算黄金标签与预测之间的相关性。这是占位方法,应根据具体指标实现。
源代码位于 src/ragas/metrics/discrete.py
def get_correlation(
self, gold_labels: t.List[str], predictions: t.List[str]
) -> float:
"""
Calculate the correlation between gold labels and predictions.
This is a placeholder method and should be implemented based on the specific metric.
"""
try:
from sklearn.metrics import cohen_kappa_score
except ImportError:
raise ImportError(
"scikit-learn is required for correlation calculation. "
"Please install it with `pip install scikit-learn`."
)
return cohen_kappa_score(gold_labels, predictions)
load
load(path: str, embedding_model: Optional[EmbeddingModelType] = None) -> DiscreteMetric
从 JSON 文件加载 DiscreteMetric。
参数:
path : str 要加载的文件路径。支持 .gz 压缩文件。embedding_model : Optional[Any] DynamicFewShotPrompt 的嵌入模型。若原始指标使用了嵌入模型则必需。
返回:
DiscreteMetric 已加载的指标实例
抛出:
ValueError:若文件无法加载或不是 DiscreteMetric
源代码位于 src/ragas/metrics/discrete.py
@classmethod
def load(
cls, path: str, embedding_model: t.Optional["EmbeddingModelType"] = None
) -> "DiscreteMetric":
"""
Load a DiscreteMetric from a JSON file.
Parameters:
-----------
path : str
File path to load from. Supports .gz compressed files.
embedding_model : Optional[Any]
Embedding model for DynamicFewShotPrompt. Required if the original used one.
Returns:
--------
DiscreteMetric
Loaded metric instance
Raises:
-------
ValueError
If file cannot be loaded or is not a DiscreteMetric
"""
# Validate metric type before loading
cls._validate_metric_type(path)
# Load using parent class method
metric = super().load(path, embedding_model=embedding_model)
# Additional type check for safety
if not isinstance(metric, cls):
raise ValueError(f"Loaded metric is not a {cls.__name__}")
return metric
NumericMetric
NumericMetric(name: str, allowed_values: Union[Tuple[float, float], range] = (0.0, 1.0), prompt: Optional[Union[str, 'Prompt']] = None)
基类: SimpleLLMMetric, NumericValidator
指定范围内的连续数值评测指标。
该类用于在定义范围内输出数值分数的指标,例如相似度分数 0.0 到 1.0,或 1-10 评分。使用 instructor 库获得结构化 LLM 输出。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
allowed_values |
Union[Tuple[float, float], range] |
指标输出的有效范围。可以是 (min, max) 浮点元组或 range 对象。默认为 (0.0, 1.0)。 |
llm |
Optional[BaseRagasLLM] |
用于评测的语言模型实例。可用 llm_factory() 创建。 |
prompt |
Optional[Union[str, Prompt]] |
指标的 prompt 模板。应包含将在运行时格式化的评测输入占位符。 |
示例:
>>> from ragas.metrics import NumericMetric
>>> from ragas.llms import llm_factory
>>> from openai import OpenAI
>>>
>>> # Create an LLM instance
>>> client = OpenAI(api_key="your-api-key")
>>> llm = llm_factory("gpt-4o-mini", client=client)
>>>
>>> # Create a custom numeric metric with 0-10 range
>>> metric = NumericMetric(
... name="quality_score",
... llm=llm,
... prompt="Rate the quality of this response on a scale of 0-10: {response}",
... allowed_values=(0.0, 10.0)
... )
>>>
>>> # Score with the metric
>>> result = metric.score(
... llm=llm,
... response="This is a great response!"
... )
>>> print(result.value) # Output: a float between 0.0 and 10.0
get_correlation
get_correlation(gold_labels: List[str], predictions: List[str]) -> float
计算黄金标签与预测之间的相关性。这是占位方法,应根据具体指标实现。
源代码位于 src/ragas/metrics/numeric.py
def get_correlation(
self, gold_labels: t.List[str], predictions: t.List[str]
) -> float:
"""
Calculate the correlation between gold labels and predictions.
This is a placeholder method and should be implemented based on the specific metric.
"""
try:
from scipy.stats import pearsonr
except ImportError:
raise ImportError(
"scipy is required for correlation calculation. "
"Please install it with `pip install scipy`."
)
# Convert strings to floats for correlation calculation
gold_floats = [float(x) for x in gold_labels]
pred_floats = [float(x) for x in predictions]
result = pearsonr(gold_floats, pred_floats)
# pearsonr returns (correlation, p-value) tuple
correlation = t.cast(float, result[0])
return correlation
load
load(path: str, embedding_model: Optional[EmbeddingModelType] = None) -> NumericMetric
从 JSON 文件加载 NumericMetric。
参数:
path : str 要加载的文件路径。支持 .gz 压缩文件。embedding_model : Optional[Any] DynamicFewShotPrompt 的嵌入模型。若原始指标使用了嵌入模型则必需。
返回:
NumericMetric 已加载的指标实例
抛出:
ValueError:若文件无法加载或不是 NumericMetric
源代码位于 src/ragas/metrics/numeric.py
@classmethod
def load(
cls, path: str, embedding_model: t.Optional["EmbeddingModelType"] = None
) -> "NumericMetric":
"""
Load a NumericMetric from a JSON file.
Parameters:
-----------
path : str
File path to load from. Supports .gz compressed files.
embedding_model : Optional[Any]
Embedding model for DynamicFewShotPrompt. Required if the original used one.
Returns:
--------
NumericMetric
Loaded metric instance
Raises:
-------
ValueError
If file cannot be loaded or is not a NumericMetric
"""
# Validate metric type before loading
cls._validate_metric_type(path)
# Load using parent class method
metric = super().load(path, embedding_model=embedding_model)
# Additional type check for safety
if not isinstance(metric, cls):
raise ValueError(f"Loaded metric is not a {cls.__name__}")
# Convert allowed_values back to tuple if it's a list (due to JSON serialization)
if hasattr(metric, "allowed_values") and isinstance(
metric.allowed_values, list
):
# Ensure it's a 2-element tuple for NumericMetric
if len(metric.allowed_values) == 2:
metric.allowed_values = (
metric.allowed_values[0],
metric.allowed_values[1],
)
else:
metric.allowed_values = tuple(metric.allowed_values) # type: ignore
return metric
RankingMetric
RankingMetric(name: str, allowed_values: int = 2, prompt: Optional[Union[str, 'Prompt']] = None)
基类: SimpleLLMMetric, RankingValidator
产出条目排序列表的评测指标。
该类用于输出有序列表的指标,例如对搜索结果排序、给功能排优先级,或按相关性排列响应。使用 instructor 库获得结构化 LLM 输出。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
allowed_values |
int |
排序列表中期望的条目数。默认为 2。 |
llm |
Optional[BaseRagasLLM] |
用于评测的语言模型实例。可用 llm_factory() 创建。 |
prompt |
Optional[Union[str, Prompt]] |
指标的 prompt 模板。应包含将在运行时格式化的评测输入占位符。 |
示例:
>>> from ragas.metrics import RankingMetric
>>> from ragas.llms import llm_factory
>>> from openai import OpenAI
>>>
>>> # Create an LLM instance
>>> client = OpenAI(api_key="your-api-key")
>>> llm = llm_factory("gpt-4o-mini", client=client)
>>>
>>> # Create a ranking metric that returns top 3 items
>>> metric = RankingMetric(
... name="relevance_ranking",
... llm=llm,
... prompt="Rank these results by relevance: {results}",
... allowed_values=3
... )
>>>
>>> # Score with the metric
>>> result = metric.score(
... llm=llm,
... results="result1, result2, result3"
... )
>>> print(result.value) # Output: a list of 3 ranked items
get_correlation
get_correlation(gold_labels: List[str], predictions: List[str]) -> float
计算黄金标签与预测之间的相关性。这是占位方法,应根据具体指标实现。
源代码位于 src/ragas/metrics/ranking.py
def get_correlation(
self, gold_labels: t.List[str], predictions: t.List[str]
) -> float:
"""
Calculate the correlation between gold labels and predictions.
This is a placeholder method and should be implemented based on the specific metric.
"""
try:
from sklearn.metrics import cohen_kappa_score
except ImportError:
raise ImportError(
"scikit-learn is required for correlation calculation. "
"Please install it with `pip install scikit-learn`."
)
kappa_scores = []
for gold_item, prediction in zip(gold_labels, predictions):
kappa = cohen_kappa_score(gold_item, prediction, weights="quadratic")
kappa_scores.append(kappa)
return sum(kappa_scores) / len(kappa_scores) if kappa_scores else 0.0
load
load(path: str, embedding_model: Optional[EmbeddingModelType] = None) -> RankingMetric
从 JSON 文件加载 RankingMetric。
参数:
path : str 要加载的文件路径。支持 .gz 压缩文件。embedding_model : Optional[Any] DynamicFewShotPrompt 的嵌入模型。若原始指标使用了嵌入模型则必需。
返回:
RankingMetric 已加载的指标实例
抛出:
ValueError:若文件无法加载或不是 RankingMetric
源代码位于 src/ragas/metrics/ranking.py
@classmethod
def load(
cls, path: str, embedding_model: t.Optional["EmbeddingModelType"] = None
) -> "RankingMetric":
"""
Load a RankingMetric from a JSON file.
Parameters:
-----------
path : str
File path to load from. Supports .gz compressed files.
embedding_model : Optional[Any]
Embedding model for DynamicFewShotPrompt. Required if the original used one.
Returns:
--------
RankingMetric
Loaded metric instance
Raises:
-------
ValueError
If file cannot be loaded or is not a RankingMetric
"""
# Validate metric type before loading
cls._validate_metric_type(path)
# Load using parent class method
metric = super().load(path, embedding_model=embedding_model)
# Additional type check for safety
if not isinstance(metric, cls):
raise ValueError(f"Loaded metric is not a {cls.__name__}")
return metric
MetricResult
MetricResult(value: Any, reason: Optional[str] = None, traces: Optional[Dict[str, Any]] = None)
保存指标评测结果的类。
该类表现得像其底层结果值,但仍可访问 reasoning 等额外元数据。
适用于:
- DiscreteMetrics(字符串结果)
- NumericMetrics(float/int 结果)
- RankingMetrics(列表结果)
源代码位于 src/ragas/metrics/result.py
def __init__(
self,
value: t.Any,
reason: t.Optional[str] = None,
traces: t.Optional[t.Dict[str, t.Any]] = None,
):
if traces is not None:
invalid_keys = [
key for key in traces.keys() if key not in {"input", "output"}
]
if invalid_keys:
raise ValueError(
f"Invalid keys in traces: {invalid_keys}. Allowed keys are 'input' and 'output'."
)
self._value = value
self.reason = reason
self.traces = traces
value
value
获取原始结果值。
to_dict
to_dict()
将结果转换为字典。
源代码位于 src/ragas/metrics/result.py
def to_dict(self):
"""Convert the result to a dictionary."""
return {"result": self._value, "reason": self.reason}
validate
validate(value: Any, info: ValidationInfo)
提供与较旧 Pydantic 版本的兼容性。
源代码位于 src/ragas/metrics/result.py
@classmethod
def validate(cls, value: t.Any, info: ValidationInfo):
"""Provide compatibility with older Pydantic versions."""
if isinstance(value, MetricResult):
return value
return cls(value=value)
discrete_metric
discrete_metric(*, name: Optional[str] = None, allowed_values: Optional[List[str]] = None, **metric_params: Any) -> Callable[[Callable[..., Any]], DiscreteMetricProtocol]
用于创建离散/类别指标的装饰器。
该装饰器把普通函数变成 DiscreteMetric 实例,可用于带预定义类别输出的评测。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
name |
str |
指标名称。若未提供,则使用函数名。 | None |
allowed_values |
List[str] |
指标输出允许的类别值列表。默认为 ["pass", "fail"]。 | None |
**metric_params |
Any |
传递给指标初始化的额外参数。 | {} |
返回:
| 类型 | 说明 |
|---|---|
Callable[[Callable[..., Any]], DiscreteMetricProtocol] |
把函数变成 DiscreteMetric 实例的装饰器。 |
示例:
>>> from ragas.metrics import discrete_metric
>>>
>>> @discrete_metric(name="sentiment", allowed_values=["positive", "neutral", "negative"])
>>> def sentiment_analysis(user_input: str, response: str) -> str:
... '''Analyze sentiment of the response.'''
... if "great" in response.lower() or "good" in response.lower():
... return "positive"
... elif "bad" in response.lower() or "poor" in response.lower():
... return "negative"
... return "neutral"
>>>
>>> result = sentiment_analysis(
... user_input="How was your day?",
... response="It was great!"
... )
>>> print(result.value) # "positive"
源代码位于 src/ragas/metrics/discrete.py
def discrete_metric(
*,
name: t.Optional[str] = None,
allowed_values: t.Optional[t.List[str]] = None,
**metric_params: t.Any,
) -> t.Callable[[t.Callable[..., t.Any]], DiscreteMetricProtocol]:
"""
Decorator for creating discrete/categorical metrics.
This decorator transforms a regular function into a DiscreteMetric instance
that can be used for evaluation with predefined categorical outputs.
Parameters
----------
name : str, optional
Name for the metric. If not provided, uses the function name.
allowed_values : List[str], optional
List of allowed categorical values for the metric output.
Default is ["pass", "fail"].
**metric_params : Any
Additional parameters to pass to the metric initialization.
Returns
-------
Callable[[Callable[..., Any]], DiscreteMetricProtocol]
A decorator that transforms a function into a DiscreteMetric instance.
Examples
--------
>>> from ragas.metrics import discrete_metric
>>>
>>> @discrete_metric(name="sentiment", allowed_values=["positive", "neutral", "negative"])
>>> def sentiment_analysis(user_input: str, response: str) -> str:
... '''Analyze sentiment of the response.'''
... if "great" in response.lower() or "good" in response.lower():
... return "positive"
... elif "bad" in response.lower() or "poor" in response.lower():
... return "negative"
... return "neutral"
>>>
>>> result = sentiment_analysis(
... user_input="How was your day?",
... response="It was great!"
... )
>>> print(result.value) # "positive"
"""
if allowed_values is None:
allowed_values = ["pass", "fail"]
decorator_factory = create_metric_decorator()
return decorator_factory(name=name, allowed_values=allowed_values, **metric_params) # type: ignore[return-value]
numeric_metric
numeric_metric(*, name: Optional[str] = None, allowed_values: Optional[Union[Tuple[float, float], range]] = None, **metric_params: Any) -> Callable[[Callable[..., Any]], NumericMetricProtocol]
用于创建数值/连续指标的装饰器。
该装饰器把普通函数变成 NumericMetric 实例,输出指定范围内的连续值。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
name |
str |
指标名称。若未提供,则使用函数名。 | None |
allowed_values |
Union[Tuple[float, float], range] |
指标输出的有效范围,为 (min, max) 元组或 range 对象。默认为 (0.0, 1.0)。 | None |
**metric_params |
Any |
传递给指标初始化的额外参数。 | {} |
返回:
| 类型 | 说明 |
|---|---|
Callable[[Callable[..., Any]], NumericMetricProtocol] |
把函数变成 NumericMetric 实例的装饰器。 |
示例:
>>> from ragas.metrics import numeric_metric
>>>
>>> @numeric_metric(name="relevance_score", allowed_values=(0.0, 1.0))
>>> def calculate_relevance(user_input: str, response: str) -> float:
... '''Calculate relevance score between 0 and 1.'''
... # Simple word overlap example
... user_words = set(user_input.lower().split())
... response_words = set(response.lower().split())
... if not user_words:
... return 0.0
... overlap = len(user_words & response_words)
... return overlap / len(user_words)
>>>
>>> result = calculate_relevance(
... user_input="What is Python?",
... response="Python is a programming language"
... )
>>> print(result.value) # Numeric score between 0.0 and 1.0
源代码位于 src/ragas/metrics/numeric.py
def numeric_metric(
*,
name: t.Optional[str] = None,
allowed_values: t.Optional[t.Union[t.Tuple[float, float], range]] = None,
**metric_params: t.Any,
) -> t.Callable[[t.Callable[..., t.Any]], NumericMetricProtocol]:
"""
Decorator for creating numeric/continuous metrics.
This decorator transforms a regular function into a NumericMetric instance
that outputs continuous values within a specified range.
Parameters
----------
name : str, optional
Name for the metric. If not provided, uses the function name.
allowed_values : Union[Tuple[float, float], range], optional
The valid range for metric outputs as (min, max) tuple or range object.
Default is (0.0, 1.0).
**metric_params : Any
Additional parameters to pass to the metric initialization.
Returns
-------
Callable[[Callable[..., Any]], NumericMetricProtocol]
A decorator that transforms a function into a NumericMetric instance.
Examples
--------
>>> from ragas.metrics import numeric_metric
>>>
>>> @numeric_metric(name="relevance_score", allowed_values=(0.0, 1.0))
>>> def calculate_relevance(user_input: str, response: str) -> float:
... '''Calculate relevance score between 0 and 1.'''
... # Simple word overlap example
... user_words = set(user_input.lower().split())
... response_words = set(response.lower().split())
... if not user_words:
... return 0.0
... overlap = len(user_words & response_words)
... return overlap / len(user_words)
>>>
>>> result = calculate_relevance(
... user_input="What is Python?",
... response="Python is a programming language"
... )
>>> print(result.value) # Numeric score between 0.0 and 1.0
"""
if allowed_values is None:
allowed_values = (0.0, 1.0)
decorator_factory = create_metric_decorator()
return decorator_factory(name=name, allowed_values=allowed_values, **metric_params) # type: ignore[return-value]
ranking_metric
ranking_metric(*, name: Optional[str] = None, allowed_values: Optional[int] = None, **metric_params: Any) -> Callable[[Callable[..., Any]], RankingMetricProtocol]
用于创建排序/次序指标的装饰器。
该装饰器把普通函数变成 RankingMetric 实例,输出条目的有序列表。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
name |
str |
指标名称。若未提供,则使用函数名。 | None |
allowed_values |
int |
排序列表中期望的条目数。默认为 2。 | None |
**metric_params |
Any |
传递给指标初始化的额外参数。 | {} |
返回:
| 类型 | 说明 |
|---|---|
Callable[[Callable[..., Any]], RankingMetricProtocol] |
把函数变成 RankingMetric 实例的装饰器。 |
示例:
>>> from ragas.metrics import ranking_metric
>>>
>>> @ranking_metric(name="priority_ranker", allowed_values=3)
>>> def rank_by_urgency(user_input: str, responses: list) -> list:
... '''Rank responses by urgency keywords.'''
... urgency_keywords = ["urgent", "asap", "critical"]
... scored = []
... for resp in responses:
... score = sum(kw in resp.lower() for kw in urgency_keywords)
... scored.append((score, resp))
... # Sort by score descending and return top items
... ranked = sorted(scored, key=lambda x: x[0], reverse=True)
... return [item[1] for item in ranked[:3]]
>>>
>>> result = rank_by_urgency(
... user_input="What should I do first?",
... responses=["This is urgent", "Take your time", "Critical issue!"]
... )
>>> print(result.value) # Ranked list of responses
源代码位于 src/ragas/metrics/ranking.py
def ranking_metric(
*,
name: t.Optional[str] = None,
allowed_values: t.Optional[int] = None,
**metric_params: t.Any,
) -> t.Callable[[t.Callable[..., t.Any]], RankingMetricProtocol]:
"""
Decorator for creating ranking/ordering metrics.
This decorator transforms a regular function into a RankingMetric instance
that outputs ordered lists of items.
Parameters
----------
name : str, optional
Name for the metric. If not provided, uses the function name.
allowed_values : int, optional
Expected number of items in the ranking list. Default is 2.
**metric_params : Any
Additional parameters to pass to the metric initialization.
Returns
-------
Callable[[Callable[..., Any]], RankingMetricProtocol]
A decorator that transforms a function into a RankingMetric instance.
Examples
--------
>>> from ragas.metrics import ranking_metric
>>>
>>> @ranking_metric(name="priority_ranker", allowed_values=3)
>>> def rank_by_urgency(user_input: str, responses: list) -> list:
... '''Rank responses by urgency keywords.'''
... urgency_keywords = ["urgent", "asap", "critical"]
... scored = []
... for resp in responses:
... score = sum(kw in resp.lower() for kw in urgency_keywords)
... scored.append((score, resp))
... # Sort by score descending and return top items
... ranked = sorted(scored, key=lambda x: x[0], reverse=True)
... return [item[1] for item in ranked[:3]]
>>>
>>> result = rank_by_urgency(
... user_input="What should I do first?",
... responses=["This is urgent", "Take your time", "Critical issue!"]
... )
>>> print(result.value) # Ranked list of responses
"""
if allowed_values is None:
allowed_values = 2
decorator_factory = create_metric_decorator()
return decorator_factory(name=name, allowed_values=allowed_values, **metric_params) # type: ignore[return-value]