LangChain4j使用文档

LangChain4j 整合 Spring Boot 完整指南

目录

  1. 基础整合(纯Java)
  2. [Spring Boot Starter 整合](#Spring Boot Starter 整合)
  3. [高阶用法 - AiServices](#高阶用法 - AiServices)
  4. 流式响应
  5. 系统提示词
  6. 用户提示词
  7. 记忆功能
  8. [RAG 检索增强生成](#RAG 检索增强生成)
  9. [Tool 工具调用](#Tool 工具调用)
  10. [SSE 服务器推送](#SSE 服务器推送)

1. 基础整合(纯Java)

1.1 环境要求

  • JDK 17 及以上
  • Maven 3.6+
  • Spring Boot 3.x

1.2 添加依赖

xml 复制代码
<!-- langchain4j OpenAI 模块,需要 JDK 17+ -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-open-ai</artifactId>
    <version>1.0.1</version>
</dependency>

<!-- 日志依赖(可选) -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.5.18</version>
</dependency>

1.3 添加配置文件 application.yml

yaml 复制代码
langchain4j:
  open-ai:
    chat-model:
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      api-key: ${DASHSCOPE_API_KEY:your-api-key-here}  # 建议使用环境变量
      model-name: qwen-plus

1.4 创建配置类

java 复制代码
@Configuration
public class ChatModelConfig {

    @Value("${langchain4j.open-ai.chat-model.base-url}")
    private String baseUrl;
    
    @Value("${langchain4j.open-ai.chat-model.api-key}")
    private String apiKey;
    
    @Value("${langchain4j.open-ai.chat-model.model-name}")
    private String modelName;

    @Bean
    public OpenAiChatModel openAiChatModel() {
        return OpenAiChatModel.builder()
                .baseUrl(baseUrl)
                .apiKey(apiKey)
                .modelName(modelName)
                .timeout(Duration.ofSeconds(60))
                .maxRetries(3)
                .logRequests(true)   // 记录请求日志,需要添加日志依赖
                .logResponses(true)  // 记录响应日志,需要添加日志依赖
                .build();
    }
}

1.5 调用API获取对话内容

java 复制代码
@RestController
@RequestMapping("/chatModel")
public class ChatModelController {

    @Resource
    private OpenAiChatModel openAiChatModel;

    /**
     * 基本用法 - 获取模型对话内容
     * 
     * @param prompt 用户输入的提示词
     * @return AI返回的内容
     */
    @GetMapping("/content")
    public String content(@RequestParam String prompt) {
        return openAiChatModel.chat(prompt);
    }
}

1.6 日志输出示例

启用日志后,控制台会输出完整的HTTP请求和响应信息:

复制代码
HTTP request:
- method: POST
- url: https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions
- headers: [Authorization: Bearer ***], [User-Agent: langchain4j-openai], [Content-Type: application/json]
- body: {
  "model": "qwen-plus",
  "messages": [{
    "role": "user",
    "content": "hello"
  }],
  "stream": false
}

HTTP response:
- status code: 200
- body: {
  "choices": [{
    "message": {
      "content": "Hello! How can I assist you today?",
      "role": "assistant"
    },
    "finish_reason": "stop"
  }],
  "usage": {
    "prompt_tokens": 11,
    "completion_tokens": 22,
    "total_tokens": 33
  }
}

注意 : 日志中API Key会自动脱敏显示为 Bearer ***


2. Spring Boot Starter 整合

使用 Spring Boot Starter 可以大大简化配置,无需手动创建配置类。

2.1 添加依赖

xml 复制代码
<properties>
    <maven.compiler.source>17</maven.compiler.source>
    <maven.compiler.target>17</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- LangChain4j Spring Boot Starter -->
    <dependency>
        <groupId>dev.langchain4j</groupId>
        <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
        <version>1.0.1-beta6</version>
    </dependency>
</dependencies>

2.2 添加配置文件

yaml 复制代码
langchain4j:
  open-ai:
    chat-model:
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      api-key: ${DASHSCOPE_API_KEY:your-api-key-here}
      model-name: qwen-plus
      # 可选:开启日志
      log-requests: true
      log-responses: true

logging:
  level:
    dev.langchain4j: DEBUG

2.3 创建Controller

java 复制代码
@RestController
@RequestMapping("/hello")
public class HelloController {

    @Resource
    private OpenAiChatModel openAiChatModel;

    @GetMapping("/test")
    public String helloWorld(@RequestParam String prompt) {
        return openAiChatModel.chat(prompt);
    }
}

3. 高阶用法 - AiServices

AiServices 提供了更强大的功能,支持声明式接口定义。

3.1 添加依赖

xml 复制代码
<!-- AiServices 所需依赖 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-spring-boot-starter</artifactId>
    <version>1.0.1-beta6</version>
</dependency>

3.2 基于配置类的方式

3.2.1 定义Service接口
java 复制代码
public interface ConsultantService {
    String chat(String message);
}
3.2.2 创建配置类
java 复制代码
@Configuration
public class CommonConfig {

    @Resource
    private OpenAiChatModel openAiChatModel;

    @Bean
    public ConsultantService consultantService() {
        return AiServices.builder(ConsultantService.class)
                .chatModel(openAiChatModel)
                .build();
    }
}
3.2.3 创建Controller
java 复制代码
@RestController
@RequestMapping("/consultant")
public class ConsultantController {

    @Resource
    private ConsultantService consultantService;

    @GetMapping("/chat")
    public String chat(@RequestParam String prompt) {
        return consultantService.chat(prompt);
    }
}

3.3 声明式方式(推荐)

直接在接口上使用 @AiService 注解,无需配置类:

java 复制代码
@AiService
public interface ConsultantService {
    String chat(String message);
}

如果需要手动指定模型:

java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,  // 手动装配模式
    chatModel = "openAiChatModel"               // 指定ChatModel Bean名称
)
public interface ConsultantService {
    String chat(String message);
}

说明:

  • wiringMode = EXPLICIT:手动指定依赖,需明确指定 chatModel
  • wiringMode = IMPLICIT(默认):自动装配,框架会自动寻找对应的模型

4. 流式响应

流式响应可以实现类似"打字机"效果,逐步返回AI生成的内容。

4.1 添加依赖

xml 复制代码
<!-- WebFlux 用于支持响应式流 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<!-- LangChain4j Reactor 支持 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-reactor</artifactId>
    <version>1.0.1-beta6</version>
</dependency>

4.2 添加配置

yaml 复制代码
langchain4j:
  open-ai:
    # 流式模型配置
    streaming-chat-model:
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      api-key: ${DASHSCOPE_API_KEY:your-api-key-here}
      model-name: qwen-plus
      log-requests: true
      log-responses: true

logging:
  level:
    dev.langchain4j: DEBUG

4.3 定义流式接口

java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "openAiStreamingChatModel"  // 指定流式模型
)
public interface ConsultantStreamService {

    /**
     * 流式对话接口
     * 返回 Flux<String> 实现流式输出
     */
    Flux<String> chat(String message);
}

4.4 创建Controller

java 复制代码
@RestController
@RequestMapping("/stream")
public class StreamController {

    @Resource
    private ConsultantStreamService consultantStreamService;

    @GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chat(@RequestParam String prompt) {
        return consultantStreamService.chat(prompt);
    }
}

5. 系统提示词

系统提示词用于设定AI的角色和行为规则。

5.1 使用 @SystemMessage 注解(内联方式)

java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "openAiStreamingChatModel"
)
public interface ConsultantStreamService {

    @SystemMessage("你是辉哥的助手小月月,人美心善又多金。")
    Flux<String> chat(String message);
}

5.2 从文件加载系统提示词

当系统提示词较长时,建议将其放在单独的文件中:

创建 resources/system.txt 文件:

复制代码
你是专业的AI志愿填报顾问,可以给用户提供如下功能:
1. 查询目标院校的院校简介
2. 查询目标院校的录取规则
3. 查询目标院校的奖学金设置状况
4. 查询目标院校的食宿条件
5. 查询目标院校招生联系方式
6. 查询目标院校2024年不同专业录取情况
7. 查询热门专业
8. 查询天坑专业
9. 根据学生提供的分数和不同学校以及学校历年录取分数,推荐合适的学校和专业
10. 高考志愿填报一对一沟通预约服务

说明:
- 每次回答完用户问题,最后都加上一句话:如需专业志愿填报指导,建议预约一对一服务。
- 不要提及"根据您提供的信息"这样的话术
- 只回答有关高考志愿填报的问题,其它问题不予回答

在代码中引用:

java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "openAiStreamingChatModel"
)
public interface ConsultantStreamService {

    @SystemMessage(fromResource = "system.txt")
    Flux<String> chat(String message);
}

6. 用户提示词

用户提示词用于格式化用户输入的消息。

6.1 使用默认变量 it

java 复制代码
@AiService
public interface ConsultantStreamService {

    @UserMessage("请帮我分析以下问题:{{it}}")
    Flux<String> chat(String message);
}

6.2 使用自定义变量名 @V

java 复制代码
@AiService
public interface ConsultantStreamService {

    @UserMessage("请帮我分析以下问题:{{question}}")
    Flux<String> chat(@V("question") String message);
}

6.3 多个变量的情况

java 复制代码
@AiService
public interface AnalysisService {

    @UserMessage("请分析{{city}}的{{topic}}情况")
    String analyze(@V("city") String city, @V("topic") String topic);
}

7. 记忆功能

记忆功能让AI能够记住对话历史,实现上下文关联的对话。

7.1 内存记忆配置

7.1.1 创建 ChatMemory Bean
java 复制代码
@Bean
public ChatMemory chatMemory() {
    return MessageWindowChatMemory.builder()
            .maxMessages(20)  // 最多保留20条消息
            .build();
}
7.1.2 在接口中配置记忆
java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "openAiStreamingChatModel",
    chatMemory = "chatMemory"  // 指定记忆Bean
)
public interface ConsultantStreamService {
    Flux<String> chat(String message);
}

