LLM驱动的自然语言界面

自然语言 (NL) 界面使用户能够使用自然语言与系统交互(而不是使用严格的命令语法或使用图形用户界面的按钮和字段)。

1、为什么构建 NL 界面如此困难

NL 界面并不新鲜。研究人员一直在研究 NL 界面以及人们如何与这些系统交互超过 50 年!以下是多年来 NL 界面的有趣列表:自然语言用户界面:历史(维基百科)

如果研究人员一直在研究 NL 界面这么长时间,为什么 NL 界面不是无处不在的?

使用传统的自然语言处理 (NLP) 技术将混乱、不合语法的 NL 输入转换为机器可以执行的精确命令非常困难。传统上,这项任务是通过识别词性并使用手工整理的词典提取关键字和特定领域的实体来完成的。然后,使用语法例程从该信息中提取含义。特殊函数处理诸如首语重复和省略之类的挑战。最后,将提取的含义映射到命令。最近,管理对话流的组件也已添加到组合中。下图显示了 1970 年代至 2020 年代相关研究论文中描述工作流程的一些图表:

将混乱、模糊的自然语言输入转换为机器可以遵循的精确指令的传统方法

哇!这需要做很多工作。而且对于具有受限域的简单输入,它只取得了轻微的成功。

2、大型语言模型来帮忙

预先训练的大型语言模型 (LLM) 是解决构建 NL 接口时将不可预测的输入转换为所需格式的输出这一挑战的完美工具:

  • 自适应分类

与传统文本分类模型不同,LLM 可以在几乎没有训练数据的情况下执行临时分类。以下提示导致 LLM 仅根据类描述对用户输入进行分类(生成的输出以粗体显示):

[ prompt ]

Classify the following user input as one of: "question", "action_request", 
or "none"

question: The user input is asking a question.

action_request: The user input is an instruction to take an action.

none: The user input is not a question and not an instruction.

User input: "filter out everything after the end of January, 2024"
Class:


[ generated output ]

action_request
  • 逻辑

LLM 可以执行伪逻辑(实际上是遵循模式。)以下提示使 LLM 识别给定用户输入的 Web 应用程序界面的哪一部分(生成的输出以粗体显示):

[ prompt ]

A web interface has the following elements:

Element: filter_icon_div
Description: Open filters menu button. Clicking this opens the filters menu

Element: filters_close_x
Description: Close filters menu button. Clicking this closes the filters menu

Element: first_date_input
Description: First date filter input. Setting this to a date causes 
question-answer pairs before this date to be filtered out of the view

Element: final_date_input
Description: Final date filter input. Setting this to a date causes 
question-answer pairs after this date to be filtered out of the view

...

Which element is the following user message about?
"filter out everything after the end of January, 2024"

Element:


[ generated output ]

final_date_input
  • 强大的实体提取

LLM 无需详尽的字典即可提取实体。以下提示导致 LLM 从给定的用户输入中提取日期值(生成的输出以粗体显示):

[ prompt ]

A web interface has the following elements:

...

Element: final_date_input
Description: Final date filter input. Setting this to a date causes 
question-answer pairs after this date to be filtered out of the view

...

Which element is the following user message about?
"filter out everything after the end of January, 2024"

Element: final_date_input

What value should the element be set to?

A note about dates:
- Date values must always be specified like YYYY-MM-DD. For example, 
  'January 17th, 2022' would be: 2022-01-17.  And '2020 Feb. 13th' 
  should be: 2020-02-13.
- If no year is given, assume the current year. The current year is 
  2024.  So, January 17th would be: 2024-01-17 and Feb. 20th would 
  be: 2024-02-20

Value: 


[ generated output ]

2024-01-31
  • 以所需格式生成输出

前面的示例还展示了 LLM 以你在提示中指定的格式生成输出的能力。

  • 翻译

面的例子不处理 SQL 之类的查询语法。但对于 LLM 来说,将 NL 查询转换为 SQL 与将英语翻译成法语没有太大区别。

