Commit 8c249ba5 authored by zhouwei's avatar zhouwei

新增翻译和打标签接口

parent 213a7ab7
package com.nanyan.securitylink.common;
public enum MsgCode {
SUCCESS(200, "success"),
FAILED(1001, "access failed"),
NOT_LOGIN(401, "not login"),
LOGIN_FAILED(402, "login failed"),
LOGIN_EXPIRE(403, "token expire")
//翻译异常
,
TRANSLATE_ERROR(500, "translate error"),
//JSON字符串异常
JSON_ERROR(501, "json error")
;
int code;
String msg;
MsgCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}
package com.nanyan.securitylink.dto;
import lombok.Data;
@Data
public class TranslateDTO {
TranslateInputDTO inputs;
String response_mode;
String user;
}
package com.nanyan.securitylink.dto;
import lombok.Data;
@Data
public class TranslateInputDTO {
String record_json;
String language;
}
package com.nanyan.securitylink.entity;
import lombok.Data;
import java.util.List;
@Data
public class ChatCompletionResponse {
private String id;
private String object;
private long created;
private String model;
private List<Choice> choices;
private Usage usage;
private String systemFingerprint;
}
package com.nanyan.securitylink.entity;
import lombok.Data;
import java.util.List;
@Data
public class ChatInputData {
private String model;
private Boolean stream = false;
private List<Message> messages;
}
package com.nanyan.securitylink.entity;
import lombok.Data;
@Data
public class Choice {
private int index;
private Message message;
private Object logprobs; // logprobs is null in the JSON
private String finishReason;
}
package com.nanyan.securitylink.entity;
import lombok.Data;
@Data
public class Message {
private String role;
private String content;
}
package com.nanyan.securitylink.entity;
import lombok.Data;
@Data
public class PromptTokensDetails {
private int cachedTokens;
}
package com.nanyan.securitylink.entity;
import lombok.Data;
@Data
public class Usage {
private int promptTokens;
private int completionTokens;
private int totalTokens;
private PromptTokensDetails promptTokensDetails;
private int promptCacheHitTokens;
private int promptCacheMissTokens;
}
package com.nanyan.securitylink.entity;
public class UserHeader {
String userId;
String accountName;
String role;
String token;
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
}
package com.nanyan.securitylink.entity;
public class UserThreadLocal {
private static final ThreadLocal<UserHeader> userHeaderThreadLocal = new ThreadLocal<>();
public static void set(UserHeader userHeader){
userHeaderThreadLocal.set(userHeader);
}
public static UserHeader get(){
return userHeaderThreadLocal.get();
}
public static void remove(){
userHeaderThreadLocal.remove();
}
}
package com.nanyan.securitylink.service;
import com.nanyan.securitylink.dto.TranslateDTO;
import com.nanyan.securitylink.vo.AIResponse;
public interface AIService {
AIResponse translate(TranslateDTO translateDTO);
AIResponse newsTags(TranslateDTO translateDTO);
}
package com.nanyan.securitylink.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nanyan.securitylink.common.MsgCode;
import com.nanyan.securitylink.config.AppConfig;
import com.nanyan.securitylink.dto.TranslateDTO;
import com.nanyan.securitylink.entity.ChatCompletionResponse;
import com.nanyan.securitylink.entity.ChatInputData;
import com.nanyan.securitylink.entity.Message;
import com.nanyan.securitylink.execption.BaseException;
import com.nanyan.securitylink.service.AIService;
import com.nanyan.securitylink.vo.AIResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.ArrayList;
import java.util.List;
@Slf4j
@Service
public class DeepSeekAIServiceImpl implements AIService {
@Autowired
AppConfig appConfig;
@Autowired
RestTemplate restTemplate;
private final static ObjectMapper objectMapper = new ObjectMapper();
// private final static String DEEP_SEEK_URL = "https://api.deepseek.com/chat/completions";
private final static String DEEP_SEEK_URL = "https://ark.cn-beijing.volces.com/api/v3/chat/completions";
@Override
public AIResponse translate(TranslateDTO translateDTO) {
ChatInputData chatInputData = new ChatInputData();
buildTranslate(chatInputData,translateDTO);
ChatCompletionResponse chatCompletionResponse = aiRequest(chatInputData, appConfig.getApiTranslateKey());
if(CollectionUtils.isNotEmpty(chatCompletionResponse.getChoices())){
AIResponse aiResponse = new AIResponse();
aiResponse.setAnswer(chatCompletionResponse.getChoices().get(0).getMessage().getContent());
return aiResponse;
}
return null;
}
public AIResponse newsTags(TranslateDTO translateDTO) {
ChatInputData chatInputData = new ChatInputData();
buildNewsTag(chatInputData,translateDTO);
ChatCompletionResponse chatCompletionResponse = aiRequest(chatInputData, appConfig.getApiTranslateKey());
if(CollectionUtils.isNotEmpty(chatCompletionResponse.getChoices())){
AIResponse aiResponse = new AIResponse();
aiResponse.setAnswer(chatCompletionResponse.getChoices().get(0).getMessage().getContent());
return aiResponse;
}
return null;
}
private void buildNewsTag(ChatInputData chatInputData, TranslateDTO translateDTO) {
chatInputData.setModel("deepseek-v3-250324");
chatInputData.setStream(false);
List<Message> messages = new ArrayList<>();
chatInputData.setMessages(messages);
Message systemRole = getSystemTagDeepSeekMessage();
messages.add(systemRole);
Message userRole = getUserTagDeepSeekMessage(translateDTO);
messages.add(userRole);
}
@NotNull
private ChatCompletionResponse aiRequest(ChatInputData chatInputData , String apiKey) {
String writeValueAsString = null;
try {
writeValueAsString = objectMapper.writeValueAsString(chatInputData);
} catch (JsonProcessingException e) {
throw new BaseException(MsgCode.JSON_ERROR);
}
log.info("translate json:{}", writeValueAsString);
HttpEntity header = getHeader(apiKey);
HttpEntity<String> entity = new HttpEntity<>(writeValueAsString,header.getHeaders());
ResponseEntity<ChatCompletionResponse> response = restTemplate.postForEntity(DEEP_SEEK_URL, entity, ChatCompletionResponse.class);
if(response.getStatusCode().is2xxSuccessful()){
log.info("translate response:{}", JSONObject.toJSONString(response.getBody()));
return response.getBody();
}
throw new BaseException(MsgCode.TRANSLATE_ERROR);
}
private void buildTranslate(ChatInputData chatInputData, TranslateDTO translateDTO) {
chatInputData.setModel("deepseek-v3-250324");
chatInputData.setStream(false);
List<Message> messages = new ArrayList<>();
chatInputData.setMessages(messages);
Message systemRole = getDeepSeekMessage(translateDTO);
messages.add(systemRole);
}
@NotNull
private static Message getDeepSeekMessage(TranslateDTO translateDTO) {
Message systemRole = new Message();
systemRole.setRole("user");
systemRole.setContent("需要翻译的JSON:"+ translateDTO.getInputs().getRecord_json() + "\n" +
"\n" +
"你是一个 JSON 翻译员,能够将给定的 JSON 中的 value 值部分翻译成 `"+ translateDTO.getInputs().getLanguage() +"`。\n" +
"\n" +
"## 限制\n" +
"- 严格按照要求进行翻译,不改变 JSON 的结构和无意义的 key 的 value。\n" +
"- 仅翻译有意义的 value 部分,确保翻译准确、通顺。"+
"- 无需任何其他说明。"+
"- 数字、特殊符号(@#%&等)连接的单词无需翻译,其他还需翻译。"
);
return systemRole;
}
private static Message getUserTagDeepSeekMessage(TranslateDTO translateDTO) {
Message userRole = new Message();
userRole.setRole("user");
userRole.setContent(translateDTO.getInputs().getRecord_json());
return userRole;
}
@NotNull
private static Message getSystemTagDeepSeekMessage() {
Message systemRole = new Message();
systemRole.setRole("system");
systemRole.setContent("```xml\n" +
"<instruction>\n" +
"对多条新闻内容进行打标签,标签分别为枪击、抢劫、爆炸、恐怖袭击、纵火、大规模伤亡事件、人质事件、毒气泄漏、自然灾害、生物危害、交通意外、建筑物倒塌、食品安全、社会冲突、群体性事件等。请按照以下步骤完成任务:\n" +
"\n" +
"1. 仔细阅读每条新闻内容,理解其核心事件。\n" +
"2. 根据新闻描述的事件类型,从给定的标签列表中选择最匹配的一个或多个标签。\n" +
"3. 确保标签与新闻内容高度相关,避免主观臆断。\n" +
"4. 如果新闻内容涉及多个事件类型,可以分配多个标签,但需确保每个标签都准确反映新闻内容。\n" +
"5. 输出结果时,仅列出标签名称,不要包含任何XML标签或其他无关内容。\n" +
"\n" +
"<examples>\n" +
"<example>\n" +
"<输入>\n" +
"\"昨日凌晨,某市一家银行发生持枪抢劫案,歹徒与警方交火后逃离现场,造成两名保安受伤。\"\n" +
"<输出>\n" +
"枪击, 抢劫\n" +
"</example>\n" +
"\n" +
"<example>\n" +
"<输入>\n" +
"\"今日上午,某化工厂发生毒气泄漏事故,附近居民已被紧急疏散,暂无人员伤亡报告。\"\n" +
"<输出>\n" +
"毒气泄漏\n" +
"</example>\n" +
"\n" +
"<example>\n" +
"<输入>\n" +
"\"近日,某地因征地问题引发大规模抗议活动,数百名民众与警方发生冲突,导致多人受伤。\"\n" +
"<输出>\n" +
"社会冲突, 群体性事件\n" +
"</example>\n" +
"</examples>\n" +
"\n" +
"注意事项:\n" +
"- 标签必须严格从给定的列表中选择,不得自行添加或修改标签名称。\n" +
"- 如果新闻内容与任何标签都不匹配,则输出\"\"。\n" +
"- 输出时标签之间用逗号分隔,不要使用编号或项目符号。\n" +
"- 确保标签的准确性和一致性,避免歧义或模糊分类。\n" +
"\n" +
"请严格按照上述要求完成任务,确保输出结果简洁、准确且符合规范。\n" +
"</instruction>\n" +
"```"
);
return systemRole;
}
private HttpEntity getHeader(String token){
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.set("Content-Type","application/json");
httpHeaders.set("Authorization",String.format("Bearer %s",token));
return new HttpEntity<>(httpHeaders);
}
}
package com.nanyan.securitylink.vo;
import lombok.Data;
@Data
public class AIResponse {
private String event;
private String task_id;
private String id;
private String message_id;
private String mode;
private String answer;
private long created_at;
}
package com.nanyan.securitylink.vo;
import com.nanyan.securitylink.common.MsgCode;
public class Response<T> {
String msg;
int code;
T data;
public static Response getResponse(MsgCode msgCode){
Response response = new Response();
response.setCode(msgCode.getCode());
response.setMsg(msgCode.getMsg());
return response;
}
public static Response getResponse(int code, String msg){
Response response = new Response();
response.setCode(code);
response.setMsg(msg);
return response;
}
public static<T> Response<T> SUCCESS(T data){
Response response = new Response<T>();
response.setCode(MsgCode.SUCCESS.getCode());
response.setMsg(MsgCode.SUCCESS.getMsg());
response.setData(data);
return response;
}
public static<T> Response<T> FAILED(T data){
Response response = new Response();
response.setCode(MsgCode.FAILED.getCode());
response.setMsg(MsgCode.FAILED.getMsg());
response.setData(data);
return response;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment