源代码:源代码
6-10对于java从业者非常easy,这里就不写了,可以直接看day6-day10的代码,
需注意day9的springboot版本降为了2.7.18

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