NEW暗黑模式现已上线 🌓 Label Studio 1.18.0 版本发布

构建数据标注智能体

指南

简介

当前人工智能领域的大部分讨论都围绕着GPT-4等大型语言模型(LLMs)及其彻底改变各行各业的潜力。这些LLMs因能生成类人文本而备受赞誉,其卓越表现源于精妙的算法设计以及严格的人工数据整理与标注工作,这凸显了人类专业知识与AI效能之间共生共荣的关系。

为什么这很重要?因为我们越来越依赖这些AI模型。它们不再局限于执行基础任务,而是积极参与决策制定、提供关键信息,并常常成为我们最初的交互入口。将LLMs集成到数据标注工作流中,不仅关乎任务自动化,更重要的是通过AI的高效性来增强人类专业知识。

几周前,我们开始讨论智能体在数据标注中的关键作用。现在,我们将进一步深入探讨如何利用LLM和智能体来变革这一流程,旨在实现数据标注更高的效率、准确性和可扩展性。

LLM作为初始标签预测器

旅程始于利用LLMs进行初始标签预测。模型接收原始数据并生成第一轮标签,这些标签作为基础而非最终结论。此时领域专家(SMEs)的关键作用显现:他们评估这些初步标签,确认准确的部分并修正那些存在偏差的标签。

有什么好处?它能显著加快标注流程。有了初步分析结果在手,标注人员无需面对从零开始的艰巨任务。这种方法节省了时间,减轻了认知负担,通过减少标注疲劳可能提升整体标注质量。

考虑一个场景,我们需要将文本样本分类为"主观"或"客观"。

PortableText [components.type] 缺少 "table" 组件
| index | text                       | label |
|-------|----------------------------|-------|
| 0     | So there is no way for     |     0 |
|       | me to plug it in here in   |       |
|       | the US unless I go by a    |       |
|       | converter.                 |       |
| 1     | "Good case, Excellent      |     1 |
|       | value."                    |       |
| 2     | Great for the jawbone.     |     1 |
| 3     | Tied to charger for        |       |
|       | conversations lasting more |       |
|       | than 45 minutes.           |       |
|       | MAJOR PROBLEMS!!           |     0 |
| 4     | The mic is great.          |     1 |

通过利用OpenAI API,我们可以用几行代码快速为每个实例生成预测结果。

prefix = '''\
Classify the text based on whether it presents an objective fact or a subjective opinion.'''


inputs = df.text.apply(lambda text: f'{prefix}\nInput:{text}\Output:\n').tolist()
completions = []
step = 20
for i in range(0, len(inputs), step):
  result = openai.Completion.create(
    model="gpt-3.5-turbo-instruct",
    prompt=inputs[i:i+step]
  )
  completions.extend(c['text'] for c in result['choices'])

然而,这种方法并非没有缺陷。完全依赖LLM以您期望的形式提供预测可能像一场赌博。LLM预测的质量在不同任务中并不一致,对于复杂或微妙的数据尤其如此。如果我们查看简单的主客观分类任务的结果,就会发现输出结果存在相当大的差异。

{'\nObjective fact', '\nObjective fact.', '\nOpinion', '\nSubjective Opinion', '\nSubjective opinion', '\nSubjective opinion ', '\nSubjective opinion.', '\nsubjective opinion', ' \nSubjective opinion', 'Objective Fact', 'Objective fact', 'Objective fact ', 'Objective fact.', 'Subjective Opinion', 'Subjective opinion', 'Subjective opinion. ', 'This text presents a subjective opinion.', 'objective fact'}

对此我们能做些什么?每次与大型语言模型的交互都始于提示词。这个提示词本质上就是你给模型的指令或问题。人们很容易忽视它的重要性,但提示词对你获得的响应类型起着至关重要的作用。精心设计的提示词可能意味着大型语言模型生成有用预测与给出完全错误回答之间的天壤之别。

在本例中,我们目前获得了期望响应的不同变体。我们可以调整提示词来标准化输出格式。具体而言,我们将使用guidance库来指定请求格式,并整合logprobs以评估预测不确定性。我们将在后续章节深入探讨提示词调整。

