概览
大语言模型拥有广泛的通用知识,但并不了解您网域中的特定指标、数据库架构或计算公式。如果没有此上下文,模型会进行猜测,从而导致 SQL 不正确和分析有缺陷。
RMI ADK 代理通过技能来解决此限制。假设用户询问“昨天 Storrow Drive 的拥堵情况如何?”。为了回答这个问题,代理必须知道 RMI 将拥堵表示为出行时间指数 (TTI),即 historical_travel_time 表中实时 duration_in_seconds 与畅通 static_duration_in_seconds 的比率。没有技能的代理可能会虚构一个 average_speed 列(RMI 报告仅包含分类速度,从不包含 km/h),或者应用错误的公式,从而生成自信但错误的答案。
虽然代理需要这些领域知识,但将每个指标定义、表架构和 SQL 注意事项都放入单个系统提示中效率低下。
大型系统提示的限制
将所有网域规则和架构都放入单个系统提示中会导致以下几个问题:
- 成本更高,响应更慢:在每个回合中发送大量提示会浪费令牌并增加延迟时间,即使对于不需要这些规则的问题也是如此。
- 指令遵循能力变差:随着提示变得越来越长,包含的极端情况也越来越多,模型更有可能忽略或忘记特定规则。
- 维护难度更大:将所有内容都整合到一个提示中,很难在不破坏其他规则的情况下更新或测试单个规则。
技能
智能体技能将领域知识整理到模块化文件夹中,智能体仅在需要时才加载这些文件夹。每项技能都是一个目录,其中包含一个 SKILL.md 文件(带有 Markdown 说明和 YAML 标头)。
智能体不会预先加载所有内容,而只会将每项技能的简短 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
这样可确保模型及时收到工具架构及其使用说明,从而保持精简的基本工具集。
示例:根据上下文信息回答拥堵查询
- 用户询问“Storrow Drive 在晚高峰时段的拥堵程度如何?”
- 基本系统提示仅宣传每项技能的名称和说明,因此代理会看到
rmi-traffic-metrics-grounding涵盖“拥堵”,并调用load_skill来获取此查询的完整指令。 - 加载技能后,智能体应用 TTI 定义和它提供的经过验证的 SQL 模板,计算与
historical_travel_time的比率,而不是猜测公式。
由于技能的正文仅在查询需要时才会被提取,因此智能体从未使用过的技能永远不会进入上下文,从而使基本系统提示保持较小的规模。
要点总结
- 根据网域指导进行接地:提供明确的指令、限制和业务逻辑,而不是依赖于一般的模型假设。
- 使用模块化技能:将知识拆分为专注的技能,而不是一个庞大的系统提示,以节省 token、缩短延迟时间并提高准确性。
- 撰写清晰的说明:在每项技能的说明中添加具体的触发短语和关键字,以便代理可靠地加载相应技能。
- 添加具体示例:向技能主体添加经过验证的示例和参考工作流,以确保输出内容的一致性和准确性。
- 捆绑工具以实现确定性:将可执行工具附加到技能,以处理严格的验证和执行,同时保持基本工具集的精简。
后续步骤
- 探索高级技能模式:阅读使用技能构建 ADK 智能体的开发者指南,了解 ADK 技能。
贡献者
Nathaniel Thomas | Google Maps Platform 软件工程实习生