Enable javascript in your browser for better experience. Need to know to enable it? Go here.

如何借助 LLM 设计和实现任务型对话 Agent

 

作者:

蒋宏宇, Thoughtworks 数据科学家

林然, Thoughtworks 首席数据科学家

刘静, Thoughtworks 首席数据科学家

吕晓曦, Thoughtworks 首席解决方案架构师

 

本文由作者与 Gluon Meson 团队联合出品,Gluon Meson 是 Thoughtworks 数据与人工智能团队旗下一个专注于 AIGC 平台底层架构的技术团队。

 

引言

 

在人工智能的快速发展中,任务型对话 Agent 正成为提升用户体验和工作效率的关键技术。这类系统通过自然语言交互,专注于高效执行特定任务,如预订酒店或查询天气。尽管市场上的开源框架如 Rasa 和 Microsoft Bot Framework 在对话理解和管理方面已经取得了不错的进展,但仍存在一定的局限性,包括对大量领域数据的依赖、对固定模板的依赖,以及在个性化服务和复杂任务处理方面的不足。

 

大型语言模型(LLM)的兴起为任务型对话 Agent 的设计和开发带来了新机遇。LLM 强大的语言理解和生成能力,能够有效提高对话系统的准确性和用户体验。得益于这些特点,我们有机会进一步简化任务型对话 Agent 的开发流程,并显著提高开发效率。

 

本文将重点介绍由 Gluon Meson 平台孵化的创新框架——Thought Agent,探讨如何利用大型语言模型来设计和实现任务型对话 Agent 。该框架已在一家大型银行的智能对话 Agent 项目中得到成功应用。本文旨在为读者提供新的视角,帮助快速构建以 LLM 为辅助的任务型 Agent。

 

 Thought agent 框架

 

Thought Agent 是一个 LLM-powered 的任务型对话 Agent 框架,在传统任务型对话 Agent 架构的基础上创新性地引入了 LLM 来强化自然语言理解、自然语言生成(NLG)等对话系统的通用核心能力,并通过将意图、槽位等信息进行配置化的设计,使得对话 Agent 的设计和实施变得更加高效、通用且易于开发,改善了传统方案的开发效率和泛化能力瓶颈。

图 1. Thought Agent 运行机制及模块功能简介


如图 1 中所示,该框架主要包含四大模块,分别是自然语言理解(NLU)、状态追踪(State Tracker)、对话策略(Dialogue Policy)以及动作执行(Action Runner)。其中:

 

  • NLU 模块是对话系统的关键部分,它负责解析用户的输入并识别出用户的意图和相关实体。

  • 对话状态追踪模块负责维护对话的上下文信息,确保系统能够根据用户的历史输入和当前意图做出恰当的响应。

  • 对话策略制定模块则根据当前的对话状态和用户的意图,决定下一步的行动。

  • 最后,动作执行模块是对话系统的输出环节,它根据前面的模块得到的信息,生成自然、准确的回复或执行相应的动作。

 

以用户消息「我要查询天气为例」,该消息首先会进入到 NLU 模块中,得到用户的意图是「查询天气」,状态追踪模块找到「查询天气」意图需要的槽位包括城市,时间等,其中城市是必填槽位,对话策略模块感知到必填槽位「城市」没有被提到,于是发起了追问槽位的策略行为,最后动作执行调用 NLG 功能生成回复 「请问你要查询哪个城市的天气?」。

 

接下来,我们将深入探讨 thought agent 框架的各个模块,并分析它们是如何共同作用,提升整个系统的智能化水平。

 

Thought Agent 各模块功能详解

 

自然语言理解(NLU)模块 

 

NLU 是对话系统的核心组件,其被设计用于理解用户的需求,它需要从用户的消息和上下文中提取出至少以下两个信息:

 

  • 用户意图 (Intent) ,指的是用户语句背后的目的和需求,如查询天气、预订机票等。正确识别用户意图对于系统给出恰当响应至关重要。

  • 槽位 (Slot) ,指包含在用户语句中的某些关键信息单元,如时间、地点等,是完成用户需求所必需的补充信息。

     

在我们的框架中,NLU 模块允许意图和槽位之间通过配置信息建立层级关系,使得对话系统更加灵活和强大。这种层级结构的设计不仅使得配置更加直观和清晰,而且有助于系统更准确地理解和处理用户的复杂场景(例如意图的描述将帮助 NLG 模块生成恰到的意图确认文本回复,槽位的描述将帮助 NLG 模块生成更自然的追问槽位的文本回复)。以下是一个具有层级关系的意图和槽位配置示例:

 

 