guidance.llm = guidance.llms.OpenAI("gpt-3.5-turbo-instruct")
labeler = guidance('''\
Classify the text based on whether it presents an objective fact or a subjective opinion.
Input: {{input}}
Output: {{select 'prediction' options=['Objective', 'Subjective'] logprobs='logprobs'}}''')


result = labeler(input=df.text[0])
result['prediction'], result['logprobs']
Classify the text based on whether it presents an objective fact or a subjective opinion.

Input: So there is no way for me to plug it in here in the US unless I go by a converter.

Output: Subjective

('Subjective', {'Objective': -2.694936, 'Subjective': -0.06993622000000005})

我们可以看到,通过修改提示词,我们可以依赖标准化的输出格式来提供结构化标签。

人在回路的数据标注

最终,我们的主要目标是开发能够熟练解决复杂现实问题的高级人工智能应用。为实现这一目标,我们需要将人类智能与AI能力相结合,确保我们创建的系统高效、具备情境感知能力且可靠。

尽管人工智能系统,尤其是大语言模型(LLMs),能够以惊人的规模和速度处理数据,但它们可能缺乏人类固有的细致理解和批判性判断能力。通过在数据标注过程中引入人类专业知识,我们为数据注入了AI无法可靠复制的关键上下文、质量和相关性特征。这种人机协同模式将数据集从单纯的信息提升为具有细致理解能力的知识。

构建基准真实数据集

在LLM模型预测之后,下一个关键阶段是构建"基准真值"数据集。基准真值数据集由经过人类专家严格审查和验证的数据样本组成。它们作为评估新数据的标准,也是机器学习模型训练和优化的基础。建立这样的数据集能确保我们的AI系统建立在经过验证的可靠数据基础之上。

由于我们在上一节中标准化了格式,因此可以轻松将预测结果导入Label Studio等工具,该工具为标注人员提供了一个简化的界面来查看预测并修改标签。在审查并修正这些预测后,我们现在就拥有了一个可靠的基准真实数据集。

评估预测器质量

Once a ground truth dataset is in place, we must assess the initial predictions made by the LLMs. This evaluation is crucial in determining the current accuracy of our AI models and identifying areas where they can be improved. By understanding the strengths and weaknesses of the LLM predictions, we can fine-tune our prompts to improve the predictor's quality.

在Label Studio中完成数据标注后,我们可以创建分类报告来分析LLM预测的表现情况。

from sklearn.metrics import classification_report


labeled_tasks = project.get_labeled_tasks()


test_set = []
for task in labeled_tasks:
  text = task['data']['text']
  prediction = task['data']['prediction']
  ground_truth = task['annotations'][0]['result'][0]['value']['choices'][0]
  test_set.append({'text': text, 'ground_truth': ground_truth, 'prediction': prediction})


test_set = pd.DataFrame.from_records(test_set)
print(classification_report(test_set.ground_truth, test_set.prediction))

这将为我们生成以下报告。

PortableText [components.type] 缺少 "table" 组件
|            | precision | recall | f1-score | support |
|------------|-----------|--------|----------|---------|
|Objective   |      0.86 |   0.75 |     0.80 |       8 |
|Subjective  |      0.67 |   0.80 |     0.73 |       5 |
|accuracy    |           |        |     0.77 |      13 |
|macro avg   |      0.76 |   0.78 |     0.76 |      13 |
|weighted avg|      0.78 |   0.77 |     0.77 |      13 |

运行后可以看到,我们的LLM预测器在初始小样本集上达到了77%的准确率——这是个不错的开端,但仍有提升空间。

手动提示优化

深入探讨LLM在数据标注中的机制时,我们会遇到提示工程(prompt engineering)这一概念——这是显著影响LLM预测质量的关键要素。我们已经进行了一些提示工程调整,使其提供一致的输出格式,现在让我们更深入地研究。

提示的力量

每次与大型语言模型(LLM)的交互都始于提示词。这是您向模型提出的指令或问题。提示词的表述方式会显著影响您获得的响应。

提示工程涉及精心设计和持续优化这些提示。这不仅关乎提出正确的问题,更在于以模型能够理解并有效回应的方式提问。这可能包括为大型语言模型提供清晰简洁的指令或具体示例,以引导其思考过程。

少样本提示