由于 LLM 的这些优势,NL 界面功能正在进入许多应用程序。

3、但一个问题正在出现

热衷于构建 NL 界面的团队正在用聊天机器人取代 GUI 功能。 唉,当面对聊天机器人输入的闪烁光标时,今天的用户与旧 UNIX 命令行界面的用户有很多共同之处,他们会问:“我应该在这里输入什么?”

用户界面是否已经走完了一个完整的循环? 回到闪烁的光标?

绝望的团队正在他们的聊天机器人界面中添加建议,例如:“问我关于 X 的问题”或“尝试搜索 Y”。但是,还有一种更好的方法可以成功设置 NL 界面……

4、构建直观 NL 界面的简单方法

这是一种构建 NL 界面的方法,它易于构建,并能生成对用户来说直观的 NL 界面:

a) 构建典型的图形用户界面 (GUI)

b) 收集有关 GUI 中元素的元数据

c) 创建提示以分析用户输入:

  • 对用户输入进行分类
  • 检测哪些 GUI 元素与用户输入相关
  • 识别用户输入中的值

d) 添加应用程序逻辑以响应用户输入:

  • 回答 NL 问题
  • 激活 GUI 元素

5、示例

假设我们正在构建一个用于查看客户问题和答案的 Web 应用程序。为了便于查看给定时间范围内的问答对,该应用程序将能够筛选第一天和最后一天。

以下是我们可以将这种 NL 界面构建方法应用于我们的应用的方式:

5.1 构建典型的图形用户界面 (GUI)

确保 GUI 的设计符合用户的心理模型,并提供执行预期任务的直接、直观的方法。

对于我们假设的应用程序,过滤菜单可能如下所示:

过滤菜单包含第一个日期输入和最后一个日期输入、用于应用指定日期范围的重新加载按钮以及用于关闭菜单的红色 X

GUI 中的元素为用户提供了急需的提示 - 影响用户的心理模型、引导他们的语言、塑造他们的行为并建议可以执行哪些任务。

5.2 收集有关 GUI 中元素的元数据

对于 GUI 中的每个元素,我们需要收集以下元数据:

  • 元素的有意义的名称
  • 元素用途和使用原因的简短描述
  • 关于在任务中使用元素的更详细的“文章”
  • 元素的 DOM 标识符
  • 激活元素时应调用的函数数组

对于我们的示例应用程序,GUI 元素元数据可能如下所示:

[
   {
      "element_name": "First date filter input",
      "task_description": "Setting this to a date causes question-answer pairs before this date to be filtered out of the view",
      "article_txt_arr": [
         "You can filter the question-answer pairs shown by date.",
         "For example, you can filter out any question-answer pairs before a given date by setting the first date filter input.",
         "In other words, you can show only question-answer pairs starting on or after a given date by setting the first date filter input."
      ],
      "dom_id": "first_date_input",
      "actions_arr": [
         {  "function": "openFiltersMenu",
            "values_needed_arr": []
         },
         {  "function": "setFirstDateInput",
            "values_needed_arr": [ "date_str" ]
         }
      ]
   },
   {
      "element_name": "Final date filter input",
      "task_description": "Setting this to a date causes question-answer pairs after this date to be filtered out of the view",
      "article_txt_arr": [
         "You can filter the question-answer pairs shown by date.",
         "For example, you can filter out any question-answer pairs after a given date by setting the final date filter input.",
         "In other words, you can show only question-answer pairs starting before or on a given date by setting the final date filter input."
      ],
      "dom_id": "final_date_input",
      "actions_arr": [
         {  "function": "openFiltersMenu",
            "values_needed_arr": []
         },
         {  "function": "setFinalDateInput",
            "values_needed_arr": [ "date_str" ]
         }
      ]
   },
   {
      "element_name": "Page reload button",
      "task_description": "Clicking this button causes the page to reload",
      "article_txt_arr": [
         "You can reload the page with the selected filters by clicking the reload page button."
      ],
      "dom_id": "reload_btn",
      "actions_arr": [
         { "function": "reloadPage",
            "values_needed_arr": []
         }
      ]
   },
   {
      "element_name": "Close filters menu button",
      "task_description": "Clicking this closes the filters menu",
      "article_txt_arr": [
         "You can close the filter menu by clicking the close filter X."
      ],
      "dom_id": "filters_close_x",
      "actions_arr": [
         { "function": "closeFiltersMenu",
            "values_needed_arr": []
         }
      ]
   }
]

