<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      SpringBoot AI Deepseek MCP 1.0 集成高德天氣預(yù)報完整方案

      SpringBoot AI Deepseek MCP 1.0 集成高德天氣預(yù)報完整方案

      本文將介紹如何使用 Spring AI 1.0.0 Release 版本深度集成高德天氣預(yù)報服務(wù),提供完整的、可直接部署的解決方案。相較于網(wǎng)上不完整的示例,本項目已解決所有依賴版本問題和代碼實現(xiàn)細(xì)節(jié)


      技術(shù)架構(gòu)概覽

      graph TD A[用戶端] --> B[Spring Boot控制器] B --> C[Spring AI ChatClient] C --> D[工具調(diào)用] D --> E[高德天氣服務(wù)] D --> F[城市編碼查詢] E --> G[高德API] F --> H[Excel數(shù)據(jù)源] C --> I[上下文記憶] I --> J[內(nèi)存存儲]

      核心依賴配置

      <!-- Spring AI BOM 管理 -->
      <dependencyManagement>
          <dependencies>
              <dependency>
                  <groupId>org.springframework.ai</groupId>
                  <artifactId>spring-ai-bom</artifactId>
                  <version>1.0.0</version>
                  <type>pom</type>
                  <scope>import</scope>
              </dependency>
          </dependencies>
      </dependencyManagement>
      
      <!-- 主要依賴 -->
      <dependencies>
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-webflux</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.ai</groupId>
              <artifactId>spring-ai-client-chat</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.ai</groupId>
              <artifactId>spring-ai-starter-model-openai</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.ai</groupId>
              <artifactId>spring-ai-autoconfigure-model-chat-client</artifactId>
          </dependency>
          <dependency>
              <groupId>org.springframework.ai</groupId>
              <artifactId>spring-ai-starter-mcp-server-webflux</artifactId>
          </dependency>
          <dependency>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
          </dependency>
          <dependency>
              <groupId>cn.idev.excel</groupId>
              <artifactId>fastexcel</artifactId>
              <version>${fastexcel.version}</version>
          </dependency>
      </dependencies>
      

      核心組件實現(xiàn)

      1. AI配置中心

      @Configuration
      public class ChatClientConfig {
      
          // 配置基于時間窗口的對話記憶
          @Bean
          public MessageChatMemoryAdvisor messageWindowChatMemory() {
              ExpireMemoryRepository memoryRepository = new ExpireMemoryRepository();
              MessageWindowChatMemory chatMemory = MessageWindowChatMemory.builder()
                      .chatMemoryRepository(memoryRepository)
                      .maxMessages(20) // 保留最近20條對話
                      .build();
      
              return MessageChatMemoryAdvisor.builder(chatMemory)
                      .scheduler(Schedulers.parallel())
                      .build();
          }
          
          // 配置ChatClient
          @Bean
          public ChatClient chatClient(ChatClient.Builder builder, 
                                     ToolCallbackProvider toolCallbackProvider,
                                     MessageChatMemoryAdvisor messageChatMemoryAdvisor) {
              
              return builder
                      .defaultSystem("""
                          你是一個地理專家和天氣預(yù)報助手,可以幫助用戶查詢天氣預(yù)報信息。
                          工作流程:
                          1. 根據(jù)用戶地址信息匹配到標(biāo)準(zhǔn)行政區(qū)劃的區(qū)縣級名稱
                          2. 根據(jù)區(qū)縣名稱獲取區(qū)域編碼
                          3. 使用區(qū)域編碼查詢天氣預(yù)報
                          4. 整理天氣信息并提供出行建議
                          """)
                        // 工具調(diào)用
                      .defaultToolCallbacks(toolCallbackProvider) 
                       // 對話記憶
                      .defaultAdvisors(messageChatMemoryAdvisor) 
                      .build();
          }
      }
      

      2. 高德天氣服務(wù)集成

      @Slf4j
      @McpService
      public class WeatherInfoService {
          
          @Resource
          private AmapConfigProperties amapConfigProperties;
          
          private Map<String, CityModel> cityModels;
          
          // 初始化城市編碼數(shù)據(jù)
          @PostConstruct
          public void init() {
              try (InputStream mapCityIo = getClass().getResourceAsStream("/xlsx/AMap_adcode_citycode.xlsx")) {
                  CommonDataListener<CityModel> dataListener = new CommonDataListener<>();
                  FastExcel.read(mapCityIo)
                          .sheet()
                          .head(CityModel.class)
                          .registerReadListener(dataListener)
                          .doRead();
                  this.cityModels = dataListener.getList().stream()
                          .collect(Collectors.toMap(CityModel::getCityName, 
                                                  Function.identity(),
                                                  (t, t2) -> t));
              } catch (IOException e) {
                  throw new RuntimeException("加載城市編碼數(shù)據(jù)失敗", e);
              }
          }
          
          // 工具方法:根據(jù)城市名查詢區(qū)域編碼
          @Tool(name = "queryAdCodeByCityName", 
                description = "根據(jù)區(qū)縣名稱獲取區(qū)域編碼")
          public Optional<String> queryAdCodeByCityName(
                  @ToolParam(description = "區(qū)縣名稱") String cityName) {
              
              log.info("查詢城市編碼: {}", cityName);
              return Optional.ofNullable(cityModels.get(cityName))
                      .map(CityModel::getAdCode);
          }
          
          // 工具方法:根據(jù)區(qū)域編碼查詢天氣
          @Tool(name = "queryByAdCode", 
                description = "根據(jù)區(qū)域編碼查詢天氣預(yù)報")
          public WeatherResponse queryByAdCode(
                  @ToolParam(description = "區(qū)域編碼") String adCode) {
              
              log.info("查詢天氣信息,區(qū)域編碼: {}", adCode);
              
              return WebClient.builder()
                      .baseUrl(amapConfigProperties.getUrl())
                      .build()
                      .get()
                      .uri(uriBuilder -> uriBuilder.path("/v3/weather/weatherInfo")
                              .queryParam("key", amapConfigProperties.getKey())
                              .queryParam("city", adCode)
                              .queryParam("extensions", "all")
                              .build())
                      .retrieve()
                      .onStatus(HttpStatusCode::isError, response -> 
                          Mono.error(new ServiceException("高德天氣服務(wù)異常")))
                      .bodyToMono(WeatherResponse.class)
                      .block();
          }
      }
      

      3. 控制器實現(xiàn)

      @RestController
      @RequestMapping("/api/chat")
      @Slf4j
      public class ChatController {
          
          @Resource
          private ChatClient chatClient;
          
          // SSE流式響應(yīng)(適合前端實時展示)
          @PostMapping(value = "stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
          public Flux<ChatResponse> chatStream(@RequestBody ChatRequest request) {
              return chatClient.prompt()
                      .user(request.getMessage())
                      .advisors(advisor -> {
                          if (request.getConversationId() != null) {
                              advisor.param("chat_memory_conversation_id", 
                                            request.getConversationId());
                          }
                      })
                      .stream()
                      .content()
                      .map(ChatResponse::new)
                      .onErrorResume(e -> Flux.just(
                          new ChatResponse("服務(wù)處理異常: " + e.getMessage(), false)));
          }
          
          // 阻塞式響應(yīng)(適合API調(diào)用)
          @PostMapping("blocking")
          public Mono<ChatResponse> chatBlocking(@RequestBody ChatRequest request) {
              return chatClient.prompt()
                      .user(request.getMessage())
                      .advisors(advisor -> {
                          if (request.getConversationId() != null) {
                              advisor.param("chat_memory_conversation_id", 
                                            request.getConversationId());
                          }
                      })
                      .call()
                      .content()
                      .map(ChatResponse::new)
                      .onErrorResume(e -> Mono.just(
                          new ChatResponse("服務(wù)處理異常: " + e.getMessage(), false)));
          }
      }
      

      4. 配置文件示例

      server:
        port: 8080
      
      amap:
        key: ${AMAP_KEY:your_amap_key}  # 高德開放平臺KEY
        url: https://restapi.amap.com
      
      spring:
        application:
          name: weather-ai-service
        ai:
          openai:
            api-key: ${OPENAI_API_KEY:your_api_key}
            base-url: ${OPENAI_BASE_URL:https://api.deepseek.com} # DeepSeek兼容URL
            chat:
              options:
                model: deepseek-chat  # 使用DeepSeek模型
                temperature: 0.7
                max-tokens: 2000
      

      系統(tǒng)工作流程

      sequenceDiagram participant User as 用戶 participant Controller as Spring控制器 participant AI as Spring AI participant Tool as 天氣工具 participant AMAP as 高德API User->>Controller: 發(fā)送天氣查詢請求 Controller->>AI: 轉(zhuǎn)發(fā)用戶請求 AI->>Tool: 調(diào)用queryAdCodeByCityName Tool->>AI: 返回區(qū)域編碼 AI->>Tool: 調(diào)用queryByAdCode Tool->>AMAP: 請求天氣數(shù)據(jù) AMAP-->>Tool: 返回天氣響應(yīng) Tool-->>AI: 返回天氣數(shù)據(jù) AI-->>Controller: 生成自然語言響應(yīng) Controller-->>User: 返回天氣信息

      使用示例與效果

      1. 請求示例

      POST /api/chat/blocking
      {
        "message": "北京海淀區(qū)明天的天氣如何?",
        "conversationId": "conv_123456"
      }
      

      2. AI工具調(diào)用過程

      INFO WeatherInfoService     : 查詢城市編碼: 海淀區(qū)
      INFO WeatherInfoService     : 查詢天氣信息,區(qū)域編碼: 110108
      
      

      3. 響應(yīng)結(jié)果

      {
          "content": "海淀區(qū)明天的天氣預(yù)報如下:\n\n- **日期**: 2025年06月05日(星期四)\n- **白天天氣**: 多云\n- **夜間天氣**: 晴\n- **白天溫度**: 36°C\n- **夜間溫度**: 22°C\n- **風(fēng)向**: 西南風(fēng)\n- **風(fēng)力**: 1-3級\n\n### 出行建議\n1. **防曬**: 白天溫度較高,注意防曬,避免長時間暴露在陽光下。\n2. **補水**: 高溫天氣容易導(dǎo)致脫水,記得多喝水。\n3. **夜間溫差**: 夜間溫度較低,建議攜帶一件薄外套。\n\n如果需要更詳細(xì)的天氣信息或其他幫助,請隨時告訴我!",
          "success": true
      }
      

      項目資源

      參考

      https://docs.spring.io/spring-ai/

      posted @ 2025-06-04 09:41  巖冰  閱讀(215)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 亚洲av色在线观看国产| 影音先锋人妻啪啪av资源网站| 好紧好湿太硬了我太爽了视频| 九九热免费公开视频在线| 亚洲日韩性欧美中文字幕| 四虎在线成人免费观看| 天堂va蜜桃一区二区三区| 加勒比无码人妻东京热| 亚洲色婷婷综合开心网| 绝顶丰满少妇av无码| 国产精品久久国产精麻豆99网站| 国产欧美日韩一区二区加勒比| 被黑人巨大一区二区三区| 精品不卡一区二区三区| 精品国产一区二区三区四区阿崩 | 国产免费高清69式视频在线观看| 一本久道中文无码字幕av| 国产精品99区一区二区三| 国产成人午夜福利在线播放| 国产成人亚洲欧美二区综合| 黄色亚洲一区二区在线观看| 99在线国内在线视频22| 国产成人无码AV片在线观看不卡| 性欧美老人牲交xxxxx视频| 亚洲国产精品久久无人区| 亚洲精品日本一区二区| 永久免费av网站可以直接看的| 农村欧美丰满熟妇xxxx| 97视频精品全国免费观看| 亚洲欧洲日韩国内高清| 国产精品久久无码一区| 九九热在线视频观看最新| 久久99热只有频精品8| 丁香色婷婷国产精品视频| 99久久免费精品色老| 亚洲国产成人极品综合| 精品国产中文字幕在线看| 免费现黄频在线观看国产| 免费国产黄线在线观看| 18禁精品一区二区三区| 又粗又大又硬又长又爽|