Here's where few-shot prompting comes into play. This technique involves providing the LLM with a handful of labeled examples to improve the quality of its output. We're essentially equipping the model with additional context, specifically in areas where it has previously faltered or shown a lack of understanding.


但为什么少量示例提示会有效呢?这归结于像GPT-4这样的大语言模型的训练方式。它们通过海量文本数据进行训练,识别不同信息片段之间的模式、结构和关联。当我们使用少量示例提示时,实际上是在利用模型的基础训练成果——通过提供与其已学习模式相匹配的具体示例。这些示例有助于明确我们的预期,并为正确答案或输出创建一条"最小阻力路径"。

通过向模型展示我们的需求,我们帮助它更准确地运用其已有的知识。这就像提醒一位专家他们过去完成的与您当前问题类似的工作;有了这个提示,他们就能更容易地运用技能和知识来满足您的需求。这就是少量样本提示如何提升大语言模型的性能,使其成为提示工程中的强大工具。

error_examples = test_set[test_set.ground_truth != test_set.prediction]


prompt = '''\
Classify the text based on whether it presents an objective fact or a subjective opinion.
{{~#each examples}}
Input: {{this.text}}
Output: {{this.ground_truth}}
{{~/each}}
Input: {{input}}
Output: {{select 'prediction' options=['Objective', 'Subjective'] logprobs='logprobs'}}'''
labeler = guidance(prompt)


examples = error_examples.to_dict(orient='records')
result = labeler(input=df.text[0], examples=examples[1:4])

这将生成以下输出。

Classify the text based on whether it presents an objective fact or a subjective opinion.

Input: A usable keyboard actually turns a PDA into a real-world useful machine instead of just a neat gadget.

Output: Objective

Input: Nice docking station for home or work.

Output: Subjective

Input: So there is no way for me to plug it in here in the US unless I go by a converter.

Output: Objective

小样本提示通过提供期望输出的明确示例来引导模型,帮助其理解我们寻求的上下文或特定响应模式。然而,随之出现的一个问题是可能产生过拟合。模型可能会过度贴合提示中的示例,从而限制其有效泛化到新未见示例的响应能力。本质上,它可能对与提供示例非常相似的场景给出准确响应,但在遇到稍有不同情况或细微差别时可能会出错。这种对示例的过度依赖可能导致模型生成上下文不恰当或事实错误的预测,特别是当提供的示例未涵盖足够广泛的可能性范围时。

这正是思维链提示等技术发挥作用的地方。

思维链

Chain-of-Thoughts 提示方法通过要求模型解释其生成答案背后的推理过程,扩展了少样本提示的范畴。这一额外步骤迫使模型形成一种通向结论的"逻辑路径",我们可以据此评估其有效性。

通过要求模型为其答案提供理由,我们可以实现几个目标。首先,这提供了一个机会来发现并纠正模型可能不加质疑地传播的潜在偏见或逻辑谬误。其次,它让用户能够理解模型回答的依据,从而增强对AI生成内容的信任。最后,它能进一步推动模型的能力,鼓励其超越简单的模式匹配(这种匹配可能源于对初始示例的过拟合),形成更细致的理解和回答生成。

通过这种方式,思维链提示(Chain-of-Thoughts prompting)与少样本学习形成互补。它要求模型进行更深层次、更具解释性的推理,从而有助于降低过拟合的部分风险,提升大语言模型预测的可靠性和质量。

labeler = guidance('''\
Classify the text based on whether it presents an objective fact or a subjective opinion.
Describe your reasoning step-by-step.
Input: {{input}}
Reasoning: {{gen 'reasoning'}}
Output: {{select 'prediction' options=['Objective', 'Subjective'] logprobs='logprobs'}}''')


result = labeler(input=df.text[0])
result['logprobs']

这将生成以下输出。

Classify the text based on whether it presents an objective fact or a subjective opinion.

Describe your reasoning step-by-step.

Input: So there is no way for me to plug it in here in the US unless I go by a converter.

Reasoning:

The text presents an objective fact. This is because it states a specific situation and limitation, without expressing any personal feelings or beliefs. The use of words like "no way" and "unless" indicate a factual statement rather than an opinion. Additionally, the mention of a converter suggests a practical solution to the problem, rather than a subjective preference.