7.2 会话记忆隔离

上面的配置是所有用户共享同一个记忆,实际应用中需要按用户隔离。

7.2.1 创建 ChatMemoryProvider
java 复制代码
@Bean
public ChatMemoryProvider chatMemoryProvider() {
    return memoryId -> MessageWindowChatMemory.builder()
            .id(memoryId)           // 每个用户独立的记忆ID
            .maxMessages(20)
            .build();
}
7.2.2 在接口中使用
java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "openAiStreamingChatModel",
    chatMemoryProvider = "chatMemoryProvider"  // 使用Provider实现隔离
)
public interface ConsultantStreamService {

    @SystemMessage(fromResource = "system.txt")
    Flux<String> chat(@MemoryId String chatMemoryId, @UserMessage String message);
}
7.2.3 Controller中使用用户ID
java 复制代码
@RestController
@RequestMapping("/stream")
public class StreamController {

    @Resource
    private ConsultantStreamService consultantStreamService;

    @GetMapping(value = "/chat", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chat(
            @RequestParam String userId,    // 用户ID用于记忆隔离
            @RequestParam String message
    ) {
        return consultantStreamService.chat(userId, message);
    }
}

7.3 记忆持久化(Redis)

内存记忆在服务重启后会丢失,可以使用Redis进行持久化。

7.3.1 添加Redis依赖
xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
7.3.2 Redis配置
yaml 复制代码
spring:
  data:
    redis:
      host: localhost
      port: 6379
      password: ${REDIS_PASSWORD:}
7.3.3 实现 ChatMemoryStore
java 复制代码
@Service
public class RedisChatMemoryStore implements ChatMemoryStore {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private static final Duration EXPIRE_TIME = Duration.ofDays(1);

