DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

测试LLM输出效果,离不开大量数据集。从零开始准备这些数据,费时、烧钱,还特别折腾。但现在情况不一样了:以前要花几周手工打造的数千条测试用例,现在几分钟就搞定。

合成数据生成的核心思路很简单:让LLM自己造数据,省掉收集、清洗、标注这些苦力活。有了GPT-4等这样的模型,合成出来的数据集比人工标注的更全面、更多样,速度还快得多。这些数据可以用来给LLM系统做基准测试,配合评测指标效果更好。

本文会教你用LLM生成合成数据集的全套方法(比如用来评测RAG管道)。内容包括:

  • 合成数据生成的两大方法:蒸馏和自我改进
  • 什么是数据演化、有哪些演化技巧、在合成数据生成中起什么作用
  • 从零开始用LLM创建高质量合成数据的详细教程
  • 如何用DeepEval在5行代码内生成合成数据集

什么是用LLM生成合成数据?

用LLM生成合成数据,就是让LLM创造人工数据。这些数据通常用来训练、微调,甚至评测LLM本身。生成合成数据集不仅比找公开数据快,比人工标注便宜,质量还更高、多样性更好,这对LLM红队测试也很重要。

整个流程从创建合成查询开始。这些查询用知识库里的上下文(通常是文档)作为参考生成。生成的查询会被多次“演化”,变得更复杂、更真实。把这些查询和原始上下文结合起来,就成了最终的合成数据集。虽然可选,但建议给每个查询-上下文对生成一个目标标签,作为LLM系统针对这个查询的预期输出。

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

生成评测用的合成数据集,主要有两种方法:从模型自己的输出做自我改进,或者从更强的模型做蒸馏。

  • 自我改进:模型从自己的输出迭代生成数据,不依赖外部资源
  • 蒸馏:用更强的模型给弱模型生成合成数据做评测

自我改进方法(像Self-Instruct或SPIN)受限于模型自身能力,可能放大偏见和错误。蒸馏技术只受限于能用到的最好模型,能保证最高质量的生成结果。

从知识库生成数据

合成数据生成的第一步,是从上下文列表创建合成查询,这些上下文直接来自知识库。说白了,上下文就是LLM应用的理想检索内容,就像预期输出是LLM实际输出的参考答案一样。

想立即上手的话,下面展示如何用DeepEval(开源LLM评测框架)生成高质量合成数据:

构建上下文

上下文生成时,知识库里的文档会用token分割器切成块(chunks)。然后随机选一个块,再根据相似度检索和分组其他块。

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

相似度可以用这几种方法计算:

  • 用相似度或距离算法,比如余弦相似度
  • 用知识图谱
  • 直接用LLM本身(虽然不太现实,但最准确)
  • 用聚类技术识别模式
  • 用机器学习模型基于特征预测分组

不管哪种方法,目标都一样:有效聚合相似的信息块。

想让这些分组发挥作用,最好在上下文生成时复制应用的检索器逻辑。token分割方法、块大小、块重叠这些细节都要仔细考虑。

这样对齐能保证合成数据的表现符合应用预期,避免因检索器复杂度不同导致结果偏差。

从上下文生成合成输入

上下文准备好后,下一步就是生成合成输入。这个方法反转了标准检索操作——不是根据输入找上下文,而是基于预设上下文创建输入。这样能确保每个合成输入都直接对应一个上下文,相关性和准确性都更高。

另外,这些上下文还能选择性地用来生成预期输出,和合成输入对齐。

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

这种非对称方法能让所有组件——输入、输出、上下文——完美同步。

过滤合成数据

开始演化新生成的数据集前,必须做彻底的质量检查,别在本来就有问题的输入上浪费时间。这步很关键,既能避免资源浪费,又能确保最终数据集只包含高质量样本。

过滤发生在两个关键阶段:上下文生成时,以及从上下文生成合成输入时。

上下文过滤

上下文生成时,可能随机抽到质量差的数据块。知识库里常有复杂结构或多余空格,切分后会变得难以理解。用LLM做评判是识别和过滤这些低质量上下文的好办法。

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

可以自定义评测和过滤标准,这里给些基础准则参考:

  • 清晰度:信息是否清楚易懂
  • 深度:有没有详细分析和原创见解
  • 结构:内容组织和逻辑是否清晰
  • 相关性:跟主题的关联度
  • 精确度:准确性和细节把控
  • 新颖性:内容是否独特原创
  • 简洁性:表达是否简洁高效
  • 影响力:对读者的潜在影响

过滤完低质量块后,还要确保剩下的块足够相似。这需要二次过滤,剔除相似度不达标的块。

这种结构化过滤能确保只有高质量、相关、有用的上下文进入下一阶段。

输入过滤

第二个过滤阶段关注从上下文生成的合成输入。这步很重要,因为就算上下文质量好,也可能生成不合格的输入。

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

评判合成输入可以用这些标准:

  • 自包含性:输入是否完整,能否独立运作
  • 清晰度:输入是否清楚传达意图,避免误解
  • 一致性:输入是否和上下文在主题和事实上一致
  • 相关性:输入是否直接关联预期任务或查询
  • 完整性:输入是否包含所有必要细节

用这些标准能确保合成输入不仅质量高,还完美适配预期应用。

风格化合成数据

最后,可能需要把查询定制成特定主题,自定义输入输出格式来适应具体用例。

比如,应用涉及文本转SQL,输出就该准确反映SQL语句。如果是评测型LLM场景,用带“score”和“reason”键的JSON格式可能更合适。

建议在初始生成、任何演化变更时,以及最终输出生成后都应用特定风格。初始生成后重新审视风格很重要,因为合成查询演化可能改变最初的风格设定。

首轮后的风格调整程度取决于你对最终产品的控制要求和预算考虑。

数据的适者生存

来说说什么是数据演化,以及为什么它对用LLM生成合成数据这么重要。数据演化最早由微软的Evol-Instruct提出,通过提示工程迭代增强现有查询集,生成更复杂更多样的查询。这步决定了数据集的质量、全面性、复杂性和多样性,也是合成数据优于公开或人工标注数据集的关键。

微软团队做了个实验:175条人工查询 → 25万条指令,这就是数据演化的威力。数据演化有三种类型:

  • 深度演化:把简单指令扩展成更详细复杂的版本
  • 广度演化:产生新的多样化指令,丰富数据集
  • 淘汰演化:移除效果差或失败的指令

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

深度演化有多种玩法,比如让输入更复杂、增加推理需求、或者添加多个步骤完成任务。每种方法都能提升生成数据的复杂度。

深度演化能创建细致入微的高质量查询,广度演化能增强多样性和全面性。多次演化每个查询或指令,就能增加复杂性,产生丰富多面的数据集。

举个例子:原始查询 —— 1+1等于多少?
深度演化后:演化查询 —— 什么情况下1+1不等于2?

这显然比普通的1+1更复杂更真实。下一节会展示如何在生成合成数据集时实际运用这些演化方法。

分步指南:用LLM生成合成数据

开始前,先看看要构建的数据合成器架构:

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

可以看到有五个主要步骤:

  • 文档分块
  • 上下文生成
  • 查询生成
  • 数据演化
  • 标签/预期输出生成(可选)

想立即上手的话,这个流程已经在DeepEval中开源了,只需2行代码就能准备好合成数据集生成,还支持过滤和风格化(稍后展示)。

想了解工作原理的话,继续往下看。

1. 文档分块

第一步是给文档分块。顾名思义,就是把文档切成更小、有意义的“块”。这样能把大文档拆解成可管理的子文档,同时保持上下文完整。分块还能让超过嵌入模型token限制的文档生成嵌入。

这步很关键,能帮你找出语义相似的块,基于共享上下文生成查询或任务。

分块策略有好几种,比如固定大小分块和上下文感知分块。还可以调整超参数,像字符大小和块重叠。下面例子用基于token的分块,字符大小1024,无重叠。分块方法:

