springboot+langchain4jDay6-Day11后续学习计划

源代码:源代码

6-10对于java从业者非常easy,这里就不写了,可以直接看day6-day10的代码,

需注意day9的springboot版本降为了2.7.18

每天的源代码基本都有readme.md

Day 11:联网搜索 Tool --- Agent 自主决策实时搜索 🔍🌤

技术栈:LangChain4j AiServices · Function Calling · 博查搜索 API · 华风爱科天气 API

核心能力

Agent 注册了两个 Tool,自主决定何时调哪个,不需要 if-else 路由:

Tool 触发场景 数据来源
WebSearchTool.search() 新闻、股价、赛事等通用搜索 博查(Bocha)Search API
WeatherTool.getWeather() 天气、温度、穿衣、出行等气象问题 华风爱科(WeatherCN)OpenAPI
复制代码
用户:「今天北京天气怎么样?」
  → LLM 判断:需要实时天气数据
  → 自动调用 WeatherTool.getWeather("北京")
      ├─ Step 1:城市搜索 → 获取城市 Key(如 "101924")
      └─ Step 2:实况天气 → 返回温度/湿度/风速等
  → LLM 整理后回复用户

架构

复制代码
┌──────────┐     ┌─────────────────────┐     ┌──────────────┐
│  用户     │────▶│  AgentService       │────▶│  DeepSeek-V3 │
│  (问题)   │     │  (AiServices 代理)  │     │  (LLM)       │
└──────────┘     └───────┬─────────────┘     └──────┬───────┘
                         │                          │
                         │  Function Calling        │
                    ┌────▼────────────────────┐     │
                    │  同时注册两个 Tool        │◀────┘
                    └────┬──────────┬──────────┘
                         │          │
              ┌──────────▼─┐  ┌─────▼──────────┐
              │WebSearchTool│  │  WeatherTool   │
              │.search(q)  │  │.getWeather(城市)│
              └──────┬──────┘  └─────┬──────────┘
                     │               │
              ┌──────▼──────┐  ┌─────▼──────────┐
              │ 博查 Search  │  │ 华风爱科 OpenAPI │
              │  API        │  │  两步查询        │
              └─────────────┘  └────────────────┘

文件结构

复制代码
day11/
├── pom.xml
└── src/main/java/com/day11/demo/
    ├── Day11Application.java
    ├── config/
    │   └── ChatModelConfig.java          ← OpenAiChatModel Bean(接 SiliconFlow)
    ├── service/
    │   └── AgentService.java             ← AiServices 组装 Agent + 双 Tool
    ├── tool/
    │   ├── WebSearchTool.java            ← 博查联网搜索 @Tool
    │   └── WeatherTool.java              ← 华风爱科天气 @Tool(城市搜索 + 实况)
    ├── controller/
    │   └── AgentController.java          ← GET /agent/chat?message=...
    └── dto/
        └── Result.java

核心代码

WeatherTool.java --- 华风爱科两步查询

java 复制代码
@Tool("查询指定城市的实时天气信息,包括气温、体感温度、湿度、风向风速...
      当用户询问天气、温度、是否下雨、穿衣建议等气象问题时使用此工具。")
public String getWeather(String cityName) {
    // Step 1:城市搜索 → 获取 Key
    String cityKey = searchCityKey(cityName);  // 调 /locations/v1/cities/search.json
    // Step 2:实况天气 → 格式化返回
    return getCurrentConditions(cityKey, cityName);  // 调 /currentconditions/v1/{Key}.json
}

AgentService.java --- 双 Tool 注入

java 复制代码
agent = AiServices.builder(WebSearchAgent.class)
    .chatLanguageModel(chatModel)
    .tools(searchTool, weatherTool)   // ← 同时注册两个 Tool
    .chatMemory(chatMemory)
    .build();
// LLM 自行判断用户意图,决定调哪个 Tool(或都不调)

API Key 配置

方式 A:直接填写 application.yml(本地开发推荐)

yaml 复制代码
bocha:
  api-key: 你的博查Key

weathercn:
  api-key: 你的华风爱科Key

方式 B:环境变量(生产/CI 推荐)

bash 复制代码
# Windows
set BOCHA_API_KEY=你的博查Key
set WEATHERCN_API_KEY=你的华风爱科Key

# Linux / macOS
export BOCHA_API_KEY=你的博查Key
export WEATHERCN_API_KEY=你的华风爱科Key

获取 API Key

服务 注册地址 说明
博查搜索 https://open.bochaai.com 微信扫码注册,免费额度
华风爱科 https://openapi.weathercn.com 官方天气 API

启动

bash 复制代码
mvn spring-boot:run

测试

bash 复制代码
# 不需要 Tool 的问题(LLM 直接回答)
curl "http://localhost:8080/agent/chat?message=你叫什么名字"

# 触发 WeatherTool(华风爱科天气)
curl "http://localhost:8080/agent/chat?message=今天北京天气怎么样"
curl "http://localhost:8080/agent/chat?message=上海明天要下雨吗,要不要带伞"
curl "http://localhost:8080/agent/chat?message=深圳现在多少度"

# 触发 WebSearchTool(博查通用搜索)
curl "http://localhost:8080/agent/chat?message=2024年NBA总冠军是谁"
curl "http://localhost:8080/agent/chat?message=最近有什么AI方面的新闻"

华风爱科接口说明

接口 1:城市搜索

复制代码
GET https://openapi.weathercn.com/locations/v1/cities/search.json
  ?apikey=YOUR_API_KEY
  &q=北京
  &language=zh-cn

返回 JSON 数组,取 [0].Key 作为后续查询的城市标识(如 "101924")。

接口 2:实况天气

复制代码
GET https://openapi.weathercn.com/currentconditions/v1/{Key}.json
  ?apikey=YOUR_API_KEY
  &language=zh-cn
  &details=true

返回 JSON 数组,[0] 包含温度、湿度、风速等完整实况数据。

面试要点

  1. 为什么要注册两个 Tool? --- 职责分离:天气专用 Tool vs 通用搜索 Tool。LLM 看到两个 Tool 的描述后,能更精准地做意图路由,不需要代码里写 if-else
  2. WeatherTool 为什么要两步请求? --- 华风爱科 API 的设计:先通过城市名拿到标准化的城市 Key,再用 Key 查实时天气。这样能精确处理同名城市
  3. @Tool 注解的描述为什么这么重要? --- 描述文本会被序列化成 Function Calling 的 JSON Schema 传给 LLM,LLM 靠描述决定何时调用。描述越准,路由越精确
  4. Key 取第一条够准确吗? --- 华风爱科接口会按相关度排序,第一条通常是最匹配的城市。如需精确可以加省份等限制词(如「北京市」)
  5. 没有 API Key 怎么办? --- WeatherTool 无 Key 时返回引导提示;WebSearchTool 无 Key 时降级返回配置说明。Agent 仍能正常对话,不会崩溃