当前位置:   article > 正文

浅析优化文本提示技术 —— TextGrad

textgrad

引言

大模型领域,现在除了不断推出各种底层大模型外,还涌现了许多包含复杂组件的复合系统,包括框架、工具等。

TextGrad VS DSPy

先来从大的概念范围看看 TextGrad 与 DSPy 的对比:

  • TextGrad:

(1)将 LLM 文本反馈“反向传播”到各组件中,无需手动调整,实现优化复合系统;

(2)在实际的各种任务中,它具备多功能性,包括:问答场景、分子优化和治疗计划等;

(3)TextGrad 可显著提升性能,例如使用 GPT-4o 在 Google-Proof 问答任务中零样本准确率从51%提高到55%。

(4)TextGrad 通过提供自然语言梯度增强可解释性;

  • DSPy:

(1)引入一种编程模型,用于将语言模型管道抽象为文本转换,同时自动优化这些管道,以最大化实现响应目标。

(2)DSPy 把 LM 调用表示为参数化模块,使用编译器优化这些模块组合,实现LM管道的系统化开发和优化。

(3)DSPy在数学文字题等任务上有超过25%和65%的性能提升。

(4)DSPy 用较小的LM(如T5和Llama2)可实现与专家编写的提示链或专有LM系统相媲美的性能。

核心组件

TextGrad 遵循 PyTorch 语法,好处就是灵活且易于使用。

PyTorch 框架把智能系统视为计算图,其中变量是复杂函数调用的输入和输出。这个框架下,LLM 提供丰富、通用的自然语言提示,优化这些计算图变量,从代码片段到分子结构。TextGrad “反向传播” LLM 提供的文本反馈,从而改进各个组件。

TextGrad 关键组件包括:

  • 变量:计算图节点,包含非结构化数据(如文本)。

  • 函数:变量转换(如LLM调用、模拟器)。

  • 梯度:LLM 自然语言反馈,描述如何修改变量。

  • 文本梯度下降(TGD):一种优化器,基于当前值和文本梯度更新变量。

TextGrad 使用链式法则构建计算图,类似于传统的自动微分算法,用语言模型提供的自然语言反馈代替了数值梯度,这是最核心的贡献。

在“梯度下降”优化过程中,“梯度”生成、“校正量”添加、以及损失函数的计算,都变成了对语言模型的调用。

这种新颖的方法利用语言模型提供表达能力来指导优化过程。

应用示例

TextGrad 在不同的场景应用下都具备通用性,比如:

  1. TextGrad 通过优化代码片段,提高处理难题的能力。
  2. TextGrad 通过优化问题解决方案,提高了LLM解决复杂任务(如科学问题)能力。
  3. TextGrad 通过优化提示,提高大模型推理能力,并能提升性能。
  4. TextGrad 通过优化化学结构设计,体现其在药物研发中潜力。
  5. TextGrad 通过优化治疗计划,改进患者的治疗效果。

TextGrad 关键应用是解决方案优化,目标是改进复杂问题的解决方案,优化过程涉及一个计算图,其中解决方案是要优化的参数,损失函数是通过使用 LLM 评估得到的。

在每次迭代中,LLM 会提示当前问题、当前解决方案和需要评估或调查当前迭代的测试指令,这个过程会在优化过程中逐渐改进解决方案。

举例,以下是使用 TextGrad 进行解决方案优化的示例实现:

!pip install TextGrad # 可能需要在安装TextGrad后重新启动笔记本
import argparse
import concurrent
from dotenv import load_dotenv
from tqdm import tqdm
import TextGrad as tg
from TextGrad.tasks import load_task
import numpy as np
import random
load_dotenv(override=True)

# 如果使用Colab
from google.colab import userdata
OPENAI_API_KEY = userdata.get('OPENAI_API_KEY')
os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY

def set_seed(seed):
    np.random.seed(seed)
    random.seed(seed)

def eval_sample(item, eval_fn, model):
    """
    该函数允许我们评估答案是否是对提示问题的好答案。
    """
    x, y = item
    x = tg.Variable(x, requires_grad=False, role_description="查询语言模型")
    y = tg.Variable(y, requires_grad=False, role_description="查询的正确答案")
    response = model(x)
    try:
        eval_output_variable = eval_fn(inputs=dict(prediction=response, ground_truth_answer=y))
        return int(eval_output_variable.value)
    except:
        eval_output_variable = eval_fn([x, y, response])
        eval_output_parsed = eval_fn.parse_output(eval_output_variable)
        return int(eval_output_parsed)