Output: Objective

{'Objective': -4.123248299946159e-06, 'Subjective': -12.375005}

提示修改的可能性是无限的,这为我们提高预测质量提供了巨大潜力。现在让我们转向自动化提示改进方法。

自动化提示词优化

目前,大部分提示工程仍是一个手动过程。它涉及大量试错:给大语言模型一个提示,检查其预测结果,调整提示内容,然后重复这一过程直到预测质量提升。虽然有效,但这种迭代过程可能耗费大量人力和时间。

此外,这需要深入理解大型语言模型(LLMs)如何处理信息。您需要预判提示词中哪些方面可能会让模型产生困惑,并知道如何调整语言或添加适当的上下文以获得期望的响应。那么,我们该如何简化这个提示调优过程呢?

如果你读过我们之前关于智能体的博客,可能已经猜到我们要讨论什么。智能体让我们能够利用LLM通过迭代来解决问题。在我们的案例中,我们希望为LLM生成一组优化后的指令,使其在基准真值集上获得最佳评分。

我们可以将这一过程系统化为三个步骤:标注、评估和调整。完整代码请参阅我们的notebook

标签

标签步骤是我们目前最常使用的环节。这是用于预测我们数据的智能体。我们一直在调整和优化标注指令,以便为模型提供更准确的预测。

def label(df, instruction):
  df[['prediction', 'logprob']] = df.progress_apply(label_row, axis=1, result_type='expand', instruction=instruction)
  return df

评估

评估步骤用于计算并比较最新预测结果与真实标注的准确性,同时返回存在问题的样本。随后我们可以根据需要利用这些有问题的样本来更新标注阶段的提示词。这可以被视为在智能体框架中评估预测质量的一个工具。

def eval_instructions(df, candidate_instructions):
  result = []
  for candidate_instruction in candidate_instructions:
    print(candidate_instruction)
    df_pred = label(df.copy(), candidate_instruction)
    accuracy = (df_pred['prediction'] == df_pred['ground_truth']).mean()
    result.append({
        'instruction': candidate_instruction,
        'accuracy': accuracy,
        'errors': df_pred[df_pred['prediction'] != df_pred['ground_truth']]
    })


  return sorted(result, key=lambda x: x['accuracy'], reverse=True)

适配

将所有环节整合在一起的是Adapt阶段。该函数接收Evaluate阶段计算出的错误列表和准确率分数,并利用LLM来修订针对LLM的指令。

def adapt(current_instruction, errors):
  num_samples = min(3, errors.shape[0])
  errors_list = errors.sample(n=num_samples).apply(lambda r: f'INPUT: {r.text}\nPREDICTED OUTPUT: {r.prediction}\nEXPECTED OUTPUT: {r.ground_truth}\n', axis=1)
  errors_str = "\n".join(errors_list.tolist())
  response = openai.ChatCompletion.create(
    model="gpt-4",
    messages=[
{"role": "system", "content": '''\
Act as an 'Instruction Tuner' for the LLM. You will be given the inputs:


- The [CURRENT INSTRUCTION] used to guide the LLM's classification, including specific examples with ground truth labels.
- [CURRENT ERRORS] that emerged when this instruction was applied to a dataset.


The current errors are presented in the following format:
INPUT: [input text]
PREDICTED OUTPUT: [predicted label]
EXPECTED OUTPUT: [ground truth label]


Carefully analyze these errors and craft a revised concise instruction for the LLM to fit the expected outputs. \
Include 2-3 examples at the end of your response to demonstrate how the new instruction would be applied. \
Use the following format for your examples:


Input: [input text]
Output: [expected output label]


Use specific error examples and generalize them to address any observed errors that may occur in the future.
Deliver your response as the refined instruction.'''},
{'role': 'user', 'content': f'''\
CURRENT INSTRUCTION: {current_instruction}
CURRENT ERRORS:


{errors_str}


New refined instruction:
'''}])


  new_instruction = response['choices'][0]['message']['content']
  return new_instruction

可以看到,我们精心设计的提示词承担了大部分繁重工作。这个LLM查询的任务是生成用于更新Label阶段提示词的指令。

创建我们的标注智能体的最后一步是迭代这些步骤。我们可以通过最后一个函数将所有内容整合在一起。

