舆情监控系统的智能化:从关键词匹配到 LLM 情感分析与摘要生成

舆情监控系统的智能化:从关键词匹配到 LLM 情感分析与摘要生成
舆情监控系统的智能化从关键词匹配到 LLM 情感分析与摘要生成一、传统舆情监控的局限性企业舆情监控是一个典型的数据量大、噪声多、时效性强的场景。我们团队此前维护的舆情系统基于传统的正则表达式和关键词匹配方案维护了约 5000 条关键词和 200 多个正则规则。这套方案运行了两年后暴露出三个致命缺陷。第一是召回率与精确率的矛盾。为了不漏掉负面舆情关键词规则覆盖很宽导致大量误报。例如股价下跌这条规则会将行业股价普遍下跌但本公司基本面稳健这样的正面报道也标记为负面运营同事每天需要花费 2 小时人工过滤误报。第二是情感理解浅层。关键词匹配只能判断提到了什么无法理解在什么语境下以什么态度提到的。讽刺、反语、隐喻等高级表达完全失效。第三是缺乏摘要能力。当某个事件爆发时运营需要在 200 多篇相关文章中快速了解全貌而传统系统只能按时间列出所有文章标题。二、LLM 情感分析的工程化范式引入 LLM 做情感分析技术原理并不复杂难点在于工程化。裸调 LLM 的单次分析延迟在 2~5 秒对于每天数百万条信息的舆情系统来说是不可接受的。我们的做法是分层流水线设计第一层是关键词粗筛保留原有的关键词匹配作为快速通道过滤掉 90% 以上的无关信息。只有命中关键词的内容才进入第二层 LLM 分析。这一层的设计思想是宁可错杀一百也不放过一个关键词规则设置得比较宽松。第二层是LLM 精细分析针对粗筛后的内容进行情感分类。我们的 Prompt 设计要求非常具体输出 JSON 格式包含sentiment正面/中性/负面、confidence0~1 浮点数、aspects涉及的企业及对应情感、is_rumor是否涉谣。结构化输出使得下游的统计分析、趋势预警都可以自动化处理。第三层是事件聚类将多条相似内容聚合为事件。我们采用两阶段策略先用文本向量做语义相似度计算引入 BGE-M3 模型相似度超过 0.85 的归为同一候选簇再用 LLM 做簇内验证确认是否属于同一事件并命名。/** * LLM舆情情感分析服务 */ Service public class SentimentAnalysisService { private static final double CONFIDENCE_THRESHOLD 0.7; private static final int MAX_RETRY_COUNT 3; Resource private LLMClient llmClient; Resource private TextDeduplicator deduplicator; Resource private EventClusterService clusterService; /** * 分析单条舆情的情感倾向 */ public SentimentResult analyzeSentiment(String text, String source) { // 文本去重相同内容不重复分析 String fingerprint deduplicator.fingerprint(text); SentimentResult cached queryCache(fingerprint); if (cached ! null) { return cached; } String prompt buildSentimentPrompt(text); SentimentResult result null; for (int i 0; i MAX_RETRY_COUNT; i) { try { String response llmClient.chat(prompt); result parseResponse(response, text); break; } catch (JsonParseException e) { log.warn(舆情分析结果JSON解析失败第{}次重试: {}, i 1, e.getMessage()); } catch (LLMException e) { log.error(LLM调用异常第{}次重试, i 1, e); if (i MAX_RETRY_COUNT - 1) { throw new SentimentAnalysisException(情感分析失败, e); } } } if (result ! null result.getConfidence() CONFIDENCE_THRESHOLD) { // 低置信度结果标记为需人工复核 result.setNeedManualReview(true); log.info(低置信度分析结果需人工复核: confidence{}, text{}, result.getConfidence(), text.substring(0, Math.min(50, text.length()))); } // 缓存分析结果 cacheResult(fingerprint, result); return result; } private String buildSentimentPrompt(String text) { return 你是一个专业的舆情分析师。请对以下文本进行情感分析以JSON格式返回 { sentiment: positive/neutral/negative, confidence: 0.0~1.0, aspects: [{entity: 实体名, sentiment: positive/neutral/negative}], is_rumor: true/false, summary: 一句话总结 } 要求sentiment必须严格是positive/neutral/negative之一 confidence基于你的确定程度打分 如果明显是谣言或未证实信息is_rumor为true。 文本内容 text; } private SentimentResult parseResponse(String response, String originalText) throws JsonParseException { try { return JSON.parseObject(response, SentimentResult.class); } catch (Exception e) { throw new JsonParseException(JSON解析失败, e); } } }三、事件摘要生成的算法设计当十条、百条相关文章涌入时运营者需要的不是列表而是一小段清晰的事件概述。我们设计的摘要生成策略分为短摘要和长摘要两个层次。短摘要≤100 字用于告警推送微信、钉钉、邮件标题要求一句话讲清楚谁发生了什么。Prompt 模板强制输出【时间】【主体】【事件】三段式结构例如今日14时某竞品发布新品评测文章其中对该公司产品存在不实对比描述目前已有37篇转载。长摘要500~800 字用于舆情日报和内部分析报告结构更完整事件概述 → 传播路径首发平台与传播时间线→ 舆论观点正面/负面观点占比及代表性评论→ 风险评估当前影响面和建议响应策略。技术上长摘要采用MapReduce 式分步摘要策略先将全部文章按来源类型分成 3~5 组每组独立生成分组摘要Map 阶段然后将所有分组摘要合并生成最终的事件报告Reduce 阶段。这个策略既能控制单次 LLM 调用的 Token 上限又能保证摘要的全面性。/** * 事件摘要生成——MapReduce策略 */ Component public class EventSummarizer { private static final int GROUP_SIZE 20; // 每组分20篇文章 Resource private LLMClient llmClient; /** * 生成事件摘要先分组摘要再合并 */ public String generateSummary(ListArticle articles) { if (articles.isEmpty()) { return 无相关文章; } // Map阶段分组摘要 ListString groupSummaries new ArrayList(); for (int i 0; i articles.size(); i GROUP_SIZE) { int end Math.min(i GROUP_SIZE, articles.size()); ListArticle group articles.subList(i, end); String groupSummary summarizeGroup(group); groupSummaries.add(groupSummary); } // Reduce阶段合并分组摘要 return mergeSummaries(groupSummaries, articles.size()); } private String summarizeGroup(ListArticle group) { ListString texts group.stream() .map(a - a.getPlatform() : a.getTitle() | a.getSummary()) .collect(Collectors.toList()); String prompt 请阅读以下关于同一事件的文章用200字以内总结核心事实和观点分布。\n\n String.join(\n---\n, texts); try { return llmClient.chat(prompt); } catch (LLMException e) { log.error(分组摘要失败, e); return 摘要生成失败: group.size() 篇文章; } } private String mergeSummaries(ListString groupSummaries, int totalCount) { String prompt 请基于以下分组摘要生成一份完整的事件舆情报告500字以内\n 文章总数 totalCount \n\n String.join(\n\n, groupSummaries); try { return llmClient.chat(prompt); } catch (LLMException e) { log.error(合并摘要失败, e); return 摘要合并失败; } } }四、准确率验证与业务效果系统上线前我们构造了一个包含 5000 条人工标注的测试集进行准确率评估。测试集中包含 1200 条普通负面新闻、800 条讽刺/反语表达、500 条谣言、200 条隐晦攻击以及 2300 条正面/中性内容。评估结果显示整体情感分类准确率从规则系统的 74.2% 提升至 91.6%讽刺/反语检测准确率从 11.3% 提升至 76.8%谣言识别准确率达到 83.1%摘要的可用性评分人工 1~5 分均值为 4.1 分。业务侧反馈也超出预期运营团队的人工过滤工作量从每天 2 小时降至 15 分钟舆情响应时效从小时级提升至分钟级多次在负面舆情发酵前 15 分钟内触发预警。/** * 舆情告警决策服务 */ Service public class AlertDecisionService { Resource private SentimentAnalysisService sentimentService; Resource private EventClusterService clusterService; Resource private NotificationService notificationService; public void processBatch(ListArticle articles) { int negativeCount 0; int rumorCount 0; ListSentimentResult negativeResults new ArrayList(); for (Article article : articles) { SentimentResult result sentimentService.analyzeSentiment( article.getContent(), article.getPlatform()); if (negative.equals(result.getSentiment()) result.getConfidence() 0.8) { negativeCount; negativeResults.add(result); } if (result.isRumor()) { rumorCount; } } // 告警规则负面文章超过阈值或涉及谣言 if (negativeCount 5 || rumorCount 1) { ListEventCluster clusters clusterService.clusterAndName(negativeResults); String summary EventSummarizer.generateShortSummary(clusters); Alert alert Alert.builder() .level(rumorCount 0 ? AlertLevel.URGENT : AlertLevel.WARNING) .negativeCount(negativeCount) .rumorCount(rumorCount) .summary(summary) .timestamp(LocalDateTime.now()) .build(); notificationService.send(alert); } } }五、反思与未来方向舆情系统的智能化改造最大的启示是AI 不是替代规则系统而是与规则系统形成互补。关键词粗筛承担了流量过滤的角色LLM 负责精细理解两者结合才能在实际生产中落地。当前方案仍有几个待解决的痛点一是多模态舆情图片中的文字、视频语音尚未覆盖二是跨语言舆情外媒报道的翻译质量影响分析准确率三是静默传播期的检测——在舆情爆发前 12~24 小时的异常信号捕捉。这些问题将在下一阶段的迭代中逐步解决。作者李然程序员鸭梨Java 架构师专注 AI 应用架构与企业级系统设计。