intent: 查询天气

    - description: 用户想要获取特定地区的天气情况。

    - slots:

      - name: 城市

        type: string

        required: true

        description: 用户想要查询天气的城市名称。

      - name: 时间

        type: datetime

        required: false

        description: 用户想要查询的天气时间点。

 

 

在这个例子中,我们定义了一个“查询天气”的意图,并且为这个意图配置了两个槽位:“城市”和“时间”。这种结构不仅有助于系统理解用户输入中的复杂信息,而且还可以用于生成更加精确和个性化的回复。

 

通过这种结构化的配置方法,thought agent 框架的 NLU 模块能够更好地处理复杂的对话场景,提升对话系统的准确性和用户体验。同时,这种设计也使得系统更加易于扩展和维护,为开发者提供了极大的便利。基于上面的意图、槽位配置信息,NLU 模块目前有两种实现范式:

 

基于大语言模型的 NLU 范式

 

利用 LLM 直接执行 NLU 任务是一种先进而高效的方法。通过设计恰当的提示词 (Prompt),能够直接让 LLM 完成意图识别和关键信息提取,无需对大量特定领域数据进行微调。这种做法可以最大限度利用 LLM 广博的知识,提高对话理解的整体水平。

 

如需融入更多领域知识,可采用 Retrieval-Augmented Inference (RAI) 技术,根据用户查询从知识库中检索相关文本作为辅助信息提供给 LLM。这种架构使 NLU 模块能够从相关的上下文中更深入的理解意图,从而增强对话智能。相比传统的数据驱动方法,基于 LLM 的 NLU 范式更高效灵活,能快速在多个场景 (如智能家居、客服等) 间迁移和复用。

 

下面则是一个基础的用于完成意图分类任务的 Prompt 例子,其中 Persona 的部分对 LLM 的职责进行交代,Retrieved shots 的部分是根据用户消息从知识库中检索到的相似的内容,LLM 可以参考这些内容推理出最后的结果,最后的 Instruction 部分是本次任务需要推理的内容:

 

 

<Persona>

你是一个用户意图分类器,你需要返回给定的用户文本的分类结果,分类候选包括

[开灯,开空调]

<Retrieved shots>

天黑了 -> 开灯

天好热 -> 开空调

<Instruction>

热死了 ->

 

 

模型最后的回复就是其对「热死了」这句话的意图分类的结果。实践中我们发现该方案对 LLM 的理解和推理的能力要求较高,选择 GPT-4 或 Claude 3 Opus 能体验到最好的效果。

 

基于微调语言模型的 NLU 范式

 

在一些特殊场景下,如存在数据隐私问题或缺乏部署大模型的算力时,我们可以选择在开源大模型或小模型的基础上进行微调以引入领域知识。

 

准备训练数据集,微调过程的关键在于构建高质量、全面覆盖各类意图场景的数据集。数据集应当包含丰富的用户语义意图和槽位信息示例,以确保微调后模型具备良好的泛化能力。在数据构建过程中,我们可以借助大语言模型强大的理解和生成能力。首先,我们需要从业务方收集一些种子问题,覆盖不同业务场景下的意图类型。然后,将这些种子问题提供给大模型,利用其文本生成能力对种子问题进行改写、扩展和细化,从而衍生出更加丰富、多样的问题表述。接下来,我们可以将这些生成的问题进行模板化处理,将不同的槽位信息与问题模板相结合,组装成贴近真实场景的训练样本就能快速获得足量所需意图的训练数据。

 

通过上述流程,我们能够高效、低成本地构建覆盖面广、语意丰富的训练数据集,为 NLU 模型的微调打下坚实基础。相比人工手写,利用大模型生成数据能显著降低数据构建的成本和工作量,提高数据质量的同时也保证了数据的多样性,有助于提升微调后模型的泛化能力。

 

保持训练数据的平衡,数据不平衡问题会对模型性能造成严重影响。通常情况下,一些常见的意图类别如问候、确认等会有大量样本数据,而其他特殊意图类别的样本则很少。如果不进行处理,模型在训练时会过度关注主导意图类别,忽视小样本意图类别,导致在这些小类别上的分类准确率低下。为了解决这一问题,我们需要采取有效措施来平衡不同意图类别的样本分布。常用的方法包括对小样本意图类别进行过采样,对大样本意图类别进行欠采样,以及在损失函数中赋予不同权重等。通过这些措施,可以减小不同意图类别之间的样本数量差异,提高模型对小样本意图的识别能力,从而获得更加均衡、稳定的意图分类模型。

 

