|
|
@@ -11,7 +11,6 @@ import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.http.HttpEntity;
|
|
|
import org.springframework.http.ResponseEntity;
|
|
|
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.web.client.RestTemplate;
|
|
|
|
|
|
@@ -44,16 +43,7 @@ public class AiGateway {
|
|
|
@Value("${python.circuit-breaker.reset-timeout-ms:30000}")
|
|
|
private int resetTimeoutMs;
|
|
|
|
|
|
- @Value("${langgraph.profile-timeout-ms:90000}")
|
|
|
- private int profileTimeoutMs;
|
|
|
-
|
|
|
private final RestTemplate restTemplate = new RestTemplate();
|
|
|
-
|
|
|
- /**
|
|
|
- * 画像生成专用客户端:独立 90s 读超时(LangGraph 推理可达 30-60s)。
|
|
|
- * 在 {@link #init()} 中设置 factory(@Value 注入晚于构造)。
|
|
|
- */
|
|
|
- private final RestTemplate profileRestTemplate = new RestTemplate();
|
|
|
private final ObjectMapper objectMapper = new ObjectMapper();
|
|
|
|
|
|
// 熔断器状态
|
|
|
@@ -63,13 +53,9 @@ public class AiGateway {
|
|
|
|
|
|
@PostConstruct
|
|
|
public void init() {
|
|
|
- SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
|
|
- factory.setConnectTimeout(5000);
|
|
|
- factory.setReadTimeout(profileTimeoutMs);
|
|
|
- profileRestTemplate.setRequestFactory(factory);
|
|
|
if (enabled) {
|
|
|
- log.info("AiGateway 已启用: baseUrl={}, timeout={}ms, profile-timeout={}ms",
|
|
|
- baseUrl, timeoutMs, profileTimeoutMs);
|
|
|
+ log.info("AiGateway 已启用: baseUrl={}, timeout={}ms",
|
|
|
+ baseUrl, timeoutMs);
|
|
|
} else {
|
|
|
log.info("AiGateway 已禁用, 所有请求走 Dify");
|
|
|
}
|
|
|
@@ -349,70 +335,5 @@ public class AiGateway {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 调用 LangGraph 动态出题(/api/v1/qna/advance)
|
|
|
- */
|
|
|
- public Map<String, Object> advanceQuestionnaire(Map<String, Object> scene, List<Map<String, Object>> history) {
|
|
|
- if (!enabled || isCircuitOpen()) return null;
|
|
|
- try {
|
|
|
- ObjectNode body = objectMapper.createObjectNode();
|
|
|
- body.set("scene", objectMapper.valueToTree(scene));
|
|
|
- ArrayNode hist = body.putArray("history");
|
|
|
- if (history != null) {
|
|
|
- for (Map<String, Object> item : history) {
|
|
|
- hist.add(objectMapper.valueToTree(item));
|
|
|
- }
|
|
|
- }
|
|
|
- HttpEntity<String> entity = new HttpEntity<>(body.toString(), createJsonHeaders());
|
|
|
- String url = baseUrl + "/api/v1/qna/advance";
|
|
|
- ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);
|
|
|
- if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
|
|
|
- JsonNode root = objectMapper.readTree(response.getBody());
|
|
|
- Map<String, Object> result = new LinkedHashMap<>();
|
|
|
- result.put("action", root.has("action") ? root.get("action").asText() : "ask");
|
|
|
- result.put("question", root.has("question") ? objectMapper.convertValue(root.get("question"), Map.class) : null);
|
|
|
- result.put("reason", root.has("reason") ? root.get("reason").asText() : "");
|
|
|
- consecutiveFailures.set(0);
|
|
|
- return result;
|
|
|
- }
|
|
|
- return null;
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("AiGateway advanceQuestionnaire 调用失败: {}", e.getMessage());
|
|
|
- recordFailure();
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 调用 LangGraph 生成画像(/api/v1/qna/profile,独立 90s 读超时)
|
|
|
- */
|
|
|
- public Map<String, Object> generateProfile(Map<String, Object> scene, List<Map<String, Object>> history) {
|
|
|
- if (!enabled || isCircuitOpen()) return null;
|
|
|
- try {
|
|
|
- ObjectNode body = objectMapper.createObjectNode();
|
|
|
- body.set("scene", objectMapper.valueToTree(scene));
|
|
|
- ArrayNode hist = body.putArray("history");
|
|
|
- if (history != null) {
|
|
|
- for (Map<String, Object> item : history) {
|
|
|
- hist.add(objectMapper.valueToTree(item));
|
|
|
- }
|
|
|
- }
|
|
|
- HttpEntity<String> entity = new HttpEntity<>(body.toString(), createJsonHeaders());
|
|
|
- String url = baseUrl + "/api/v1/qna/profile";
|
|
|
- ResponseEntity<String> response = profileRestTemplate.postForEntity(url, entity, String.class);
|
|
|
- if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
|
|
|
- JsonNode root = objectMapper.readTree(response.getBody());
|
|
|
- Map<String, Object> result = new LinkedHashMap<>();
|
|
|
- result.put("profile", root.has("profile") ? objectMapper.convertValue(root.get("profile"), Map.class) : null);
|
|
|
- result.put("kb_used", root.has("kb_used") ? root.get("kb_used").asBoolean() : false);
|
|
|
- consecutiveFailures.set(0);
|
|
|
- return result;
|
|
|
- }
|
|
|
- return null;
|
|
|
- } catch (Exception e) {
|
|
|
- log.warn("AiGateway generateProfile 调用失败: {}", e.getMessage());
|
|
|
- recordFailure();
|
|
|
- return null;
|
|
|
- }
|
|
|
- }
|
|
|
+
|
|
|
}
|