|
|
@@ -22,6 +22,7 @@ import org.springframework.ai.chat.model.ChatModel;
|
|
|
import org.springframework.ai.chat.model.ChatResponse;
|
|
|
import org.springframework.ai.chat.prompt.ChatOptions;
|
|
|
import org.springframework.ai.chat.prompt.Prompt;
|
|
|
+import org.springframework.ai.model.tool.ToolCallingChatOptions;
|
|
|
import org.springframework.ai.model.tool.ToolCallingManager;
|
|
|
import org.springframework.ai.model.tool.ToolExecutionResult;
|
|
|
import org.springframework.ai.tool.ToolCallback;
|
|
|
@@ -294,7 +295,7 @@ public class ToolCallAgent extends ReActAgent {
|
|
|
.map(this::eventToSse)
|
|
|
.doOnCancel(() -> {
|
|
|
log.warn("[ToolCallAgent] 客户端取消订阅 - chatId: {}", chatId);
|
|
|
- state = AgentState.IDLE;
|
|
|
+ cleanup();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -420,7 +421,7 @@ public class ToolCallAgent extends ReActAgent {
|
|
|
return sink.asFlux()
|
|
|
.doOnCancel(() -> {
|
|
|
log.warn("[ToolCallAgent] SSE流式 - 客户端取消订阅 - chatId: {}", chatId);
|
|
|
- state = AgentState.IDLE;
|
|
|
+ cleanup();
|
|
|
});
|
|
|
}
|
|
|
|
|
|
@@ -438,7 +439,19 @@ public class ToolCallAgent extends ReActAgent {
|
|
|
// 获取最后一条消息作为结果
|
|
|
Message lastMsg = CollUtil.getLast(currentConversationMessages);
|
|
|
if (lastMsg instanceof AssistantMessage) {
|
|
|
- emitEvent(StreamEvent.contentChunk(((AssistantMessage) lastMsg).getText()));
|
|
|
+ String fullText = ((AssistantMessage) lastMsg).getText();
|
|
|
+ if (fullText != null && !fullText.isEmpty()) {
|
|
|
+ // 打字机效果:按单个字符分片发射(模拟打字机)
|
|
|
+ for (int i = 0; i < fullText.length(); i++) {
|
|
|
+ emitEvent(StreamEvent.contentChunk(String.valueOf(fullText.charAt(i))));
|
|
|
+ // 可选:加个小延迟让打字效果更明显(但不要太长影响体验)
|
|
|
+ try {
|
|
|
+ Thread.sleep(10);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
state = AgentState.FINISHED;
|
|
|
return false;
|
|
|
@@ -490,11 +503,17 @@ public class ToolCallAgent extends ReActAgent {
|
|
|
try {
|
|
|
String enhancedSystemPrompt = buildEnhancedSystemPrompt();
|
|
|
|
|
|
- // 使用完整的对话历史
|
|
|
+ // 【关键】注册工具让 AI 知道,但设置 .internalToolExecutionEnabled(false) 不让 Spring AI 自动执行!
|
|
|
+ // 工具执行交给 act() 方法手动执行
|
|
|
+ ToolCallingChatOptions chatOptions = ToolCallingChatOptions.builder()
|
|
|
+ .toolCallbacks(toolRegister.getTools().toArray(new ToolCallback[0]))
|
|
|
+ .internalToolExecutionEnabled(false) // 【关键】禁用自动执行!
|
|
|
+ .build();
|
|
|
+
|
|
|
ChatResponse chatResponse = chatClient.prompt()
|
|
|
.system(enhancedSystemPrompt)
|
|
|
.messages(currentConversationMessages)
|
|
|
- .toolCallbacks(toolRegister.getTools().toArray(new ToolCallback[0]))
|
|
|
+ .options(chatOptions)
|
|
|
.call()
|
|
|
.chatResponse();
|
|
|
|
|
|
@@ -669,4 +688,21 @@ public class ToolCallAgent extends ReActAgent {
|
|
|
.doOnNext(chunk -> log.debug("[ToolCallAgent] 流式输出 - chatId: {}, chunk: {}", chatId, chunk))
|
|
|
.doOnComplete(() -> log.info("[ToolCallAgent] 流式对话完成 - chatId: {}", chatId));
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 清理资源,重置状态
|
|
|
+ * 每次对话结束后调用,确保可以进行下一次对话
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ protected void cleanup() {
|
|
|
+ log.info("[ToolCallAgent] 清理资源,重置状态");
|
|
|
+ // 重置状态
|
|
|
+ this.state = AgentState.IDLE;
|
|
|
+ // 清空对话上下文
|
|
|
+ this.currentConversationMessages.clear();
|
|
|
+ // 重置当前步数
|
|
|
+ this.currentStep = 0;
|
|
|
+ // 清空 eventSink
|
|
|
+ this.eventSink = null;
|
|
|
+ }
|
|
|
}
|