选择合适的模型,意图识别和槽位提取两个任务可采用联合模型同时完成,也可选择独立的序列分类和序列标注模型分别优化每个子任务的性能。意图分类任务可以选择 BERT-base 后接 MLP 的网络结构,槽位提取任务可以使用 BERT-CRF 以及 BERT-Span 的网络结构。针对意图分类和槽位提取任务,其目标都是将自然语言输入映射到意图类别标签或序列标注的槽位标记上。 当然,因为这两个任务之间密切相关,也可以采用 Joint 模型同时完成(例如 JointBert),利用联合学习的方式让两者相互约束和辅助、捕捉语义关联。相较于基于大模型的方案,这类方案能够额外输出置信度信息,通过设置置信度阈值以及通过人机交互机制确认低置信度结果,NLU 的稳健性得到了进一步提高。

 

处理层级化意图

 

在实际的意图分类任务中,不同意图之间可能存在从属关系,既可能是显式的层级关系,也可能是隐式的语义关联。例如 "查实时天气","查未来天气" 都属于更广义的 查天气"  意图的子类,它们之间存在着明确的层级从属关系。如果待分类的意图中存在这种显式或隐式的层次关系,我们可以采用分层式的模型架构,先对更广义的大类意图进行分类,再细化到具体的子类意图上。如未采用这种层次化模型,而是使用普通的扁平化分类模型,会导致一些潜在问题,比如意图混淆、泛化能力差、数据稀疏问题加剧等。

 

具体来说,这个分类模型包含若干个专门处理大类意图的模块和针对每个大类意图的细分模块,能够充分利用不同层级的语义信息,综合提升模型的准确性和稳定性。在推理时,输入的用户消息首先被提交到大类分类器,确定其所属的大类意图。然后将用户消息和大类标签一并输入到该大类意图的细分模块,得到具体的子类意图输出。

 

除此之外,当意图类别的数量较大(超过 30-50 个),普通的基于 BERT 的分类器以及基于 LLM 的分类器都可能存在性能下降的问题。大量细分的类别间界限可能较为模糊,类内差异加大,类间差异变小,给分类器带来更多困难。对于这类情况,我们还是建议考虑层次分类方法,将大量类别分成若干个粗粒度的组,先分类到组级别,再在组内细分类。当然,分层模型也带来了更复杂的模型结构和计算量,在实践中需要根据具体情况权衡收益和代价,做出最优的设计选择。

 

状态追踪 (State Tracker) 模块

 

状态追踪模块在任务型对话系统中扮演着关键角色,它的主要任务是动态地追踪和记录对话的状态。

 

对话状态管理

 

对话过程是连续的,Tracker 需要正确的追踪上下文信息,记录用户历史意图、槽位值的变化情况以及完整的对话历史记录,确保对话 Agent 具备深层次的理解和回应能力。对话过程也是动态变化的,Tracker 需要实现高效的状态更新策略。在每一轮对话后,正确地更新对话状态且保持信息的一致性。可采用合理的算法和数据结构来优化更新过程,确保实时性和高性能。在小规模应用中,可以将状态直接存储在内存中;而在大规模分布式应用中,则需要将状态持久化存储,如使用 Redis 等内存数据库,根据 session ID 快速读写对话状态。用户的意图不仅需要考虑当前用户消息给到模型后的结果,还需要考虑上下文信息以及槽位等信息。

 

基于上下文的意图更新: 根据历史意图和最新对话轮的最新意图综合判断用户的当前意图。例如在下面的对话历史中,用户第一轮意图是订飞机票,第二轮的意图是填充槽位,由于填充槽位只是辅助意图,Agent 可以认为订飞机票这个意图将继续保持。

 

 

例:

User: 订飞机票 -> 订机票

Agent: 请问您要预订的线路是什么

User: 成都到东京的 -> 订机票

Agent: 什么时候出发呢?

...

 

 

槽位与意图矫正,在对话过程中,用户提供的槽位信息有时会与当前识别出的意图不匹配。这种情况下,Tracker 需要根据槽位信息对意图进行矫正。例如,当前意图被识别为A,但用户提供的大部分槽位值均属于意图B,那么很有可能用户的真实意图是 B 而不是 A。为了处理这种情况,Tracker 可以采取以下策略:设置一个阈值,如果发现与当前意图不匹配的槽位数量超过阈值时,就触发意图矫正流程,在接下来的 Action 模块中,Agent 可以主动与用户确认:"根据您提供的信息,我猜测您是想 XX,是这样的吗?"。如果用户确认了,就将意图更新为正确的意图;否则保持原意图不变。通过这种策略,Tracker 能够及时发现并纠正意图识别的错误,保证后续处理的正确性。同时也增加了人机交互的环节,提高了对话的自然度和用户体验。

 

