微调 LLM 以构建任务型对话 Agent

为什么?

在对话系统的设计和实现中,传统的基于 Rasa-like 框架的方法往往需要依赖于多个模块的紧密协作,例如我们在之前的文章中提到的基于大模型(LLM)构建的任务型对话 Agent,Thought Agent,其由自然语言理解(NLU)、对话管理(DM)和对话策略(DP)等模块共同协作组成。这种模块化的设计虽然在理论上具有灵活性,但在实践中却带来了诸多挑战,尤其是在系统集成、错误传播、维护更新以及开发门槛等方面。为了克服这些挑战,构建一个端到端(E2E)的模型显得尤为关键。E2E 的模型通过将对话的各个阶段集成到一个统一的框架中,极大地简化了系统架构,提高了处理效率,并减少了错误传递的可能性。此外,由于其简化的架构,也更易于维护和更新,从而降低了开发和维护的成本。在我们看来,端到端的对话 Agent 不仅在技术上更具优势,而且在实际应用中也展现了其独特的价值和潜力,例如能够快速构建帮助用户查询信息、调度技能的 Agent。

本文将指导读者如何采用蒙特卡洛方法(Monte Carlo)模拟用户行为并结合 LLM 的方法来构建训练数据集;使用 LLaMA Factory 对多种 LLM 进行高效微调构建任务型对话 Agent。该方案允许用户快速创建出能够精准调用外部工具的 Agent。

挑战

任务型对话系统的核心需求包括意图识别、槽位填充、状态管理和策略决策。我们识别了以下几个关键挑战:

  • 微调后的 LLM 能够从用户的问题中识别到用户意图和关键信息(槽位)
  • 微调后的 LLM 能够对用户的问题有判断边界的能力,容易混淆的内容将触发意图确认,完全无关的内容将触发兜底话术
  • 微调后的 LLM 能够根据槽位填充状态判断合适的触发功能调用(Function calling)的时机
  • 微调后的 LLM 能够对根据上下文正确的识别到需要用于调用功能的关键信息

构造数据集

为了应对上述挑战,首先我们需要构造能够覆盖大部分场景的对话数据集,我们面临的核心难点是如何模拟真实世界中用户的多样化行为和对话系统的有效响应。但是对于任务型对话 Agent 来说,用户和 Agent 之间的对话域是有限的,因为 Agent 只需要处理业务范围内的用户意图,超出处理范围的内容,只需要返回一些固定的兜底话术即可。因此我们可以采用了状态图对对话的过程进行建模,使用蒙特卡洛方法对真实的对话过程进行模拟,接着使用 LLM 的生成能力来创建符合状态、角色定义的对话内容从而达到构建数据集的目的。

基于图的对话流程图的建模

我们使用有向图(Directed Graph)的数据结构来对通用的任务型对话流程进行建模,这比传统的有限状态机更加灵活和通用。在构建对话流程图时,我们首先定义了一组节点,每个节点代表了对话中的一个关键状态。例如,一个理想的对话过程至少包含以下节点:

  • Start: 对话开始
  • IntentAcquire: Agent 询问用户意图
  • UserInquiry: 用户发起新的提问
  • IntentConfirm: Agent 向用户确认意图 (用户意图不明确时)
  • UserConfirm: 用户确认意图
  • UserDeny: 用户否认意图
  • AskSlot: 追问用户关于该意图的关键信息(槽位)
  • ProvideSlot: 用户提供或更新关键信息(槽位)
  • FunctionCalling: 调用功能,传递槽位信息
  • Chitchat: 用户闲聊
  • End: 对话结束

在定义了节点之后,我们使用边将可以进行状态转移的节点连接起来,从而构建一个有向图用来表征对话过程中所有可能的转移关系,如下图。在这个图中,主要的变量是用户对话内容,Agent 的回复内容是随着用户的对话意图和槽位状态发生的变化而变化。 对于每个原子对话(Atomic Dialogue)来说,我们认为在用户提供了清晰的意图以及提供了全部的必填槽位信息之后,这个原子对话就算结束了,即可以触发 Function calling 的指令。

对话流程转移图示例(可能没有覆盖全部场景)

图 1. 对话流程转移图示例(可能没有覆盖全部场景)

初始状态随机生成

在对话系统的开始阶段,用户的首次提问可能包含从零到全部所需槽位的不同信息量。为了模拟这种多样性,我们可以使用蒙特卡洛方法来随机决定哪些槽位在用户的首次提问中被提及。具体来说,对于一个意图中的所有槽位,我们可以生成一个由 0 或 1 组成的随机数组,其中 0 表示该槽位不能再首次提问中提及,而 1 表示需要被提及。

例如,考虑一个酒店预订任务,可能的关键信息包括「入住日期」、「退房日期」 和 「房间类型」。利用上述的方法,我们可以为每个槽位生成一个对应的随机值,从而决定用户的首次提问中需要包含哪些信息。这不仅增加了对话样本的多样性,也使得训练数据集更加贴近真实世界的对话情况。

随机游走模拟用户行为

初始状态生成了之后,我们需要生成生成多样化的对话路径,这里采用蒙特卡洛方法使得当前的对话状态在建立好的对话转移状态图中随机游走。在每个状态完成之后,将随机选择下一个状态,各状态的转移概率可以根据经验进行定义,从而模拟用户可能采取的不同行动。例如,用户在首问中没有提供全部的必填槽位, Agent 将发起槽位的追问,对于 Agent 的追问,用户可能认真的回答槽位信息,也有可能发起闲聊,还有可能改变了主意,问了一个新的问题,不同的转移路径我们可以设置不同的概率,例如上面的转移路径我们根据经验分为设置概率为 [0.8, 0.1, 0.1]。通过这种随机游走的方式,可以生成不同的对话状态路径,每条路径都代表了一种可能的用户行为和 Agent 响应。这些路径为我们提供了丰富的训练数据,帮助对话系统学习如何处理各种情况。

对上下文理解能力的增强

在实际对话中,用户通常不会在每个回合都重复提供所有相关信息。相反,他们会根据上下文,利用代词、省略或简化的表述来替代之前已经提及过的内容。为了让对话系统能够正确理解这种上下文依赖的表达方式,我们需要在训练数据中模拟这种用户行为模式。

具体来说,我们将对话分为多个阶段,每个阶段对应不同的任务意图。在后续阶段生成语料时,我们会考虑之前阶段已经提供的槽位信息。如果用户的新问题与之前的问题存在槽位重叠,且该槽位已在先前回合中提供过,那么在生成新问题时,我们将有意识地省略这部分信息,只保留用户需要补充的新信息。

例如,假设用户之前已经询问过「成都市内哪家火锅好吃」,这句话中包含了用户想要了解的位置和餐厅类型两个槽位信息。在后续对话中,如果用户想询问这些餐馆的价格区间,可能会使用「它们的价格大概是多少?」这样的省略式表述,而非重复提供完整的问句。通过模拟这种情况,我们可以增强模型对于上下文依赖的理解能力。

基于 LLM 的对话内容生成

LLM 在这一过程中扮演了至关重要的角色。我们利用 LLM 的强大生成能力来模拟用户的提问和系统的追问,生成接近真实对话的数据。例如,以推荐餐厅这个意图为例, 用于生成首问的 Prompt 可以这样写,

你是一个用户,你现在想要「根据自己的位置、兴趣和预算,让智能客服推荐当地的餐厅」,请向智能客服寻求帮助
你的问题需要满足以下几个条件
1. 在问题中需要提到具体的用户当前的区域或希望探索的区域。
2. 在问题中一定不要提到具体的用户感兴趣的餐厅类型,中餐,日料,西餐等。
3. 在问题中一定不要提到具体的用户的最大预算。
请生成一句满足当前的场景和设定的问题