    @Override
    public List<ChatMessage> getMessages(Object memoryId) {
        String json = redisTemplate.opsForValue().get(memoryId.toString());
        return ChatMessageDeserializer.messagesFromJson(json);
    }

    @Override
    public void updateMessages(Object memoryId, List<ChatMessage> messages) {
        String json = ChatMessageSerializer.messagesToJson(messages);
        redisTemplate.opsForValue().set(memoryId.toString(), json, EXPIRE_TIME);
    }

    @Override
    public void deleteMessages(Object memoryId) {
        redisTemplate.delete(memoryId.toString());
    }
}
7.3.4 配置使用Redis存储
java 复制代码
@Configuration
public class ChatMemoryConfig {

    @Resource
    private ChatMemoryStore redisChatMemoryStore;

    @Bean
    public ChatMemoryProvider chatMemoryProvider() {
        return memoryId -> MessageWindowChatMemory.builder()
                .id(memoryId)
                .maxMessages(20)
                .chatMemoryStore(redisChatMemoryStore)  // 使用Redis存储
                .build();
    }
}

8. RAG 检索增强生成

RAG(Retrieval-Augmented Generation)可以让AI基于私有知识库回答问题。

8.1 添加依赖

xml 复制代码
<!-- Easy RAG 依赖,包含文档加载、分割、向量化等功能 -->
<dependency>
    <groupId>dev.langchain4j</groupId>
    <artifactId>langchain4j-easy-rag</artifactId>
    <version>1.0.1-beta6</version>
</dependency>

8.2 基础用法 - 加载文档到向量数据库

java 复制代码
@Configuration
public class RagConfig {

