通过技能让 RMI ADK 智能体具备领域专业知识

进行推理的智能体。

概览

大语言模型拥有广泛的通用知识,但它们并不了解您所在领域的具体指标、数据库架构或计算公式。如果没有这种背景信息,模型就会进行猜测,从而导致 SQL 错误和分析缺陷。

RMI ADK 智能体通过技能 解决了这一限制。假设用户 询问 “昨天 Storrow Drive 的拥堵情况如何?”。为了回答这个问题,智能体必须 知道 RMI 将拥堵情况表示为 出行时间指数 (TTI),即 实时 duration_in_seconds 与自由流 static_duration_in_secondshistorical_travel_time 表中的比率。没有技能的智能体可能会发明一个 average_speed 列(RMI 仅报告分类速度,从不报告 km/h),或者应用错误的公式,从而生成一个自信但错误的答案。

虽然智能体需要这种领域知识,但将每个指标定义、表架构和 SQL 注意事项都放入单个系统提示中效率低下。

大型系统提示的限制

将所有领域规则和架构都放入单个系统提示中会导致以下几个问题:

  • 成本更高,响应速度更慢:每次都发送大量提示会浪费令牌并增加延迟时间,即使对于不需要这些规则的问题也是如此。
  • 指令遵循能力更差:随着提示因极端情况而变得越来越长, 模型更有可能忽略或忘记特定规则。
  • 维护难度更大:将所有内容组合到一个提示中,使得在不破坏其他规则的情况下更新或测试单个规则变得困难。

技能

智能体技能 将领域知识整理到模块化文件夹中,智能体仅在需要时加载这些文件夹。每个技能都是一个目录,其中包含一个带有 Markdown 说明和 YAML 标头的 SKILL.md 文件。

智能体不会预先加载所有内容,而是在其基本提示中仅保留每个技能的简短 description。当用户提出与技能相关的问题时,智能体会加载该轮的完整说明。这样可以保持提示较小,并为实际对话记录节省上下文空间。

技能还提供了清晰的关注点分离:您可以单独编写、测试和更新各个功能,而不会在不相关的领域中造成意外的副作用。生产智能体通常使用多个专注的技能,而不是一个巨大的提示。

技能剖析

SKILL.md 文件包含两个部分:用于路由的 YAML 标头和用于说明的 Markdown 正文。

1. YAML 标头

---
name: rmi-traffic-metrics-grounding
description: >
  Standard traffic performance metrics computable from RMI BigQuery
  tables. Covers congestion severity (TTI), delay, travel time
  reliability (LOTTR, BTI, PTI, CoV), congestion frequency, speed
  breakdowns, and network-wide congestion rates. Use when the user asks
  about traffic conditions, congestion, reliability, delay, or network
  health.
---

模型使用 description 来决定是否加载技能。由于模型在决定加载技能之前只会看到此说明,因此请确保其中清楚列出了涵盖的主题、典型的用户措辞以及何时触发该技能。

2. Markdown 正文

正文提供了模型加载后遵循的领域特定指导。 RMI 指标技能正文包括确切的 TTI 公式 (duration_in_seconds / static_duration_in_seconds)、每个指标的经过验证的 BigQuery SQL 模板,以及将用户意图映射到正确指标的触发短语。提供结构化、经过验证的说明可确保模型有依据,并防止其猜测架构或公式详细信息。

使用 ADK 注册技能

将技能分组到 SkillToolset 中,并将其添加到智能体的工具列表中:

from google.adk import skills
from google.adk.tools import skill_toolset

rmi_skill_toolset = skill_toolset.SkillToolset(
    skills=[
        # TRAFFIC_METRICS_SKILL_DIR points to the skill's SKILL.md folder.
        skills.load_skill_from_dir(TRAFFIC_METRICS_SKILL_DIR),
    ],
)

# root_agent = llm_agent.Agent(..., tools=[*bq_tools, rmi_skill_toolset])

在这里,TRAFFIC_METRICS_SKILL_DIR 指向包含流量指标接地技能的目录。

将工具与技能捆绑

由于技能是基于文本的说明,因此仅依靠模型来解释和执行复杂的逻辑可能会导致不一致。将可执行工具附加到技能可提供确定性:代码处理严格的计算、验证和 API 交互,而技能则指示模型何时以及如何使用它们。

捆绑工具还可以避免全局上下文膨胀。工具不会预先公开每个专用工具,而是限定为仅在相应的领域技能处于活动状态时加载。

您可以直接在技能的 YAML 标头中将特定工具附加到技能:

metadata:
  adk_additional_tools:
    - calculate_custom_metric

这样可确保模型及时收到工具架构及其使用说明,从而保持基本工具集的精简。

示例:接地拥堵查询

  1. 用户询问“晚高峰时段 Storrow Drive 的拥堵情况如何?”
  2. 基本系统提示仅宣传每个技能的名称和说明,因此智能体看到 rmi-traffic-metrics-grounding 涵盖“拥堵”,并调用 load_skill 以提取此查询的完整说明。
  3. 加载技能后,智能体会应用 TTI 定义及其提供的经过验证的 SQL 模板,根据 historical_travel_time 计算比率,而不是猜测公式。

由于仅在查询需要时才会提取技能的正文,因此智能体从未使用过的技能永远不会进入上下文,从而保持基本系统提示较小。

要点总结

  • 使用领域指导接地:提供明确的说明、约束、 和业务逻辑,而不是依赖于一般的模型假设。
  • 使用模块化技能:将知识拆分为专注的技能,而不是一个巨大的系统提示,以节省 token、缩短延迟时间并提高准确率。
  • 编写清晰的说明:添加特定的触发短语和关键字 在每个技能的说明中,以便智能体可靠地加载该技能。
  • 添加具体示例:向技能正文中添加经过验证的示例和参考 工作流,以保持输出的一致性和准确性。
  • 捆绑工具以实现确定性:将可执行工具附加到技能,以 处理严格的验证和执行,同时保持基本工具集的精简。

后续步骤

贡献者

Nathaniel Thomas | 软件工程实习生,Google Maps Platform