2. 数据合成流程详解

DeepEval 的数据合成流程包含四个核心步骤:文档分块与嵌入、上下文生成、查询生成以及查询演化。

1. 文档分块与嵌入

首先,将原始文档(如PDF)分割成语义连贯的文本块,并为每个块生成向量嵌入,以捕获其语义信息。

# Step 1. Chunk Documents
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import TokenTextSplitter

text_splitter = TokenTextSplitter(chunk_size=1024, chunk_overlap=0)
loader = PyPDFLoader("chatbot_information.pdf")
raw_chunks = loader.load_and_split(text_splitter)

分块完成后,将每个块转换为嵌入向量,并与原始内容结合,形成 Chunk 对象列表。

from langchain_openai import OpenAIEmbeddings

embedding_model = OpenAIEmbeddings(api_key="...")
content = [rc.page_content for rc in raw_chunks]
embeddings = embedding_model.embed_documents(content)

2. 上下文生成

生成上下文时,首先随机选择一个数据块作为“锚点”,用于寻找语义上相关的其他块。

# Step 2: Generate context by selecting chunks
import random

reference_index = random.randint(0, len(embeddings) - 1)
reference_embedding = embeddings[reference_index]
contexts = [content[reference_index]]

随后,通过计算余弦相似度,将与锚点块相似度超过设定阈值的块纳入上下文,从而构建一个围绕同一主题的、信息丰富的上下文集合。

similarity_threshold = 0.8
similar_indices = []
for i, embedding in enumerate(embeddings):
    product = np.dot(reference_embedding, embedding)
    norm = np.linalg.norm(reference_embedding) * np.linalg.norm(embedding)
    similarity = product / norm
    if similarity >= similarity_threshold:
        similar_indices.append(i)

for i in similar_indices:
    contexts.append(content[i])

此步骤至关重要,它能通过整合多个来源的信息,增强查询的鲁棒性,并为后续的查询生成提供更细致、全面的背景信息。

3. 查询生成

利用大语言模型(LLM),基于上一步生成的上下文来创建初始查询或任务。通过结构化提示词,引导模型生成一个包含 input 键(即问题或陈述)的 JSON 对象列表。

# Step 3. Generate a series of queries for similar chunks
from langchain_openai import ChatOpenAI

prompt = f"""
I want you act as a copywriter. Based on the given context,
which is list of strings, please generate a list of JSON objects
with a `input` key. The `input` can either be a question or a
statement that can be addressed by the given context.

contexts:
{contexts}
"""

query = ChatOpenAI(openai_api_key="...").invoke(prompt)

这些初始查询构成了最终评测数据集的基础。

4. 查询演化

最后一步是对初始查询进行演化,以增加问题的多样性和复杂性。通过应用不同的“演化模板”,可以生成多种类型的查询。DeepEval 主要关注三类演化:
* 多上下文理解:要求模型综合多个上下文块的信息进行回答。
* 多步推理:设计需要多个逻辑步骤才能解决的问题。
* 假设场景:基于给定上下文,提出“如果…会怎样”类型的问题。

通过这一流程,DeepEval 能够自动化、低成本地合成高质量、多样化的评测数据,为 LLM 的评估提供了坚实的基础。

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升

查询演化模板与步骤

每个演化模板都对输出有特定约束。根据您希望评测查询在最终数据集中的呈现方式,可以自由调整这些模板。通过多次随机选择模板来演化原始查询,可以生成多样化的数据。

# 演化提示词模板
multi_context_template = f"""I want you to rewrite the given `input` so that it requires readers to use information from all elements in `Context`.
1. `Input` should require information from all `Context` elements.
2. `Rewritten Input` must be concise and fully answerable from `Context`.
3. Do not use phrases like 'based on the provided context.'
4. `Rewritten Input` should not exceed 15 words.

Context: {context}
Input: {original_input}
Rewritten Input:"""

