扣子智能体调用

This commit is contained in:
tanglong 2026-07-13 17:43:17 +08:00
parent e12583c41c
commit b72d166adb
3 changed files with 77 additions and 8 deletions

View File

@ -2,7 +2,6 @@ package com.company.agentfoundation.integration.coze.client;
import com.company.agentfoundation.config.FoundationProperties; import com.company.agentfoundation.config.FoundationProperties;
import com.company.agentfoundation.integration.coze.dto.CozeWorkflowRequest; import com.company.agentfoundation.integration.coze.dto.CozeWorkflowRequest;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -23,13 +22,13 @@ public class CozeWorkflowClient {
.build(); .build();
} }
public JsonNode chat(CozeWorkflowRequest request) { public String chat(CozeWorkflowRequest request) {
return webClient.post() return webClient.post()
.uri(properties.getCoze().getChatPath()) .uri(properties.getCoze().getChatPath())
.header(HttpHeaders.AUTHORIZATION, "Bearer " + properties.getCoze().getApiKey()) .header(HttpHeaders.AUTHORIZATION, "Bearer " + properties.getCoze().getApiKey())
.bodyValue(request) .bodyValue(request)
.retrieve() .retrieve()
.bodyToMono(JsonNode.class) .bodyToMono(String.class)
.retryWhen(Retry.backoff(properties.getCoze().getMaxRetries(), Duration.ofMillis(300))) .retryWhen(Retry.backoff(properties.getCoze().getMaxRetries(), Duration.ofMillis(300)))
.block(Duration.ofMillis(properties.getCoze().getReadTimeoutMs())); .block(Duration.ofMillis(properties.getCoze().getReadTimeoutMs()));
} }

View File

@ -55,7 +55,7 @@ public class CozeWorkflowService {
List.of(new CozeMessage("text", "user", "question", userText == null ? "" : userText)) List.of(new CozeMessage("text", "user", "question", userText == null ? "" : userText))
); );
JsonNode response = client.chat(request); String response = client.chat(request);
String reply = extractReply(response).orElse(""); String reply = extractReply(response).orElse("");
log.info("coze workflow chat success workflowKey={} replyPreview={}", workflowKey, preview(reply)); log.info("coze workflow chat success workflowKey={} replyPreview={}", workflowKey, preview(reply));
return reply; return reply;
@ -117,6 +117,76 @@ public class CozeWorkflowService {
return Optional.empty(); return Optional.empty();
} }
private Optional<String> extractReply(String response) {
if (isBlank(response)) {
return Optional.empty();
}
String trimmed = response.trim();
if (isJson(trimmed)) {
try {
return extractReply(objectMapper.readTree(trimmed));
} catch (Exception e) {
log.warn("coze workflow json response parse failed err={}", e.getMessage());
}
}
Optional<String> eventReply = extractFromEventStream(trimmed);
if (eventReply.isPresent()) {
return eventReply;
}
if (looksLikeEventStream(trimmed)) {
log.warn("coze workflow event stream response did not include completed content");
return Optional.empty();
}
return Optional.of(trimmed);
}
private Optional<String> extractFromEventStream(String response) {
String currentEvent = "";
StringBuilder data = new StringBuilder();
String[] lines = response.replace("\r\n", "\n").replace('\r', '\n').split("\n", -1);
for (String line : lines) {
if (line.isBlank()) {
Optional<String> content = extractCompletedEventContent(currentEvent, data.toString());
if (content.isPresent()) {
return content;
}
currentEvent = "";
data.setLength(0);
continue;
}
if (line.startsWith("event:")) {
currentEvent = line.substring("event:".length()).trim();
} else if (line.startsWith("data:")) {
if (data.length() > 0) {
data.append('\n');
}
data.append(line.substring("data:".length()).trim());
}
}
return extractCompletedEventContent(currentEvent, data.toString());
}
private Optional<String> extractCompletedEventContent(String event, String data) {
if (!"conversation.message.completed".equals(event) || isBlank(data) || !isJson(data.trim())) {
return Optional.empty();
}
try {
JsonNode message = objectMapper.readTree(data);
String role = message.path("role").asText("");
String type = message.path("type").asText("");
if (("assistant".equalsIgnoreCase(role) || role.isBlank()) && ("answer".equalsIgnoreCase(type) || type.isBlank())) {
return firstText(message, "content", "text", "answer", "output");
}
} catch (Exception e) {
log.warn("coze workflow completed event parse failed err={}", e.getMessage());
}
return Optional.empty();
}
private boolean looksLikeEventStream(String response) {
return response.startsWith("event:") || response.contains("\nevent:") || response.startsWith("data:") || response.contains("\ndata:");
}
private Optional<String> extractFromMessages(JsonNode messages) { private Optional<String> extractFromMessages(JsonNode messages) {
if (messages == null || !messages.isArray()) { if (messages == null || !messages.isArray()) {
return Optional.empty(); return Optional.empty();

View File

@ -26,7 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
public class WecomCallbackController { public class WecomCallbackController {
private static final Logger log = LoggerFactory.getLogger(WecomCallbackController.class); private static final Logger log = LoggerFactory.getLogger(WecomCallbackController.class);
private static final long MESSAGE_DEDUP_TTL_SECONDS = 600; private static final long MESSAGE_DEDUP_TTL_SECONDS = 600;
private static final String FIXED_REPLY = "\u4f60\u597d"; private static final String ERROR_REPLY = "\u6263\u5b50\u667a\u80fd\u4f53\u8c03\u7528\u5931\u8d25\uff0c\u8bf7\u7a0d\u540e\u91cd\u8bd5";
private final CozeWorkflowService cozeWorkflowService; private final CozeWorkflowService cozeWorkflowService;
private final WecomClient wecomClient; private final WecomClient wecomClient;
private final WecomCryptoService wecomCryptoService; private final WecomCryptoService wecomCryptoService;
@ -97,11 +97,11 @@ public class WecomCallbackController {
reply = cozeWorkflowService.chatDefault(userText); reply = cozeWorkflowService.chatDefault(userText);
} catch (Exception e) { } catch (Exception e) {
log.error("wecom callback coze workflow failed fromUser={} err={}", msg.getFromUserName(), e.getMessage(), e); log.error("wecom callback coze workflow failed fromUser={} err={}", msg.getFromUserName(), e.getMessage(), e);
reply = FIXED_REPLY; reply = ERROR_REPLY;
} }
if (reply == null || reply.isBlank()) { if (reply == null || reply.isBlank()) {
log.warn("wecom callback coze reply blank, fallback to fixed reply"); log.warn("wecom callback coze reply blank, fallback to error reply");
reply = FIXED_REPLY; reply = ERROR_REPLY;
} }
log.info("wecom callback sending coze reply toUser={} replyPreview={}", msg.getFromUserName(), preview(reply)); log.info("wecom callback sending coze reply toUser={} replyPreview={}", msg.getFromUserName(), preview(reply));
wecomClient.sendText(msg.getFromUserName(), reply); wecomClient.sendText(msg.getFromUserName(), reply);