    /**
     * 构建向量数据库
     */
    @Bean
    public EmbeddingStore embeddingStore() {
        // 加载 classpath:contents 目录下的文档
        List<Document> documents = ClassPathDocumentLoader.loadDocuments("contents");
        
        // 创建内存向量存储
        InMemoryEmbeddingStore store = new InMemoryEmbeddingStore();

        // 将文档向量化并存入
        EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
                .embeddingStore(store)
                .build();
        ingestor.ingest(documents);
        
        return store;
    }

    /**
     * 构建内容检索器
     */
    @Bean
    public ContentRetriever contentRetriever(EmbeddingStore embeddingStore) {
        return EmbeddingStoreContentRetriever.builder()
                .embeddingStore(embeddingStore)
                .minScore(0.5)   // 最小相似度分数
                .maxResults(5)   // 最多返回5条结果
                .build();
    }
}

8.3 进阶用法 - 文档分割

直接将整个文档进行embedding效果不佳,需要对文本进行切分:

java 复制代码
@Bean
public ContentRetriever contentRetriever(EmbeddingStore embeddingStore) {
    // 1. 加载PDF文档(使用Apache PDFBox解析器)
    List<Document> documents = ClassPathDocumentLoader.loadDocuments(
            "contents", 
            new ApachePdfBoxDocumentParser()
    );

    // 2. 创建文本分割器
    // 参数:chunkSize=500字符,chunkOverlap=100字符
    DocumentSplitter documentSplitter = DocumentSplitters.recursive(500, 100);
    
    // 3. 配置Ingestor
    EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
            .embeddingStore(embeddingStore)
            .documentSplitter(documentSplitter)  // 使用文本分割器
            .build();
    ingestor.ingest(documents);

    // 4. 返回检索器
    return EmbeddingStoreContentRetriever.builder()
            .embeddingStore(embeddingStore)
            .minScore(0.5)
            .maxResults(5)
            .build();
}

8.4 在AiService中使用RAG

java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "openAiStreamingChatModel",
    chatMemoryProvider = "chatMemoryProvider",
    contentRetriever = "contentRetriever"  // 配置RAG检索器
)
public interface ConsultantStreamService {

    @SystemMessage(fromResource = "system.txt")
    Flux<String> chat(@MemoryId String chatMemoryId, @UserMessage String message);
}

9. Tool 工具调用

Tool功能让AI能够调用外部工具(如查询天气、计算等)。

9.1 创建工具类

java 复制代码
@Component
public class WeatherTool {