5.3 创建提示以分析用户输入

分类用户提示

当用户提交 NL 输入时,我们的 NL 界面需要区分不同的用户需求(或意图)。例如,用户可能会询问如何操作的问题以获得答案,或者他们可能会给出指示以引起操作。

对于我们的示例应用程序,以下提示可用于使 LLM 对用户输入进行分类。在运行时,用户输入将替换用户输入占位符:

Classify the following user input as one of: "question", "action_request", 
or "none"

question: The user input is asking a question.

action_request: The user input is an instruction to take an action.

none: The user input is not a question and not an instruction.

User input: __PLACEHOLDER_FOR_USER_INPUT__
Class:
检测哪个 GUI 元素与用户输入相关

当用户提出问题或发出操作请求时,我们必须确定输入与哪个 GUI 元素相关。

如果你的 GUI 设计与用户的任务非常吻合,那么用户可能提交的输入将与至少一个 GUI 元素相关。

对于我们的示例应用,以下提示可用于识别哪个 GUI 元素与给定的用户输入最密切相关。在运行时,可以从我们的 GUI 元素元数据中提取元素详细信息占位符:

A web interface has the following elements:
__PLACEHOLDER_FOR_ELEMENT_DETAILS__

Which element is the following user message about?
__PLACEHOLDER_FOR_USER_INPUT__

Element:
识别用户输入中的值

如果用户给出的指令导致将值分配给 GUI 元素,我们需要从用户输入中提取该值。并且我们需要以可以编程使用的方式表达该值。例如,数字“五”将需要是数字“5”。

对于我们的示例应用程序,以下提示可用于提取用户输入中指定的任何值。此提示由上一个提示、提示生成的输出以及导致 LLM 识别值的额外部分组成:

A web interface has the following elements:
__PLACEHOLDER_FOR_ELEMENT_DETAILS__

Which element is the following user message about?
__PLACEHOLDER_FOR_USER_INPUT__

Element: __PLACEHOLDER_FOR_ELEMENT_ID__

What value should the element be set to?

Value:

5.4 添加应用程序逻辑以响应用户输入

回答 NL 问题

如果用户输入被归类为问题(上面的提示 3.1),我们的应用程序必须确定问题涉及哪个元素(提示 3.2)。然后,应用程序需要提示 LLM 回答问题,并基于相关元素的信息。

对于我们的应用,以下提示可用于回答用户基于从 GUI 元素元数据中提取的信息提出的问题:

Article:
-------
## Element name
__ELEMENT_PLACEHOLDER__

## Task element performs
__TASK_PLACEHOLDER__

## About this element
__ARTICLE_PLACEHOLDER__
-------

Answer the following question using only information from the article.

Question: __USER_INPUT_PLACEHOLDER__

Answer: 
激活 GUI 元素

当用户输入被归类为操作请求(提示 3.1)时,应用程序需要执行以下步骤:

  • 确定操作请求与哪个元素相关(提示 3.2)
  • 提取用户输入中指定的任何值(提示 3.3)
  • 执行相关元素元数据中指定的actions_arr 中列出的函数

假设我们的应用程序收到以下用户输入:

过滤掉 1 月底之后的所有内容

我们的应用程序将按如下方式处理此输入:

  • 相关元素是 final_date_input
  • 值为 2024-01-31
  • 要执行的函数是:openFiltersMenu 和 setFinalDateInput(传入日期字符串值)

要重新加载应用了过滤器的页面,用户需要单击“重新加载”按钮(或提供 NL 输入,如“重新加载页面”。)