对话策略 (Dialogue Policy) 模块

 

对话策略模块是对话 Agent 系统的决策中枢,根据对话状态和用户意图为系统分配合理的行为策略 (Action)。为提高系统的适应性和智能化水平,我们设计了多种策略以应对不同情况(详见图 2),下面将分别对不同策略的设计进行解释。

图 2. 不同对话状态对应的对话策略


对话终止策略,通过综合分析用户意图、任务状态等多个维度的信息,对话终止策略判断是否需要结束当前对话。例如用户长时间无响应、明确表达结束意图或关闭对话界面等,均可视为终止对话的触发条件。合理的终止策略可以避免不必要的冗长交互,提升用户体验。

 

对话转移策略,当前对话 Agent 无法完全解决用户问题时,对话转移策略将决定是否需要将对话转移给其他 Agent 或人工客服。这需要 Policy 模块能够准确评估当前 Agent 的能力边界,并作出合理的转移决策,从而为用户提供更完整的解决方案。

 

追问槽位策略,追踪并补全对话中遗漏的关键槽位信息是槽位追踪策略的核心职责。该策略需要基于 NLU 模块的理解结果,通过巧妙设计的提示语引导用户补充遗漏的槽位,以确保获取任务所需的全部信息。优秀的追踪策略可显著提高任务完成率。假设用户想要订购外卖,但未提供送餐地址这一关键槽位信息。对话 Agent 可以根据槽位追踪策略生成如下 Prompt 进行追问:

 

 

User: 我想点一个牛肉汉堡外卖。

Agent: 好的,请问需要送到什么地址呢? 我们需要您的送餐地址来安排外卖员配送。

User: 送到xx街道xx号xx小区xx单元就可以了。

Agent: 收到您的送餐地址为xx街道xx号xx小区xx单元,我已将它添加到订单中。您还需要指定其他要求吗?

 

 

通过上述 Prompt,结合 "请问...","我们需要..." 等短语模板的 Fewshot,Agent 能够巧妙地引导用户补充遗漏的槽位信息,使其感受自然、不显生硬。

意图和槽位确认策略,为应对 NLU 模块中存在的不确定性,需要引入意图和槽位确认策略。当模型对用户意图或提取的槽位的置信度较低时,该策略会发起与用户确认的文本回复,以保证对话 Agent 正确理解语义,从而提高对话质量。确认策略需要合理计算置信度阈值,并设计自然的确认交互方式。例如下面的例子:

 

 

User: 啥都看不清楚 -> NLU 理解的意图(调整灯具亮度)的置信度较低

Agent: 对不起,我没有完全理解您想做什么操作,是想调整灯具的亮度吗?可以再说得更清楚一些吗?

User: 是想把卧室里的吸顶灯打开。

Agent: 好的,我明白了,我将为您打开卧室里的吸顶灯。-> 通过意图确认机制带来的用户交互,提高NLU结果的置信度。

 

 

从上述例子中,可以发现 Agent 对初始用户语句的理解把握不高,表现为意图识别的结果的置信度较低,因此使用"我没有完全理解","可以再说得更清楚一些吗" 等确认性文字回复给用户请求用户重新阐述,从而降低错误的风险。

 

触发下游动作策略,触发下游行为策略旨在根据特定的对话状态、用户意图等条件,为 Agent 分配合适的下游行为,如向后端系统发起请求、生成特定响应、执行一系列复杂操作等。通过明确的策略规则,可确保 Agent 及时执行正确的下游行为,提高系统效率。

 

动作执行(Action Runner)模块

 

动作执行模块负责具体行为的实现。在面向任务的场景中,最常用的行为是 RAG(检索内容作为参考信息生成回答)、通用文本回复和智能调用。例如上述的确认意图的策略对应的就是通用文本回复行为,如果用户的意图是打开一个功能,则对应的就是给下游发动一个 RPA (Robotic Process Automation) 的请求(如图 3)。通过这些组件的协同作用,使对话 Agent 能够以智能、自然的方式响应用户。得益于大语言模型强大的理解和生成能力,Agent 的人机交互体验能够进一步得到提高。

图 3. 动作执行模块中不同功能的消息路径


RAG 功能的设计要点

 

