Solon v3.8.3

skills - 提示语(Prompt)的动态赋能

</> markdown
2026年1月22日 下午10:58:43

在 Solon AI 中,ChatPrompt(实现类为 Prompt) 不仅仅是一个简单的消息集合,它是一个具备感知能力的“执行上下文”。通过 attrs(属性)机制,开发者可以为 AI 的执行过程注入动态参数与运行时资源,这是构建工业级 Agent 的核心基础。

1、Prompt 及运行时属性

ChatPrompt 接口通过 attrs() 提供了一个全生命周期的属性桶(Attribute Bucket)。与传统的静态元数据(Metadata)不同,attrs 专为运行态设计:

  • 动态性: 支持挂载 ChatSession(有状态会话)、业务拦截器状态、或数据库连接等动态对象。
  • 本地化隔离: attrs 中的数据仅在后端流转,不参与提示词染色。这意味着你可以放心地放入 user_idrole_level 等敏感业务属性,而不用担心它们被泄露给远端大模型。
  • 语义萃取: 提供了 getUserContent() 逆序查找算法。它能穿透多轮对话的噪音,精准定位用户最后一次输入的有效意图,确保 Skill 的判断始终基于当前的最新上下文。

接口参考:

public interface ChatPrompt {
    //获取属性
    Map<String, Object> attrs();

    //获取属性
    default Object attr(String key) {
        return attrs().get(key);
    }
    
    //获取属性
    default <T> T attrAs(String key) {
        return (T) attrs().get(key);
    }

    //获取属性
    default <T> T attrOrDefault(String key, T def) {
        return (T) attrs().getOrDefault(key, def);
    }

    //获取消息
    List<ChatMessage> getMessages();

    //获取首条消息
    ChatMessage getFirstMessage();

    //获取最后消息
    ChatMessage getLastMessage();

    //获取用户消息内容
    String getUserContent();

    //获取系统消息内容
    String getSystemContent();

    //是否为空
    boolean isEmpty();

    //是否为空
    static boolean isEmpty(ChatPrompt prompt) {
        return prompt == null || prompt.isEmpty();
    }
}

2、动态赋能:基于业务上下文的 Skill 决策逻辑

基于 Prompt 的属性机制,Skill 获得了超越普通工具(Tool)的“工程智力”,主要体现在以下三个维度:

A. 环境感知的准入检查 (isSupported)

Skill 可以通过 Prompt.attr() 实时感知业务环境,实现动态唤醒:

  • 权限管控:只有当 attr("role") 为管理员时,才激活“系统管理技能”。
  • 状态过滤:根据 attr("step") 的进度,动态决定当前是否应该唤醒某个特定环节的技能包。

B. 运行时资源共享 (onAttach)

Skill 可以在执行生命周期内操作 Prompt 的属性,实现黑板模式的协作:

  • 上下文补全:在 Skill 被附着(Attach)时,根据 attrs 中的用户信息,预先从数据库加载业务背景存入 attrs
  • 信息共享:多个协同的 Skill 之间可以通过修改 attrs 共享中间计算结果,避免重复查库或重复计算。

C. 指令的动态增强 (getInstruction)

Skill 不再提供死板的提示词,而是可以根据属性动态生成。

  • 个性化偏好:读取 attr("language_style"),动态调整注入给大模型的 System Instruction,实现一套代码适配万千租户的业务规约。

3、代码实战:多租户权限感知技能

在这个示例中,我们实现一个“订单管理专家”技能。它会根据 attrs 里的租户 ID 锁定数据范围,并根据用户角色决定是否开放“取消订单”的工具。

public class OrderManagerSkill implements Skill {
    
    @Override
    public boolean isSupported(ChatPrompt prompt) {
        // 1. 语义检查:用户当前意图是否与“订单”相关(逆序获取最新意图)
        boolean isOrderTask = prompt.getUserContent().contains("订单");
        
        // 2. 环境检查:必须持有合法的租户 ID 属性才能激活
        boolean hasTenant = prompt.attr("tenant_id") != null;
        
        return isOrderTask && hasTenant;
    }

    @Override
    public String getInstruction(ChatPrompt prompt) {
        // 3. 动态指令:从 attrs 获取租户名,注入隔离指令
        // 这样模型就知道它只能处理该租户的数据,而不需要前端在 Prompt 里写明
        String tenantName = prompt.attrOrDefault("tenant_name", "未知租户");
        return "你现在是[" + tenantName + "]的订单主管。请只处理该租户下的订单数据,禁止跨租户查询。";
    }

    @Override
    public Collection<FunctionTool> getTools(ChatPrompt prompt) {
        List<FunctionTool> tools = new ArrayList<>();
        
        // 基础查询工具(所有激活技能的用户都有)
        tools.add(new OrderQueryTool());
        
        // 4. 权限隔离:只有属性中标记为 ADMIN 的用户,才动态挂载“取消订单”工具
        if ("ADMIN".equals(prompt.attr("user_role"))) {
            tools.add(new OrderCancelTool());
        }
        
        return tools;
    }
}