跳转至正文

交互模式

了解如何平衡 LLM 能力与传统代码,并实现护栏以管理非确定性的 AI 行为。

把对 LLM 的请求想成调用函数是一个错误。在相同顺序下给定相同输入,函数行为可预测。我们可以编写测试、注入故障,并针对多种输入加固函数。

LLM 并非如此。更好的做法是把 LLM 当作用户,并同样对待从它获得的数据。与用户一样,LLM 是非确定性的,常常出错(部分或全部),有时纯属随机。要在这些条件下保护应用,我们需要围绕 LLM 输入建立与用户输入相同的护栏。

若能做到这一点,我们就能为应用带来可与人类媲美的解题与创造力等非凡能力。

关注点分离

#

LLM 有擅长与不擅长之事;关键是在应用中发挥长处、减轻短处。以 Crossword Companion 中的任务列表为例:

Crossword task list showing solved clues in green with confidence
percentages and unsolved clues in red

任务列表是需要求解的线索集合。目标是用任务列表中的颜色和解法在求解过程中展示进度。最初实现为模型提供了管理任务列表的工具,要求它在进行时更新进度。 Flash 无法以此方式解谜,Pro 可以。不幸的是,它大块求解,只记得更新一两次任务列表,中间间隔很长。无论怎么提示都无法让它边做边更新任务。你会在现代 AI 智能体管理自己的任务列表时看到同样行为;这正是当前 LLM 演进所处的阶段。

那么如何一致、确定地更新任务列表?把任务管理从 LLM 手中拿走,在代码中处理。

概括而言,在对你面临的问题应用 LLM 方案之前,先问自己 LLM 是否最适合该工作。类人的解题与创造力是否值得不可预测性的代价?

答案需要实验。以下是示例中的一些例子:

任务 LLM 适用性 代码适用性
解析网格的尺寸、内容与线索 借助视觉与语言理解,非常适合 LLM 用代码实现很困难
验证网格内容 可用另一个 LLM 检查工作 人类扫一眼并调整更容易
处理任务列表 LLM 很难一致完成 用代码遍历任务列表并边做边更新很容易
求解每条线索 借助语言理解与生成,非常适合 LLM 现实线索依赖文字游戏、人名、俚语时很难用代码做
解决冲突 LLM 在这种循环上不一致 人类扫一眼并调整很容易

这当然是判断题,但若能合理用代码实现,结果就可预测。若写代码不合理地困难,则考虑 LLM,并知道你必须像示例中那样建立护栏。

询问 (Ask) 与智能体 (Agent)

#

除了代码与 LLM 之外,还要考虑的不止一个支点。模型大致有两种模式:「ask(询问)」和「agent(智能体)」。

当我们提示 LLM 却不给它能改变世界状态的工具时,它处于「ask」模式,例如完全没有工具,或只有查找数据的工具。填字游戏推断模型和线索求解模型都在 ask 模式下运行,工具仅用于获取额外数据。

另一方面,当我们给 LLM 一组工具,让它代表我们在世界中操作——如读写文件、执行 bash 命令、加载网页、调用 Web API 等—— 该 LLM 处于「agent」模式。

护栏

#

ask 与 agent 模式的区别不在于你选的模型或给的提示词,而在于你提供的工具。工具与工具调用一节所述的智能体循环结合,允许 LLM 按自己的决定任意次数调用这些工具。赋予这种能力意味着你有责任将其视为不可预测——更像人而非程序。

做法与验证用户输入相同:建立一套测试,观察应用如何应对 LLM 响应。给真实 LLM 多种提示词并 mock 工具,评估 LLM 如何使用它们。就像第一次用户测试,第一次 LLM 测试结果可能让你意外。用这些数据建立加固应用所需的护栏。

在示例中,我们不必防范伤害,但要防范不完美结果。针对真实数据的广泛测试促成了人机回圈 (human-in-the-loop) 护栏:防止尝试求解无效谜题或冲突解法。这样,Flutter 与 Firebase AI Logic 成为驾驭 LLM 能力、为应用带来独特功能的理想组合。