RAG 是对话 Agent 中重要的生成模块,通过结合检索和生成的方式,实现更智能、个性化的回复。在 Action 模块中,我们强调以下关键点:

 

选择合适的 Embedding 模型,如果是对话的场景是通用领域,可使用预训练好的 Embedding 模型,如在多语言场景下表现较好的 E5 系列模型,在中文场景下表现不俗的 BGE 系列模型等。它们能提供不错的语义表征能力。在检索任务中,我们主要关注模型在 Pair Classification 维度上的得分,即给定模型输入,模型将输入相关的内容全部检索出来的能力。如果对话场景是特定领域(例如对话中涉及较多的行业黑话或专业名词),建议在预训练模型的基础上进行进一步微调,以更好地捕捉领域特征。我们需要准备高质量的领域语料(Monologue 或 Dialogue ),对 Embedding 模型进行微调。

 

权衡检索召回率与准确率,如果模型分析和推理能力很强,可以适当的降低相似度阈值,将可能与用户问题相关的内容全部检索到并放入 Prompt 中交给大模型来分析具体什么内容可以参考,什么内容与用户的问题相关;但相对而言,如果基础大模型的分析能力不够强,这时候就需要尽量提高相似度阈值,过滤掉容易干扰模型分析思考的内容,进而降低模型出现幻觉的概率。

 

优化用于检索的 Query,在多轮对话的场景中,用户当前轮的消息可能会存在缺少主语导致检索内容不完整的情况。而如果单纯将多轮消息直接拼接用于检索内容,又会降低检索内容的准确率,两种情况都会影响 LLM 最终回复内容的准确性。这里可以引入一个多轮转写模型,将用户的对话历史输入到模型,模型能够自动补齐当前用户消息中的主语,忽略掉与当前轮用户消息无关的信息,如下例所示:

 

 

<对话历史>

User: 网银如何在线下开通

Agent: 需要。。。。

User: 真麻烦

Agent: 抱歉。。。

User: 线上呢

<转写结果>

网银如何在线上开通

 

 

可以看到,转写后的结果相较于直接将每一轮的用户消息进行拼接,信息更加纯粹,检索到的内容也会更加精准。

 

通用型 NLG 功能的设计范式

 

在实现文本回复时,强调回复的正确性、自然性以及用户体验。需要关注以下两个方面:

 

合理定义 Agent 个性 (Persona),对话 Agent 的人格特征设计是赋予其鲜明个性和身份认同的关键。我们需要紧密结合应用场景,量身定制符合场景语境的人格特征。例如在客户服务场景中, Agent 应展现出善解人意、专业值得信赖的一面,以缓解用户不满情绪、树立专业形象;在智能助手场景中, Agent 则需呈现高效务实、智能灵活的风格,快速解决实际需求、处理复杂任务。而在教育领域, Agent 必须富有耐心、严谨权威,引导学生主动探索新知识;至于娱乐场景,诙谐幽默、活泼生动是 Agent 人格的基本要素,以提供新颖有趣的娱乐体验。人格特征的合理设计不仅能增强 Agent 的身份认同感,更能为用户营造更加沉浸、契合的对话体验,提升对话 Agent 的友好度和可接受性。同时我们也需注意把控人格设计的程度,避免过度夸张或不当设定。

图 4. 合理的 Persona 定义能够为 Agent 带来不同维度的增益


平衡回复的拟人性和模型幻觉(Hallucinations),LLM 为 Agent 提供了更拟人、自然的语言表达可能,但同时也存在着产生幻觉的风险,在面向任务的场景中,回复文本的时候需要平衡模型的幻觉和回复的类人性,特别是使用小参数推理能力较差的的 LLM 时,如果提示词过于复杂(指令中涉及到需要大模型分析和推理的内容过多)需要特别注意模型的幻觉发生,例入下面这个例子:

 

你是一个智能客服,用户想要查询天气信息但没有提供必要的信息【地点】

你和用户的对话历史如下:

----------

你的回复:

 

上述例子中给到 LLM 的指令十分模糊,这需要 LLM 自己思考如何根据上下文给出合适的回复。此外,Prompt 中 Persona 的定义和最终的指令之间还穿插了之前的对话记录,模型需要根据对话上下文考虑合适的回复内容以及上下文的一致性,在此基础上还要保证该回复符合 Persona 的定义,这对于小参数的 LLM 来说是极具考验的,在真实的对话场景中,这类指令带来模型幻觉的概率会非常高。为了降低 LLM 的推理负载,我们首先考虑将指令和对话历史的位置进行对调,其次需要提高指令的明确性使得其导向型更强,下面的 Prompt 是优化后的结果。

 

