智能体之外部工具篇(2)
一、序言
随着大语言模型(LLM)能力的突飞猛进,它们已能完成复杂的自然语言生成、推理与规划任务。然而,绝大多数 LLM 在脱离训练语料后,无法直接感知实时世界、调用系统服务或访问业务数据,导致它们成为“闭门造车”的天才语言工匠。
在智能体(Agent)架构中,连接外部工具(Tools)正成为打破这一瓶颈的关键路径。通过调用搜索引擎、数据库、API 接口,或执行脚本等能力,LLM 能够获得“行动力”与“环境反馈”,逐步实现认知—执行闭环。
二、工具方案
目前,业界围绕 “如何让 LLM 连接工具” 形成了两大主流技术路径:
Function Calling:模型主导式,由 LLM 主动生成结构化的函数调用请求;
Agent + Tools 调度框架(如 LangChain):框架主导式,通过工具选择器(Tool Executor)、规划器(Planner)等组件动态调度工具链。
这两类方案背后折射出不同的设计哲学与技术演进路径,如何选择、组合、实现,成为构建智能体系统的核心工程问题。
三、具体实践
1、Function Calling实现查询天气
@RestController
@RequestMapping("/chat")
public class ChatController {private static final String OPENAI_API_KEY = "你的API Key";private static final String OPENAI_API_URL = "https://api.openai.com/v1/chat/completions";private final RestTemplate restTemplate = new RestTemplate();private final ObjectMapper mapper = new ObjectMapper();@PostMapping("/ask")public String ask(@RequestParam String userInput) throws Exception {// 1. 构造用户消息List<Map<String, Object>> messages = new ArrayList<>();messages.add(Map.of("role", "user", "content", userInput));// 2. 定义函数 schemaMap<String, Object> getWeatherFunction = Map.of("name", "getWeather","description", "获取城市的天气","parameters", Map.of("type", "object","properties", Map.of("city", Map.of("type", "string", "description", "城市名")),"required", List.of("city")));// 3. 构造请求体Map<String, Object> request = new HashMap<>();request.put("model", "gpt-4");request.put("messages", messages);request.put("functions", List.of(getWeatherFunction));request.put("function_call", "auto");HttpHeaders headers = new HttpHeaders();headers.setContentType(MediaType.APPLICATION_JSON);headers.setBearerAuth(OPENAI_API_KEY);HttpEntity<String> entity = new HttpEntity<>(mapper.writeValueAsString(request), headers);ResponseEntity<String> response = restTemplate.postForEntity(OPENAI_API_URL, entity, String.class);// 4. 解析返回JsonNode root = mapper.readTree(response.getBody());JsonNode message = root.at("/choices/0/message");if (message.has("function_call")) {String functionName = message.at("/function_call/name").asText();String arguments = message.at("/function_call/arguments").asText();JsonNode argsNode = mapper.readTree(arguments);String city = argsNode.get("city").asText();// 5. 模拟调用函数String weather = "今天 " + city + " 晴转多云,25°C~30°C";// 6. 把函数返回值交给模型继续回答Map<String, Object> funcResponse = Map.of("role", "function","name", functionName,"content", weather);messages.add(Map.of("role", "assistant", "function_call", message.get("function_call")));messages.add(funcResponse);Map<String, Object> followUp = Map.of("model", "gpt-4","messages", messages);HttpEntity<String> followEntity = new HttpEntity<>(mapper.writeValueAsString(followUp), headers);ResponseEntity<String> followResponse = restTemplate.postForEntity(OPENAI_API_URL, followEntity, String.class);return followResponse.getBody();}return mapper.writeValueAsString(message);}
}
Function Calling 是一种“模型建议调用函数,人类程序负责实际执行”的模式。即:
模型返回需要调用的函数名和参数 ——由你(开发者)写代码调用对应函数 ——将结果回传给模型继续回答。
2、LangChain实现查询天气
from langchain import OpenAI, LLMChain
from langchain.agents import Tool, initialize_agent
from langchain.agents import AgentType
import requests# 1) 自定义天气查询函数(调用公开API)
def get_weather(city: str) -> str:# 这里用的是免费的wttr.in天气API,无需keyurl = f"https://wttr.in/{city}?format=3"try:res = requests.get(url)if res.status_code == 200:return res.textelse:return "无法获取天气信息"except Exception as e:return f"请求出错:{e}"# 2) 包装成Tool,供Agent调用
weather_tool = Tool(name="Weather Query",func=get_weather,description="用于查询指定城市的实时天气,输入城市名"
)# 3) 初始化OpenAI LLM
llm = OpenAI(temperature=0)# 4) 初始化Agent,支持工具调用
agent = initialize_agent(tools=[weather_tool],llm=llm,agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,verbose=True
)# 5) 输入查询,运行Agent
query = "请告诉我北京的天气"
result = agent.run(query)print("Agent回答:", result)
用户输入:“请告诉我北京的天气”
Agent 内部调用 LLM,理解用户想查询天气。
Agent 决定调用
weather_tool
(它其实是get_weather
函数的代理)Agent 执行
weather_tool.func("北京")
→ 实际调用get_weather("北京")
get_weather
函数请求天气接口,返回天气字符串,比如"北京: 🌤 +27°C"
Agent 收到函数结果后,把结果融入回答,返回给用户。
维度 | OpenAI Function Calling | LangChain 实现查询天气 |
---|---|---|
调用触发 | GPT-4 等模型在生成响应时,内嵌调用函数意图信息(函数名和参数),API 返回调用指令 | 由 LangChain Agent(基于 LLM)判断是否调用封装的工具(Tool),动态执行对应函数 |
函数执行时机 | 客户端接收到模型返回的函数调用指令后,调用相应本地/远程函数 | Agent 执行过程中,遇到调用指令时自动调用对应函数 |
代码结构 | 需要调用方自己写函数,负责参数解析、请求调用、结果返回和再输入模型 | 通过 Tool 封装函数,Agent 自动管理调用和结果集成,封装更完整 |
四、总结
方案 | 适用场景示例 |
---|
OpenAI Function Calling | 简单工具调用,如天气、计算器、数据库查询,快速集成API调用;微服务接入;对接已有函数接口 |
LangChain Agent | 复杂多工具协作任务,如多步决策、角色分工、复杂多轮对话、带记忆的智能体系统 |
可以结合自己的使用场景选择对应的解决方案,技术是用来解决实际业务问题的,切记为了使用某种技术而使用,为了设计好看而设计。