### 1、引入依赖

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


### 2、构建技能组件（Skill）

```java
@Component
public class WeatherSkill extends AbsSkill {
    //封装权限（准入控制）
    @Override
    public boolean isSupported(Prompt prompt) {
        //演示：获取更多属性，用于准入控制（需要请求明传入）
        String role = prompt.attrAs("role");

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

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

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


### 3、聊天模型配置与构建


```java
@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 控制器集成


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

    @Produces(MimeType.TEXT_PLAIN_VALUE)
    @Mapping("call")
    public String call(String query) throws Exception {
        //演示：添加提示词属性
        Prompt prompt = Prompt.of(query).attrPut("role", "ADMIN");
    
        return chatModel.prompt(prompt)
                .call()
                .getContent();
    }

    @Produces(MimeType.TEXT_EVENT_STREAM_VALUE)
    @Mapping("stream")
    public Flux<String> stream(String query) throws Exception {
        //演示：添加提示词属性
        Prompt prompt = Prompt.of(query).attrPut("role", "ADMIN");
        
        return chatModel.prompt(prompt)
                      .stream()
                      .subscribeOn(Schedulers.boundedElastic()) //加这个打印效果更好
                      .filter(resp -> resp.hasContent())
                      .map(resp -> resp.getContent())
                      .concatWithValues("[DONE]"); //有些前端框架，需要 [DONE] 实识用作识别
    }
}
```