def optimize_instructions(df, initial_instruction, max_iterations=3, max_instructions=3):
  candidate_instructions = [initial_instruction]
  for iteration in range(max_iterations):
    results = eval_instructions(df, candidate_instructions)
    print(f'\nResults for the iteration #{iteration}:')
    display(pd.DataFrame.from_records([{'instruction': r['instruction'], 'accuracy': r['accuracy']} for r in results]))


    best_instruction = results[0]
    errors = best_instruction['errors']
    if errors.empty or iteration == max_iterations - 1:
        return best_instruction['instruction']


    print('Adapting the best instruction...')
    refined_instruction = adapt(best_instruction['instruction'], best_instruction['errors'])
    candidate_instructions.insert(0, refined_instruction)
    candidate_instructions = candidate_instructions[:max_instructions]


  return refined_instruction

当我们运行这个函数时,将看到智能体开始工作,优化我们的提示并评估标注器的结果。经过几轮迭代后,我们可以查看为标注步骤提供的优化指令。

Please classify the following sentences as being 'Objective' or 'Subjective'. An 'Objective' statement is based on verifiable facts with no influence of personal emotions, opinions or interpretations. On the other hand, 'Subjective' sentences reflect personal judgement, feelings, or perspectives. 

Additionally, objective sentences can sometimes reference individuals or groups of people, as long as the statement doesn't reflect a personal perspective, sentiment, or judgment. For example, "People couldn't hear me talk", though it references a personal experience, should be categorized as 'Objective' because it's a factual statement not influenced by emotions or personal bias. 

At the same time, be aware that a sentence could start or even seem objective but ends up being subjective because it carries an opinion, evaluation, or judgement. For instance, sentences beginning with "This device is great" followed by personal favorites, preferences or the likes are inherently subjective.

Here are few examples to illustrate the above points:

1.) 
Input: A usable keyboard actually turns a PDA into a real-world useful machine instead of just a neat gadget.
Output: Objective 

2.) 
Input: People couldn't hear me talk and I had to pull out the earphone and talk on the phone.
Output: Objective 

3.) 
Input: This device is great in several situations.
Output: Subjective

最终,我们的智能体将预测器的准确率提升到了92%——相比最初的77%有了显著提升。

结论

基于智能体的标注代表了机器学习领域的一大飞跃。通过实施一个动态、迭代的流程,结合人类专业知识和AI能力的优势,我们不仅简化了数据标注流程,还显著提升了为AI模型提供动力的数据的准确性和可靠性。

Label Studio在生态系统中促进了这种平衡。其用户友好的界面和灵活的功能使专业人士能够深入贡献,同时高效自动化重复性任务。这种方法确保我们有效利用自动化,而不会掩盖人类专业知识提供的不可替代的洞察力。

大型语言模型(LLMs)在数据标注领域的未来不仅取决于先进模型的发展,更在于促进人类与AI之间更好的协作,这正是Label Studio致力于实现的目标。

请务必查看我们的notebook以获取此处提供的所有示例的完整代码。

相关内容

  • 每个人都在(无意中)作弊

    AI基准测试正在悄然失效。研究表明,数据泄露、排行榜操纵和激励错配正在夸大模型性能。本文探讨了改革的四大支柱:治理、透明度、广谱指标和监督,并概述了企业如何通过集中式基准管理平台建立信任。

    尼古拉·柳比莫夫

    2025年5月13日

  • 提升标注质量和速度的3种标注团队操作手册

    每个机器学习团队都不尽相同,您的标注工作流程也应如此。本指南将解析三种常见的标注团队配置方案,以及如何定制您的工具和流程来提升质量、速度和规模。

    Alec Harris

    2025年5月7日

  • 您的RAG系统可能失败的七种情况及解决方法

    RAG系统承诺提供更准确的人工智能响应,但由于检索错误、幻觉和不完整答案等问题,它们往往表现不佳。本文探讨了七种常见的RAG系统故障——从遗漏排名靠前的文档到格式错误——并提供了实用解决方案来提高检索准确性、排序质量和响应质量。了解如何优化您的RAG系统,确保其提供可靠、具备上下文感知能力的人工智能响应

    米凯拉·卡普兰

    2025年3月19日