你和用户的对话历史如下

----------

你是一个智能客服,被设计用来帮助用户解决日常的问题,用户现在想要查询天气,但是没有提供【地点】的信息

请使用一句简洁的话来引导用户提供【地点】信息

你的回复:

 

此外,为了降低对话历史对 LLM 生成内容的影响,对话的历史还需要被剪裁,在我们的实验对象 ChatGLM3-6B 模型中,对话历史的长度最好不要超过 3 轮,否则模型的幻觉出现的概率仍然显著。此外,在使用大型语言模型直接回复用户时,尤其是结合参考资料进行回答生成(如 RAG)时,我们需要意识到这种方法仍然存在一定的风险。大模型在结合参考资料生成内容时,可能无法完全保证内容的正确性。因此,在实际应用中,可能需要引入前置的分类器或者验证机制,来判断模型生成的内容是否准确可靠。

 

因此,在实施基于 LLM 的对话 Agent 到面向客户的场景之前,进行大量的测试和验证是必不可少的。这包括但不限于单元测试、集成测试以及用户接受测试等,以确保模型在实际应用中的稳定性和准确性。同时,还需要对模型进行持续的监控和优化,以便及时发现并解决可能出现的问题。

 

智能调用功能的设计范式

 

智能调用功能是任务型对话 Agent 与外界交互的重要模块,它负责将用户的意图和提取出的槽位值转换为具体的操作,以完成用户的任务需求。为了实现高效且准确的智能调用,我们需要关注以下两个设计范式:

 

意图与行为的映射,在智能调用过程中,需要将识别出的意图和槽位值映射到后端系统中的具体操作上。这通常涉及到构建一个意图-操作的映射表,以及为每个槽位值确定相应的参数。例如,如果用户的意图是“预订酒店”,那么映射表应该指明这一意图对应的操作是调用酒店预订系统,而槽位值如“日期”、“房间类型”等则作为调用参数。

 

槽位标准化,用户在提供槽位值时,常常会使用非标准或者口语化的表达方式,如 "三块五毛" 、"九月十五号" 等。对于这类简单的数字、日期等槽位值,我们可以通过维护同义词词典或使用正则表达式的方式进行标准化替换。但在一些复杂的业务场景下,用户可能会提供功能名称的简称,或是一个描述性的句子来表达需求,这时词典和正则就力有未足了。我们需要引入模糊搜索的算法和接口,来支持对这些复杂槽位值的标准化。对于用户输入的功能简称或描述性句子,可以使用模糊字符串匹配算法 (如编辑距离、字符级 TF-IDF 等) 在标准功能名库中搜索最为相近的条目。我们还可以构建语义匹配模型,利用词向量或预训练语言模型捕捉用户输入与标准名称间的语义相关性,来处理同义表述的情况。

 

在实践中,需要综合使用字典精确匹配、正则表达式、模糊字符串匹配、语义匹配等多种策略,构建分层的槽位标准化流程。对于无法高置信度匹配的情况,需要保留人工确认的环节,让人工选择或是重新输入标准化结果,并将反馈数据用于优化标准化策略。

 

面向任务型对话 Agent 的评估框架

 

对于设计面向任务的对话 Agent,评估框架的建立至关重要,可以确保系统在不同场景和用户输入下的准确性和稳定性。除此之外,在Agent的优化迭代中,该评估框架也确保了优化方向的正确性。以下是针对面向任务的对话 Agent 的评估框架的关键组成部分:

 

针对 NLU 的自动评估

 

针对模型的意图识别和槽位提取部分,我们可以创建包含各种语境和输入的测试用例,确保模型在各种核心业务场景下都能够正确地处理用户意图和提取相关信息。

 

基于普通测试集的评估,对于测试集的评估,我们可以将训练数据拆分出一部分来做测试集,也可以制作一个固定的测试数据集,其中包含不同的输入以及对应的用户意图和需要被提取出来的槽位。确保测试集具有代表性,能覆盖大多数的应用场景,以便我们能够全面了解模型在实际应用中的性能。评估指标可以包括准确率、召回率、精确度等。

 

基于增强测试集的评估,为了模拟模型在真实场景中的表现,一方面可以使用自然语言处理中的对抗攻击方法, 例如基于规则、基于模型等生成对抗性样本,评估模型的抗攻击能力;另一方面,还可以构造包含拼写错误、语法错误、同音字等噪声的测试集,模拟真实场景下存在的语言噪声。无论是基于语言模型的随机替换,还是基于同音字的文本替换,都可以使用 TextAttack 开源库生成对抗样本。 下面是一些使用模型对原文进行改写的样例:

 