reasoning_template = f"""I want you to rewrite the given `input` so that it explicitly requests multi-step reasoning.
1. `Rewritten Input` should require multiple logical connections or inferences.
2. `Rewritten Input` should be concise and understandable.
3. Do not use phrases like 'based on the provided context.'
4. `Rewritten Input` must be fully answerable from `Context`.
5. `Rewritten Input` should not exceed 15 words.

Context: {context}
Input: {original_input}
Rewritten Input:"""

hypothetical_scenario_template = f"""I want you to rewrite the given `input` to incorporate a hypothetical or speculative scenario.
1. `Rewritten Input` should encourage applying knowledge from `Context` to deduce outcomes.
2. `Rewritten Input` should be concise and understandable.
3. Do not use phrases like 'based on the provided context.'
4. `Rewritten Input` must be fully answerable from `Context`.
5. `Rewritten Input` should not exceed 15 words.

Context: {context}
Input: {original_input}
Rewritten Input:"""
# 步骤 4:演化查询
example_generated_query = "How do chatbots use natural language understanding?"
context = contexts
original_input = example_generated_query
evolution_templates = [multi_context_template, reasoning_template, hypothetical_scenario_template]

# 设定演化步数
num_evolution_steps = 3

# 执行随机演化步骤的函数
def evolve_query(original_input, context, steps):
    current_input = original_input
    for _ in range(steps):
        # 从列表中随机选择一个模板
        chosen_template = random.choice(evolution_templates)
        # 用当前上下文和输入替换占位符
        evolved_prompt = chosen_template.replace("{context}", str(context)).replace("{original_input}", current_input)
        # 使用“Rewritten Input”部分更新当前输入
        current_input = ChatOpenAI(openai_api_key="...").invoke(evolved_prompt)
    return current_input

# 通过随机选择演化类型来演化输入
evolved_query = evolve_query(original_input, context, num_evolution_steps)

通过上述过程即可获得最终演化的查询。重复此过程可以生成更多查询,从而进一步完善数据集。为了进行评测,需要将这些输入查询和上下文正确格式化为适合的测试框架。

5. 预期输出生成

此步骤为可选,但强烈建议为每个演化查询生成预期输出。相较于从头创建,人工评测员修改和标注预期输出可以节省大量时间和精力。

Step 5. Generate Expected Output

最后一步是生成预期输出。这需要将演化后的查询和上下文输入给LLM,并要求其生成一个与上下文事实相符的答案。

# Define prompt template
expected_output_template = f"""I want you to generate an answer for the given `input`. This answer has to be factually aligned to the provided context.

Context: {context}
Input: {evolved_query}
Answer:"""

# Fill in the values
prompt = expected_output_template.replace("{context}", str(context)).replace("{evolved_query}", evolved_query)

# Generate expected output
expected_output = ChatOpenAI(openai_api_key="...").invoke(prompt)

至此,我们已获得所有必要组件:演化查询、上下文和预期输出。接下来,将它们组合成合成数据集中的一条记录。

from pydantic import BaseModel
from typing import Optional, List

class SyntheticData(BaseModel):
    query: str
    expected_output: Optional[str]
    context: List[str]

synthetic_data = SyntheticData(
    query=evolved_query,
    expected_output=expected_output,
    context=context
)

# Simple implementation of synthetic dataset
synthetic_dataset = []
synthetic_dataset.append(synthetic_data)

现在,只需重复步骤1至5,即可生成规模合理的合成数据集。之后,这个数据集就可以直接用于评测您的LLM系统。

总结

利用LLM生成合成数据集,其核心优势在于能够快速、低成本地获取大量数据。然而,原始生成的数据往往存在模式单一、重复性高的问题,难以真实反映现实世界的数据分布,从而限制了其实际应用价值。

本文介绍的方法旨在解决这一痛点。其核心流程是:首先从文档中选取相关的上下文片段,然后基于这些上下文生成能够有效测试目标LLM系统的查询。此外,我们还探讨了通过“数据演化”技术,使生成的查询更加多样化和贴近真实场景。

