Solon v3.8.3

skills - helloworld

</> markdown
2026年1月22日 下午10:19:50

1、引入依赖

<dependency>
    <groupId>org.noear</groupId>
    <artifactId>solon-ai</artifactId>
</dependency>

2、构建技能组件(Skill)

@Component
public class WeatherSkill extends AbsSkill {
    //封装权限(准入控制)
    @Override
    public boolean isSupported(ChatPrompt prompt) {
        //演示:获取更多属性,用于准入控制(需要请求明传入)
        ChatSession session = prompt.attrAs("session");

        return prompt.getUserContent().contains("天气");
    }

    //封装指令
    @Override
    public String getInstruction(ChatPrompt prompt) {
        return "如果有什么天气问题,可以问我";
    }

    //封装能力
    @ToolMapping(description = "查询天气预报")
    public String getWeather(@Param(description = "城市位置") String location) {
        return "晴,14度";
    }
}

3、聊天模型配置与构建

@Configuration
public class ChatConfig {
    @Bean
    public ChatModel chatModelForSkill(WeatherSkill weatherSkill) {
        return ChatModel.of(_Constants.chat_apiUrl)
                .provider(_Constants.chat_provider)
                .model(_Constants.chat_model)
                .defaultSkillAdd(weatherSkill)
                .build();
    }
}

4、与 Web 控制器集成


@Mapping("chat")
@Controller
public class ChatController {
    @Inject
    ChatModel chatModel;

    @Produces(MimeType.TEXT_PLAIN_VALUE)
    @Mapping("call")
    public String call(String query) throws Exception {
        //仅用于演示
        ChatSession session = InMemoryChatSession.builder().build();

        //演示:添加提示词属性(用于 Skill)
        Prompt prompt = Prompt.of(query).attrPut("session", session);
    
        return chatModel.prompt(prompt)
                .session(session)
                .call()
                .getMessage()
                .getContent();
    }

    @Produces(MimeType.TEXT_EVENT_STREAM_VALUE)
    @Mapping("stream")
    public Flux<String> stream(String prompt) throws Exception {
        return Flux.from(chatModel.prompt(prompt).stream())
                .subscribeOn(Schedulers.boundedElastic()) //加这个打印效果更好
                .filter(resp -> resp.hasContent())
                .map(resp -> resp.getContent())
                .concatWithValues("[DONE]"); //有些前端框架,需要 [DONE] 实识用作识别
    }
}