原文:  预定从成都到上海的机票

改写:

1. 安排从成都到上海的机票 (同语义扰乱)

2. 予定从成都到上海的机票 (同音字扰乱)

3. 预定丛成都到上海的机票 (字形扰乱)

 

「TextAttack 提供了一个集成和可扩展的框架,极大方便了 NLP 模型对抗攻击评估的进行,它主要被研究人员用于评估 NLP 模型的鲁棒性水平,揭示模型薄弱点,从而指导模型优化和防御对抗攻击。同时也适用于提高模型泛化能力、测试情况覆盖率、生成对抗训练样本等需求。」

 

此外,还可以人工制造一些处于意图识别或槽位提取的决策边界上的样本,检测模型在这些边缘样例上的泛化能力。可以通过对训练样本做小扰动、改写等手段生成边界样本。

 

结合解释性技术对模型能力进行分析

 

结合降维可视化方法对模型进行解释,为了深入理解模型的决策过程,评估其在特定场景下的不确定性以及对抗性输入的反应,我们还可以借助解释性技术对 NLU 模型以及 RAG 中依赖的Embedding 模型进行可视化分析。

 

通过将模型的高维输出 Embedding 降维到 2D 或 3D 空间,我们能够直观地观察模型在不同类别上的决策边界和聚类情况。常用的降维技术包括 t-SNE、PCA 等。以意图分类为例,我们可以将同一意图类别的样本点用相同颜色表示,不同颜色代表不同意图类别。这种可视化方式能让我们大致了解模型在不同意图类别上的分布和判别能力。在降维的 Embedding 空间中,我们还可以根据模型在每个样本上的分类是否正确,使用不同颜色或标记对正确和错误预测进行区分。这种正确性可视化能帮助我们发现模型在输入空间中的哪些区域表现较差,为我们优化模型和数据提供依据。

 

结合降维可视化方法对模型决策边界进行分析,对于包含噪音、同音字等攻击性样本的增强数据集,我们也可以将 Embedding 层投影到二维空间中进行可视化。通过观察这些攻击样本在决策边界周围的分布情况,我 们能评估模型对此类输入的稳定性和泛化能力。同时,结合分类正确性的显示,能让我们洞见模型在应对攻击样本时的薄弱环节。

图 5. 意图分类结果投影,左侧子图为模型在测试数据中的分类情况,右侧子图为模型在扰动后测试数据中的分类情况,使用 t-SNE 进行降维可视化,红色点为错误分类的结果,灰色点为正确分类的结果


面向多轮的策略测试

 

为了确保 Agent 在多轮对话场景中表现良好,我们还需要验证 Tracker 模块的上下文追踪和状态更新策略,确保核心模块的准确性。此外,策略测试阶段还需聚焦于对话管理策略的可靠性,确保 Agent 能够正确判断任务完成和转交对话。针对多轮对话场景,我们需要模拟用户的不同回复,并对应检验策略模块的决策是否合理。这通常需要 mock NLU 模块的输出结果 (包括用户意图和提取的槽位值),并将其输入到策略模块,检查策略生成的对话行为是否符合预期。

 

以机票预订为例,我们可以构造如下测试案例:

 

  1. Mock NLU 识别为 "查询航班" 意图,但没有提取到任何槽位值 (如出发地、目的地等),策略应决定询问缺失的必要信息。

  2. Mock NLU 识别为 "预订机票" 意图,已提取部分槽位值 (如出发地),策略应决定询问其余缺失的信息。

  3. 经过多轮交互,Mock NLU 模块模块提取了全部必要信息 (如出发地、目的地、日期等),策略应决定进入机票搜索和预订流程,或进行确认。

     

通过模拟各种多轮交互场景,我们可以全面测试策略模块对 NLU 结果的处理逻辑,以及与对话状态 Tracker 模块的交互,检验其是否能够合理地驱动对话前进、终止会话。同时也可以测试策略在处理异常或未知输入时的容错能力。

 

主观评估方法

 

对于对话 Agent 而言,每一次的回复往往没有一个明确且唯一的「Golden truth」,传统的自动评估指标 (如 BLEU、Perplexity 等) 在评价生成的自然语言回复时,很容易出现评估偏颇。因此,在对话系统的测试中,引入人工评估是非常必要的。人工评估可以从多个维度对 Agent 生成的回复进行评分,如合理性、语言自然度、情感适当性等,并综合这些分数得到回复质量的整体评价。同时,人工评估员还可以针对整个对话会话,对 Agent 的整体表现如任务完成度、一致性等进行评分。

 

