|
@@ -2,6 +2,7 @@ package com.tzld.piaoquan.api.component;
|
|
|
|
|
|
|
|
import com.alibaba.fastjson.JSONArray;
|
|
import com.alibaba.fastjson.JSONArray;
|
|
|
import com.alibaba.fastjson.JSONObject;
|
|
import com.alibaba.fastjson.JSONObject;
|
|
|
|
|
+import com.tzld.piaoquan.api.common.enums.ApiChannelEnum;
|
|
|
import com.tzld.piaoquan.api.model.dto.AIOfficialApiResponse;
|
|
import com.tzld.piaoquan.api.model.dto.AIOfficialApiResponse;
|
|
|
import com.tzld.piaoquan.api.model.dto.AIResult;
|
|
import com.tzld.piaoquan.api.model.dto.AIResult;
|
|
|
import com.tzld.piaoquan.growth.common.utils.MapBuilder;
|
|
import com.tzld.piaoquan.growth.common.utils.MapBuilder;
|
|
@@ -26,6 +27,21 @@ public class DeepSeekApiService {
|
|
|
@Value("${deepseek.default.model:deepseek-v4-flash}")
|
|
@Value("${deepseek.default.model:deepseek-v4-flash}")
|
|
|
private String defaultModel;
|
|
private String defaultModel;
|
|
|
|
|
|
|
|
|
|
+ @Value("${deepseek.official.url:https://api.deepseek.com/chat/completions}")
|
|
|
|
|
+ private String officialUrl;
|
|
|
|
|
+
|
|
|
|
|
+ @Value("${deepseek.official.apiKey:sk-62d7b2c37f824735aa4985852c919c1f}")
|
|
|
|
|
+ private String officialApiKey;
|
|
|
|
|
+
|
|
|
|
|
+ @Value("${deepseek.volcengine.url:https://ark.cn-beijing.volces.com/api/v3/chat/completions}")
|
|
|
|
|
+ private String volcengineUrl;
|
|
|
|
|
+
|
|
|
|
|
+ @Value("${deepseek.volcengine.apiKey:ark-b5d6fcbb-14f9-4f70-a92d-605ec6a72c8d-40883}")
|
|
|
|
|
+ private String volcengineApiKey;
|
|
|
|
|
+
|
|
|
|
|
+ @Value("${deepseek.volcengine.model:ep-20250717193758-8gvmz}")
|
|
|
|
|
+ private String volcengineModel;
|
|
|
|
|
+
|
|
|
@PostConstruct
|
|
@PostConstruct
|
|
|
public void init() {
|
|
public void init() {
|
|
|
client = new OkHttpClient().newBuilder()
|
|
client = new OkHttpClient().newBuilder()
|
|
@@ -35,7 +51,17 @@ public class DeepSeekApiService {
|
|
|
.build();
|
|
.build();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public AIResult requestOfficialApi(String prompt, String model, Double temperature, Boolean isJSON) {
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 默认调用火山引擎 API
|
|
|
|
|
+ */
|
|
|
|
|
+ public AIResult request(String prompt, String model, Double temperature, Boolean isJSON) {
|
|
|
|
|
+ return request(prompt, model, temperature, isJSON, ApiChannelEnum.VOLCENGINE);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 支持指定渠道的 API 调用
|
|
|
|
|
+ */
|
|
|
|
|
+ public AIResult request(String prompt, String model, Double temperature, Boolean isJSON, ApiChannelEnum channel) {
|
|
|
AIResult result = new AIResult();
|
|
AIResult result = new AIResult();
|
|
|
result.setSuccess(false);
|
|
result.setSuccess(false);
|
|
|
if (TextUtils.isBlank(prompt) || TextUtils.isBlank(prompt.trim())) {
|
|
if (TextUtils.isBlank(prompt) || TextUtils.isBlank(prompt.trim())) {
|
|
@@ -43,6 +69,28 @@ public class DeepSeekApiService {
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ String url;
|
|
|
|
|
+ String apiKey;
|
|
|
|
|
+ String defaultChannelModel;
|
|
|
|
|
+ String channelName;
|
|
|
|
|
+
|
|
|
|
|
+ if (channel == ApiChannelEnum.OFFICIAL) {
|
|
|
|
|
+ url = officialUrl;
|
|
|
|
|
+ apiKey = officialApiKey;
|
|
|
|
|
+ defaultChannelModel = defaultModel;
|
|
|
|
|
+ channelName = "official";
|
|
|
|
|
+ } else {
|
|
|
|
|
+ url = volcengineUrl;
|
|
|
|
|
+ apiKey = volcengineApiKey;
|
|
|
|
|
+ defaultChannelModel = volcengineModel;
|
|
|
|
|
+ channelName = "volcengine";
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (TextUtils.isBlank(apiKey)) {
|
|
|
|
|
+ result.setFailReason(channelName + " apiKey is not configured");
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
try {
|
|
try {
|
|
|
JSONArray jsonArray = new JSONArray();
|
|
JSONArray jsonArray = new JSONArray();
|
|
|
JSONObject message = new JSONObject();
|
|
JSONObject message = new JSONObject();
|
|
@@ -50,9 +98,15 @@ public class DeepSeekApiService {
|
|
|
message.put("content", prompt);
|
|
message.put("content", prompt);
|
|
|
jsonArray.add(message);
|
|
jsonArray.add(message);
|
|
|
|
|
|
|
|
|
|
+ String useModel = Optional.ofNullable(model).orElse(defaultChannelModel);
|
|
|
|
|
+ if (TextUtils.isBlank(useModel)) {
|
|
|
|
|
+ result.setFailReason("model is empty");
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
Map<Object, Object> bodyParam = MapBuilder
|
|
Map<Object, Object> bodyParam = MapBuilder
|
|
|
.builder()
|
|
.builder()
|
|
|
- .put("model", Optional.ofNullable(model).orElse(defaultModel))
|
|
|
|
|
|
|
+ .put("model", useModel)
|
|
|
.put("temperature", Optional.ofNullable(temperature).orElse(0.3))
|
|
.put("temperature", Optional.ofNullable(temperature).orElse(0.3))
|
|
|
.put("messages", jsonArray)
|
|
.put("messages", jsonArray)
|
|
|
.build();
|
|
.build();
|
|
@@ -65,17 +119,17 @@ public class DeepSeekApiService {
|
|
|
MediaType mediaType = MediaType.parse("application/json");
|
|
MediaType mediaType = MediaType.parse("application/json");
|
|
|
RequestBody body = RequestBody.create(mediaType, JSONObject.toJSONString(bodyParam));
|
|
RequestBody body = RequestBody.create(mediaType, JSONObject.toJSONString(bodyParam));
|
|
|
Request request = new Request.Builder()
|
|
Request request = new Request.Builder()
|
|
|
- .url("https://api.deepseek.com/chat/completions")
|
|
|
|
|
|
|
+ .url(url)
|
|
|
.method("POST", body)
|
|
.method("POST", body)
|
|
|
.addHeader("Content-Type", "application/json")
|
|
.addHeader("Content-Type", "application/json")
|
|
|
.addHeader("Accept", "application/json")
|
|
.addHeader("Accept", "application/json")
|
|
|
- .addHeader("Authorization", "Bearer sk-62d7b2c37f824735aa4985852c919c1f")
|
|
|
|
|
|
|
+ .addHeader("Authorization", "Bearer " + apiKey)
|
|
|
.build();
|
|
.build();
|
|
|
Response response = client.newCall(request).execute();
|
|
Response response = client.newCall(request).execute();
|
|
|
|
|
|
|
|
String responseContent = response.body().string();
|
|
String responseContent = response.body().string();
|
|
|
result.setResponseStr(responseContent);
|
|
result.setResponseStr(responseContent);
|
|
|
- log.info("deepseek api responseContent = {}", responseContent);
|
|
|
|
|
|
|
+ log.info("deepseek {} api responseContent = {}", channelName, responseContent);
|
|
|
if (response.isSuccessful()) {
|
|
if (response.isSuccessful()) {
|
|
|
AIOfficialApiResponse obj = JSONObject.parseObject(responseContent, AIOfficialApiResponse.class);
|
|
AIOfficialApiResponse obj = JSONObject.parseObject(responseContent, AIOfficialApiResponse.class);
|
|
|
if (CollectionUtils.isNotEmpty(obj.getChoices())) {
|
|
if (CollectionUtils.isNotEmpty(obj.getChoices())) {
|
|
@@ -89,9 +143,16 @@ public class DeepSeekApiService {
|
|
|
result.setFailReason("request error code:" + response.code() + " message:" + json.getString("error"));
|
|
result.setFailReason("request error code:" + response.code() + " message:" + json.getString("error"));
|
|
|
}
|
|
}
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
- log.error("deepseek official api fail: " + e.getMessage());
|
|
|
|
|
|
|
+ log.error("deepseek {} api fail: {}", channelName, e.getMessage());
|
|
|
result.setFailReason(e.getMessage());
|
|
result.setFailReason(e.getMessage());
|
|
|
}
|
|
}
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 调用 DeepSeek 官方 API(向后兼容)
|
|
|
|
|
+ */
|
|
|
|
|
+ public AIResult requestOfficialApi(String prompt, String model, Double temperature, Boolean isJSON) {
|
|
|
|
|
+ return request(prompt, model, temperature, isJSON, ApiChannelEnum.OFFICIAL);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|