    /**
     * 查询天气工具
     * 方法描述非常重要,AI会根据描述判断是否调用此方法
     */
    @Tool("查询指定城市的当前天气情况,返回温度和天气状况")
    public String getWeather(String city) {
        System.out.println("正在查询天气: " + city);
        // 实际项目中可以调用第三方天气API
        if ("北京".equalsIgnoreCase(city)) {
            return "北京今天晴朗,气温 25°C";
        } else if ("上海".equalsIgnoreCase(city)) {
            return "上海今天多云,气温 22°C";
        }
        return "暂时无法查询 " + city + " 的天气";
    }

    /**
     * 计算工具
     */
    @Tool("计算两个数字的乘积")
    public double multiply(double a, double b) {
        return a * b;
    }
}

9.2 在AiService中配置工具

java 复制代码
@AiService(
    wiringMode = AiServiceWiringMode.EXPLICIT,
    streamingChatModel = "openAiStreamingChatModel",
    chatMemoryProvider = "chatMemoryProvider",
    contentRetriever = "contentRetriever",
    tools = "weatherTool"  // 指定工具Bean名称
)
public interface ConsultantStreamService {
    Flux<String> chat(@MemoryId String chatMemoryId, @UserMessage String message);
}

9.3 动态工具提供(高级)

根据上下文动态决定是否提供某个工具:

java 复制代码
@Component
public class ContextAwareToolProvider implements ToolProvider {

    private final WeatherTool weatherTool;

    public ContextAwareToolProvider(WeatherTool weatherTool) {
        this.weatherTool = weatherTool;
    }

    @Override
    public ToolProviderResult provideTools(ToolProviderRequest request) {
        String userMessage = extractUserMessage(request);
        ToolProviderResult.Builder builder = ToolProviderResult.builder();

        // 根据用户消息动态决定是否提供天气工具
        if (needsWeatherTool(userMessage)) {
            try {
                Method method = WeatherTool.class.getMethod("getWeather", String.class);
                builder.add(
                    ToolSpecifications.toolSpecificationFrom(method),
                    new DefaultToolExecutor(weatherTool, method)
                );
                System.out.println("✅ 检测到天气相关查询,启用 WeatherTool");
            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        } else {
            System.out.println("❌ 未检测到天气相关查询,不启用 WeatherTool");
        }

        return builder.build();
    }

    private String extractUserMessage(ToolProviderRequest request) {
        if (request == null || request.userMessage() == null) {
            return "";
        }
        return request.userMessage().singleText().toLowerCase();
    }

    private boolean needsWeatherTool(String message) {
        if (message == null || message.isEmpty()) {
            return false;
        }
        String[] weatherKeywords = {
            "天气", "weather", "气温", "温度",
            "下雨", "晴天", "阴天", "多云",
            "冷", "热", "凉爽", "温暖"
        };
        for (String keyword : weatherKeywords) {
            if (message.contains(keyword)) {
                return true;
            }
        }
        return false;
    }
}

9.4 配置动态工具

java 复制代码
@Bean
public ConsultantService consultantService(
        ChatModel openAiChatModel,
        StreamingChatModel openAiStreamingChatModel,
        ChatMemoryProvider chatMemoryProvider,
        ContentRetriever contentRetriever,
        ToolProvider toolProvider) {

    return AiServices.builder(ConsultantService.class)
            .chatModel(openAiChatModel)
            .streamingChatModel(openAiStreamingChatModel)
            .chatMemoryProvider(chatMemoryProvider)
            .contentRetriever(contentRetriever)
            .toolProvider(toolProvider)  // 使用动态工具提供者
            .build();
}

10. SSE 服务器推送

10.1 添加sse客户端依赖

复制代码
       <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-mcp</artifactId>
            <version>1.0.1-beta6</version>
        </dependency>

10.2 创建配置类

复制代码
@Configuration
public class McpClientConfig {

