【Spring AI】本地大模型接入MCP实现联网搜索
本地大模型的知识库都是在训练时获取的信息,所以实时性较差,又因为大模型本身并不具备联网查询的功能,所以在使用时无法获得实时性较强的内容,导致功能局限性较强。本篇我将介绍如何让本地部署的大模型能够借助互联网来获取实时性的信息。
这个图中的DB同样可以看做联网搜索,因为实质上mcp server就是一个中间工具,用它来与各个服务商或者数据源建立连接
要接入MCP首先就要有一个客户端和服务端,我会分别讲解对应步骤。我这里只会举一个简单的示例,为了让大家快速体验,大家可以自行拓展
MCP Server
首先引入Spring AI的相关依赖,详细的我就不再演示了,因为Spring AI的版本更迭非常快,我使用的是M7版本。不过必须要引入的依赖就是mcp server的依赖,选择webmvc或者是webflux的版本根据自己选择
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server</artifactId>
</dependency>
由于网络搜索需要调用API,大家需要进行注册,我这里推荐一款适合开发测试阶段的API,每个月有100次免费调用次数: https://serpapi.com
编写配置文件,包括端口号、mcp相关配置以及网络搜索API的相关参数
这里我选择的是sse的http请求的方式进行连接
pring.application.name=mcp-server
server.port=1631management.endpoints.web.exposure.include=*
spring.mvc.converters.preferred-json-mapper=jackspring.main.web-application-type=servlet
spring.ai.mcp.server.name=weather-service
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.enabled=true
spring.ai.mcp.server.type=async
spring.ai.mcp.server.sse-message-endpoint=/mcp/sse
spring.ai.mcp.server.resource-change-notification=true
spring.ai.mcp.server.prompt-change-notification=true
spring.ai.mcp.server.tool-change-notification=truespring.ai.mcp.web-search.endpoint=https://serpapi.com/search
spring.ai.mcp.web-search.api-key=你的密钥
spring.jackson.time-zone=Asia/Shanghai
定义一个工具类,用于实现网络搜索。这是一套基础模版,如果使用的是其他服务或者要在此基础上扩展,都是可以进行修改的
这里的@Tool注解表示这是一个工具方法,后面的description表示这个工具方法的描述,用于让大模型理解并决定是否调用,这个参数是关键,描述的清晰与否直接决定了回答质量
@Service
public class WebSearchTool {@Value("${spring.ai.mcp.web-search.api-key}")private String apiKey;@Value("${spring.ai.mcp.web-search.endpoint}")private String searchEndpoint;private final WebClient webClient = WebClient.builder().build();@Tool(description = "联网搜索实时信息")public String webSearch(@ToolParam(description = "搜索关键词") String query,@ToolParam(description = "返回结果数量(1-10)") Integer numResults) {UriComponentsBuilder uriBuilder = UriComponentsBuilder.fromHttpUrl(searchEndpoint).queryParam("q", query).queryParam("num", numResults != null ? numResults : 3).queryParam("api_key", apiKey);System.err.println("调用联网搜索传入的参数: "+"查询: "+query+",\n时间范围: "+",\n结果数: "+numResults);return webClient.get().uri(uriBuilder.build().toUri()).retrieve().bodyToMono(SearchResult.class).map(this::formatResults).block();}private String formatResults(SearchResult result) {StringBuilder sb = new StringBuilder();for (SearchResult.Item item : result.items) {sb.append("标题:").append(item.title).append("\n链接:").append(item.link).append("\n摘要:").append(item.snippet).append("\n\n");}return sb.toString();}// 定义搜索结果结构public static class SearchResult {@JsonProperty("organic_results") // 匹配实际API字段List<Item> items;public static class Item {String title;String link;String snippet;}}
}
然后是在启动类中注册这些工具,并暴露出去
这里的toolObjects可以接收多参数,后续扩展工具的时候可以在这里不断添加
@Beanpublic ToolCallbackProvider getToolCallbacks(WebSearchTool webSearchTool){return MethodToolCallbackProvider.builder().toolObjects(webSearchTool).build();}
MCP Client
mcp客户端同样要加上对应依赖
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>
客户端我会写一个简单的示例演示,在这个示例中,首先定义了ChatClient,它用来构建模型的信息。mcpSyncClients是一个列表,这是必须的,用它来获取当前的mcp服务列表。
在构造函数中,传入三个参数,分别是ChatClient的构造器、工具提供商、mcp服务列表。
然后写一个简单的方法用于请求大模型。如果你想要实现模型的上下文记忆功能或者记忆的持久化操作。可以看我的上一篇文章 【Spring AI】模型记忆持久化 + 自动加载记忆上下文_spring ai会话记忆-CSDN博客
@RestController
public class AiController {private final ChatClient chatClient;private final List<McpSyncClient> mcpSyncClients;public AiController(ChatClient.Builder chatClientBuilder,ToolCallbackProvider tools,List<McpSyncClient> mcpSyncClients) {this.chatClient = chatClientBuilder.defaultTools(tools).build();this.mcpSyncClients = mcpSyncClients;}public Flux<String> chat(String userMessage) {return this.chatClient.prompt().system("填写系统提示词").user(userMessage).call().content();}
然后编写配置信息,这里我只将重要的信息列出。
我这里选择的是异步回调的方式,最下面一行是指定mcp服务端的列表,server1表示服务端的名称,可以自拟,后面的url表示服务端的节点路径
其余的模型配置信息等不不再列出,根据你使用的模型服务比如ollama等进行配置
# mcp-client配置
spring.ai.mcp.client.enabled=true
spring.ai.mcp.client.name=mcp-client
spring.ai.mcp.client.version=1.0.0
spring.ai.mcp.client.request-timeout=30s
spring.ai.mcp.client.type=async
spring.ai.mcp.client.sse.connections.server1.url=http://localhost:1631
启动服务端
当看到这个,表示注册的工具数,因为我还注册了其他的工具,所以显示3,。这种情况表示注册成功
启动客户端
客户端启动启动完成后应该在服务端日志中看到这一内容
测试效果
在我的开源项目Local_Helper中测试效果