TestsetGenerator
TestsetGenerator(llm: BaseRagasLLM, embedding_model: BaseRagasEmbeddings, knowledge_graph: KnowledgeGraph = KnowledgeGraph(), persona_list: Optional[List[Persona]] = None, llm_context: Optional[str] = None)
根据给定场景和参数生成评测数据集。
属性:
| 名称 | 类型 | 说明 |
|---|---|---|
llm |
BaseRagasLLM |
用于生成过程的语言模型。 |
knowledge_graph |
KnowledgeGraph, default empty |
用于生成过程的知识图谱。 |
llm_context |
Optional[str], default None |
生成回复时提供给 LLM 的额外上下文。该上下文将用于指导 LLM 如何生成查询和答案。 |
from_langchain
from_langchain(llm: BaseLanguageModel, embedding_model: Embeddings, knowledge_graph: Optional[KnowledgeGraph] = None, llm_context: Optional[str] = None) -> TestsetGenerator
从 Langchain LLM 创建 TestsetGenerator。
源代码位于 src/ragas/testset/synthesizers/generate.py
@classmethod
def from_langchain(
cls,
llm: LangchainLLM,
embedding_model: LangchainEmbeddings,
knowledge_graph: t.Optional[KnowledgeGraph] = None,
llm_context: t.Optional[str] = None,
) -> TestsetGenerator:
"""
Creates a `TestsetGenerator` from a Langchain LLMs.
"""
knowledge_graph = knowledge_graph or KnowledgeGraph()
return cls(
LangchainLLMWrapper(llm),
LangchainEmbeddingsWrapper(embedding_model),
knowledge_graph,
llm_context=llm_context,
)
from_llama_index
from_llama_index(llm: BaseLLM, embedding_model: BaseEmbedding, knowledge_graph: Optional[KnowledgeGraph] = None, llm_context: Optional[str] = None) -> TestsetGenerator
从 LlamaIndex LLM 和 embedding 模型创建 TestsetGenerator。
源代码位于 src/ragas/testset/synthesizers/generate.py
@classmethod
def from_llama_index(
cls,
llm: LlamaIndexLLM,
embedding_model: LlamaIndexEmbedding,
knowledge_graph: t.Optional[KnowledgeGraph] = None,
llm_context: t.Optional[str] = None,
) -> TestsetGenerator:
"""
Creates a `TestsetGenerator` from a LlamaIndex LLM and embedding model.
"""
knowledge_graph = knowledge_graph or KnowledgeGraph()
return cls(
LlamaIndexLLMWrapper(llm),
LlamaIndexEmbeddingsWrapper(embedding_model),
knowledge_graph,
llm_context=llm_context,
)
generate_with_langchain_docs
generate_with_langchain_docs(documents: Sequence[Document], testset_size: int, transforms: Optional[Transforms] = None, transforms_llm: Optional[BaseRagasLLM] = None, transforms_embedding_model: Optional[BaseRagasEmbeddings] = None, query_distribution: Optional[QueryDistribution] = None, run_config: Optional[RunConfig] = None, callbacks: Optional[Callbacks] = None, token_usage_parser: Optional[TokenUsageParser] = None, with_debugging_logs=False, raise_exceptions: bool = True, return_executor: bool = False) -> Union[Testset, Executor]
根据给定的 Langchain documents 和参数生成评测数据集。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
documents |
Sequence[Document] |
用作源材料的 Langchain documents 序列 | required |
testset_size |
int |
要生成的测试样本数量 | required |
transforms |
Optional[Transforms] |
应用到文档的自定义 transforms,默认 None | None |
transforms_llm |
Optional[BaseRagasLLM] |
若与实例 LLM 不同,用于 transforms 的 LLM,默认 None | None |
transforms_embedding_model |
Optional[BaseRagasEmbeddings] |
若与实例模型不同,用于 transforms 的 embedding 模型,默认 None | None |
query_distribution |
Optional[QueryDistribution] |
要生成的查询类型分布,默认 None | None |
run_config |
Optional[RunConfig] |
生成运行的配置,默认 None | None |
callbacks |
Optional[Callbacks] |
生成期间使用的 callbacks,默认 None | None |
token_usage_parser |
Optional[TokenUsageParser] |
解析 LLMResult 对象并返回 TokenUsage 对象。用于计算生成过程的成本。 | None |
with_debugging_logs |
bool |
是否包含调试日志,默认 False | False |
raise_exceptions |
bool |
生成期间是否抛出异常,默认 True | True |
return_executor |
bool |
若为 True,返回 Executor 实例而不运行生成。返回的 executor 可通过调用 executor.cancel() 取消执行。要获取结果,调用 executor.results()。默认值为 False。 | False |
返回:
| 类型 | 说明 |
|---|---|
Testset or Executor |
若 return_executor 为 False,返回生成的评测数据集。若 return_executor 为 True,返回可用于取消执行的 Executor 实例。 |
抛出:
| 类型 | 说明 |
|---|---|
ValueError |
若初始化时或作为参数都未提供 LLM 或 embedding 模型 |
源代码位于 src/ragas/testset/synthesizers/generate.py
def generate_with_langchain_docs(
self,
documents: t.Sequence[LCDocument],
testset_size: int,
transforms: t.Optional[Transforms] = None,
transforms_llm: t.Optional[BaseRagasLLM] = None,
transforms_embedding_model: t.Optional[BaseRagasEmbeddings] = None,
query_distribution: t.Optional[QueryDistribution] = None,
run_config: t.Optional[RunConfig] = None,
callbacks: t.Optional[Callbacks] = None,
token_usage_parser: t.Optional[TokenUsageParser] = None,
with_debugging_logs=False,
raise_exceptions: bool = True,
return_executor: bool = False,
) -> t.Union[Testset, Executor]:
"""
Generates an evaluation dataset based on given Langchain documents and parameters.
Parameters
----------
documents : Sequence[LCDocument]
A sequence of Langchain documents to use as source material
testset_size : int
The number of test samples to generate
transforms : Optional[Transforms], optional
Custom transforms to apply to the documents, by default None
transforms_llm : Optional[BaseRagasLLM], optional
LLM to use for transforms if different from instance LLM, by default None
transforms_embedding_model : Optional[BaseRagasEmbeddings], optional
Embedding model to use for transforms if different from instance model, by default None
query_distribution : Optional[QueryDistribution], optional
Distribution of query types to generate, by default None
run_config : Optional[RunConfig], optional
Configuration for the generation run, by default None
callbacks : Optional[Callbacks], optional
Callbacks to use during generation, by default None
token_usage_parser : Optional[TokenUsageParser], optional
Parse the LLMResult object and return a TokenUsage object. This is used to
calculate the cost of the generation process.
with_debugging_logs : bool, optional
Whether to include debug logs, by default False
raise_exceptions : bool, optional
Whether to raise exceptions during generation, by default True
return_executor : bool, optional
If True, returns the Executor instance instead of running generation.
The returned executor can be used to cancel execution by calling executor.cancel().
To get results, call executor.results(). Default is False.
Returns
-------
Testset or Executor
If return_executor is False, returns the generated evaluation dataset.
If return_executor is True, returns the Executor instance for cancellable execution.
Raises
------
ValueError
If no LLM or embedding model is provided either during initialization or as arguments
"""
# force the user to provide an llm and embedding client to prevent use of default LLMs
if not self.llm and not transforms_llm:
raise ValueError(
"""An llm client was not provided.
Provide an LLM on TestsetGenerator instantiation or as an argument for transforms_llm parameter.
Alternatively you can provide your own transforms through the `transforms` parameter."""
)
if not self.embedding_model and not transforms_embedding_model:
raise ValueError(
"""An embedding client was not provided. Provide an embedding through the transforms_embedding_model parameter. Alternatively you can provide your own transforms through the `transforms` parameter."""
)
if not transforms:
transforms = default_transforms(
documents=list(documents),
llm=transforms_llm or self.llm,
embedding_model=transforms_embedding_model or self.embedding_model,
)
# convert the documents to Ragas nodes
nodes = []
for doc in documents:
node = Node(
type=NodeType.DOCUMENT,
properties={
"page_content": doc.page_content,
"document_metadata": doc.metadata,
},
)
nodes.append(node)
kg = KnowledgeGraph(nodes=nodes)
# apply transforms and update the knowledge graph
apply_transforms(kg, transforms, run_config=run_config or RunConfig())
self.knowledge_graph = kg
return self.generate(
testset_size=testset_size,
query_distribution=query_distribution,
run_config=run_config,
callbacks=callbacks,
token_usage_parser=token_usage_parser,
with_debugging_logs=with_debugging_logs,
raise_exceptions=raise_exceptions,
return_executor=return_executor,
)
generate_with_llamaindex_docs
generate_with_llamaindex_docs(documents: Sequence[Document], testset_size: int, transforms: Optional[Transforms] = None, transforms_llm: Optional[BaseLLM] = None, transforms_embedding_model: Optional[BaseEmbedding] = None, query_distribution: Optional[QueryDistribution] = None, run_config: Optional[RunConfig] = None, callbacks: Optional[Callbacks] = None, token_usage_parser: Optional[TokenUsageParser] = None, with_debugging_logs=False, raise_exceptions: bool = True)
根据给定场景和参数生成评测数据集。
源代码位于 src/ragas/testset/synthesizers/generate.py
def generate_with_llamaindex_docs(
self,
documents: t.Sequence[LlamaIndexDocument],
testset_size: int,
transforms: t.Optional[Transforms] = None,
transforms_llm: t.Optional[LlamaIndexLLM] = None,
transforms_embedding_model: t.Optional[LlamaIndexEmbedding] = None,
query_distribution: t.Optional[QueryDistribution] = None,
run_config: t.Optional[RunConfig] = None,
callbacks: t.Optional[Callbacks] = None,
token_usage_parser: t.Optional[TokenUsageParser] = None,
with_debugging_logs=False,
raise_exceptions: bool = True,
):
"""
Generates an evaluation dataset based on given scenarios and parameters.
"""
run_config = run_config or RunConfig()
# force the user to provide an llm and embedding client to prevent use of default LLMs
if not self.llm and not transforms_llm:
raise ValueError(
"An llm client was not provided. Provide an LLM on TestsetGenerator instantiation or as an argument for transforms_llm parameter. Alternatively you can provide your own transforms through the `transforms` parameter."
)
if not self.embedding_model and not transforms_embedding_model:
raise ValueError(
"An embedding client was not provided. Provide an embedding through the transforms_embedding_model parameter. Alternatively you can provide your own transforms through the `transforms` parameter."
)
if not transforms:
# use TestsetGenerator's LLM and embedding model if no transforms_llm or transforms_embedding_model is provided
if transforms_llm is None:
llm_for_transforms = self.llm
else:
llm_for_transforms = LlamaIndexLLMWrapper(transforms_llm)
if transforms_embedding_model is None:
embedding_model_for_transforms = self.embedding_model
else:
embedding_model_for_transforms = LlamaIndexEmbeddingsWrapper(
transforms_embedding_model
)
# create the transforms
transforms = default_transforms(
documents=[LCDocument(page_content=doc.text) for doc in documents],
llm=llm_for_transforms,
embedding_model=embedding_model_for_transforms,
)
# convert the documents to Ragas nodes
nodes = []
for doc in documents:
if doc.text is not None and doc.text.strip() != "":
node = Node(
type=NodeType.DOCUMENT,
properties={
"page_content": doc.text,
"document_metadata": doc.metadata,
},
)
nodes.append(node)
kg = KnowledgeGraph(nodes=nodes)
# apply transforms and update the knowledge graph
apply_transforms(kg, transforms, run_config)
self.knowledge_graph = kg
return self.generate(
testset_size=testset_size,
query_distribution=query_distribution,
run_config=run_config,
callbacks=callbacks,
token_usage_parser=token_usage_parser,
with_debugging_logs=with_debugging_logs,
raise_exceptions=raise_exceptions,
return_executor=False, # Default value for llamaindex_docs method
)
generate_with_chunks
generate_with_chunks(chunks: Sequence[Union[Document, str]], testset_size: int, transforms: Optional[Transforms] = None, transforms_llm: Optional[BaseRagasLLM] = None, transforms_embedding_model: Optional[BaseRagasEmbeddings] = None, query_distribution: Optional[QueryDistribution] = None, run_config: Optional[RunConfig] = None, callbacks: Optional[Callbacks] = None, token_usage_parser: Optional[TokenUsageParser] = None, with_debugging_logs=False, raise_exceptions: bool = True, return_executor: bool = False) -> Union[Testset, Executor]
根据已切分好的文档生成评测数据集。
该方法允许用户通过提供已经切分好的文档来跳过内部 chunking 过程。输入文档会直接作为 NodeType.CHUNK 处理。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
chunks |
Sequence[Union[Document, str]] |
用作 chunks 的 Langchain documents 或字符串序列。字符串会自动转换为 Documents。 | required |
testset_size |
int |
要生成的测试样本数量 | required |
transforms |
Optional[Transforms] |
应用到 chunks 的自定义 transforms,默认 None | None |
transforms_llm |
Optional[BaseRagasLLM] |
若与实例 LLM 不同,用于 transforms 的 LLM,默认 None | None |
transforms_embedding_model |
Optional[BaseRagasEmbeddings] |
若与实例模型不同,用于 transforms 的 embedding 模型,默认 None | None |
query_distribution |
Optional[QueryDistribution] |
要生成的查询类型分布,默认 None | None |
run_config |
Optional[RunConfig] |
生成运行的配置,默认 None | None |
callbacks |
Optional[Callbacks] |
生成期间使用的 callbacks,默认 None | None |
token_usage_parser |
Optional[TokenUsageParser] |
解析 LLMResult 对象并返回 TokenUsage 对象。 | None |
with_debugging_logs |
bool |
是否包含调试日志,默认 False | False |
raise_exceptions |
bool |
生成期间是否抛出异常,默认 True | True |
return_executor |
bool |
若为 True,返回 Executor 实例而不运行生成。 | False |
返回:
| 类型 | 说明 |
|---|---|
Testset or Executor |
若 return_executor 为 False,返回生成的评测数据集。若 return_executor 为 True,返回 Executor 实例。 |
源代码位于 src/ragas/testset/synthesizers/generate.py
def generate_with_chunks(
self,
chunks: t.Sequence[t.Union[LCDocument, str]],
testset_size: int,
transforms: t.Optional[Transforms] = None,
transforms_llm: t.Optional[BaseRagasLLM] = None,
transforms_embedding_model: t.Optional[BaseRagasEmbeddings] = None,
query_distribution: t.Optional[QueryDistribution] = None,
run_config: t.Optional[RunConfig] = None,
callbacks: t.Optional[Callbacks] = None,
token_usage_parser: t.Optional[TokenUsageParser] = None,
with_debugging_logs=False,
raise_exceptions: bool = True,
return_executor: bool = False,
) -> t.Union[Testset, Executor]:
"""
Generates an evaluation dataset based on provided pre-chunked documents.
This method allows users to skip the internal chunking process by providing
documents that are already chunked. The input documents are treated as
`NodeType.CHUNK` directly.
Parameters
----------
chunks : Sequence[Union[LCDocument, str]]
A sequence of Langchain documents or strings to use as chunks.
Strings will be automatically converted to Documents.
testset_size : int
The number of test samples to generate
transforms : Optional[Transforms], optional
Custom transforms to apply to the chunks, by default None
transforms_llm : Optional[BaseRagasLLM], optional
LLM to use for transforms if different from instance LLM, by default None
transforms_embedding_model : Optional[BaseRagasEmbeddings], optional
Embedding model to use for transforms if different from instance model, by default None
query_distribution : Optional[QueryDistribution], optional
Distribution of query types to generate, by default None
run_config : Optional[RunConfig], optional
Configuration for the generation run, by default None
callbacks : Optional[Callbacks], optional
Callbacks to use during generation, by default None
token_usage_parser : Optional[TokenUsageParser], optional
Parse the LLMResult object and return a TokenUsage object.
with_debugging_logs : bool, optional
Whether to include debug logs, by default False
raise_exceptions : bool, optional
Whether to raise exceptions during generation, by default True
return_executor : bool, optional
If True, returns the Executor instance instead of running generation.
Returns
-------
Testset or Executor
If return_executor is False, returns the generated evaluation dataset.
If return_executor is True, returns the Executor instance.
"""
# force the user to provide an llm and embedding client
if not self.llm and not transforms_llm:
raise ValueError(
"""An llm client was not provided.
Provide an LLM on TestsetGenerator instantiation or as an argument for transforms_llm parameter.
Alternatively you can provide your own transforms through the `transforms` parameter."""
)
if not self.embedding_model and not transforms_embedding_model:
raise ValueError(
"""An embedding client was not provided. Provide an embedding through the transforms_embedding_model parameter. Alternatively you can provide your own transforms through the `transforms` parameter."""
)
if transforms is None:
transforms = default_transforms_for_prechunked(
llm=transforms_llm or self.llm,
embedding_model=transforms_embedding_model or self.embedding_model,
)
# convert the chunks to Ragas nodes
nodes = []
for chunk in chunks:
if isinstance(chunk, str):
page_content = chunk
metadata = {}
else:
page_content = chunk.page_content
metadata = chunk.metadata
if page_content is not None and page_content.strip() != "":
node = Node(
type=NodeType.CHUNK,
properties={
"page_content": page_content,
"document_metadata": metadata,
},
)
nodes.append(node)
kg = KnowledgeGraph(nodes=nodes)
# apply transforms and update the knowledge graph
apply_transforms(kg, transforms, run_config=run_config or RunConfig())
self.knowledge_graph = kg
return self.generate(
testset_size=testset_size,
query_distribution=query_distribution,
run_config=run_config,
callbacks=callbacks,
token_usage_parser=token_usage_parser,
with_debugging_logs=with_debugging_logs,
raise_exceptions=raise_exceptions,
return_executor=return_executor,
)
generate
generate(testset_size: int, query_distribution: Optional[QueryDistribution] = None, num_personas: int = 3, run_config: Optional[RunConfig] = None, batch_size: Optional[int] = None, callbacks: Optional[Callbacks] = None, token_usage_parser: Optional[TokenUsageParser] = None, with_debugging_logs=False, raise_exceptions: bool = True, return_executor: bool = False) -> Union[Testset, Executor]
根据给定场景和参数生成评测数据集。
参数:
| 名称 | 类型 | 说明 | 默认值 |
|---|---|---|---|
testset_size |
int |
要生成的样本数量。 | required |
query_distribution |
Optional[QueryDistribution] |
包含场景模拟器及其概率的元组列表。若为 None,将使用默认模拟器。 | None |
num_personas |
int |
从 persona_list 生成或使用的 persona 数量。 | 3 |
run_config |
Optional[RunConfig] |
运行生成过程的配置。 | None |
batch_size |
Optional[int] |
批次应有多大。若设为 None(默认),则不做分批。 | None |
callbacks |
Optional[Callbacks] |
用于生成过程的 Langchain 风格 callbacks。可用于记录生成过程或添加其他元数据。 | None |
token_usage_parser |
Optional[TokenUsageParser] |
解析 LLMResult 对象并返回 TokenUsage 对象。用于计算生成过程的成本。 | None |
with_debugging_logs |
bool |
若为 True,为各组件启用调试日志。 | False |
raise_exceptions |
bool |
若为 True,在生成过程中抛出异常。 | True |
return_executor |
bool |
若为 True,返回 Executor 实例而不运行生成。返回的 executor 可通过调用 executor.cancel() 取消执行。要获取结果,调用 executor.results()。 | False |
返回:
| 类型 | 说明 |
|---|---|
Testset or Executor |
若 return_executor 为 False,返回包含所生成 TestsetSamples 的数据集。若 return_executor 为 True,返回可用于取消执行的 Executor 实例。 |
备注
该函数执行以下步骤:
- 如需要,设置场景并开启调试日志。
- 使用 Executor 生成场景。
- 计算不同场景类型的拆分值。
- 为每个场景生成样本。
- 将结果编译为 EvaluationDataset。
源代码位于 src/ragas/testset/synthesizers/generate.py
def generate(
self,
testset_size: int,
query_distribution: t.Optional[QueryDistribution] = None,
num_personas: int = 3,
run_config: t.Optional[RunConfig] = None,
batch_size: t.Optional[int] = None,
callbacks: t.Optional[Callbacks] = None,
token_usage_parser: t.Optional[TokenUsageParser] = None,
with_debugging_logs=False,
raise_exceptions: bool = True,
return_executor: bool = False,
) -> t.Union[Testset, Executor]:
"""
Generate an evaluation dataset based on given scenarios and parameters.
Parameters
----------
testset_size : int
The number of samples to generate.
query_distribution : Optional[QueryDistribution], optional
A list of tuples containing scenario simulators and their probabilities.
If None, default simulators will be used.
num_personas : int, default 3
The number of personas to generate or use from the persona_list.
run_config : Optional[RunConfig], optional
Configuration for running the generation process.
batch_size: int, optional
How large should batches be. If set to None (default), no batching is done.
callbacks : Optional[Callbacks], optional
Langchain style callbacks to use for the generation process. You can use
this to log the generation process or add other metadata.
token_usage_parser : Optional[TokenUsageParser], optional
Parse the LLMResult object and return a TokenUsage object. This is used to
calculate the cost of the generation process.
with_debugging_logs : bool, default False
If True, enable debug logging for various components.
raise_exceptions : bool, default True
If True, raise exceptions during the generation process.
return_executor : bool, default False
If True, returns the Executor instance instead of running generation.
The returned executor can be used to cancel execution by calling executor.cancel().
To get results, call executor.results().
Returns
-------
Testset or Executor
If return_executor is False, returns a dataset containing the generated TestsetSamples.
If return_executor is True, returns the Executor instance for cancellable execution.
Notes
-----
This function performs the following steps:
1. Set up scenarios and debug logging if required.
2. Generate scenarios using an Executor.
3. Calculate split values for different scenario types.
4. Generate samples for each scenario.
5. Compile the results into an EvaluationDataset.
"""
if run_config is not None:
# Only BaseRagasLLM has set_run_config method, not InstructorBaseRagasLLM
if isinstance(self.llm, BaseRagasLLM):
self.llm.set_run_config(run_config)
query_distribution = query_distribution or default_query_distribution(
self.llm, self.knowledge_graph, self.llm_context
)
callbacks = callbacks or []
# dict to store any callbacks we define
ragas_callbacks = {}
# set the token usage parser
if token_usage_parser is not None:
from ragas.cost import CostCallbackHandler
cost_cb = CostCallbackHandler(token_usage_parser=token_usage_parser)
ragas_callbacks["cost_cb"] = cost_cb
else:
cost_cb = None
# append all the ragas_callbacks to the callbacks
for cb in ragas_callbacks.values():
if isinstance(callbacks, BaseCallbackManager):
callbacks.add_handler(cb)
else:
callbacks.append(cb)
# new group for Testset Generation
testset_generation_rm, testset_generation_grp = new_group(
name=RAGAS_TESTSET_GENERATION_GROUP_NAME,
inputs={"testset_size": testset_size},
callbacks=callbacks,
)
if with_debugging_logs:
# TODO: Edit this before pre-release
from ragas.utils import patch_logger
patch_logger("ragas.experimental.testset.synthesizers", logging.DEBUG)
patch_logger("ragas.experimental.testset.graph", logging.DEBUG)
patch_logger("ragas.experimental.testset.transforms", logging.DEBUG)
if self.persona_list is None:
self.persona_list = generate_personas_from_kg(
llm=self.llm,
kg=self.knowledge_graph,
num_personas=num_personas,
callbacks=callbacks,
)
else:
random.shuffle(self.persona_list)
splits, _ = calculate_split_values(
[prob for _, prob in query_distribution], testset_size
)
# new group for Generation of Scenarios
scenario_generation_rm, scenario_generation_grp = new_group(
name="Scenario Generation",
inputs={"splits": splits},
callbacks=testset_generation_grp,
)
# generate scenarios
exec = Executor(
desc="Generating Scenarios",
raise_exceptions=raise_exceptions,
run_config=run_config,
keep_progress_bar=False,
batch_size=batch_size,
)
# generate samples
splits, _ = calculate_split_values(
[prob for _, prob in query_distribution], testset_size
)
for i, (scenario, _) in enumerate(query_distribution):
exec.submit(
scenario.generate_scenarios,
n=splits[i],
knowledge_graph=self.knowledge_graph,
persona_list=self.persona_list[:num_personas],
callbacks=scenario_generation_grp,
)
try:
scenario_sample_list: t.List[t.List[BaseScenario]] = exec.results()
except Exception as e:
scenario_generation_rm.on_chain_error(e)
raise e
else:
scenario_generation_rm.on_chain_end(
outputs={"scenario_sample_list": scenario_sample_list}
)
# new group for Generation of Samples
sample_generation_rm, sample_generation_grp = new_group(
name="Sample Generation",
inputs={"scenario_sample_list": scenario_sample_list},
callbacks=testset_generation_grp,
)
exec = Executor(
"Generating Samples",
raise_exceptions=raise_exceptions,
run_config=run_config,
keep_progress_bar=True,
batch_size=batch_size,
)
additional_testset_info: t.List[t.Dict] = []
for i, (synthesizer, _) in enumerate(query_distribution):
for sample in scenario_sample_list[i]:
exec.submit(
synthesizer.generate_sample,
scenario=sample,
callbacks=sample_generation_grp,
)
# fill out the additional info for the TestsetSample
additional_testset_info.append(
{
"synthesizer_name": synthesizer.name,
}
)
# Return executor for cancellable execution if requested
if return_executor:
return exec
try:
eval_samples = exec.results()
except Exception as e:
sample_generation_rm.on_chain_error(e)
raise e
else:
sample_generation_rm.on_chain_end(outputs={"eval_samples": eval_samples})
# build the testset
testsets = []
for sample, additional_info in zip(eval_samples, additional_testset_info):
testsets.append(TestsetSample(eval_sample=sample, **additional_info))
testset = Testset(samples=testsets, cost_cb=cost_cb)
testset_generation_rm.on_chain_end({"testset": testset})
# tracking how many samples were generated
track(
TestsetGenerationEvent(
event_type="testset_generation",
evolution_names=[
e.__class__.__name__.lower() for e, _ in query_distribution
],
evolution_percentages=[p for _, p in query_distribution],
num_rows=testset_size,
language="english",
)
)
return testset