LLM 广阔的知识面为我们提供了丰富的语言资源,支持我们模拟各种场景的对话。此外,LLM 还能够根据上下文生成连贯且逻辑性强的回复,进一步提高了数据集的质量。

**通过 RAG 增强生成对话的质量和多样性,**在任务型对话 Agent 中,尤其是当涉及到特定业务功能开通的意图时,领域知识会显得十分重要。为了在用户问题中融入这些领域知识,同时保持问题的多样性,我们可以利用 RAG 技术将领域知识附加到 LLM 中。首先,我们构建一个包含所有业务功能的槽位列表,这些功能可能包括各种服务、产品特性或用户可能感兴趣的特定操作。接着,通过随机化的方法,从这个槽位列表中选择一个或多个功能,这一步确保了每次生成的问题都可能关注不同的业务点,增加了对话的多样性。然后,我们设计一个 RAG 模板,这个模板预留了位置来插入特定的业务功能信息。接下来,我们将随机选中的业务功能信息填充到模板中,生成具体的用户问题。

易扩展的意图配置

对于任务型 Agent 来说,对话的目标是一致,即收集足够的信息帮助用户执行任务。我们可以通过一个 YAML 文件来对任务的详细内容和槽位信息进行描述,用户意图增加和减少都可以通过编辑一系列 YAML 配置文件来实现,而无需对有状态转移图或生成流程进行复杂的更改。这种设计提高了本文方案的可扩展性。例如想生成一个根据地点,餐厅类型,最大预算推荐餐厅任务相关的数据集,只需要编写如下配置文件即可:

name: recommend_restaurant 
description: 根据自己的位置、兴趣和预算,让智能客服推荐当地的餐厅
parameters:
  - name: destination
    description: 用户当前的区域或希望探索的区域。
    type: text 
    required: True
  - name: cuisine_type
    description: 用户感兴趣的餐厅类型,中餐,日料,西餐等 
    type: text 
    required: True
  - name: budget
    description: 用户的最大预算
    type: float 
    required: False

目标为任务型对话 Agent 的 LLM 微调

我们选择 LLaMA Factory 作为我们的微调工具,这是一个开源的高效微调框架,专为 LLMs 设计,能够适应各种下游任务,并且兼容大部分主流模型,同时提供一个图形界面 LLaMA Board 帮助用户更友好的执行和管理微调任务。对于本文的任务,对 LLM 按照任务型 Agent 方向进行微调,因为需要学习的知识较少,并且不会对模型整体的回答能力进行大的变化,这里我们采用 LoRA 微调技术对模型进行 SFT。在基础模型的选择上,没有经过指令微调的 Base 模型和有过指令微调后的 Chat 模型(e.g., Qwen 1.5 和 ChatGLM3)都会被纳入选择范围。

面向 LLM 微调的 LLaMA Board

图 2. 面向 LLM 微调的 LLaMA Board 系统

LLaMA Factory 支持 Alpaca 和 ShareGPT 两种数据集的格式,这里我们将上面使用蒙卡 + LLM 生成的数据集处理为 ShareGPT 格式。下面就是个 sharegpt 格式包含功能调用内容的数据例子,其中 conversations 中是对话历史,tools 是当前对话中所有可用的工具。

{
  "conversations": [
    {
      "from": "human",
      "value": "I saw a dress that I liked. It was originally priced at $200 but it's on sale for 20% off. Can you tell me how much it will cost after the discount?"
    },
    {
      "from": "function_call",
      "value": "{\"name\": \"calculate_discount\", \"arguments\": {\"original_price\": 200, \"discount_percentage\": 20}}"
    },
    {
      "from": "observation",
      "value": "{\"discounted_price\": 160}"
    },
    {
      "from": "gpt",
      "value": "The dress will cost you $160 after the 20% discount."
    }
  ],
  "tools": "[{\"name\": \"calculate_discount\", \"description\": \"Calculate the discounted price\", \"parameters\": {\"type\": \"object\", \"properties\": {\"original_price\": {\"type\": \"number\", \"description\": \"The original price of the item\"}, \"discount_percentage\": {\"type\": \"number\", \"description\": \"The percentage of discount\"}}, \"required\": [\"original_price\", \"discount_percentage\"]}}]"
}