如果您希望从头构建一个高质量的数据合成器,本文提供的思路和步骤将是一个实用的起点。


关于大模型评测诊断NoneLinear
https://nonelinear.com

  1. 评测榜单——已囊括300+大模型、300+评测维度,每周更新大模型评测结果
  2. 模型选型降本——一键选出最合适模型,效果更优,成本降低50%以上
  3. 智能模型超市——统一API,一键调用全球所有大模型,GPT5 / Gemini2.5 / Claude4.5免费体验,高并发,自动故障切换,实时监控模型调用效果

DeepEval开源方案:用LLM合成数据,90%成本锐减,评测效率飙升


关注“鲸栖”小程序,掌握最新AI资讯

本文来自网络搜集,不代表鲸林向海立场,如有侵权,联系删除。转载请注明出处:http://www.itsolotime.com/archives/14691

(0)
上一篇 2025年10月24日 上午11:48
下一篇 2025年10月24日 下午7:04

相关推荐

  • AI Agent架构评测:从实验室到生产环境的Skills解耦工程化实践

    评测盲区:为什么「能用」不等于「可用」? 在大模型评测领域,我们有 MMLU 测知识、HumanEval 测代码、BFCL 测函数调用。但对于 Agent 系统,评测维度往往停留在「任务完成率」这个单一指标上。 这里存在一个评测盲区:我们很少评测 Agent 能力的「可迁移性」和「可工程化程度」。 举个例子:在 Claude Code 环境中,构建了一套完整…

    2天前
    4200
  • 中国团队首创医疗AI临床安全-有效性双轨评估标准CSEDB,MedGPT全球评测夺冠

    中国团队首创医疗AI临床安全-有效性双轨评估标准CSEDB,获《npj Digital Medicine》收录 中国团队首次在全球顶尖期刊发表“大模型+医疗”领域的相关标准研究。 作为Nature体系中专注于数字医疗的旗舰期刊,《npj Digital Medicine》(JCR影响因子15.1,中科院医学大类1区Top期刊)此次收录的CSEDB研究,首次提…

    2026年1月21日
    7000
  • ERNIE-5.0全面评测:2.4万亿参数旗舰大模型性能与成本深度解析

    百度近期正式发布了原生全模态大模型ERNIE-5.0(文心5.0),这是一款参数达2.4万亿、采用原生全模态统一建模技术的旗舰级产品,支持文本、图像、音频、视频等多种信息的输入与输出。我们对ERNIE-5.0正式版与此前的ERNIE-5.0-Thinking-Preview版本进行了全面的对比评测,测试其在准确率、响应时间、token消耗和成本等关键指标上的…

    2026年1月24日
    5100
  • 评测驱动时代开启:李飞飞World Labs联手光轮智能,破解具身智能规模化评测难题

    最火世界模型,最火具身智能基建,联手了! 前者,是李飞飞旗下的World Labs;后者,是一家炙手可热的仿真合成数据公司——光轮智能。 具身智能生态中最受关注的两家公司双刃合璧,原因无他,正是瞄准困扰行业已久的「规模化评测」问题,发起一波攻势。 而随着这波号角的吹响,也标志着具身智能正式迈入评测驱动时代。 在这个赛道上,光轮智能基于全栈自研仿真技术体系所构…

    2026年1月19日
    6700
  • 文心一言5.0正式版深度评测:国产大模型如何突破算力桎梏,在多模态赛道站稳脚跟?

    核心结论: 文心一言5.0正式版在预览版基础上进行了针对性打磨,整体可用性有所提升,在国产大模型中站稳了第二梯队的位置。其核心优势在于长链推理、多轮对话的稳定性,但算力消耗与上下文幻觉问题仍是主要挑战。 逻辑能力表现:注1:表格为突出对比关系,仅展示部分可对照模型,非完整排序。注2:题目及测试方式,参见《大语言模型逻辑能力横评(25年12月榜)》,新增#55…

    2026年1月23日
    5300