chat - Talent 开发详解与预置封装
2026年7月30日 下午3:58:34
这部分内容比较多,专门做了一个分组:
1、Talent 接口方法一览
Talent 是 Solon AI 中领域能力的顶层接口,定义于 org.noear.solon.ai.chat.talent.Talent,自 3.8.4 起提供。接口所有方法均提供 default 实现,子类按需覆盖。
| 方法签名 | 默认值 | 说明 |
|---|---|---|
boolean isEnabled() | true | 是否启用该才能 |
void setEnabled(Boolean enabled) | — | 动态启用或禁用(@since 4.0.4) |
String name() | 类名 | 才能名称,用于标识与 System Message 注入 |
String description() | null | 才能描述 |
TalentMetadata metadata() | name + description | 才能元信息(含 name / description / category / tags / sensitive) |
boolean isSupported(Prompt prompt) | true | 准入检查,决定本才能是否对当前请求生效 |
void onAttach(Prompt prompt) | 空实现 | 激活钩子,才能被激活时调用,可用于初始化或审计 |
String getInstruction(Prompt prompt) | null | 动态指令注入,返回值追加至 System Message |
Collection<FunctionTool> getTools(Prompt prompt) | null | 动态工具注入,返回本才能提供的工具集合 |
TalentMetadata 用于携带才能的元信息,支持链式构建:
new TalentMetadata("weather", "提供天气查询能力")
.category("tools")
.tags("weather", "query")
.sensitive(false);
2、自定义 Talent 开发步骤
自定义 Talent 有两种构建方式,视场景选择。
方式一:继承 AbsTalent(推荐,工程化程度高)
继承 AbsTalent 基类,通过 @ToolMapping 注解定义工具方法。基类会在构造时通过 MethodToolProvider 自动扫描并注册所有带注解的方法,无需手动维护工具列表。
@Component
public class WeatherTalent extends AbsTalent {
@Override
public String name() {
return "weather";
}
@Override
public String description() {
return "提供天气查询能力";
}
@Override
public boolean isSupported(Prompt prompt) {
// 根据 Prompt 内容决定是否激活,此处对所有请求生效
return true;
}
@Override
public String getInstruction(Prompt prompt) {
return "当用户询问天气时,使用 get_weather 工具查询实时天气数据。";
}
@ToolMapping(description = "查询指定城市的天气")
public String get_weather(@Param(description = "城市名称") String city) {
// 调用天气 API 或本地逻辑
return city + ":晴天,25°C";
}
}
@Component场景下,可通过@Inject在 Talent 内注入其他 Bean,实现与业务服务的解耦。
方式二:通过 TalentDesc 声明式构建(轻量场景)
适合不需要独立类文件的简单或临时才能,使用 Lambda 进行函数式定义:
Talent weatherTalent = new TalentDesc("weather")
.description("提供天气查询能力")
.isSupported(prompt -> true)
.instruction(prompt -> "当用户询问天气时,使用 get_weather 工具查询实时天气数据。")
.toolAdd(/* 通过 FunctionTool 工厂方法或 @ToolMapping 扫描结果添加工具 */)
.build();
两种方式对比
| 特性 | TalentDesc 声明式 | AbsTalent 继承式 |
|---|---|---|
| 构建风格 | 函数式 / 链式调用 | 面向对象 / Override |
| 工具定义 | Lambda / 手动添加 | @ToolMapping 自动扫描 |
| 依赖注入 | 需手动从上下文获取 | 可通过容器 @Inject 注入 |
| 状态维护 | 不易持有复杂成员状态 | 支持成员变量与生命周期管理 |
| 推荐用途 | 快速定义、局部动态逻辑 | 复杂业务、多工具协作、深度工程化 |
注册到 ChatModel
ChatModel chatModel = ChatModel.of("https://...")
.apiKey("...")
.model("...")
.build();
// 全局默认注册(对该 ChatModel 的所有请求生效)
chatModel.defaultTalentAdd(new WeatherTalent());
// 单次请求临时注册
chatModel.prompt("明天上海天气如何?")
.options(o -> o.talentAdd(new WeatherTalent()))
.call();
3、内置预置 Talent 列表
HarnessEngine 内置 Talent(14 个)
HarnessEngine 是 Solon AI 的运行时编排中心,通过工具权限名(ToolName)按需激活对应 Talent。以下为全部 14 个内置 Talent:
| Talent 类名 | 工具权限名 | 主要能力 |
|---|---|---|
TerminalTalent | read / write / edit / glob / grep / ls / bash | 终端交互、文件读写、内容搜索、Shell 命令执行 |
CodeTalent | code | 代码项目分析,自动识别技术栈并向 System Message 注入工程规约 |
TodoTalent | todo / todoread / todowrite | 任务清单管理(主代理文件持久化模式,子代理内存模式) |
TaskTalent | task / subagent | 复杂任务拆解与子 Agent 委派(需启用 subagent 能力) |
GenerateTalent | generate | 调用子 Agent 执行内容生成任务(需启用 subagent 能力) |
ClockTalent | —(始终注册) | 提供当前时间感知,任意工具注册后自动添加,无需显式指定 |
WebfetchTalent | webfetch | 抓取指定 URL 的网页内容并转换为 Markdown 格式返回 |
WebsearchTalent | websearch | 执行实时 Web 搜索并返回摘要结果 |
CodeSearchTalent | codesearch | 编程相关知识检索,针对 API、库与代码模式查询优化 |
LspTalent | lsp | 语言服务协议(LSP)集成,提供代码补全、跳转定义、诊断等 |
McpGatewayTalent | mcp | MCP 协议服务端工具聚合网关,动态代理已注册的 MCP 工具集 |
OpenApiGatewayTalent | openapi / restapi | OpenAPI/REST 服务工具聚合网关,根据 OpenAPI 描述文件暴露工具 |
MemoryTalent | memory | 对话记忆持久化与语义检索,支持跨会话长期记忆 |
SkillTalent | skill | 技能库发现与动态加载,从 SKILL.md 驱动 Agent 专项行为 |
预定义权限组合
HarnessEngine 提供三组开箱即用的工具权限常量集合,通过 toolsAdd(TOOL_ALL_PUBLIC) 等方式使用:
| 常量名 | 说明 |
|---|---|
TOOL_ALL_FULL | 全量工具(含高级工具:mcp / openapi / hitl / memory / lsp / generate 等) |
TOOL_ALL_PUBLIC | 公有工具全集(主流场景推荐,不含高级网关与人机交互) |
TOOL_PI | 编程交互精简集(仅 read / write / edit / bash 系列) |
4、Talent 与 Tool 的关系
Talent 是 Tool 的聚合载体,二者的核心关系:
- 一个 Talent 可包含多个 Tool:
getTools()返回多个FunctionTool,统一挂载到推理上下文,模型可在同一才能语境下按需调用。 - Talent 额外提供 Instruction:通过
getInstruction()向 System Message 注入领域 SOP,裸 Tool 本身不具备此能力。 - 注册 Talent 自动注册其工具:无需再单独调用
toolAdd(),Talent 注册后其内含的所有工具自动对本次推理可见。 - 工具染色:借鉴 MCP 思想,Talent 的元信息(name / description)会注入到旗下工具的元数据中,模型可感知工具的才能归属。
- 整体开关:
isEnabled / setEnabled对整个 Talent 及其内含工具做统一启用/禁用(@since 4.0.4)。
Talent 生命周期
每次推理调用时,Talent 框架按以下顺序驱动所有已注册才能:
注册阶段
└─ chatModel.defaultTalentAdd(talent) // 全局
options.talentAdd(talent) // 单次
触发阶段(每次推理)
├─ isEnabled() → false 则跳过整个才能
├─ isSupported(prompt) → false 则跳过(基于 Prompt 上下文感知)
├─ onAttach(prompt) → 初始化 / 审计日志
├─ getInstruction(prompt) → 注入 System Message(独立 Talent 块)
└─ getTools(prompt) → 挂载并染色工具集合
5、Talent 的动态启用与禁用(@since 4.0.4)
Talent 接口提供 setEnabled(Boolean enabled) 方法,AbsTalent 基类已提供线程安全的 volatile boolean 默认实现。调用该方法可在不取消注册的前提下临时禁用某个 Talent。
WeatherTalent weatherTalent = new WeatherTalent();
chatModel.defaultTalentAdd(weatherTalent);
// 临时禁用(不移除注册结构,不影响其他 Talent)
weatherTalent.setEnabled(false);
// 重新启用
weatherTalent.setEnabled(true);
典型应用场景:
- A/B 测试:对不同用户会话启用不同的 Talent 组合,无需重建 ChatModel 实例。
- 资源控制:在高并发或资源受限时临时关闭消耗较大的 Talent(如
WebsearchTalent)。 - 权限管控:根据用户角色或请求上下文动态开关敏感 Talent,无需维护多套注册配置。
- 调试隔离:在排查问题时单独禁用某个 Talent,保持整体注册结构不变。
与 isSupported() 的区别:
setEnabled(false) | isSupported() 返回 false | |
|---|---|---|
| 触发时机 | 一次性全局开关,持续生效 | 每次推理时动态评估 |
| 决策依据 | 外部主动调用 | 基于当前 Prompt 上下文 |
| 生命周期 | 跳过全部钩子(onAttach 等也不执行) | 跳过激活阶段,但 isEnabled 已通过 |
| 典型用途 | 资源控制、运维开关 | 按场景/内容智能感知 |