package com.nanyan.securitylink.service.impl; import com.alibaba.fastjson.JSONArray; 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.AIRequestDTO; import com.nanyan.securitylink.entity.*; import com.nanyan.securitylink.execption.BaseException; import com.nanyan.securitylink.service.AIService; import com.nanyan.securitylink.vo.AIResponse; import com.nanyan.securitylink.vo.AnswerVO; import com.nanyan.securitylink.vo.CodeVO; import com.nanyan.securitylink.vo.ResultVO; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; 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.HashMap; import java.util.List; import java.util.Map; @Slf4j @Service public class AIServiceImpl implements AIService { @Autowired AppConfig appConfig; @Autowired RestTemplate restTemplate; private static final Map<String, String> NEWS_LABEL_MAP = new HashMap<>(); private static final Map<String, String> NATURAL_DISASTER_LABEL_MAP = new HashMap<>(); static { NEWS_LABEL_MAP.put("其他","TagOther"); NEWS_LABEL_MAP.put("枪击","TagShooting"); NEWS_LABEL_MAP.put("抢劫","TagRobbery"); NEWS_LABEL_MAP.put("事故爆炸","TagExplosion"); NEWS_LABEL_MAP.put("恐怖袭击","TagTerroristAttack"); NEWS_LABEL_MAP.put("纵火","TagArson"); NEWS_LABEL_MAP.put("大规模伤亡事件","TagMassCasualtyIncident"); NEWS_LABEL_MAP.put("人质事件","TagHostageSituation"); NEWS_LABEL_MAP.put("毒气泄漏","TagToxicGasLeak"); NEWS_LABEL_MAP.put("生物危害","TagBiologicalHazard"); NEWS_LABEL_MAP.put("交通事故","TagTrafficAccident"); NEWS_LABEL_MAP.put("建筑物倒塌","TagBuildingCollapse"); NEWS_LABEL_MAP.put("食品安全事件","TagFoodSafety"); NEWS_LABEL_MAP.put("社会冲突","TagSocialConflict"); NEWS_LABEL_MAP.put("群体性事件","TagMassGatheringIncident"); NEWS_LABEL_MAP.put("环境污染","TagEnvironmentalPollution"); NEWS_LABEL_MAP.put("抗议示威","TagProtestDemonstration"); NEWS_LABEL_MAP.put("集体维权","TagCollectiveAdvocacy"); NEWS_LABEL_MAP.put("活动失控骚乱","TagUncontrolledEventRiot"); NEWS_LABEL_MAP.put("地域冲突","TagTerritorialConflict"); NEWS_LABEL_MAP.put("性别冲突","TagGenderConflict"); NEWS_LABEL_MAP.put("宗教冲突","TagReligiousConflict"); NEWS_LABEL_MAP.put("民族冲突","TagEthnicConflict"); NEWS_LABEL_MAP.put("阶级冲突","TagClassConflict"); NEWS_LABEL_MAP.put("食物中毒","TagFoodPoisoning"); NEWS_LABEL_MAP.put("地震","TagEarthquake"); NEWS_LABEL_MAP.put("火山爆发","TagVolcanicEruption"); NEWS_LABEL_MAP.put("山体滑坡","TagLandslide"); NEWS_LABEL_MAP.put("泥石流","TagMudslide"); NEWS_LABEL_MAP.put("雪崩","TagAvalanche"); NEWS_LABEL_MAP.put("水坝决口","TagDamBreach"); NEWS_LABEL_MAP.put("水坝溃坝","TagDamBurst"); NEWS_LABEL_MAP.put("台风/飓风","TagTyphoonHurricane"); NEWS_LABEL_MAP.put("龙卷风","TagTornadoWarning"); NEWS_LABEL_MAP.put("暴雨","TagRainstorm"); NEWS_LABEL_MAP.put("洪水","TagFlood"); NEWS_LABEL_MAP.put("寒潮","TagColdWave"); NEWS_LABEL_MAP.put("高温热浪","TagHeatWave"); NEWS_LABEL_MAP.put("干旱","TagDrought"); NEWS_LABEL_MAP.put("沙尘暴","TagDustStorm"); NEWS_LABEL_MAP.put("冻雨","TagFreezingRain"); NEWS_LABEL_MAP.put("冰雹","TagHail"); NEWS_LABEL_MAP.put("雷暴","TagThunderstormWarning"); NEWS_LABEL_MAP.put("大风","TagHighWind"); NEWS_LABEL_MAP.put("山林火灾","TagForestFire"); NEWS_LABEL_MAP.put("冰川融化","TagGlacialMelting"); NEWS_LABEL_MAP.put("海啸","TagTsunami"); NEWS_LABEL_MAP.put("霾","TagHazeWarning"); NEWS_LABEL_MAP.put("化学品泄漏","TagChemicalSpill"); NEWS_LABEL_MAP.put("核事故","TagNuclearAccident"); NEWS_LABEL_MAP.put("矿难","TagMiningAccident"); NEWS_LABEL_MAP.put("油轮泄漏","TagOilSpill"); NEWS_LABEL_MAP.put("火灾","TagFire"); NEWS_LABEL_MAP.put("工业污染","TagIndustrialPollution"); NEWS_LABEL_MAP.put("工业事故","TagIndustriaAccident"); NEWS_LABEL_MAP.put("传染病爆发","TagDiseaseOutbreak"); NEWS_LABEL_MAP.put("公共卫生事件","TagPublicHealthEmergency"); NEWS_LABEL_MAP.put("持刀伤人","TagKnifeAttack"); NEWS_LABEL_MAP.put("恐怖爆炸","TerroristBombing"); NEWS_LABEL_MAP.put("暴力冲突","TagViolentClashes"); NEWS_LABEL_MAP.put("战争","TagWar"); NEWS_LABEL_MAP.put("游行抗议","TagProtest"); NATURAL_DISASTER_LABEL_MAP.put("地震","earthquake"); NATURAL_DISASTER_LABEL_MAP.put("火山爆发","volcanicEruption"); NATURAL_DISASTER_LABEL_MAP.put("海啸","tsunami"); NATURAL_DISASTER_LABEL_MAP.put("台风/飓风","typhoonHurricane"); NATURAL_DISASTER_LABEL_MAP.put("龙卷风","tornadowarning"); NATURAL_DISASTER_LABEL_MAP.put("洪水","flood"); NATURAL_DISASTER_LABEL_MAP.put("干旱","drought"); NATURAL_DISASTER_LABEL_MAP.put("山体滑坡","landslide"); NATURAL_DISASTER_LABEL_MAP.put("泥石流","mudslide"); NATURAL_DISASTER_LABEL_MAP.put("雪崩","avalanche"); NATURAL_DISASTER_LABEL_MAP.put("森林火灾","forestFire"); NATURAL_DISASTER_LABEL_MAP.put("冰川融化","glacialMelting"); NATURAL_DISASTER_LABEL_MAP.put("沙尘暴","dustStorm"); NATURAL_DISASTER_LABEL_MAP.put("高温热浪","heatWave"); NATURAL_DISASTER_LABEL_MAP.put("寒潮","coldWave"); NATURAL_DISASTER_LABEL_MAP.put("暴雨","rainstorm"); NATURAL_DISASTER_LABEL_MAP.put("工业事故","IndustriaAccident"); NATURAL_DISASTER_LABEL_MAP.put("交通事故","TrafficAccident"); NATURAL_DISASTER_LABEL_MAP.put("火灾","Fire"); NATURAL_DISASTER_LABEL_MAP.put("爆炸","Explosion"); NATURAL_DISASTER_LABEL_MAP.put("核事故","NuclearAccident"); NATURAL_DISASTER_LABEL_MAP.put("化学品泄漏","ChemicalSpill"); NATURAL_DISASTER_LABEL_MAP.put("油轮泄漏","OilSpill"); NATURAL_DISASTER_LABEL_MAP.put("矿难","MiningAccident"); NATURAL_DISASTER_LABEL_MAP.put("食物中毒","FoodPoisoning"); NATURAL_DISASTER_LABEL_MAP.put("公共卫生事件","PublicHealthEmergency"); NATURAL_DISASTER_LABEL_MAP.put("建筑物倒塌","BuildingCollapse"); NATURAL_DISASTER_LABEL_MAP.put("恐怖袭击","Terrorism"); NATURAL_DISASTER_LABEL_MAP.put("水坝溃坝","DamBurst"); NATURAL_DISASTER_LABEL_MAP.put("游行抗议","Protest"); NATURAL_DISASTER_LABEL_MAP.put("冰雹","hail"); NATURAL_DISASTER_LABEL_MAP.put("冻雨","freezingRain"); NATURAL_DISASTER_LABEL_MAP.put("霾","hazeWarning"); NATURAL_DISASTER_LABEL_MAP.put("雷暴","thunderstormWarning"); NATURAL_DISASTER_LABEL_MAP.put("大风","highWind"); } 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<String> translate(AIRequestDTO AIRequestDTO) { ChatInputData chatInputData = new ChatInputData(); buildTranslate(chatInputData, AIRequestDTO); String apiKey = getModelApiKey(); ChatCompletionResponse chatCompletionResponse = aiRequest(chatInputData, apiKey); if (CollectionUtils.isNotEmpty(chatCompletionResponse.getChoices())) { AIResponse<String> aiResponse = new AIResponse<>(); aiResponse.setFinish_reason(chatCompletionResponse.getChoices().get(0).getFinish_reason()); String content = chatCompletionResponse.getChoices().get(0).getMessage().getContent(); content = content.replaceAll("```json","").replaceAll("```", ""); aiResponse.setAnswer(content); return aiResponse; } return null; } public AIResponse<CodeVO> newsTags(AIRequestDTO aiRequestDTO) { ChatInputData chatInputData = new ChatInputData(); buildNewsTag(chatInputData, aiRequestDTO); String apiKey = getModelApiKey(); ChatCompletionResponse chatCompletionResponse = aiRequest(chatInputData, apiKey); if (CollectionUtils.isNotEmpty(chatCompletionResponse.getChoices())) { AIResponse<CodeVO> aiResponse = new AIResponse<>(); String content = chatCompletionResponse.getChoices().get(0).getMessage().getContent(); aiResponse.setFinish_reason(chatCompletionResponse.getChoices().get(0).getFinish_reason()); if(StringUtils.isNotEmpty(content)){ content = content.replaceAll("```json","").replaceAll("```", ""); String[] split = content.split(",", -1); List<CodeVO> result = new ArrayList<>(); ResultVO<CodeVO> outputs = new ResultVO<>(); outputs.setResult(result); aiResponse.setOutputs(outputs); for (String s : split) { if(NEWS_LABEL_MAP.containsKey(s)){ CodeVO codeVO = new CodeVO(); codeVO.setCode(NEWS_LABEL_MAP.get(s)); codeVO.setName(s); result.add(codeVO); } } } return aiResponse; } return null; } @Override public AIResponse<CodeVO> naturalDisasterTag(AIRequestDTO aiRequestDTO) { ChatInputData chatInputData = new ChatInputData(); buildNaturalDisasterTag(chatInputData, aiRequestDTO); String apiKey = getModelApiKey(); ChatCompletionResponse chatCompletionResponse = aiRequest(chatInputData, apiKey); if (CollectionUtils.isNotEmpty(chatCompletionResponse.getChoices())) { AIResponse<CodeVO> aiResponse = new AIResponse<>(); String content = chatCompletionResponse.getChoices().get(0).getMessage().getContent(); aiResponse.setFinish_reason(chatCompletionResponse.getChoices().get(0).getFinish_reason()); if(StringUtils.isNotEmpty(content)){ content = content.replaceAll("```json","").replaceAll("```", ""); String[] split = content.split(",", -1); List<CodeVO> result = new ArrayList<>(); ResultVO<CodeVO> outputs = new ResultVO<>(); outputs.setResult(result); aiResponse.setOutputs(outputs); for (String s : split) { if(NATURAL_DISASTER_LABEL_MAP.containsKey(s)){ CodeVO codeVO = new CodeVO(); codeVO.setCode(NATURAL_DISASTER_LABEL_MAP.get(s)); codeVO.setName(s); result.add(codeVO); } } } return aiResponse; } return null; } @Override public AIResponse<JSONObject> newsTagAndTranslate(AIRequestDTO aiRequestDTO) { ChatInputData chatInputData = new ChatInputData(); buildNewsTagAndTranslate(chatInputData, aiRequestDTO); String apiKey = getModelApiKey(); ChatCompletionResponse chatCompletionResponse = aiRequest(chatInputData, apiKey); if (CollectionUtils.isNotEmpty(chatCompletionResponse.getChoices())) { AIResponse<JSONObject> aiResponse = new AIResponse<>(); String content = chatCompletionResponse.getChoices().get(0).getMessage().getContent(); if(StringUtils.isNotEmpty(content)){ content = content.replaceAll("```json","").replaceAll("```", ""); JSONArray objects = JSONArray.parseArray(content); ArrayList<JSONObject> jsonObjects = new ArrayList<>(); for (int i = 0; i < objects.size(); i++) { JSONObject jsonObject = objects.getJSONObject(i); jsonObjects.add(jsonObject); if(jsonObject.containsKey("news_tag")){ List<CodeVO> codes = new ArrayList<>(); JSONArray newsTags = jsonObject.getJSONArray("news_tag"); for (int j = 0; j < newsTags.size(); j++) { String newsTag = newsTags.getString(j); if(NEWS_LABEL_MAP.containsKey(newsTag)){ String c = NEWS_LABEL_MAP.get(newsTag); CodeVO code = new CodeVO(); code.setCode(c); code.setName(newsTag); codes.add(code); } } jsonObject.put("news_tag", JSONObject.toJSON(codes)); } } ResultVO<JSONObject> outputs = new ResultVO<>(); AnswerVO<JSONObject> answer = new AnswerVO<>(); answer.setResult(jsonObjects); answer.setFinish_reason(chatCompletionResponse.getChoices().get(0).getFinish_reason()); outputs.setAnswer(answer); aiResponse.setOutputs(outputs); } return aiResponse; } return null; } private void buildNewsTagAndTranslate(ChatInputData chatInputData, AIRequestDTO aiRequestDTO) { setModel(chatInputData); chatInputData.setStream(false); List<Message> messages = new ArrayList<>(); chatInputData.setMessages(messages); Message systemRole = getSystemMessageForNewsTagAndTranslate(); messages.add(systemRole); Message userRole = getUserMessageForNewsTagAndTranslate(aiRequestDTO); messages.add(userRole); } private String getModelApiKey() { UserHeader userHeader = UserThreadLocal.get(); String apiKey = appConfig.getApiTranslateKey(); if(StringUtils.isNotEmpty(userHeader.getModelKey())){ apiKey = userHeader.getModelKey(); } return apiKey; } private void buildNaturalDisasterTag(ChatInputData chatInputData, AIRequestDTO aiRequestDTO) { setModel(chatInputData); chatInputData.setStream(false); List<Message> messages = new ArrayList<>(); chatInputData.setMessages(messages); Message systemRole = getSystemMessageForNatureDisaster(); messages.add(systemRole); Message userRole = getUserMessageForNaturalDisasterTag(aiRequestDTO); messages.add(userRole); } private static void setModel(ChatInputData chatInputData) { UserHeader userHeader = UserThreadLocal.get(); if(StringUtils.isNotEmpty(userHeader.getModel())){ chatInputData.setModel(userHeader.getModel()); }else { chatInputData.setModel("ep-20250407100626-cz4xb"); } } private void buildNewsTag(ChatInputData chatInputData, AIRequestDTO AIRequestDTO) { setModel(chatInputData); chatInputData.setStream(false); List<Message> messages = new ArrayList<>(); chatInputData.setMessages(messages); Message systemRole = getSystemMessageForNewsTag(); messages.add(systemRole); Message userRole = getUserMessageForNewsTag(AIRequestDTO); 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("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, AIRequestDTO AIRequestDTO) { setModel(chatInputData); chatInputData.setStream(false); List<Message> messages = new ArrayList<>(); chatInputData.setMessages(messages); Message systemRole = getDeepSeekMessage(AIRequestDTO); messages.add(systemRole); } @NotNull private static Message getDeepSeekMessage(AIRequestDTO AIRequestDTO) { Message systemRole = new Message(); systemRole.setRole("user"); systemRole.setContent("需要翻译的JSON:" + AIRequestDTO.getInputs().getRecord_json() + "\n" + "\n" + "你是一个 JSON 翻译员,能够将给定的 JSON 中的 value 值部分翻译成 `" + AIRequestDTO.getInputs().getLanguage() + "`。\n" + "\n" + "## 限制\n" + "- 严格按照要求进行翻译,不改变 JSON 的结构和无意义的 key 的 value。\n" + "- 仅翻译有意义的 value 部分,确保翻译准确、通顺。" + "- 无需任何其他说明。" + "- 数字、特殊符号(@#%&等)连接的单词无需翻译,其他还需翻译。" ); return systemRole; } private static Message getUserMessageForNewsTagAndTranslate(AIRequestDTO AIRequestDTO) { Message userRole = new Message(); userRole.setRole("user"); userRole.setContent(AIRequestDTO.getInputs().getMsg_info()); return userRole; } private static Message getUserMessageForNaturalDisasterTag(AIRequestDTO AIRequestDTO) { Message userRole = new Message(); userRole.setRole("user"); userRole.setContent(AIRequestDTO.getInputs().getWarn_info()); return userRole; } private static Message getUserMessageForNewsTag(AIRequestDTO AIRequestDTO) { Message userRole = new Message(); userRole.setRole("user"); userRole.setContent(AIRequestDTO.getInputs().getMsg_info()); return userRole; } @NotNull private static Message getSystemMessageForNewsTagAndTranslate() { Message systemRole = new Message(); systemRole.setRole("system"); systemRole.setContent("```xml\n" + "<instruction>\n" + "同时对多条新闻内容进行打上新闻标签分类和翻译成指定语言,仅当新闻标签评分达到或超过80分时才应用新闻标签,翻译必须进行,每条数据都唯一标识ID。输入为JSON数组,输出也为JSON数组。具体要求如下:\n" + "\n" + "1. **输入格式**: \n" + " - 输入是一个JSON数组,每个对象包含以下字段: \n" + " - `content`:新闻内容文本 \n" + " - `id`:唯一标识ID \n" + " - `language`:目标翻译语言 \n" + "\n" + "2. **输出格式**: \n" + " - 输出是一个JSON数组,每个对象包含以下字段:\n" + " - `content`:翻译后的新闻内容 \n" + " - `id`:与输入相同的唯一标识ID \n" + " - `language`:目标翻译语言 \n" + " - `news_tag`:新闻标签列表(仅当评分≥80分时应用) \n" + "\n" + "3. **标签分类规则**: \n" + " - 新闻标签的评分范围为0-100分,仅当评分≥80分时才将标签添加到输出中。 \n" + " - 翻译必须执行,无论标签评分如何。 \n" + "\n" + "4. **标签列表**: \n" + " - 人为灾害标签包括:枪击,抢劫,事故爆炸,恐怖袭击,纵火,大规模伤亡事件,人质事件,毒气泄漏,生物危害,交通事故,建筑物倒塌,食品安全事件,社会冲突,群体性事件,环境污染,抗议示威,集体维权,活动失控骚乱,地域冲突,性别冲突,宗教冲突,民族冲突,阶级冲突,食物中毒,地震,火山爆发,山体滑坡,泥石流,雪崩,水坝决口,水坝溃坝,台风/飓风,龙卷风,暴雨,洪水,寒潮,高温热浪,干旱,沙尘暴,冻雨,冰雹,雷暴,大风,山林火灾,冰川融化,海啸,霾,化学品泄漏,核事故,矿难,油轮泄漏,火灾,工业污染,工业事故,传染病爆发,公共卫生事件,持刀伤人,恐怖爆炸,暴力冲突,战争,游行抗议,其他。\n" + "\n" + "5. **注意事项**: \n" + " - 输出中不得包含任何XML标签。 \n" + " - 确保每条数据的唯一标识ID与输入一致。 \n" + " - 如果新闻内容无法分类或评分低于80分,则输出“其他”。\n" + "</instruction>\n" + "```" ); return systemRole; } @NotNull private static Message getSystemMessageForNatureDisaster() { Message systemRole = new Message(); systemRole.setRole("system"); systemRole.setContent("```xml\n" + "<instruction>\n" + "根据给定的天气预警信息,打上相应的标签。标签列表包括:大风,雷暴,霾,冻雨,地震,火山爆发,海啸,台风/飓风,龙卷风,洪水,干旱,山体滑坡,泥石流,雪崩,森林火灾,冰川融化,沙尘暴,高温热浪,寒潮,暴雨,工业事故,交通事故,火灾,爆炸,核事故,化学品泄漏,油轮泄漏,矿难,食物中毒,公共卫生事件,建筑物倒塌,恐怖袭击,水坝溃坝,游行抗议,冰雹。\n" + "\n" + "<instructions>\n" + "1. 仔细阅读输入的天气预警信息,理解其描述的具体事件或现象。\n" + "2. 根据预警信息的内容,从提供的标签列表中选择最匹配的一个或多个标签。\n" + "3. 确保所选标签与预警信息描述的事件或现象完全一致,避免无关标签。\n" + "4. 如果预警信息描述的事件或现象不在标签列表中,则忽略该信息或选择最接近的标签。\n" + "5. 输出时仅列出匹配的标签,不要包含任何额外的解释或XML标签。\n" + "6. 如果预警信息包含多个事件或现象,请为每个事件或现象分别打上对应的标签。\n" + "\n" + "<examples>\n" + "<example>\n" + "输入:今日预计有强风,风速可达10级以上,请市民注意防范。\n" + "输出:大风\n" + "</example>\n" + "\n" + "<example>\n" + "输入:受台风影响,沿海地区将出现暴雨和大风天气,局部地区可能有洪水。\n" + "输出:台风/飓风,暴雨,洪水\n" + "</example>\n" + "\n" + "<example>\n" + "输入:某化工厂发生泄漏事故,导致周边空气质量下降,建议居民关闭门窗。\n" + "输出:化学品泄漏,工业事故\n" + "</example>\n" + "\n" + "<notes>\n" + "1. 标签之间用逗号分隔,不要使用空格或其他符号。\n" + "2. 如果预警信息描述的事件或现象与多个标签相关,请列出所有相关标签。\n" + "3. 确保标签的准确性,避免主观判断或猜测。\n" + "4. 输出格式应简洁明了,仅包含标签名称。\n" + "</notes>\n" + "</instruction>\n" + "```" ); return systemRole; } @NotNull private static Message getSystemMessageForNewsTag() { Message systemRole = new Message(); systemRole.setRole("system"); systemRole.setContent("```xml\n" + "<instruction>\n" + "对新闻内容进行标签分类,仅当标签评分达到或超过80分时才应用该标签。可选的标签包括:枪击,抢劫,事故爆炸,恐怖袭击,纵火,大规模伤亡事件,人质事件,毒气泄漏,生物危害,交通事故,建筑物倒塌,食品安全事件,社会冲突,群体性事件,环境污染,抗议示威,集体维权,活动失控骚乱,地域冲突,性别冲突,宗教冲突,民族冲突,阶级冲突,食物中毒,地震,火山爆发,山体滑坡,泥石流,雪崩,水坝决口,水坝溃坝,台风/飓风,龙卷风,暴雨,洪水,寒潮,高温热浪,干旱,沙尘暴,冻雨,冰雹,雷暴,大风,山林火灾,冰川融化,海啸,霾,化学品泄漏,核事故,矿难,油轮泄漏,火灾,工业污染,工业事故,传染病爆发,公共卫生事件,持刀伤人,恐怖爆炸,暴力冲突,战争,游行抗议,其他。\n" + "\n" + "<instructions>\n" + "1. 仔细阅读新闻内容,理解其核心事件和背景。\n" + "2. 根据新闻内容,评估每个标签的适用性,并为每个标签打分(0-100分)。\n" + "3. 仅选择评分达到或超过80分的标签作为最终标签。\n" + "4. 如果新闻内容与任何标签的匹配度均低于80分,则输出“其他”。\n" + "5. 确保输出结果不包含任何XML标签,仅列出适用的标签名称,多个标签用逗号分隔。\n" + "6. 如果新闻内容涉及多个高评分标签,则按相关性从高到低排序。\n" + "\n" + "<examples>\n" + "<example>\n" + "输入:某市发生一起持枪抢劫银行事件,造成3人死亡,5人受伤。\n" + "输出:枪击, 抢劫, 大规模伤亡事件\n" + "</example>\n" + "\n" + "<example>\n" + "输入:某工厂发生化学气体泄漏,导致附近居民出现中毒症状。\n" + "输出:毒气泄漏\n" + "</example>\n" + "\n" + "<example>\n" + "输入:某地区因土地纠纷引发大规模抗议活动,警方与示威者发生冲突。\n" + "输出:社会冲突, 群体性事件\n" + "</example>\n" + "\n" + "<note>\n" + "1. 标签评分必须严格遵循80分的阈值,低于80分的标签不得使用。\n" + "2. 确保标签的准确性和相关性,避免过度标记或遗漏重要标签。\n" + "3. 对于模糊或不确定的内容,优先选择最相关的标签,避免猜测。\n" + "4. 输出结果必须简洁明了,仅包含适用的标签名称。\n" + "</note>\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); } }