From 1668b4ce8fb82ddfd54b44b86e78e3080b99a1cc Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期六, 21 三月 2026 08:44:07 +0800
Subject: [PATCH] #ai
---
rsf-server/src/main/java/com/vincent/rsf/server/ai/tool/RsfWmsTaskTools.java | 116 +++++++++++++++++++++--------
rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java | 15 ---
rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiOpenAiApiSupport.java | 86 +++++++++++++++++++++
rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamValidationSupport.java | 19 ----
4 files changed, 173 insertions(+), 63 deletions(-)
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java
index 0430123..40d5594 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiChatServiceImpl.java
@@ -51,12 +51,9 @@
import org.springframework.ai.util.json.schema.SchemaType;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.http.MediaType;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
-import org.springframework.web.client.RestClient;
-import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import reactor.core.publisher.Flux;
@@ -479,17 +476,7 @@
}
private OpenAiApi buildOpenAiApi(AiParam aiParam) {
- int timeoutMs = aiParam.getTimeoutMs() == null ? AiDefaults.DEFAULT_TIMEOUT_MS : aiParam.getTimeoutMs();
- SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
- requestFactory.setConnectTimeout(timeoutMs);
- requestFactory.setReadTimeout(timeoutMs);
-
- return OpenAiApi.builder()
- .baseUrl(aiParam.getBaseUrl())
- .apiKey(aiParam.getApiKey())
- .restClientBuilder(RestClient.builder().requestFactory(requestFactory))
- .webClientBuilder(WebClient.builder())
- .build();
+ return AiOpenAiApiSupport.buildOpenAiApi(aiParam);
}
private OpenAiChatOptions buildChatOptions(AiParam aiParam, ToolCallback[] toolCallbacks, Long userId, Long tenantId,
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiOpenAiApiSupport.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiOpenAiApiSupport.java
new file mode 100644
index 0000000..bb404b9
--- /dev/null
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiOpenAiApiSupport.java
@@ -0,0 +1,86 @@
+package com.vincent.rsf.server.ai.service.impl;
+
+import com.vincent.rsf.server.ai.config.AiDefaults;
+import com.vincent.rsf.server.ai.entity.AiParam;
+import org.springframework.ai.openai.api.OpenAiApi;
+import org.springframework.http.client.SimpleClientHttpRequestFactory;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestClient;
+import org.springframework.web.reactive.function.client.WebClient;
+
+import java.util.Locale;
+
+final class AiOpenAiApiSupport {
+
+ private static final String DEFAULT_COMPLETIONS_PATH = "/v1/chat/completions";
+ private static final String DEFAULT_EMBEDDINGS_PATH = "/v1/embeddings";
+ private static final String V1_SEGMENT = "/v1";
+ private static final String COMPLETIONS_SEGMENT = "/chat/completions";
+ private static final String EMBEDDINGS_SEGMENT = "/embeddings";
+
+ private AiOpenAiApiSupport() {
+ }
+
+ static OpenAiApi buildOpenAiApi(AiParam aiParam) {
+ int timeoutMs = aiParam.getTimeoutMs() == null ? AiDefaults.DEFAULT_TIMEOUT_MS : aiParam.getTimeoutMs();
+ SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
+ requestFactory.setConnectTimeout(timeoutMs);
+ requestFactory.setReadTimeout(timeoutMs);
+
+ EndpointConfig endpointConfig = resolveEndpointConfig(aiParam.getBaseUrl());
+ return OpenAiApi.builder()
+ .baseUrl(endpointConfig.baseUrl())
+ .completionsPath(endpointConfig.completionsPath())
+ .embeddingsPath(endpointConfig.embeddingsPath())
+ .apiKey(aiParam.getApiKey())
+ .restClientBuilder(RestClient.builder().requestFactory(requestFactory))
+ .webClientBuilder(WebClient.builder())
+ .build();
+ }
+
+ static EndpointConfig resolveEndpointConfig(String rawBaseUrl) {
+ String normalizedBaseUrl = trimTrailingSlash(rawBaseUrl);
+ String lowerCaseBaseUrl = normalizedBaseUrl.toLowerCase(Locale.ROOT);
+
+ if (lowerCaseBaseUrl.endsWith(DEFAULT_COMPLETIONS_PATH)) {
+ String baseUrl = trimTrailingSlash(normalizedBaseUrl.substring(0,
+ normalizedBaseUrl.length() - DEFAULT_COMPLETIONS_PATH.length()));
+ return new EndpointConfig(baseUrl, DEFAULT_COMPLETIONS_PATH, DEFAULT_EMBEDDINGS_PATH);
+ }
+ if (lowerCaseBaseUrl.endsWith(DEFAULT_EMBEDDINGS_PATH)) {
+ String baseUrl = trimTrailingSlash(normalizedBaseUrl.substring(0,
+ normalizedBaseUrl.length() - DEFAULT_EMBEDDINGS_PATH.length()));
+ return new EndpointConfig(baseUrl, DEFAULT_COMPLETIONS_PATH, DEFAULT_EMBEDDINGS_PATH);
+ }
+ if (lowerCaseBaseUrl.endsWith(COMPLETIONS_SEGMENT)) {
+ String baseUrl = trimTrailingSlash(normalizedBaseUrl.substring(0,
+ normalizedBaseUrl.length() - COMPLETIONS_SEGMENT.length()));
+ return new EndpointConfig(baseUrl, COMPLETIONS_SEGMENT, EMBEDDINGS_SEGMENT);
+ }
+ if (lowerCaseBaseUrl.endsWith(EMBEDDINGS_SEGMENT)) {
+ String baseUrl = trimTrailingSlash(normalizedBaseUrl.substring(0,
+ normalizedBaseUrl.length() - EMBEDDINGS_SEGMENT.length()));
+ return new EndpointConfig(baseUrl, COMPLETIONS_SEGMENT, EMBEDDINGS_SEGMENT);
+ }
+ if (lowerCaseBaseUrl.endsWith(V1_SEGMENT)) {
+ String baseUrl = trimTrailingSlash(normalizedBaseUrl.substring(0,
+ normalizedBaseUrl.length() - V1_SEGMENT.length()));
+ return new EndpointConfig(baseUrl, DEFAULT_COMPLETIONS_PATH, DEFAULT_EMBEDDINGS_PATH);
+ }
+ return new EndpointConfig(normalizedBaseUrl, DEFAULT_COMPLETIONS_PATH, DEFAULT_EMBEDDINGS_PATH);
+ }
+
+ private static String trimTrailingSlash(String baseUrl) {
+ String normalized = baseUrl == null ? "" : baseUrl.trim();
+ if (!StringUtils.hasText(normalized)) {
+ return normalized;
+ }
+ while (normalized.endsWith("/")) {
+ normalized = normalized.substring(0, normalized.length() - 1);
+ }
+ return normalized;
+ }
+
+ record EndpointConfig(String baseUrl, String completionsPath, String embeddingsPath) {
+ }
+}
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamValidationSupport.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamValidationSupport.java
index 1d05099..09362c7 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamValidationSupport.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/service/impl/AiParamValidationSupport.java
@@ -18,11 +18,8 @@
import org.springframework.ai.tool.resolution.SpringBeanToolCallbackResolver;
import org.springframework.ai.util.json.schema.SchemaType;
import org.springframework.context.support.GenericApplicationContext;
-import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
-import org.springframework.web.client.RestClient;
-import org.springframework.web.reactive.function.client.WebClient;
import java.text.SimpleDateFormat;
import java.util.Date;
@@ -98,20 +95,8 @@
}
private OpenAiApi buildOpenAiApi(AiParam aiParam) {
- /**
- * 鏍规嵁琛ㄥ崟閲岀殑 Base URL銆丄PI Key 鍜岃秴鏃跺弬鏁版瀯閫� OpenAI 鍏煎瀹㈡埛绔��
- * 璇ユ柟娉曡鏄惧紡鎷嗗嚭鏉ワ紝鏄负浜嗚鈥滅綉缁滆繛鎺ュ弬鏁扳�濆拰鈥滄ā鍨嬮�夐」鈥濊亴璐e垎绂汇��
- */
- int timeoutMs = aiParam.getTimeoutMs() == null ? AiDefaults.DEFAULT_TIMEOUT_MS : aiParam.getTimeoutMs();
- SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
- requestFactory.setConnectTimeout(timeoutMs);
- requestFactory.setReadTimeout(timeoutMs);
- return OpenAiApi.builder()
- .baseUrl(aiParam.getBaseUrl())
- .apiKey(aiParam.getApiKey())
- .restClientBuilder(RestClient.builder().requestFactory(requestFactory))
- .webClientBuilder(WebClient.builder())
- .build();
+ /** 缁熶竴鍏煎鏍瑰湴鍧�銆�/v1 鍓嶇紑鍜屽畬鏁� completions endpoint 涓夌甯歌濉硶銆� */
+ return AiOpenAiApiSupport.buildOpenAiApi(aiParam);
}
private String formatDate(Date date) {
diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/ai/tool/RsfWmsTaskTools.java b/rsf-server/src/main/java/com/vincent/rsf/server/ai/tool/RsfWmsTaskTools.java
index 377a73b..249d4bd 100644
--- a/rsf-server/src/main/java/com/vincent/rsf/server/ai/tool/RsfWmsTaskTools.java
+++ b/rsf-server/src/main/java/com/vincent/rsf/server/ai/tool/RsfWmsTaskTools.java
@@ -2,7 +2,10 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.vincent.rsf.framework.exception.CoolException;
+import com.vincent.rsf.server.common.utils.FieldsUtils;
import com.vincent.rsf.server.manager.entity.Task;
+import com.vincent.rsf.server.manager.entity.TaskItem;
+import com.vincent.rsf.server.manager.service.TaskItemService;
import com.vincent.rsf.server.manager.service.TaskService;
import lombok.RequiredArgsConstructor;
import org.springframework.ai.tool.annotation.Tool;
@@ -14,12 +17,14 @@
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
@Component
@RequiredArgsConstructor
public class RsfWmsTaskTools {
private final TaskService taskService;
+ private final TaskItemService taskItemService;
/**
* 鏌ヨ浠诲姟鍒楄〃銆�
@@ -70,42 +75,21 @@
* 鏌ヨ鍗曚釜浠诲姟璇︽儏銆�
* 涓庡垪琛ㄦ煡璇笉鍚岋紝杩欓噷鍏佽杩斿洖鏇翠赴瀵岀殑瀛楁锛屼絾浠嶇劧瑕佹眰璋冪敤鏂归�氳繃浠诲姟 ID 鎴栦换鍔″彿鍋氱簿纭畾浣嶃��
*/
- @Tool(name = "rsf_query_task_detail", description = "鍙鏌ヨ宸ュ叿銆傛牴鎹换鍔� ID 鎴栦换鍔″彿鏌ヨ浠诲姟璇︽儏銆�")
+ @Tool(name = "rsf_query_task_detail", description = "鍙鏌ヨ宸ュ叿銆傛煡璇换鍔″垪琛ㄦ湁姝e父杩斿洖鍊煎彲浠ユ牴鎹换鍔D鏌ヨ浠诲姟璇︽儏銆�")
public Map<String, Object> queryTaskDetail(
- @ToolParam(description = "浠诲姟 ID") Long taskId,
- @ToolParam(description = "浠诲姟鍙�") String taskCode) {
- String normalizedTaskCode = BuiltinToolGovernanceSupport.sanitizeQueryText(taskCode, "浠诲姟鍙�", 64);
- if (taskId == null && !StringUtils.hasText(normalizedTaskCode)) {
- throw new CoolException("浠诲姟 ID 鍜屼换鍔″彿鑷冲皯闇�瑕佹彁渚涗竴涓�");
+ @ToolParam(description = "浠诲姟 ID") Long taskId
+ ) {
+
+ if (taskId == null) {
+ throw new CoolException("浠诲姟 ID 闇�瑕佹彁渚�");
}
- Task task;
- if (taskId != null) {
- task = taskService.getById(taskId);
- } else {
- task = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getTaskCode, normalizedTaskCode));
- }
- if (task == null) {
+ List<TaskItem> taskItems = new ArrayList<>();
+ taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, taskId));
+
+ if (taskItems.isEmpty()) {
throw new CoolException("鏈煡璇㈠埌浠诲姟");
}
- Map<String, Object> result = buildTaskSummary(task);
- result.put("resource", task.getResource());
- result.put("exceStatus", task.getExceStatus());
- result.put("orgLoc", task.getOrgLoc());
- result.put("targLoc", task.getTargLoc());
- result.put("orgSite", task.getOrgSite());
- result.put("orgSiteLabel", task.getOrgSite$());
- result.put("targSite", task.getTargSite());
- result.put("targSiteLabel", task.getTargSite$());
- result.put("barcode", task.getBarcode());
- result.put("robotCode", task.getRobotCode());
- result.put("memo", task.getMemo());
- result.put("expCode", task.getExpCode());
- result.put("expDesc", task.getExpDesc());
- result.put("startTime", task.getStartTime$());
- result.put("endTime", task.getEndTime$());
- result.put("createTime", task.getCreateTime$());
- result.put("updateTime", task.getUpdateTime$());
- return result;
+ return buildTaskItemDetail(taskItems);
}
private Map<String, Object> buildTaskSummary(Task task) {
@@ -128,4 +112,72 @@
return item;
}
+ private Map<String, Object> buildTaskItemDetail(List<TaskItem> taskItems) {
+ Map<String, Object> result = new LinkedHashMap<>();
+ result.put("taskId", taskItems.get(0).getTaskId());
+ result.put("itemCount", taskItems.size());
+
+ double totalAnfme = 0D;
+ double totalWorkQty = 0D;
+ double totalQty = 0D;
+ List<Map<String, Object>> items = new ArrayList<>();
+ for (TaskItem taskItem : taskItems) {
+ totalAnfme += taskItem.getAnfme() == null ? 0D : taskItem.getAnfme();
+ totalWorkQty += taskItem.getWorkQty() == null ? 0D : taskItem.getWorkQty();
+ totalQty += taskItem.getQty() == null ? 0D : taskItem.getQty();
+ items.add(buildTaskItemRow(taskItem));
+ }
+
+ result.put("totalAnfme", totalAnfme);
+ result.put("totalWorkQty", totalWorkQty);
+ result.put("totalQty", totalQty);
+ result.put("items", items);
+ return result;
+ }
+
+ private Map<String, Object> buildTaskItemRow(TaskItem taskItem) {
+ if (!Objects.isNull(taskItem.getFieldsIndex())) {
+ taskItem.setExtendFields(FieldsUtils.getFields(taskItem.getFieldsIndex()));
+ }
+ Map<String, Object> item = new LinkedHashMap<>();
+ item.put("id", taskItem.getId());
+ item.put("taskId", taskItem.getTaskId());
+ item.put("matnrId", taskItem.getMatnrId());
+ item.put("matnrCode", taskItem.getMatnrCode());
+ item.put("maktx", taskItem.getMaktx());
+ item.put("trackCode", taskItem.getTrackCode());
+ item.put("splrBatch", taskItem.getSplrBatch());
+ item.put("batch", taskItem.getBatch());
+ item.put("spec", taskItem.getSpec());
+ item.put("model", taskItem.getModel());
+ item.put("unit", taskItem.getUnit());
+ item.put("anfme", taskItem.getAnfme());
+ item.put("workQty", taskItem.getWorkQty());
+ item.put("qty", taskItem.getQty());
+ item.put("ableQty", taskItem.getAbleQty());
+ item.put("source", taskItem.getSource());
+ item.put("sourceId", taskItem.getSourceId());
+ item.put("sourceCode", taskItem.getSourceCode());
+ item.put("orderId", taskItem.getOrderId());
+ item.put("orderItemId", taskItem.getOrderItemId());
+ item.put("platItemId", taskItem.getPlatItemId());
+ item.put("platOrderCode", taskItem.getPlatOrderCode());
+ item.put("platWorkCode", taskItem.getPlatWorkCode());
+ item.put("projectCode", taskItem.getProjectCode());
+ item.put("orderType", taskItem.getOrderType());
+ item.put("orderTypeLabel", taskItem.getOrderType$());
+ item.put("wkType", taskItem.getWkType());
+ item.put("wkTypeLabel", taskItem.getWkType$());
+ item.put("isptResult", taskItem.getIsptResult());
+ item.put("isptResultLabel", taskItem.getIsptResult$());
+ item.put("fieldsIndex", taskItem.getFieldsIndex());
+ item.put("extendFields", taskItem.getExtendFields());
+ item.put("status", taskItem.getStatus());
+ item.put("statusLabel", taskItem.getStatus$());
+ item.put("memo", taskItem.getMemo());
+ item.put("createTime", taskItem.getCreateTime$());
+ item.put("updateTime", taskItem.getUpdateTime$());
+ return item;
+ }
+
}
--
Gitblit v1.9.1