当用户看到 GUI 中的字段被填充或激活时,这有助于解释发生了什么以及系统如何响应用户输入。

6、扩展此方法

上面的例子非常简单。以下是将此方法应用于为实际应用程序构建 NL 界面的注意事项。

更复杂的用户输入:

  • 不同类型的输入 - 除了问题和操作请求之外,还会有其他类型的用户输入。并且用户输入的类型会有所不同,具体取决于应用程序的性质。
  • 复杂的多跳输入 - 上面的示例用户输入一次仅与一个元素相关。实际上,您的用户将给出与多个元素相关的指令,并且需要多个操作来响应。处理这些情况的一种策略是预处理用户输入以将输入分解为其组成部分。
  • 多个输入值 — 上面的示例用户输入仅包含一个需要传递给函数的值(日期字符串)。实际上,某些函数需要多个参数。当参数属于不同的数据类型时,处理这些情况的一种策略是按数据类型分离提取的值。

更复杂的应用程序:

  • 许多 GUI 元素 — 大多数应用程序都包含如此多的元素,以至于您无法一次性将所有元素元数据拉入提示中获得良好的结果。(LLM 会迷失在所有这些信息中。)因此,您的应用程序需要搜索可能元素的子集,并仅包含提示中这些元素的元数据。
  • 生成元素元数据 — 构建 GUI 后,可以从应用程序代码中自动提取大部分元素元数据。
  • 利用文档 — 您的应用更有可能从其他地方(例如文档、博客文章等)提取文章,而不是将文章硬编码到 article_txt_arr 中。

UX 设计:

  • 将填写字段与提交操作分开 — 在上面的示例中,当用户要求过滤掉 1 月底之后的所有数据时,final_date_input 字段已填写,但未触发“重新加载”按钮。将 reloadPage 函数添加到 final_date_input 元素的 action_arr 中很简单。但有时,采取这样的两个步骤可以让用户更容易看到系统的响应方式。
  • 不可逆操作 — 考虑某些操作是否不应该通过 NL 界面进行。正如 GUI 如今使用确认弹出窗口一样,实施某种机制来防止误解的指令永久删除文件、将所有资金转出账户、通过电子邮件回复所有人或任何其他潜在危险且不可逆的操作是明智之举。
  • 脱离上下文的输入 — 用户会询问超出应用范围的问题,并指示应用执行不属于其编程的任务。如果您尝试通过用于范围内输入的逻辑来限制所有输入,用户会对结果不满意,并不断重新措辞他们的输入,以尝试让应用执行他们想要的操作。相反,最好构建一个可以识别输入何时超出范围的组件,然后将该信息传递给用户。
  • LLM 错误处理 — 上述建议的方法旨在降低 LLM 幻觉的可能性和影响。例如,当上面的示例应用程序对用户输入进行分类时,如果 LLM 生成除问题或 action_request 之外的任何内容,则应用程序逻辑可以指示用户重新措辞输入。同样,在识别相关元素时,只有当生成的输出是 GUI 元素元数据中列出的有效 DOM 标识符时,应用程序才会继续前进。在这两种情况下,即使 LLM 产生了奇怪或可恶的输出,应用程序逻辑也会防止用户受到伤害。对于问答系统,有多种策略可以识别有害输出,以便不返回该输出。在生产应用中,为 LLM 生成输出的每个步骤构建保护措施。

7、结束语

随着时间的推移,常见的 NL 界面模式将会出现,用户会认识甚至期待这些模式。但就目前而言,当我们正处于向广泛采用 NL 界面过渡的开始阶段时,将 GUI 元素与 NL 输入相结合是两全其美的:GUI 设计的结构有助于我们构建 NL 界面,而 GUI 的元素则为用户提供有关他们可以执行哪些任务以及如何谈论这些任务的提示。就像拥有安全网一样,拥有 GUI 可以让您的 NL 界面更加大胆和创新。


原文链接:Natural language interfaces powered by large language models

汇智网翻译整理,转载请标明出处