def eval_dataset(test_set, eval_fn, model, max_samples: int=None):
    if max_samples is None:
        max_samples = len(test_set)
    accuracy_list = []
    with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
        futures = []
        for _, sample in enumerate(test_set):
            future = executor.submit(eval_sample, sample, eval_fn, model)
            futures.append(future)
            if len(futures) >= max_samples:
                break
        tqdm_loader = tqdm(concurrent.futures.as_completed(futures), total=len(futures), position=0)
        for future in tqdm_loader:
            acc_item = future.result()
            accuracy_list.append(acc_item)
            tqdm_loader.set_description(f"准确率: {np.mean(accuracy_list)}")
    return accuracy_list

def run_validation_revert(system_prompt: tg.Variable, results, model, eval_fn, val_set):
    val_performance = np.mean(eval_dataset(val_set, eval_fn, model))
    previous_performance = np.mean(results["validation_acc"][-1])
    print("验证性能: ", val_performance)
    print("之前的性能: ", previous_performance)
    previous_prompt = results["prompt"][-1]

    if val_performance < previous_performance:
        print(f"拒绝的提示: {system_prompt.value}")
        system_prompt.set_value(previous_prompt)
        val_performance = previous_performance

    results["validation_acc"].append(val_performance)

set_seed(12)
llm_api_eval = tg.get_engine(engine_name="gpt-4o")
llm_api_test = tg.get_engine(engine_name="gpt-3.5-turbo-0125")
tg.set_backward_engine(llm_api_eval, override=True)

# 加载数据和评估函数
train_set, val_set, test_set, eval_fn = load_task("BBH_object_counting", evaluation_api=llm_api_eval)
print("训练/验证/测试集长度: ", len(train_set), len(val_set), len(test_set))
STARTING_SYSTEM_PROMPT = train_set.get_task_description()

train_loader = tg.tasks.DataLoader(train_set, batch_size=3, shuffle=True)

# 测试评估引擎的0样本性能
system_prompt = tg.Variable(STARTING_SYSTEM_PROMPT,
                            requires_grad=True,
                            role_description="系统提示语言模型")
model_evaluation = tg.BlackboxLLM(llm_api_eval, system_prompt)

system_prompt = tg.Variable(STARTING_SYSTEM_PROMPT,
                            requires_grad=True,
                            role_description="结构化系统提示,针对QA任务指定行为和策略的有一定能力的语言模型")
model = tg.BlackboxLLM(llm_api_test, system_prompt)

# 文本梯度下降优化器初始化评估模型的API和要优化的系统提示参数。
optimizer = tg.TextualGradientDescent(engine=llm_api_eval, parameters=[system_prompt])

results = {"test_acc": [], "prompt": [], "validation_acc": []}
results["test_acc"].append(eval_dataset(test_set, eval_fn, model))
results["validation_acc"].append(eval_dataset(val_set, eval_fn, model))
results["prompt"].append(system_prompt.get_value())

for epoch in range(3):
    for steps, (batch_x, batch_y) in enumerate((pbar := tqdm(train_loader, position=0))):
       

 pbar.set_description(f"训练步骤 {steps}. 轮次 {epoch}")
        optimizer.zero_grad()
        losses = []
        for (x, y) in zip(batch_x, batch_y):
            x = tg.Variable(x, requires_grad=False, role_description="查询语言模型")
            y = tg.Variable(y, requires_grad=False, role_description="查询的正确答案")
            response = model(x)
            try:
                eval_output_variable = eval_fn(inputs=dict(prediction=response, ground_truth_answer=y))
            except:
                eval_output_variable = eval_fn([x, y, response])
            losses.append(eval_output_variable)
        total_loss = tg.sum(losses)
        total_loss.backward()
        optimizer.step()

        run_validation_revert(system_prompt, results, model, eval_fn, val_set)

        print("系统提示: ", system_prompt)
        test_acc = eval_dataset(test_set, eval_fn, model)
        results["test_acc"].append(test_acc)
        results["prompt"].append(system_prompt.get_value())
        if steps == 3:
            break

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128

上述代码演示了如何使用 TextGrad 库对语言模型的系统提示进行基于梯度的优化,从而提高在特定问答任务上的性能。

TextGrad 库简化了将梯度应用于提示并评估模型性能的过程。

据研究表明,通过在测试时使用 TextGrad 进行自我优化,可明显提升大模型的问答能力。

小结

TextGrad 是一种通过文本反馈反向传播优化大模型系统的新范式,DSPy 则专注于通过参数化模块和编译器优化实现LM管道的系统化开发和优化。

随着开发人员继续探索 TextGrad 和其他创新框架的能力,我们可以期待在人工智能系统优化方面看到更多突破性的进展~~

如何系统的去学习大模型LLM ?

作为一名热心肠的互联网老兵,我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。

但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将并将重要的 AI大模型资料 包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/喵喵爱编程/article/detail/866018
推荐阅读
相关标签