为了保证不同的意图和槽位能被相对准确的识别到,根据实践经验我们认为训练数据量需要满足意图数 x 槽位数 x 500 的规模。这里我们构造了 5 个任务,分别是根据实时汇率转换货币金额,了解某个地区的习俗和文化特点,根据用户的位置或兴趣,推荐附近的博物馆,根据自己的位置、兴趣和预算,推荐当地的餐厅以及查询去某个目的地的交通方式。每个意图包含 2 至 3 个槽位,共生成了 6000 条左右的数据,覆盖了 5 个任务大部分用户状态变化路径,接下来将对微调训练的部分进行详细的介绍。

实验结果

本文选择在 A6000 显卡上进行微调,微调精度选择 fp16,LoRA Rank 设置为 4,训练 3 个 Epoch。在不使用 flash attention 加速时整个训练过程耗时 1.5h 左右,对于 6B - 7B 的模型,显存占用在 20 - 22G 左右。实验对象包括目前市面上主流的开源模型,ChatGLM3 6B,Qwen 1.5 7B,Yi 6B 系列的 Chat 模型和 Base 模型。在额外构造了 100 个验证对话集对模型进行评估之后,这里将微调前的 Qwen 1.5 Chat 模型作为基线对比了不同模型微调后的表现,

ModelSizeIntent AccuracyIntent RecallSlot AccuracySlot Recall
ChatGLM3 Chat6B----
ChatGLM36B----
Qwen 1.5 Chat7B96.23%97.76%93.98%95.11%
Qwen 1.57B94.79%98.31%91.80%94.01%
Yi Chat6B92.73%95.44%89.21%91.77%
Yi6B94.19%97.09%91.34%92.17%
Qwen 1.5 Chat(微调前), Baseline7B82.64%85.32%75.74%89.67%

💡 ChatGLM3 在 LoRA 微调之后幻觉情况特别严重,无法称之为可用,因此 ChatGLM3 系列的模型暂无法计算具体的性能指标。可能是因为 ChatGLM3 的 Prompt 格式比较特殊, LLaMA Factory 官方没有对 ChatGLM3 进行特殊优化。同时,在 ChatGLM3 的 Repo 中发现官方删除了 ChatGLM3 使用 P-tuning 微调 Agent 的代码,给出的理由是效果较差。关于 ChatGLM3 的 Agent 微调至此作罢,接下来会持续跟踪后续进展。

从对比结果可以发现,经过我们微调后的 Qwen 1.5 Chat 模型在整体性能上表现最佳,相对于 Baseline(微调前的 Qwen 1.5 Chat 模型),除了微调不成功的 ChatGLM3 之外,性能上都有比较显著的提升。Qwen 1.5 的意图召回率略高于 Qwen 1.5 Chat 的原因是 Qwen 1.5 出现幻觉的概率较高,在给出 Tools 之后,没有明显调用工具的提问也较容易触发工具调用。

对比一下 Qwen 1.5 Chat 微调前和微调后的表现,下图 3 为 Qwen 1.5 Chat 微调前的对话表现,图 4 为 Qwen 1.5 Chat 经过微调后的对话表现。可以明显发现微调后的模型对于槽位的识别方面提升很大,并且还附加了槽位追问的能力。

Qwen 1.5 Chat 微调前的对话表现

图 3. Qwen 1.5 Chat 微调前的对话表现

Qwen 1.5 Chat 微调后的对话表现

图 4. Qwen 1.5 Chat 微调后的对话表现

