Dify 配置外置并切至内网实例
接口地址与各应用 API Key 原先硬编码在 AiController 与 KnowledgeBaseController 中,换环境要改代码、密钥还会散落在多处。 新增 DifyProperties 统一收敛到 dify 配置节点,并补上文档中缺失的 两个应用与知识库管理接口。 - 新增 DifyProperties,外置 base-url / 8 个应用 Key / 知识库密钥, 默认值保持公网实例,本地开发不受影响 - 生产 profile 覆盖为内网 10.100.158.15,含全部 8 个应用 Key 与 两个知识库的独立密钥 - 新增申报书生成、智能文档处理两个工作流接口(含文件上传版本), 接入既有的 WebSocket 流式推送与停止机制 - KnowledgeBaseController 补齐知识库增删改查、文档管理与索引进度, 并对文档状态动作加白名单,避免路径参数被任意拼接 - 修正 AI 内容创作的 number 变量名:Dify 侧为 Number, 变量名大小写敏感,此前一直发送小写导致该功能缺参 - 生产下显式覆盖公网知识库 ID 的密钥:YAML 的 map 按键合并而非整体 替换,不覆盖会残留指向公网实例的死密钥 工作流变量名取自内网实例实测(probe-dify.sh),其中申报书生成与 文档处理两组变量与公网命名习惯不一致,故以配置映射承载,改名只需 改 yml 而非改代码。 新增 18 项测试,覆盖配置绑定、profile 覆盖完整性(逐项断言 8 个 Key 均已覆盖且不残留公网 Key)与入参到 Dify inputs 的映射。
This commit is contained in:
@@ -4,9 +4,13 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.gxwebsoft.ai.config.DifyProperties;
|
||||
import com.gxwebsoft.ai.entity.ActivityOutlineInputs;
|
||||
import com.gxwebsoft.ai.entity.AiChatHistory;
|
||||
import com.gxwebsoft.ai.entity.AiChatList;
|
||||
import com.gxwebsoft.ai.entity.DeclarationInputs;
|
||||
import com.gxwebsoft.ai.entity.DocumentProcessInputs;
|
||||
import com.gxwebsoft.ai.entity.ManuscriptGenInputs;
|
||||
import com.gxwebsoft.ai.service.AiChatHistoryService;
|
||||
import com.gxwebsoft.ai.service.AiChatListService;
|
||||
@@ -16,6 +20,7 @@ import com.gxwebsoft.common.core.web.BaseController;
|
||||
import com.gxwebsoft.ai.config.WebSocketServer;
|
||||
import com.gxwebsoft.ai.entity.ChatMessage;
|
||||
import io.swagger.annotations.Api;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@@ -54,28 +59,53 @@ public class AiController extends BaseController {
|
||||
private AiChatHistoryService aiChatHistoryService;
|
||||
@Resource
|
||||
private AiChatListService aiChatListService;
|
||||
@Resource
|
||||
private DifyProperties difyProperties;
|
||||
|
||||
/**
|
||||
* 用于把入参实体序列化成 Map,尊重 Jackson 注解
|
||||
*/
|
||||
private final ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* Dify 接口地址前缀,取自 {@code dify.base-url}
|
||||
*/
|
||||
private String aiUrl() {
|
||||
return difyProperties.getBaseUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* 各应用 API Key,取自 {@code dify.apps.*}。
|
||||
*
|
||||
* <p>原先这些 Key 硬编码在字段上,现统一外置到配置;取 Key 一律走这里,
|
||||
* 便于换环境时只动 yml。
|
||||
*/
|
||||
private DifyProperties.AppKeys appKeys() {
|
||||
return difyProperties.getApps();
|
||||
}
|
||||
|
||||
/**
|
||||
* 单次请求超时(毫秒)
|
||||
*/
|
||||
private int aiTimeout() {
|
||||
Integer timeout = difyProperties.getTimeoutMs();
|
||||
return timeout == null || timeout <= 0 ? 600000 : timeout;
|
||||
}
|
||||
|
||||
private String aiUrl = "http://82.156.98.71/v1";
|
||||
private String key = "app-ou0qPesouiopaPpmxcFV2gFG";
|
||||
private String manuscriptKey = "app-hCzkdd6OsnMnwI2dQByLyNIN";
|
||||
private String creativeAssistantKey = "app-l3accBEJLDAh9Pn8fLW8nNJ0";
|
||||
private String activityOutlineKey = "app-hp4PJknbejImmdDuMfziVcnN";
|
||||
private String competitionHistoryPreprocessKey = "app-bhyQLMAw2JEDXMTs2mzNRiIU";
|
||||
private String projectQualityReviewKey = "app-HiI2FrNjcwL0A7QOOf7GIP50";
|
||||
private final Map<String, ActiveAiTask> activeAiTaskMap = new ConcurrentHashMap<>();
|
||||
|
||||
@PostMapping("/chat/message")
|
||||
public ApiResult<?> message(@RequestBody ChatMessage message) throws IOException {
|
||||
try {
|
||||
URL url = new URL(aiUrl + "/chat-messages");
|
||||
URL url = new URL(aiUrl() + "/chat-messages");
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", "Bearer " + key);
|
||||
connection.setRequestProperty("Authorization", "Bearer " + appKeys().getChat());
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("Accept", "text/event-stream");
|
||||
connection.setDoOutput(true);
|
||||
connection.setConnectTimeout(600000);
|
||||
connection.setReadTimeout(600000);
|
||||
connection.setConnectTimeout(aiTimeout());
|
||||
connection.setReadTimeout(aiTimeout());
|
||||
|
||||
Integer chatId = message.getChatId();
|
||||
if (chatId == null || chatId == 0) {
|
||||
@@ -137,7 +167,7 @@ public class AiController extends BaseController {
|
||||
String event = eventObj == null ? "" : eventObj.toString();
|
||||
if (StrUtil.isNotBlank(stringValue(data.get("task_id")))) {
|
||||
taskId = stringValue(data.get("task_id"));
|
||||
recordActiveAiTask(getLoginUserId(), "chat", taskId, key);
|
||||
recordActiveAiTask(getLoginUserId(), "chat", taskId, appKeys().getChat());
|
||||
}
|
||||
String currentConversationId = data.get("conversation_id") == null
|
||||
? conversationId
|
||||
@@ -239,15 +269,15 @@ public class AiController extends BaseController {
|
||||
@PostMapping("/manuscriptGen")
|
||||
public ApiResult<?> manuscriptGen(@RequestBody ManuscriptGenInputs message) throws IOException {
|
||||
try {
|
||||
URL url = new URL(aiUrl + "/workflows/run");
|
||||
URL url = new URL(aiUrl() + "/workflows/run");
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", "Bearer " + manuscriptKey);
|
||||
connection.setRequestProperty("Authorization", "Bearer " + appKeys().getManuscript());
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("Accept", "text/event-stream");
|
||||
connection.setDoOutput(true);
|
||||
connection.setConnectTimeout(600000);
|
||||
connection.setReadTimeout(600000);
|
||||
connection.setConnectTimeout(aiTimeout());
|
||||
connection.setReadTimeout(aiTimeout());
|
||||
|
||||
Map<String, Object> inputs = buildManuscriptInputs(message);
|
||||
Object files = normalizeFiles(message.getFiles());
|
||||
@@ -302,7 +332,7 @@ public class AiController extends BaseController {
|
||||
taskId = stringValue(data.get("id"));
|
||||
}
|
||||
if (StrUtil.isNotBlank(taskId)) {
|
||||
recordActiveAiTask(getLoginUserId(), "workflow", taskId, manuscriptKey);
|
||||
recordActiveAiTask(getLoginUserId(), "workflow", taskId, appKeys().getManuscript());
|
||||
}
|
||||
System.out.println(data);
|
||||
String answer = extractAnswer(data);
|
||||
@@ -427,7 +457,7 @@ public class AiController extends BaseController {
|
||||
List<Object> uploadedFiles = new ArrayList<>();
|
||||
for (MultipartFile file : files) {
|
||||
if (file != null && !file.isEmpty()) {
|
||||
uploadedFiles.add(uploadMultipartToAi(file, competitionHistoryPreprocessKey, loginUserId));
|
||||
uploadedFiles.add(uploadMultipartToAi(file, appKeys().getCompetitionHistoryPreprocess(), loginUserId));
|
||||
}
|
||||
}
|
||||
if (uploadedFiles.isEmpty()) {
|
||||
@@ -435,12 +465,12 @@ public class AiController extends BaseController {
|
||||
} else {
|
||||
inputs.put("file_upload", uploadedFiles);
|
||||
if (scoreFile != null && !scoreFile.isEmpty()) {
|
||||
inputs.put("score_file", uploadMultipartToAi(scoreFile, competitionHistoryPreprocessKey, loginUserId));
|
||||
inputs.put("score_file", uploadMultipartToAi(scoreFile, appKeys().getCompetitionHistoryPreprocess(), loginUserId));
|
||||
}
|
||||
if (StrUtil.isNotBlank(manualText)) {
|
||||
inputs.put("manual_text", manualText.trim());
|
||||
}
|
||||
result = executeWorkflowForResult(inputs, competitionHistoryPreprocessKey,
|
||||
result = executeWorkflowForResult(inputs, appKeys().getCompetitionHistoryPreprocess(),
|
||||
"competitionHistoryPreprocess", loginUserId, true);
|
||||
}
|
||||
}
|
||||
@@ -465,11 +495,11 @@ public class AiController extends BaseController {
|
||||
return fail("请上传待审项目申报书");
|
||||
}
|
||||
Map<String, Object> inputs = new LinkedHashMap<>();
|
||||
inputs.put("new_project", uploadMultipartToAi(newProject, projectQualityReviewKey, loginUserId));
|
||||
inputs.put("new_project", uploadMultipartToAi(newProject, appKeys().getProjectQualityReview(), loginUserId));
|
||||
if (customRubric != null && !customRubric.isEmpty()) {
|
||||
inputs.put("custom_rubric", uploadMultipartToAi(customRubric, projectQualityReviewKey, loginUserId));
|
||||
inputs.put("custom_rubric", uploadMultipartToAi(customRubric, appKeys().getProjectQualityReview(), loginUserId));
|
||||
}
|
||||
return executeWorkflowForResult(inputs, projectQualityReviewKey,
|
||||
return executeWorkflowForResult(inputs, appKeys().getProjectQualityReview(),
|
||||
"projectQualityReview", loginUserId, true);
|
||||
} catch (Exception e) {
|
||||
logger.error("project quality review failed", e);
|
||||
@@ -479,6 +509,104 @@ public class AiController extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("申报书生成")
|
||||
@PostMapping("/declarationGen")
|
||||
public ApiResult<?> declarationGen(@RequestBody DeclarationInputs message) {
|
||||
Integer loginUserId = getLoginUserId();
|
||||
if (message == null) {
|
||||
return fail("请求参数不能为空");
|
||||
}
|
||||
// 核心创意是必填项(内网工作流 core_idea);upload_file 为可选的已有初稿/参考资料
|
||||
if (StrUtil.isBlank(message.getCoreIdea())) {
|
||||
return fail("coreIdea不能为空");
|
||||
}
|
||||
try {
|
||||
Map<String, Object> inputs = buildMappedInputs(message, message.getInputs(),
|
||||
difyProperties.getWorkflows().getDeclaration());
|
||||
return executeWorkflowForResult(inputs, appKeys().getDeclaration(),
|
||||
"declaration", loginUserId, true);
|
||||
} catch (Exception e) {
|
||||
logger.error("declaration gen failed", e);
|
||||
sendWorkflowSocketMessage("出错了,请晚点再试~", null, null, "declaration", false, loginUserId);
|
||||
sendWorkflowSocketEnd(null, null, "declaration", loginUserId);
|
||||
return fail("申报书生成失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("智能文档处理")
|
||||
@PostMapping("/documentProcess")
|
||||
public ApiResult<?> documentProcess(@RequestBody DocumentProcessInputs message) {
|
||||
Integer loginUserId = getLoginUserId();
|
||||
if (message == null) {
|
||||
return fail("请求参数不能为空");
|
||||
}
|
||||
// 网络地址与上传文件至少一个(内网工作流 pdf_url / pdf_file)
|
||||
if (StrUtil.isBlank(message.getPdfUrl()) && !hasFileValue(message.getPdfFile())) {
|
||||
return fail("pdfUrl与pdfFile至少需要一个");
|
||||
}
|
||||
try {
|
||||
Map<String, Object> inputs = buildMappedInputs(message, message.getInputs(),
|
||||
difyProperties.getWorkflows().getDocumentProcess());
|
||||
return executeWorkflowForResult(inputs, appKeys().getDocumentProcess(),
|
||||
"documentProcess", loginUserId, true);
|
||||
} catch (Exception e) {
|
||||
logger.error("document process failed", e);
|
||||
sendWorkflowSocketMessage("出错了,请晚点再试~", null, null, "documentProcess", false, loginUserId);
|
||||
sendWorkflowSocketEnd(null, null, "documentProcess", loginUserId);
|
||||
return fail("文档处理失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@ApiOperation("智能文档处理(文件上传)")
|
||||
@PostMapping("/documentProcess/upload")
|
||||
public DeferredResult<ApiResult<?>> documentProcessUpload(
|
||||
@RequestParam(value = "file", required = false) MultipartFile file,
|
||||
@RequestParam(value = "pdfUrl", required = false) String pdfUrl,
|
||||
@RequestParam(value = "query", required = false) String query) {
|
||||
final Integer loginUserId = getLoginUserId();
|
||||
final DeferredResult<ApiResult<?>> deferredResult = new DeferredResult<>(AI_REQUEST_TIMEOUT);
|
||||
final AtomicBoolean requestActive = new AtomicBoolean(true);
|
||||
deferredResult.onTimeout(() -> {
|
||||
requestActive.set(false);
|
||||
if (!deferredResult.isSetOrExpired()) {
|
||||
deferredResult.setResult(fail("文档处理超时,请稍后查看知识库列表"));
|
||||
}
|
||||
});
|
||||
deferredResult.onError((throwable) -> requestActive.set(false));
|
||||
deferredResult.onCompletion(() -> requestActive.set(false));
|
||||
CompletableFuture.runAsync(() -> {
|
||||
ApiResult<?> result;
|
||||
try {
|
||||
if ((file == null || file.isEmpty()) && StrUtil.isBlank(pdfUrl)) {
|
||||
result = fail("请上传文件或提供pdfUrl");
|
||||
} else {
|
||||
// 键名直接用业务字段名,再交给 remapInputs 按配置映射成真实变量名,
|
||||
// 避免在这里手写 "pdf_file" 之类的 Dify 变量名造成两处维护。
|
||||
Map<String, Object> inputs = new LinkedHashMap<>();
|
||||
if (file != null && !file.isEmpty()) {
|
||||
inputs.put("pdfFile", uploadMultipartToAi(file, appKeys().getDocumentProcess(), loginUserId));
|
||||
}
|
||||
if (StrUtil.isNotBlank(pdfUrl)) {
|
||||
inputs.put("pdfUrl", pdfUrl.trim());
|
||||
}
|
||||
if (StrUtil.isNotBlank(query)) {
|
||||
inputs.put("query", query.trim());
|
||||
}
|
||||
result = executeWorkflowForResult(
|
||||
remapInputs(inputs, difyProperties.getWorkflows().getDocumentProcess()),
|
||||
appKeys().getDocumentProcess(), "documentProcess", loginUserId, true);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("document process upload failed", e);
|
||||
result = fail("文档处理失败: " + e.getMessage());
|
||||
}
|
||||
if (requestActive.get() && !deferredResult.isSetOrExpired()) {
|
||||
deferredResult.setResult(result);
|
||||
}
|
||||
});
|
||||
return deferredResult;
|
||||
}
|
||||
|
||||
@PostMapping("/activityOutlineGen")
|
||||
public ApiResult<?> activityOutlineGen(@RequestBody ActivityOutlineInputs message) {
|
||||
if (message == null) {
|
||||
@@ -498,15 +626,15 @@ public class AiController extends BaseController {
|
||||
}
|
||||
|
||||
try {
|
||||
URL url = new URL(aiUrl + "/chat-messages");
|
||||
URL url = new URL(aiUrl() + "/chat-messages");
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", "Bearer " + activityOutlineKey);
|
||||
connection.setRequestProperty("Authorization", "Bearer " + appKeys().getActivityOutline());
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("Accept", "text/event-stream");
|
||||
connection.setDoOutput(true);
|
||||
connection.setConnectTimeout(600000);
|
||||
connection.setReadTimeout(600000);
|
||||
connection.setConnectTimeout(aiTimeout());
|
||||
connection.setReadTimeout(aiTimeout());
|
||||
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
payload.put("query", "请根据已提供的活动信息生成完整的活动策划大纲");
|
||||
@@ -642,15 +770,15 @@ public class AiController extends BaseController {
|
||||
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
URL url = new URL(aiUrl + "/workflows/run");
|
||||
URL url = new URL(aiUrl() + "/workflows/run");
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", "Bearer " + creativeAssistantKey);
|
||||
connection.setRequestProperty("Authorization", "Bearer " + appKeys().getCreativeAssistant());
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("Accept", "text/event-stream");
|
||||
connection.setDoOutput(true);
|
||||
connection.setConnectTimeout(600000);
|
||||
connection.setReadTimeout(600000);
|
||||
connection.setConnectTimeout(aiTimeout());
|
||||
connection.setReadTimeout(aiTimeout());
|
||||
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
payload.put("inputs", buildCreativeAssistantInputs(requestBody));
|
||||
@@ -706,7 +834,7 @@ public class AiController extends BaseController {
|
||||
taskId = stringValue(data.get("id"));
|
||||
}
|
||||
if (StrUtil.isNotBlank(taskId)) {
|
||||
recordActiveAiTask(loginUserId, "workflow", taskId, creativeAssistantKey);
|
||||
recordActiveAiTask(loginUserId, "workflow", taskId, appKeys().getCreativeAssistant());
|
||||
}
|
||||
|
||||
String event = stringValue(data.get("event"));
|
||||
@@ -811,7 +939,9 @@ public class AiController extends BaseController {
|
||||
inputs.put("highlights", message.getHighlights());
|
||||
}
|
||||
if (message.getNumber() != null) {
|
||||
inputs.put("number", message.getNumber());
|
||||
// Dify 工作流里该变量名首字母大写(Number),与其它小写变量不一致。
|
||||
// 变量名大小写敏感,发 "number" 会因缺参报错,故按实际变量名发送。
|
||||
inputs.put("Number", message.getNumber());
|
||||
}
|
||||
return inputs;
|
||||
}
|
||||
@@ -845,6 +975,69 @@ public class AiController extends BaseController {
|
||||
return inputs;
|
||||
}
|
||||
|
||||
/**
|
||||
* 把入参实体的业务字段转成 Dify 工作流的 inputs。
|
||||
*
|
||||
* <p>调用方显式传了 {@code inputs} 时以它为准(可覆盖映射配置);
|
||||
* 否则按 {@code mapping} 把非空业务字段改名后透传,未登记的字段按原名发送。
|
||||
* 这样即使内网工作流的变量名与业务字段不一致,改 yml 即可对齐,无需改代码。
|
||||
*/
|
||||
private Map<String, Object> buildMappedInputs(Object source,
|
||||
Map<String, Object> explicitInputs,
|
||||
DifyProperties.VariableMapping mapping) {
|
||||
if (explicitInputs != null && !explicitInputs.isEmpty()) {
|
||||
return new LinkedHashMap<>(explicitInputs);
|
||||
}
|
||||
Map<String, Object> raw = objectToMap(source);
|
||||
return remapInputs(raw, mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* 按映射表改写 inputs 的键名。
|
||||
*/
|
||||
private Map<String, Object> remapInputs(Map<String, Object> raw, DifyProperties.VariableMapping mapping) {
|
||||
Map<String, Object> result = new LinkedHashMap<>();
|
||||
if (raw == null) {
|
||||
return result;
|
||||
}
|
||||
for (Map.Entry<String, Object> entry : raw.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
if (value instanceof String && StrUtil.isBlank((String) value)) {
|
||||
continue;
|
||||
}
|
||||
String variable = mapping == null ? entry.getKey() : mapping.variableOf(entry.getKey());
|
||||
// 映射为空串表示该字段不发给 Dify
|
||||
if (StrUtil.isBlank(variable)) {
|
||||
continue;
|
||||
}
|
||||
result.put(variable, value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用 Jackson 把入参实体转成 Map,跳过 null 字段。
|
||||
*
|
||||
* <p>不用 JSONUtil:它对实体走的是 fastjson,字段命名策略与 Jackson 注解
|
||||
* ({@code @JsonProperty}/{@code @JsonAlias})不一致。
|
||||
*/
|
||||
private Map<String, Object> objectToMap(Object source) {
|
||||
if (source == null) {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
try {
|
||||
String json = objectMapper.writeValueAsString(source);
|
||||
Map<String, Object> map = JSONUtil.parseObject(json, Map.class);
|
||||
return map == null ? new LinkedHashMap<>() : map;
|
||||
} catch (Exception e) {
|
||||
logger.warn("入参实体转换失败: {}", source.getClass().getSimpleName(), e);
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> buildCreativeAssistantInputs(Map<String, Object> requestBody) {
|
||||
Map<String, Object> inputs = new LinkedHashMap<>();
|
||||
if (requestBody == null) {
|
||||
@@ -872,15 +1065,15 @@ public class AiController extends BaseController {
|
||||
boolean streamToSocket) throws IOException {
|
||||
HttpURLConnection connection = null;
|
||||
try {
|
||||
URL url = new URL(aiUrl + "/workflows/run");
|
||||
URL url = new URL(aiUrl() + "/workflows/run");
|
||||
connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("Authorization", "Bearer " + apiKey);
|
||||
connection.setRequestProperty("Content-Type", "application/json");
|
||||
connection.setRequestProperty("Accept", "text/event-stream");
|
||||
connection.setDoOutput(true);
|
||||
connection.setConnectTimeout(600000);
|
||||
connection.setReadTimeout(600000);
|
||||
connection.setConnectTimeout(aiTimeout());
|
||||
connection.setReadTimeout(aiTimeout());
|
||||
|
||||
Map<String, Object> payload = new LinkedHashMap<>();
|
||||
payload.put("inputs", inputs == null ? new LinkedHashMap<>() : inputs);
|
||||
@@ -1046,11 +1239,11 @@ public class AiController extends BaseController {
|
||||
}
|
||||
tempFile = File.createTempFile("ai-upload-", suffix);
|
||||
file.transferTo(tempFile);
|
||||
HttpResponse response = HttpRequest.post(aiUrl + "/files/upload")
|
||||
HttpResponse response = HttpRequest.post(aiUrl() + "/files/upload")
|
||||
.header("Authorization", "Bearer " + apiKey)
|
||||
.form("user", loginUserId == null ? "0" : loginUserId.toString())
|
||||
.form("file", tempFile, originalFilename)
|
||||
.timeout(600000)
|
||||
.timeout(aiTimeout())
|
||||
.execute();
|
||||
String responseBody = response.body();
|
||||
Map<String, Object> result = JSONUtil.parseObject(responseBody, Map.class);
|
||||
@@ -1319,18 +1512,24 @@ public class AiController extends BaseController {
|
||||
return activeTask.getApiKey();
|
||||
}
|
||||
if ("image".equals(mode)) {
|
||||
return creativeAssistantKey;
|
||||
return appKeys().getCreativeAssistant();
|
||||
}
|
||||
if ("writing".equals(mode)) {
|
||||
return manuscriptKey;
|
||||
return appKeys().getManuscript();
|
||||
}
|
||||
if ("projectQualityReview".equals(mode)) {
|
||||
return projectQualityReviewKey;
|
||||
return appKeys().getProjectQualityReview();
|
||||
}
|
||||
if ("competitionHistoryPreprocess".equals(mode)) {
|
||||
return competitionHistoryPreprocessKey;
|
||||
return appKeys().getCompetitionHistoryPreprocess();
|
||||
}
|
||||
return key;
|
||||
if ("documentProcess".equals(mode)) {
|
||||
return appKeys().getDocumentProcess();
|
||||
}
|
||||
if ("declaration".equals(mode)) {
|
||||
return appKeys().getDeclaration();
|
||||
}
|
||||
return appKeys().getChat();
|
||||
}
|
||||
|
||||
private String normalizeStopMode(String mode) {
|
||||
@@ -1343,7 +1542,6 @@ public class AiController extends BaseController {
|
||||
|| "message".equals(mode)
|
||||
|| "activityOutline".equals(mode);
|
||||
}
|
||||
|
||||
private String buildActiveTaskKey(Integer userId, String mode) {
|
||||
return userId + ":" + mode;
|
||||
}
|
||||
@@ -1387,11 +1585,11 @@ public class AiController extends BaseController {
|
||||
Map<String, Object> postData = new HashMap<>();
|
||||
postData.put("user", loginUserId == null ? "0" : loginUserId.toString());
|
||||
logger.info("AI stop payload: mode={}, taskId={}, path={}", mode, taskId, stopPath);
|
||||
HttpResponse response = HttpRequest.post(aiUrl + stopPath)
|
||||
HttpResponse response = HttpRequest.post(aiUrl() + stopPath)
|
||||
.header("Authorization", "Bearer " + apiKey)
|
||||
.header("Content-Type", "application/json")
|
||||
.body(JSONObject.toJSONString(postData))
|
||||
.timeout(600000)
|
||||
.timeout(aiTimeout())
|
||||
.execute();
|
||||
String responseBody = response.body();
|
||||
if (response.getStatus() < 200 || response.getStatus() >= 300) {
|
||||
@@ -1411,9 +1609,9 @@ public class AiController extends BaseController {
|
||||
}
|
||||
File tempFile = null;
|
||||
try {
|
||||
String token = manuscriptKey;
|
||||
String token = appKeys().getManuscript();
|
||||
if (type == null || type == 0) {
|
||||
token = key;
|
||||
token = appKeys().getChat();
|
||||
}
|
||||
String originalFilename = StrUtil.blankToDefault(file.getOriginalFilename(), "upload.bin");
|
||||
String suffix = "";
|
||||
@@ -1424,11 +1622,11 @@ public class AiController extends BaseController {
|
||||
tempFile = File.createTempFile("ai-upload-", suffix);
|
||||
file.transferTo(tempFile);
|
||||
|
||||
HttpResponse response = HttpRequest.post(aiUrl + "/files/upload")
|
||||
HttpResponse response = HttpRequest.post(aiUrl() + "/files/upload")
|
||||
.header("Authorization", "Bearer " + token)
|
||||
.form("user", StrUtil.blankToDefault(user, getLoginUserId().toString()))
|
||||
.form("file", tempFile, originalFilename)
|
||||
.timeout(600000)
|
||||
.timeout(aiTimeout())
|
||||
.execute();
|
||||
|
||||
int responseCode = response.getStatus();
|
||||
|
||||
Reference in New Issue
Block a user