-
Notifications
You must be signed in to change notification settings - Fork 2
feat(core): Add deepseek support #2123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Close: #2100 Signed-off-by: unknowIfGuestInDream <liang.tang.cx@gmail.com>
Thank you for following naming conventions! 😻 |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Their most recently public accepted PR is: #2122 |
Reviewer's GuideThis pull request integrates the DeepSeek AI chat completion API by introducing a File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
""" Walkthrough本次变更在 Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant DeepSeekChatClient
participant DeepSeek API
User->>DeepSeekChatClient: chat(userMessage, ...)
DeepSeekChatClient->>DeepSeek API: 发送 ChatCompletionRequest
DeepSeek API-->>DeepSeekChatClient: 返回 ChatCompletionResponse
DeepSeekChatClient-->>User: 返回 assistant 回复
User->>DeepSeekChatClient: chatStream(userMessage, ..., chunkConsumer)
DeepSeekChatClient->>DeepSeek API: 发送流式请求
loop 数据流
DeepSeek API-->>DeepSeekChatClient: 返回数据块
DeepSeekChatClient-->>User: chunkConsumer 消费内容
end
DeepSeekChatClient-->>User: 返回完整 assistant 回复 future
Assessment against linked issues
Suggested labels
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @unknowIfGuestInDream - I've reviewed your changes - here's some feedback:
- Consider running the DeepSeek tests as integration tests rather than excluding the entire package in
pom.xml
. - Consider using environment variables or a configuration file for the API key in tests instead of embedding an encrypted key.
- The private
streamChatCompletion
method appears unused; consider removing it if the publicchatStream
method provides the necessary functionality.
Here's what I looked at during the review
- 🟡 General issues: 2 issues found
- 🟡 Security: 1 issue found
- 🟡 Testing: 3 issues found
- 🟢 Documentation: all looks good
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Qodana Community for JVMIt seems all right 👌 No new problems were found according to the checks applied 💡 Qodana analysis was run in the pull request mode: only the changed files were checked Contact Qodana teamContact us at qodana-support@jetbrains.com
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (20)
core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionDelta.java (1)
33-53
: 建议增强数据模型类这个类作为聊天完成增量内容的数据容器实现得当,但可以考虑以下改进:
- 为字段添加初始化值或构造器
- 实现toString()、equals()和hashCode()方法
- 如果使用Jackson,添加相关序列化/反序列化注解
- 为类和字段添加更详细的Javadoc注释,说明其用途和功能
public class ChatCompletionDelta { - private String content; - private String role; + private String content = null; + private String role = null; + + public ChatCompletionDelta() { + } + + public ChatCompletionDelta(String content, String role) { + this.content = content; + this.role = role; + } public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getRole() { return role; } public void setRole(String role) { this.role = role; } + + @Override + public String toString() { + return "ChatCompletionDelta{" + + "content='" + content + '\'' + + ", role='" + role + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ChatCompletionDelta that = (ChatCompletionDelta) o; + return Objects.equals(content, that.content) && + Objects.equals(role, that.role); + } + + @Override + public int hashCode() { + return Objects.hash(content, role); + } }不要忘记添加
import java.util.Objects;
core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatMessage.java (3)
30-33
: 建议补充类级别 Javadoc 描述
当前仅有作者注解,缺少对该类在 DeepSeek 聊天 API 中表示角色和内容的数据结构说明,有助于维护者快速理解用途。
35-36
: 可考虑将字段声明为final
以增强不可变性
如果业务场景不需要在实例化后修改role
和content
,可将字段设为private final
并移除对应的 setter,提升线程安全性和可维护性。
38-44
: 建议实现toString
、equals
和hashCode
方法
目前仅提供默认构造器和全参构造器,补充常用方法重写可方便日志记录、单元测试和集合操作。core/src/main/java/com/tlcsdm/core/ai/deepseek/Usage.java (3)
30-33
: 建议补充类级别 Javadoc 描述
缺少对Usage
类在 DeepSeek API 中用于表示令牌使用统计的说明,建议添加以提高可读性。
34-36
: 可考虑将字段设为final
并通过构造器初始化
若不需要修改,使用不可变字段并移除对应 setter 方法可提升线程安全性。
38-60
: 建议实现toString
、equals
和hashCode
方法
增强调试、日志记录及集合操作时的一致性和可用性。core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionChoice.java (3)
30-33
: 建议补充类和字段的 Javadoc 注释
应为ChatCompletionChoice
及其index
、message
、finishReason
字段添加详细说明,明确其在响应中的含义和取值范围。
35-37
: 可将字段声明为final
并通过构造器赋值
如果不需要在对象创建后修改这些字段,使用不可变设计可减少潜在问题。
39-61
: 建议重写toString
、equals
和hashCode
方法
提高对响应选择项的调试、日志和集合处理能力。core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionStreamChoice.java (3)
30-33
: 建议补充类级别和字段的 Javadoc 注释
为ChatCompletionStreamChoice
及其index
、delta
、finishReason
字段添加说明,帮助使用者理解流式响应片段的作用。
35-37
: 可将字段设为final
并通过构造器初始化
若不需要后续修改,采用不可变设计可提高代码健壮性。
39-61
: 建议实现toString
、equals
和hashCode
方法
方便对流式响应数据进行日志打印和集合处理。core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionStreamResponse.java (3)
32-35
: 建议补充类级别 Javadoc 描述
为ChatCompletionStreamResponse
添加用途说明,并在 Javadoc 中说明与流式响应相关的字段。
37-41
: 可考虑将字段声明为final
并移除 setter
如果该响应对象仅用于反序列化并且不需修改,使用不可变字段有助于线程安全。
43-82
: 建议重写toString
、equals
和hashCode
方法
增强调试和集合处理时的可用性及一致性。core/src/test/java/com/tlcsdm/core/ai/DeepseekTest.java (2)
45-53
: 建议加强密钥安全性处理当前实现中的 API 密钥虽然通过 AES 加密,但硬编码在测试代码中仍存在潜在风险。考虑通过环境变量或配置文件来提供加密密钥。
-private static final String aesKey = "3f4alpd3525678154a5e3a0183d8087b"; -private static final String encryptStr = "aac70872f21545ff2c56a590188bbe4c20035e0e130568c8dabeb699947e6cdf6df2dd72f573c55a8829ea53a2e22cd4"; +private static final String aesKey = System.getenv("DEEPSEEK_AES_KEY"); +private static final String encryptStr = System.getenv("DEEPSEEK_ENCRYPTED_TOKEN");
104-152
: 移除或实现被注释的超时处理代码代码中存在被注释掉的超时处理逻辑。建议要么移除这些未使用的代码,要么实现它们以提供完整的超时机制。
-//为流式响应添加超时机制 -// future.orTimeout(30, TimeUnit.SECONDS) -// .exceptionally(e -> { -// if (e instanceof TimeoutException) { -// System.err.println("响应超时"); -// } -// return null; -// }); +// 为流式响应添加超时机制 +future.orTimeout(30, TimeUnit.SECONDS) + .exceptionally(e -> { + if (e instanceof TimeoutException) { + System.err.println("响应超时"); + } + return null; + });core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java (2)
77-115
: 加强错误处理和异常恢复机制当 API 调用失败时,当前实现会从会话历史中移除最后一条用户消息。这种处理方式合理,但可以考虑添加日志记录,以便于调试和监控。
} catch (DeepSeekApiException e) { // 移除最后一条用户消息,因为对话失败 if (!conversationHistory.isEmpty() && "user".equals(conversationHistory.get(conversationHistory.size() - 1).getRole())) { conversationHistory.remove(conversationHistory.size() - 1); + // 添加日志记录 + System.err.println("对话失败,已移除最后一条用户消息: " + userMessage); } throw e; }
200-252
: 考虑添加对话历史管理机制当前实现允许对话历史无限增长,可能导致内存问题或超出 API 的 token 限制。建议添加对话历史的大小限制或清理机制。
public void addAssistantMessage(String content) { conversationHistory.add(new ChatMessage("assistant", content)); + // 确保对话历史不会过长 + if (conversationHistory.size() > 20) { // 设置一个合理的限制 + // 保留最新的对话,移除较早的 + conversationHistory.removeIf(message -> + !"system".equals(message.getRole()) && conversationHistory.indexOf(message) < conversationHistory.size() - 20); + } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (13)
core/pom.xml
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionChoice.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionDelta.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionRequest.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionResponse.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionStreamChoice.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionStreamResponse.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatMessage.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekApiException.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java
(1 hunks)core/src/main/java/com/tlcsdm/core/ai/deepseek/Usage.java
(1 hunks)core/src/main/java/module-info.java
(2 hunks)core/src/test/java/com/tlcsdm/core/ai/DeepseekTest.java
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java (1)
core/src/main/java/com/tlcsdm/core/util/JacksonUtil.java (1)
JacksonUtil
(60-381)
⏰ Context from checks skipped due to timeout of 90000ms (10)
- GitHub Check: automerge
- GitHub Check: StepSecurity Harden-Runner
- GitHub Check: Summary
- GitHub Check: qodana
- GitHub Check: build (21, windows-latest, false)
- GitHub Check: build (21, macos-latest, false)
- GitHub Check: build (21, ubuntu-latest, false)
- GitHub Check: build (17, windows-latest, false)
- GitHub Check: build (17, ubuntu-latest, false)
- GitHub Check: build (17, macos-latest, false)
🔇 Additional comments (9)
core/pom.xml (1)
474-474
: Maven Surefire配置更新完成排除了AI相关的测试文件,与新增的DeepSeek AI包的引入保持一致。这种配置确保了AI相关的测试不会在常规构建过程中自动运行,避免了可能需要额外配置或外部服务的测试失败问题。
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekApiException.java (1)
28-41
: 异常类实现正确异常类的实现遵循了Java标准的异常处理模式,提供了两个构造方法用于不同场景的异常处理。代码结构清晰,符合最佳实践。
core/src/main/java/module-info.java (2)
52-53
: Jackson模块依赖顺序优化将Jackson相关的依赖项进行了重新排序和分组,提高了代码的可读性和维护性。
134-135
: 新增AI包和水印包的导出正确导出了新的包,确保了DeepSeek AI功能可以被其他模块访问和使用。
core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatMessage.java (1)
46-61
: Getter/Setter 实现清晰且符合 Java Bean 规范
当前实现满足 Jackson 等序列化框架要求,无需修改。core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionResponse.java (1)
35-91
: POJO 类结构合理且完整该类作为 DeepSeek API 响应的数据模型,设计符合标准的 POJO 模式,提供了所有必要字段的访问器方法。
core/src/main/java/com/tlcsdm/core/ai/deepseek/ChatCompletionRequest.java (1)
35-113
: 请求模型设计合理该请求类包含了 DeepSeek API 所需的全部参数字段,提供了默认构造函数和全参数构造函数,结构清晰。
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java (2)
53-74
: 客户端构造函数配置合理客户端初始化了 HTTP 客户端、对象映射器和对话历史,配置看起来合理且全面。
138-203
:⚠️ Potential issue流式处理方法中的资源释放问题
在
chatStream
方法中的response.body().close()
调用可能存在问题,因为HttpResponse<Stream<String>>
的 body 不一定有 close 方法。建议检查并修正资源管理方式。-} finally { - response.body().close(); +} finally { + // HttpResponse<Stream<String>> 的 body 是一个 Stream,不需要显式关闭 + // 如果确实需要关闭基础资源,可以考虑其他方式 }Likely an incorrect or invalid review comment.
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java
Outdated
Show resolved
Hide resolved
Close: #2100 Signed-off-by: unknowIfGuestInDream <liang.tang.cx@gmail.com>
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (4)
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java (2)
151-175
: 流式处理异常可能多次 completeExceptionally与之前评论一致,
forEach
内部发生异常时应立即中断循环,避免对同一CompletableFuture
多次completeExceptionally
,也能省去无意义的行解析。
56-58
:⚠️ Potential issueconversationHistory 线程安全问题仍未解决
conversationHistory
由同步chat
与异步chatStream
方法共同读写,目前使用ArrayList
无任何并发控制,容易出现数据竞争或ConcurrentModificationException
。请考虑以下方案:- private final List<ChatMessage> conversationHistory; + private final List<ChatMessage> conversationHistory = Collections.synchronizedList(new ArrayList<>());或在 Javadoc 明确声明客户端非线程安全、需由调用方保证串行访问。
core/src/test/java/com/tlcsdm/core/ai/DeepseekTest.java (2)
63-89
: 缺少断言,无法自动验证行为该测试仅打印结果,无法在 CI 中捕获功能回归。请添加必要的
assertNotNull / assertTrue / assertEquals
等断言,或拆分为多个单元测试并使用 mock。
90-110
: 测试依赖真实外网 API,稳定性差且可能耗费额度
use()
方法同样无断言且直接调用线上接口。建议:
- 将其标记为集成测试(如使用 JUnit
@Tag("integration")
),并在 CI 中按需跳过。- 或使用 Mockito/ WireMock 模拟 DeepSeek API。
🧹 Nitpick comments (2)
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java (1)
123-125
: 空字符串也会被当作用户消息写入历史在调用方想利用“空消息=仅使用上下文”场景下,
addUserMessage("")
会把空内容写入历史,产生噪音。可在此处跳过空/null 内容:- addUserMessage(userMessage); + if (userMessage != null && !userMessage.isBlank()) { + addUserMessage(userMessage); + }core/src/test/java/com/tlcsdm/core/ai/DeepseekTest.java (1)
199-225
: 共用的 makeApiRequest 方法未设置超时与重试策略直接阻塞调用线上接口,若网络抖动将导致测试卡死。请至少:
- 给
send
调用添加Duration
超时:httpClient.send(request, BodyHandlers.ofString(Duration.ofSeconds(10)))
。- 或引入简单重试机制。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java
(1 hunks)core/src/test/java/com/tlcsdm/core/ai/DeepseekTest.java
(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
core/src/main/java/com/tlcsdm/core/ai/deepseek/DeepSeekChatClient.java (1)
core/src/main/java/com/tlcsdm/core/util/JacksonUtil.java (1)
JacksonUtil
(60-381)
🪛 Gitleaks (8.21.2)
core/src/test/java/com/tlcsdm/core/ai/DeepseekTest.java
53-53: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms (9)
- GitHub Check: qodana
- GitHub Check: build (21, macos-latest, false)
- GitHub Check: build (21, ubuntu-latest, false)
- GitHub Check: build (21, windows-latest, false)
- GitHub Check: build (17, windows-latest, false)
- GitHub Check: build (17, macos-latest, false)
- GitHub Check: build (17, ubuntu-latest, false)
- GitHub Check: StepSecurity Harden-Runner
- GitHub Check: Summary
Close: #2100
Fixes #
Proposed Changes
Readiness Checklist
Author/Contributor
Reviewing Maintainer
enhancement
,bug
,documentation
ordependencies
Summary by Sourcery
Add DeepSeek AI chat client support to the core module, enabling interaction with the DeepSeek AI API
New Features:
Enhancements:
Build:
Summary by CodeRabbit