此外,Agent 对于用户在对话中省略主语时也能正确的识别槽位信息,如下图所示,用户在说「5000 人民币可以在当地还多少钱呢」的时候,模型能够智能的将「当地」和上文中提到的「京都」联系起来,在上下文结合和理解上的表现上比传统的 Rasa-like 对话 Agent 表现的更加智能和灵活,达到了我们的预期水平。

本文微调的 Agent 模型超越普通 Rasa-like 对话 Agent 的能力

图 5. 本文微调的 Agent 模型超越普通 Rasa-like 对话 Agent 的能力

对比经过指令微调的 Chat 模型和没有指令微调过的 Base 模型我们还发现,经过指令微调的 Chat 模型得到的微调反馈最佳,特别是经过 Agent 相关指令微调的 Chat 模型,这主要是这类模型已经使用了大量的 Function Calling 进行训练,我们在此基础上进行微调实际上属于同方向的增量学习,需要 Agent 额外的学习成本更小。

结论

本文提出了一种利用蒙卡方法和 LLM 生成训练数据集,并将其与 LLaMA Factory 框架相结合,高效微调多种语言模型,构建任务型对话 Agent 的新颖方案。该方案不仅保留了大语言模型强大的理解和生成能力,而且显著提高了微调后模型在意图识别、槽位填充等关键任务上的性能表现。

与传统的模块化对话系统相比,本文方法构建的端到端 Agent 架构更加简洁高效,易于部署和维护。实验结果表明,经过微调的语言模型不仅能够准确识别用户意图和关键信息,还能根据上下文理解用户的省略表达,并在必要时主动追问槽位信息,相较于微调前的模型,展现出更强的理解和交互能力,相较于传统的模型,展现出了更多的智能性。

尽管如此,该方案仍然存在一定的缺陷,首先在数据集的构建方面,靠人脑整理的行为状态图很难考虑到所有可能的用户路径,建模的过程十分耗时。在 Agent 微调方面,准确率还有待进一步提高,因为是 E2E 的系统,整体的可控性和可解释性相对较差。未来我们的工作重点将包括,1. 优化数据集生成方法,例如结合蒙特卡罗树搜索(MCTS)和打分模型的方案对对话状态空间进行探索和筛选。 2. 进一步优化微调方法、探索提高模型可解释性的技术路线等,以期在保持语言模型强大能力的同时,进一步增强任务型对话 Agent 的性能和可靠性。

如何学习大模型

现在社会上大模型越来越普及了,已经有很多人都想往这里面扎,但是却找不到适合的方法去学习。

作为一名资深码农,初入大模型时也吃了很多亏,踩了无数坑。现在我想把我的经验和知识分享给你们,帮助你们学习AI大模型,能够解决你们学习中的困难。

我已将重要的AI大模型资料包括市面上AI大模型各大白皮书、AGI大模型系统学习路线、AI大模型视频教程、实战学习,等录播视频免费分享出来,需要的小伙伴可以扫取。

一、AGI大模型系统学习路线

很多人学习大模型的时候没有方向,东学一点西学一点,像只无头苍蝇乱撞,我下面分享的这个学习路线希望能够帮助到你们学习AI大模型。

在这里插入图片描述

二、AI大模型视频教程

在这里插入图片描述

三、AI大模型各大学习书籍

在这里插入图片描述

四、AI大模型各大场景实战案例

在这里插入图片描述

五、结束语

学习AI大模型是当前科技发展的趋势,它不仅能够为我们提供更多的机会和挑战,还能够让我们更好地理解和应用人工智能技术。通过学习AI大模型,我们可以深入了解深度学习、神经网络等核心概念,并将其应用于自然语言处理、计算机视觉、语音识别等领域。同时,掌握AI大模型还能够为我们的职业发展增添竞争力,成为未来技术领域的领导者。

再者,学习AI大模型也能为我们自己创造更多的价值,提供更多的岗位以及副业创收,让自己的生活更上一层楼。

因此,学习AI大模型是一项有前景且值得投入的时间和精力的重要选择。

  • 22
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值