除了人工评估,我们还可以借助大型语言模型的能力,将其作为 「裁判 (discriminator)」 评判 Agent 回复的合理性。具体来说,我们可以将 Agent 的回复和上下文对话一并输入到大模型中,根据大模型对这一完整对话场景的判断分数,来衡量 Agent 回复的质量。大模型的评判能力源自其广博的知识基础和对自然语言表达的深入理解。这种基于大模型的评估方式,不仅能够高效地为大量回复进行评分,还能避免人工评估中潜在的主观偏差。我们还可以设计不同的评判维度,结合真实用户的 Person 分布,将具有不同 Persona 的大模型观察者的综合评估结果作为优化 Agent 回复能力的决策依据。

 

综合人工评估和基于大模型的自动化评估手段,能够有效弥补各自的缺陷,全面检视对话系统生成的自然语言响应质量,为系统的优化和改进提供可靠的评估依据。

 

结语

 

至此,一个基础的面向任务的对话 Agent 的全貌就全部呈现在读者的眼前了。相比当前流行的对话 Agent 框架,thought agent 在多个方面都具有显著的优势: 

 

  • 开发效率更高,thought agent 依赖 LLM 强大的自然语言理解和生成能力,无需从头构建 NLU。避免了标注大量的数据(在选用的 LLM 能力较强的情况下,如 GPT-4),只需标注少量的数据以及合理设计 Prompt,即可快速开发出适用于多场景的对话系统。能够大幅降低工程成本和人力投入。

  • 泛化能力更强,基于大模型的 NLU 方案能够最大限度利用 LLM 的语义理解能力和广博知识,具有很强的泛化能力。传统的基于规则或数据驱动的方案,需要针对每个新场景重复标注训练数据的工作。而 thought agent 只需增加一些配置,标注少量的配置即可快速迁移部署。

  • 对话质量更佳,依托 LLM 的强大语言生成能力,thought agent 能够生成高质量、多样、上下文关联的自然语言回复,避免了传统模板式的生硬和单一的回复。回复的个性化程度和交互体验也得到极大增强。

     

在未来,我们将进一步提高该框架的复用性,提供易于使用的配置界面,降低使用门槛。同时也将提高自动化程度,使框架能自动完成一些重复性的工作,如用于 RAG 的知识库的构建、模型评估等,进一步减轻开发者的工作负担。我们希望该创新框架能够在更多场景中帮助开发者快速搭建任务型对话系统,用于进行 POC 验证或落地部署。

 

参考资料

 

  1. Jiang, H, Guo, A, and Ma, J. (2020). Personality-aware Chatbot: An Emerging Area in Conversational Agents. 10.13140/RG.2.2.15957.86249.
  2. Ni J, Young T, Pandelea V, et al. Recent advances in deep learning based dialogue systems: A systematic survey[J]. Artificial intelligence review, 2023, 56(4): 3055-3155.
  3. RASA, Next-level Generative Conversational AI Platform,  https://rasa.com
  4. Morris J X, Lifland E, Yoo J Y, et al. Textattack: A framework for adversarial attacks, data augmentation, and adversarial training in nlp[J]. arXiv preprint arXiv:2005.05909, 2020.
  5. Chen Q, Zhuo Z, Wang W. Bert for joint intent classification and slot filling[J]. arXiv preprint arXiv:1902.10909, 2019.
  6. Siro C, Aliannejadi M, de Rijke M. Understanding user satisfaction with task-oriented dialogue systems[C]//Proceedings of the 45th International ACM SIGIR Conference on Research and Development in Information Retrieval. 2022: 2018-2023.
  7. Hudeček V, Dušek O. Are large language models all you need for task-oriented dialogue?[C]//Proceedings of the 24th Annual Meeting of the Special Interest Group on Discourse and Dialogue. 2023: 216-228.
  8. Deriu J, Rodrigo A, Otegi A, et al. Survey on evaluation methods for dialogue systems[J]. Artificial Intelligence Review, 2021, 54: 755-810.
  9. Chen J, Xiao S, Zhang P, et al. Bge m3-embedding: Multi-lingual, multi-functionality, multi-granularity text embeddings through self-knowledge distillation[J]. arXiv preprint arXiv:2402.03216, 2024.

免责声明:本文内容仅表明作者本人观点,并不代表Thoughtworks的立场