    @Bean(destroyMethod = "close")
    public McpClient userScoreMcpClient(@Value("${mcp.sse-server.url}") String sseUrl,
                                        @Value("${mcp.sse-server.log-requests:true}") boolean logRequests,
                                        @Value("${mcp.sse-server.log-responses:true}") boolean logResponses) {
        McpTransport transport = new HttpMcpTransport.Builder()
                .sseUrl(sseUrl)
                .timeout(Duration.ofSeconds(30))
                .logRequests(logRequests)
                .logResponses(logResponses)
                .build();

        return new DefaultMcpClient.Builder()
                .clientName("langchain4j-demo")
                .clientVersion("1.0.0")
                .transport(transport)
                .toolExecutionTimeout(Duration.ofSeconds(30))
                .build();
    }

    @Bean
    public McpToolProvider mcpToolProvider(McpClient userScoreMcpClient) {
        return McpToolProvider.builder()
                .mcpClients(userScoreMcpClient)
                .filterToolNames("getScore")
                .build();
    }
}

@Component
public class ContextAwareToolProvider implements ToolProvider {

    private final WeatherTool weatherTool;
    private final McpToolProvider mcpToolProvider;

    public ContextAwareToolProvider(WeatherTool weatherTool, McpToolProvider mcpToolProvider) {
        this.weatherTool = weatherTool;
        this.mcpToolProvider = mcpToolProvider;
    }

    @Override
    public ToolProviderResult provideTools(ToolProviderRequest request) {
        
        // 获取用户消息
        String userMessage = extractUserMessage(request);
        
        ToolProviderResult.Builder builder = ToolProviderResult.builder();
        ToolProviderResult mcpTools = mcpToolProvider.provideTools(request);
        builder.addAll(mcpTools.tools());

        // 根据消息内容判断是否需要天气工具
        if (needsWeatherTool(userMessage)) {
            Class<WeatherTool> weatherToolClass = WeatherTool.class;
            try {
                Method method = weatherToolClass.getMethod("getWeather", String.class);
                builder.add(ToolSpecifications.toolSpecificationFrom(method),  new DefaultToolExecutor(weatherTool, method));

            } catch (NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
            System.out.println("✅ 检测到天气相关查询,启用 WeatherTool");
        } else {
            System.out.println("❌ 未检测到天气相关查询,不启用 WeatherTool");
        }
        
        // 返回工具结果
        return builder.build();
    }

    /**
     * 从请求中提取用户消息
     */
    private String extractUserMessage(ToolProviderRequest request) {
        if (request == null || request.userMessage() == null) {
            return "";
        }
        return request.userMessage().singleText().toLowerCase();
    }

    /**
     * 判断是否需要天气工具
     * 通过关键词匹配来判断用户是否在询问天气
     */
    private boolean needsWeatherTool(String message) {
        if (message == null || message.isEmpty()) {
            return false;
        }
        
        // 定义天气相关的关键词
        String[] weatherKeywords = {
            "天气", "weather", "气温", "温度", 
            "下雨", "晴天", "阴天", "多云",
            "冷", "热", "凉爽", "温暖",
            "摄氏度", "°c", "度"
        };
        
        // 检查消息中是否包含任何天气关键词
        for (String keyword : weatherKeywords) {
            if (message.contains(keyword.toLowerCase())) {
                return true;
            }
        }
        
        return false;
    }
}
相关推荐
程序员小羊!1 小时前
12.Java 多线程编程
java·开发语言
乐观勇敢坚强的老彭1 小时前
C++信息学奥赛lesson1
java·开发语言·c++
belong_my_offer1 小时前
在Pycharm中安装conda的保姆级教学
python
jllllyuz1 小时前
MATLAB实现滚动轴承故障诊断(外圈故障)
开发语言·人工智能·matlab
github_czy1 小时前
更加优雅的类型检查与传参---mcp源码分析
java·服务器·开发语言
CTA终结者1 小时前
期货量化合约代码写错:天勤 symbol 格式与 silent 订阅坑
python·区块链
c_lb72881 小时前
期货程序化撤单改价后仓位乱了:cancel_order 与 TargetPosTask 协作
python
Irissgwe1 小时前
C++ STL关联式容器详解:set、multiset、map、multimap
开发语言·c++·stl·set·map·multiset·关联式容器
叶帆2 小时前
【YFIOs】用C#开发硬件之WiFi网络
开发语言·网络·c#