|
|
|
@ -66,6 +66,9 @@ public class AgentLoop { |
|
|
|
/** 拒绝追踪器 */ |
|
|
|
/** 拒绝追踪器 */ |
|
|
|
private final DenialTracker denialTracker = new DenialTracker(); |
|
|
|
private final DenialTracker denialTracker = new DenialTracker(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 中断标志 —— 用于取消当前运行中的 Agent 循环 */ |
|
|
|
|
|
|
|
private volatile boolean cancelled = false; |
|
|
|
|
|
|
|
|
|
|
|
/** 消息历史 —— 自行管理,不依赖 Spring AI ChatMemory */ |
|
|
|
/** 消息历史 —— 自行管理,不依赖 Spring AI ChatMemory */ |
|
|
|
private final List<Message> messageHistory = new ArrayList<>(); |
|
|
|
private final List<Message> messageHistory = new ArrayList<>(); |
|
|
|
|
|
|
|
|
|
|
|
@ -132,6 +135,16 @@ public class AgentLoop { |
|
|
|
this.onThinkingContent = onThinkingContent; |
|
|
|
this.onThinkingContent = onThinkingContent; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 取消当前运行中的 Agent 循环 */ |
|
|
|
|
|
|
|
public void cancel() { |
|
|
|
|
|
|
|
cancelled = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** 重置取消标志(每次新的循环开始时调用) */ |
|
|
|
|
|
|
|
private void resetCancel() { |
|
|
|
|
|
|
|
cancelled = false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ==================== 阻塞模式 ====================
|
|
|
|
// ==================== 阻塞模式 ====================
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
@ -161,6 +174,7 @@ public class AgentLoop { |
|
|
|
// ==================== 核心循环(统一阻塞/流式) ====================
|
|
|
|
// ==================== 核心循环(统一阻塞/流式) ====================
|
|
|
|
|
|
|
|
|
|
|
|
private String executeLoop(boolean streaming, Consumer<String> onToken) { |
|
|
|
private String executeLoop(boolean streaming, Consumer<String> onToken) { |
|
|
|
|
|
|
|
resetCancel(); |
|
|
|
List<ToolCallback> callbacks = toolRegistry.toCallbacks(toolContext); |
|
|
|
List<ToolCallback> callbacks = toolRegistry.toCallbacks(toolContext); |
|
|
|
ChatOptions options = ToolCallingChatOptions.builder() |
|
|
|
ChatOptions options = ToolCallingChatOptions.builder() |
|
|
|
.toolCallbacks(callbacks) |
|
|
|
.toolCallbacks(callbacks) |
|
|
|
@ -171,6 +185,13 @@ public class AgentLoop { |
|
|
|
String lastAssistantText = ""; |
|
|
|
String lastAssistantText = ""; |
|
|
|
|
|
|
|
|
|
|
|
while (iteration < MAX_ITERATIONS) { |
|
|
|
while (iteration < MAX_ITERATIONS) { |
|
|
|
|
|
|
|
// 检查取消标志
|
|
|
|
|
|
|
|
if (cancelled) { |
|
|
|
|
|
|
|
log.info("Agent loop cancelled by user at iteration {}", iteration); |
|
|
|
|
|
|
|
lastAssistantText += "\n\n[Interrupted by user]"; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
iteration++; |
|
|
|
iteration++; |
|
|
|
log.debug("Agent loop iteration {} ({})", iteration, streaming ? "streaming" : "blocking"); |
|
|
|
log.debug("Agent loop iteration {} ({})", iteration, streaming ? "streaming" : "blocking"); |
|
|
|
|
|
|
|
|
|
|
|
@ -184,6 +205,12 @@ public class AgentLoop { |
|
|
|
result = blockingIteration(prompt); |
|
|
|
result = blockingIteration(prompt); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 检查取消标志(API调用后)
|
|
|
|
|
|
|
|
if (cancelled) { |
|
|
|
|
|
|
|
log.info("Agent loop cancelled by user after API call at iteration {}", iteration); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// 记录 Token 使用量
|
|
|
|
// 记录 Token 使用量
|
|
|
|
if (result.promptTokens > 0 || result.completionTokens > 0) { |
|
|
|
if (result.promptTokens > 0 || result.completionTokens > 0) { |
|
|
|
tokenTracker.recordUsage(result.promptTokens, result.completionTokens); |
|
|
|
tokenTracker.recordUsage(result.promptTokens, result.completionTokens); |
|
|
|
|