一. 环境要求
-
JDK 8 / 17
-
SpringBoot 2.x / 3.x
-
Forest 1.6.4+
-
Fastjson2
依赖配置
除了 SpringBoot 和 Lombok 等基础框架之外,再加上 Forest 和 Fastjson2 的依赖
二. 申请 DeepSeek 的 API Key
打开 DeepSeek 官网,进入到 API Key 的管理页面(
如果还没有 KEY,可以点击页面下方的创建API Key
按钮
创建完之后,会弹出一个对话框告诉您新生成的 API Key 字符串,然后要及时把它复制下来保存到一个安全的地方。
三. 配置项目
进入 SpringBoot 的配置文件application.yml
,加入以下代码:
四. 创建声名式接口
Forest 支持以声名式的方式发送 HTTP 请求,以下代码就是将 DeepSeek API 请求以声名式接口的方式进行定义
以上的代码意思也很明显,调用该接口方法就会发送一个POST
请求,URL 地址为 https://api.deepseek.com/chat/completions
其中 {apiKey} 和 {model} 的意思为读取配置文件中的 apiKey 字段,{content} 则是读取 @Var("content") 注解修饰的参数。 并且请求体数据为官网文档提供的 JSON 字符串,然后通过{变量名}
这种字符串模板占位符的形式拼接出您想要的参数。
接口方法的返回类型为ForestSSE
,这是 Forest 框架提供的内置类型,主要用于接受和处理 SSE 事件流消息。
五. 调用接口
在声名式接口创建完之后,可以通过 Spring 的@Resouce
注解将此接口实例注入到启动类中,Forest框架会利用动态代理模式自动生成相应的接口代理类实例,并将其自动注入到您所需要调用的类中。
然后就可以调用接口进行发送请求的操作了,并设置Lambda表达式来接收和处理返回的 SSE 流式事件消息
其中,DeepSeekResult 是根据返回的消息格式定义的数据类,具体代码如下
其他的数据类包括 DeepSeekResultChoice 类也都类似。如果要看具体代码,在文章末尾会提供代码仓库地址。
六. 应答测试
调用方法写完之后,我们就可以跑一下代码看看了,点击 Run 之后可以看到控制台日志会打印以下内容
日志上半部分POST https://api.deepseek.com/chat/completions HTTPS [SSE]
这类信息为 Forest 的请求日志,会告诉您发出去的 HTTP 请求信息中有些什么数据和参数。
而下半部分 “您好!我是由中国的深度求索(DeepSeek)公司开发的智能助手DeepSeek-R1...” 自然就是 DeepSeek 的回答了。
七. 思维链
以上的代码案例,只会返回 DeepSeek 的回答内容,不包含他的思考过程,拿怕模型是DeepSeek-R1
也一样。如果要打印出思维链,就要修改一下代码
首先要修改 DeepSeekResult 类中的 content() 方法
添加 DeepSeekContent 类
最后,修改接口的调用部分
八. 思维链消息测试
接下来就可以运行程序测试了,看看日志中是否包含了思维链的过程
从日志中可以看出,程序正常运行了,其中被包裹在<思维链>
和</思维链>
标签中间的部分就是 DeepSeek 告诉我们的思维过程。 而在</思维链>
结束标签之后的文字就是他的正式回答内容。
九. 错误处理
本文案例调用的是 DeepSeek 官方的 API。由于众所周知的原因,调用接口时极有可能发生401
等网络错误。
遇到这种请求,加一个拦截器就完事了
然后,将拦截器绑定到接口上
十. 总结
可以看到,通过 Forest 这种声名式的形式来对接 DeepSeek API,相比于 OkHttp 和 HttpClient 有很多明显的好处。除了代码简洁,容易实现之外,更重要的是声名式代码天然更容易解耦。文本代码很自然的就实现了在参数配置、HTTP请求参数、以及接口调用的业务逻辑之间实现了代码解耦。如果要修改 API Key 或者模型,直接该配置文件就行。如果要修改 HTTP 的 URL 或参数,可以直接改声名式接口,而不会影响到调用接口的业务代码。而且可以很自然地将 DeepSeek API 的 HTTP 代码统一放到一个接口类中,方便管理,而且请求中的 URL、请求头、请求体参数都都一目了然。
代码仓库地址: