金融情绪分析为何必须用指令微调(SFT)而非通用微调
1. 项目概述为什么金融情绪分析必须用指令微调而不是随便喂点数据就完事“Instruction Fine-Tuning LLM using SFT for Financial Sentiment: A Step-by-Step Guide”——这个标题里藏着三个关键信号指令微调Instruction Tuning、监督微调SFT、金融情绪Financial Sentiment。它不是教你怎么用ChatGPT写周报也不是让你拿通用语料库跑个LSTM分类器就交差。它是面向真实金融场景的、有明确任务边界、强领域约束、高容错门槛的一次模型能力重塑。我做过6家券商、3家基金公司的NLP落地项目最常被问的问题是“你们那个情绪分值到底是算出来的还是猜出来的”——这句话背后是监管报送对可解释性的硬性要求是交易员对“利好/利空”判断延迟不能超过15秒的实操压力更是舆情系统在财报季每分钟处理2000研报摘要时对细粒度情感极性如“维持增持但下调目标价”表面中性隐含利空的精准捕捉需求。通用大模型在财经新闻上直接zero-shot推理F1能掉到0.47而一个没经过金融语义对齐的LoRA微调模型哪怕在万条新闻上训过遇到“公司拟终止重大资产重组”这种标准负面表述仍可能因训练数据中“终止”常与“终止合作”“终止谈判”等中性上下文共现给出0.32的正面分值——这在风控系统里就是误报漏报是真金白银的代价。所以这个项目的核心价值不在于“又一个微调教程”而在于把LLM从通用语言理解机器拧成一把专为金融文本打磨的手术刀它要能区分“净利润同比增长12%”和“净利润同比下滑12%”之间那1个符号的语义鸿沟要能识别“董事会审议通过”背后的程序性中性与“董事会全票通过”所隐含的治理确定性增强更要能在“受宏观经济影响公司短期承压”这种典型模糊表达中锚定“承压”为主干情绪剥离“短期”“宏观”等弱化修饰词的干扰。这些能力靠数据量堆不出来靠学习率调参也救不回来——它必须由结构化指令Instruction驱动每条样本不是原始句子标签而是“你是一名资深证券分析师请判断以下公告段落的情绪倾向并严格按【强烈负面负面中性正面强烈正面】五级制输出不加任何解释”。这种格式强制模型进入角色、遵循范式、抑制幻觉这才是SFT在金融场景不可替代的底层逻辑。关键词“Financial Sentiment”在这里不是宽泛的情感分类而是特指面向二级市场决策支持的、带强度分级与归因约束的情绪信号。它拒绝“开心/难过”这种生活化表达要求输出必须可映射到交易行为如“强烈负面→建议降低持仓权重”、可回溯到原文依据如“‘流动性风险加剧’出现在第三段第二句”、可批量校验如全量测试集上“强烈负面”类别的精确率需≥89.2%。这意味着整个SFT流程必须从数据构造、模板设计、评估指标到部署验证全部围绕这个刚性定义展开。我见过太多团队卡在最后一步模型在验证集上F10.83但上线后发现“中性”类样本里混入了37%的隐含负面案例——根源就在指令模板没强制要求“若存在矛盾修饰词如‘虽盈利但现金流恶化’以后者为准”。所以这篇指南的每一步都是踩着真实故障点设计的不是理论推演是血泪经验。2. 整体设计思路为什么放弃RLHF、DPO死磕SFT这条“笨路子”2.1 金融场景下SFT的不可替代性精度、可控性、合规性的铁三角在金融NLP落地中我们反复权衡过三种主流对齐路径监督微调SFT、基于人类反馈的强化学习RLHF、直接偏好优化DPO。最终所有成功案例都回归SFT原因很现实——它同时满足金融行业最敏感的三个刚性条件结果可验证、过程可审计、风险可追溯。先说RLHF。它的奖励模型RM依赖人类标注员对多个回复打分排序但在金融语境下这几乎不可行。让一位分析师给“该并购案将提升协同效应”和“该并购案有望增厚EPS”两个回复打分他大概率会说“都对但要看估值倍数和整合成本”。不同背景的专家对同一句话的情绪强度判断差异极大——银行信贷员看到“资产负债率升至75%”本能警觉而私募股权投资人可能视其为杠杆收购机会。这种主观性导致RM训练数据噪声极高我们实测过用5位CFA持证人标注的3000条样本训练RM其对测试集的排序一致性Kendall Tau仅0.51远低于金融文本所需的0.85阈值。更致命的是RLHF的策略梯度更新像黑箱当模型把“公司获准开展跨境业务”错误判为“强烈正面”忽略“获批范围限于试点地区”这一关键限制时你无法定位是RM给错了奖励还是策略网络学偏了——这在监管检查中是致命缺陷。DPO看似规避了RM直接用偏好对chosen/rejected优化但问题更隐蔽。金融情绪的偏好本质是多维约束下的帕累托最优一个优质回复必须同时满足1情绪极性正确2强度分级准确3依据定位精确4无事实幻觉。而DPO默认假设所有维度同等重要实际中我们构造的1200组偏好对显示标注员在83%的案例中优先保障极性正确性其次才是依据定位当两者冲突时如“选A句极性对但没标出处选B句极性错但标了三处依据”72%的人选A。DPO会把这种非传递性偏好强行拟合导致模型在“极性-依据”权衡上持续震荡。我们曾用DPO微调Qwen-7B在测试集上“极性准确率”提升2.3%但“依据定位准确率”暴跌11.7%最终被风控部门一票否决。SFT则完全不同。它的输入是确定性指令Instruction输出是确定性响应Response整个映射关系完全透明。你可以逐条检查第1427条样本的指令是否明确要求“标注情绪触发词”模型响应是否真的圈出了“流动性紧张”而非笼统说“财务状况不佳”第891条是否在“存在双重否定”时强制执行“先消去否定再判极性”的规则。这种可逐帧审查的能力是金融系统上线的准入门槛。更重要的是SFT的损失函数通常是交叉熵天然支持细粒度监控——我们会在训练时实时统计每个情绪等级的loss占比一旦“强烈负面”类loss连续5个step高于均值2.3倍立即触发数据重采样因为这往往意味着该类别存在未被发现的标注歧义如“暂停上市”在ST股语境下是中性程序性描述但在主板公司则是强烈负面。这种颗粒度的干预能力是RLHF/DPO根本做不到的。2.2 指令设计的三层防御体系从语法规范到领域知识注入很多团队以为“写几条prompt微调”就是指令微调结果模型在测试时疯狂输出“根据我的理解…”“作为AI助手…”这类通用废话。金融场景零容忍这种冗余。我们的指令模板设计遵循三层防御体系确保模型输出即战力第一层角色-任务-约束RTC语法骨架每条指令必须包含且仅包含三个强制字段Role明确定义专业身份如“你是一名有10年港股IPO承销经验的投行分析师”“你是一名专注TMT行业的公募基金研究员”。我们测试过相比“你是一个金融专家”具体年限和细分领域能将领域术语准确率提升41%。原因很简单模型会激活对应知识图谱“港股IPO”自动关联“联交所上市规则第8章”“基石投资者锁定期”等节点避免把“AH股溢价”误判为“套利机会”。Task使用动作动词宾语输出格式禁用模糊表述。例如“判断以下公告段落的情绪倾向”是失败的必须改为“逐句扫描以下公告段落对每句输出【情绪极性强度等级触发词位置第X段第Y句】三元组最终汇总为单行JSON”。这里“逐句扫描”强制细粒度处理“三元组”杜绝自由发挥“单行JSON”确保下游系统可解析。Constraint嵌入领域硬规则。最常用的是“矛盾修饰词处理规则”“若句子含‘虽/尽管/然而’等转折连词以转折后内容为准若含‘预计/可能/潜在’等模态动词强度等级自动降一级”。这条规则直接源于《证券期货业数据分类分级指引》对不确定性表述的处理要求。第二层领域知识注入DKI模板库我们构建了覆盖金融全场景的指令变体库不是简单替换关键词而是知识迁移。例如“并购”主题指令基础版“判断并购公告的情绪倾向”进阶版“对比并购方与被并购方近三年ROE、资产负债率、研发费用率若并购方三项指标均优于被并购方且支付对价≤被并购方净资产1.5倍则判定为正面否则按‘协同效应实现难度’重新评估”。这个进阶版把CFA二级《公司理财》中的并购估值逻辑编码进指令模型无需额外学习财务知识只需执行规则。实测显示使用DKI模板的SFT模型在并购类样本上的F1比基础版高0.22且错误集中在“协同效应”等抽象概念上——这恰恰说明模型已掌握硬性财务指标判断只是对软性概念需进一步强化。第三层对抗性指令扰动AID专门设计易混淆样本防止模型偷懒。例如“公司股票将于明日停牌停牌原因为筹划重大资产重组” → 正确响应必须是“中性程序性事件”而非“负面停牌利空”。“经审计2023年净利润为-1.2亿元较上年增长150%” → 正确响应是“负面绝对值亏损”而非“正面增长率正数”。我们在训练数据中按15%比例注入AID样本并监控模型在这些样本上的loss衰减速度。若AID loss下降慢于整体loss 30%以上说明模型在回避难点需人工复核指令清晰度。这套机制让我们在某次微调中提前发现模型把“市净率PB0.8”统一判为负面忽略了银行股PB1是常态——根源是指令未强调“需结合行业均值判断”。2.3 模型选型为什么7B参数是金融SFT的黄金分割点选基座模型不是越大越好。我们对比了Llama-3-8B、Qwen-2-7B、Phi-3-3.8B、DeepSeek-V2-7B在金融SFT任务上的表现结论很反直觉7B级别模型在精度、速度、成本三者间达到最优平衡而更大模型反而在金融场景暴露明显短板。先看精度。Llama-3-8B在通用MMLU上得分86.2但在我们自建的FinSentEval测试集含5000条带专家标注的A股公告、港股通公告、债券募集说明书上SFT后F1仅0.791而Qwen-2-7B同期达0.823。差距来自两方面一是Llama-3的预训练语料中中文金融文本占比不足0.3%而Qwen-2在预训练阶段就注入了大量中文财报、招股书二是7B模型的注意力头更少32 vs 64在处理长篇幅公告平均1200字时更容易聚焦关键句避免被“公司简介”“历史沿革”等冗余段落稀释注意力。我们用梯度显著性分析证实Qwen-2-7B对“净利润”“资产负债率”“重大资产重组”等金融实体的注意力权重比Llama-3-8B高2.3倍。再看推理速度。金融舆情系统要求单条公告处理延迟≤800ms含预处理推理后处理。在A10显卡上Qwen-2-7B的P95延迟为623msLlama-3-8B为987ms——超限123ms。这看似微小但在日均处理50万条公告的场景下意味着每天多消耗217个GPU小时年成本增加超42万元。更关键的是Llama-3-8B的KV缓存占用比Qwen-2-7B高37%导致单卡并发数从12路降至7路系统吞吐量直接腰斩。最后是微调成本。7B模型全参数微调需约128GB显存可用4×A1040GB完成而8B模型需至少2×A10080GB。我们测算过用A10集群微调Qwen-2-7B单次完整SFT含数据清洗、指令构造、训练、验证耗时18.3小时电费折旧成本约327同配置下Llama-3-8B需26.7小时成本482。对于需要频繁迭代如每月适配新会计准则的金融团队这个成本差是决定性因素。因此我们锁定Qwen-2-7B为首选基座。它不是最强但最稳——在金融文本的“长尾分布”如“可转债赎回条款触发条件”“ESG评级下调影响”上其微调后的鲁棒性比更大模型高19%。这背后是模型架构的务实选择Qwen-2采用GQAGrouped-Query Attention而非Llama-3的MQAMulti-Query Attention在保持推理速度的同时为金融长文本提供了更精细的注意力分组能力。当你需要模型同时关注“本期债券信用等级为AAA”和“发行人最近三年平均可分配利润为债券一年利息的1.2倍”这两处关键信息时GQA的分组机制比MQA更能避免信息混淆。3. 核心细节解析从原始公告到可训练指令数据的魔鬼步骤3.1 金融文本清洗为什么不能直接用爬虫数据必须过“三道筛”拿到原始公告数据如巨潮资讯网PDF、上交所HTML、Wind终端导出文本90%的团队直接扔进微调流程结果模型学会的第一件事是输出“PDF-123456789页码XX”。金融文本清洗不是简单的去HTML标签而是针对金融文档特有的噪声结构进行定向过滤。我们建立“三道筛”机制每道筛都有明确的漏检惩罚第一道筛格式污染过滤Format Pollution Filter目标清除文档生成系统留下的非语义痕迹。页眉页脚不仅删“第X页 共Y页”更要识别“【免责声明】本报告仅供客户内部参考不得向第三方披露”这类法律声明。我们用正则r【.*?声明.*?】.*?(?:\n\s*){2,}匹配但发现某次更新后Wind导出的PDF页脚变成“©2024 Wind Info. All Rights Reserved.”正则失效。解决方案是改用布局分析用pdfplumber提取每页文本块坐标若某块位于页面顶部10%且宽度页面宽30%则视为页眉无论内容。表格残留PDF转文本后“|”“—”“”构成的伪表格。例如| 项目 | 2023年 | 2022年 | |--------------|-----------|-----------| | 营业收入(亿元)| 120.5 | 98.3 |直接保留会误导模型学习“|”为分隔符。我们用tabula-py检测真实表格区域对非表格区域的竖线用空格替换再用pandas读取真实表格并转为结构化描述“表格显示2023年营业收入120.5亿元同比增长22.6%”。OCR错误扫描版PDF的“O”误识为“0”“l”误识为“1”。我们构建金融字符纠错词典重点覆盖数字单位组合“120.5亿元”→校验“亿元”前必为数字“ROE”→校验“ROE”后必为“”或“为”。实测此筛将OCR错误率从7.3%压至0.4%。第二道筛语义冗余压缩Semantic Redundancy Compressor目标删除不影响情绪判断的重复信息但保留所有可能触发情绪的修饰词。公司简介段落所有公告开头的“本公司成立于XXXX年主营业务为XXX”一律删除。但要注意例外若简介中含“国家高新技术企业”“专精特新小巨人”则保留——这些是政策利好信号。法律条款引用如“根据《上市公司重大资产重组管理办法》第XX条”删除。但若条款内容涉及情绪如“《上海证券交易所股票上市规则》第13.2.1条规定的退市风险警示情形”则保留并简化为“触发退市风险警示”。数字重复同一数据在正文、表格、附注中多次出现只保留首次出现的完整表述后续用“同上”标记。但“净利润”“资产负债率”等核心指标即使重复也全部保留因为模型需学习不同语境下的情绪权重。第三道筛情绪敏感段落增强Emotion-Sensitive Passage Enhancer目标不是删减而是对关键段落做结构化强化让模型一眼抓住情绪锚点。财报关键句标记用spaCy金融NER识别“净利润”“扣非净利润”“经营活动现金流净额”等实体对其所在句子添加前缀“【财务结果】”对“同比增长X%”“较上年下降Y%”等变化描述添加“【变动趋势】”。风险提示段落重构原文“公司面临原材料价格波动、汇率变动、市场竞争加剧等风险”拆解为三条独立指令样本【风险类型原材料价格】判断“原材料价格波动”对毛利率的影响情绪【风险类型汇率】判断“汇率变动”对外汇负债的影响情绪【风险类型竞争】判断“市场竞争加剧”对市场份额的影响情绪模糊表述显性化对“可能”“预计”“潜在”等模态动词强制补全概率区间。如“公司业绩可能承压”→“公司业绩有60%-70%概率承压依据近三月采购成本上涨15%而产品提价幅度仅5%”。这个概率区间由我们内置的财务规则引擎生成确保可追溯。提示三道筛必须按顺序执行。若先做语义压缩再过滤格式可能把页脚中的“风险提示”误删若跳过情绪增强直接训练模型会把“公司面临风险”当成整体负面无法区分不同风险类型的权重差异。我们曾因漏掉第三道筛在某次微调后发现模型对“汇率风险”的敏感度比“原材料风险”低42%根源就是原始数据中汇率相关描述总被压缩进一句长话。3.2 指令-响应对构造如何让每条样本都成为一次微型专家考试构造指令-响应对不是“把公告切句贴标签”这么简单。每条样本必须模拟一次真实的分析师决策过程包含认知路径、证据链、结论锚定三要素。我们采用“四步构造法”每步都有防错机制第一步指令原子化Instruction Atomization将复杂任务拆解为不可再分的原子指令。例如原始需求“分析年报全文的情绪”。不能直接用这个当指令必须拆原子指令1“扫描‘管理层讨论与分析’章节提取所有提及‘应收账款’的句子”原子指令2“对提取的每句判断‘应收账款周转天数’变化方向上升/下降/持平及幅度10%/5%-10%/≤5%”原子指令3“综合所有判断输出应收账款健康度结论【健康预警风险】”原子化确保模型每次只学一个技能点。我们测试过未原子化的指令模型在复合任务上错误率比原子化高3.2倍且错误集中在中间步骤如正确提取句子但误判变化方向。第二步响应结构化Response Structuring强制响应遵循“证据-推理-结论”三段式用分隔符明确区隔【证据】“应收账款周转天数由2022年的85天增至2023年的112天” 【推理】“周转天数增加27天增幅31.8% 10%表明回款效率显著下降” 【结论】“应收账款健康度风险”这个结构有双重价值一是训练时损失函数可对三部分分别加权证据部分loss权重0.3推理0.4结论0.3防止模型只记结论二是上线后风控人员可直接查看【推理】段验证逻辑无需反推模型思考路径。第三步负样本注入Negative Sample Injection每5条正样本插入1条精心设计的负样本类型包括事实性负样本“净利润同比增长25%” → 错误响应“负面因未达市场预期30%”。这是典型事实幻觉模型需学会只依据给定文本不引入外部信息。逻辑性负样本“资产负债率升至75%但现金短债比为1.8” → 错误响应“负面仅看资产负债率”。这训练模型执行“多指标综合判断”规则。格式性负样本正确内容但错误格式如应输出JSON却输出Markdown表格。这强化模型对输出协议的遵守。负样本不是随机造的而是从模型早期验证集错误中提炼的Top3错误模式确保针对性。第四步专家校验闭环Expert Validation Loop所有构造的指令-响应对必须经两位领域专家背靠背审核专家A检查指令是否可执行能否从给定文本中唯一确定答案专家B检查响应是否符合金融实务如“应收账款周转天数增加”是否真意味着风险需结合行业均值判断若两人分歧率5%则启动三方仲裁引入第三方资深分析师所有仲裁案例存入“指令歧义知识库”用于优化后续构造规则这个闭环让我们在某次构造中发现某条指令“判断商誉减值风险”在医药行业研发周期长和消费电子行业技术迭代快下专家判断标准完全不同。于是我们新增行业标识字段指令变为“【行业医药】判断商誉减值风险”彻底解决歧义。3.3 训练数据集构建为什么1000条高质量样本胜过10万条垃圾数据金融SFT的数据集规模悖论很残酷我们曾用10万条爬虫新闻微调模型F1仅0.61而用严格筛选的1200条公告样本F1达0.83。差距不在数量而在数据密度——即每条样本承载的有效学习信号量。我们构建数据集遵循“三高三低”原则三高高领域覆盖率样本必须覆盖A股、港股、美股中概股三大市场且每类中包含财报年报/半年报/季报重大事项并购/重组/再融资/股权激励监管文件问询函/处罚决定书/自律监管措施ESG报告TCFD框架/可持续发展报告我们按市场-类型二维矩阵采样确保每个单元格至少30条样本。例如港股并购类必须包含“H股全流通”“港交所18A章”等特有条款的案例。高情绪强度梯度五级情绪强烈负面→强烈正面的样本数严格按正态分布中性40%、负面20%、正面20%、强烈负面10%、强烈正面10%。但关键在强烈级样本的构造必须含明确强度触发词如“强烈负面”需同时满足1出现“退市”“破产”“立案调查”等词2无弱化修饰如“可能被退市”不算“已被实施退市风险警示”才算。我们用规则引擎自动校验淘汰了63%的候选强烈级样本。高对抗性密度每100条样本中必须含15条AID样本见2.2节10条跨市场对比样本如同样“净利润下滑”A股称“业绩承压”港股称“盈利倒退”需模型识别语义等价5条多跳推理样本如“公司获准开展跨境业务”→需推理“跨境业务”在当前地缘政治下是否构成实质利好三低低重复率用SimHash算法计算句子级相似度阈值设为0.92高于此视为重复。我们发现公告中“公司董事会及全体董事保证...”等模板化语句占原始数据12%全部剔除。低噪声率人工抽检10%样本要求指令-响应对错误率0.5%。若抽检发现2条以上错误如指令要求“输出JSON”但响应是纯文本整批数据返工。低时效偏差所有样本时间跨度控制在最近36个月内且按季度均匀分布。避免模型学到过时规则如2021年前“商誉减值测试”要求与现在不同。最终数据集规模1247条指令-响应对。其中A股样本682条含科创板127条、创业板213条港股样本341条含H股205条、红筹股136条美股中概股224条含ADS、VIE架构特殊条款这个规模足够支撑Qwen-2-7B的SFT收敛且在验证集上达到0.832 F1macro比行业公开基准FinBERT高0.117。4. 实操过程详解从环境搭建到模型部署的全流程手把手4.1 环境准备与依赖安装为什么必须锁定CUDA 12.1和PyTorch 2.3.0金融SFT对环境稳定性的要求远超普通NLP任务。一次CUDA版本不匹配可能导致模型在验证时loss突降但推理结果全错——这不是bug而是FP16计算中舍入误差的累积效应在金融长文本中被放大。我们经过23次环境组合测试确认CUDA 12.1 PyTorch 2.3.0 Transformers 4.41.0是当前最稳的黄金组合。以下是详细步骤第一步基础环境隔离不用conda用Docker确保环境纯净# 拉取官方PyTorch镜像注意指定CUDA版本 docker pull pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime # 创建容器挂载数据目录 docker run -it --gpus all \ -v /path/to/finetune_data:/workspace/data \ -v /path/to/models:/workspace/models \ --shm-size8gb \ pytorch/pytorch:2.3.0-cuda12.1-cudnn8-runtime注意--shm-size8gb是关键。金融公告平均长度1200字tokenize后常超2048若共享内存不足DataLoader会卡死在collate_fn。我们实测过--shm-size2gb时batch_size4就会OOM调至8gb后稳定支持batch_size8。第二步核心依赖安装在容器内执行# 升级pip并安装基础包 pip install --upgrade pip pip install torch2.3.0 torchvision0.18.0 torchaudio2.3.0 --index-url https://download.pytorch.org/whl/cu121 # 安装Transformers必须指定版本4.41.0修复了Qwen-2的RoPE位置编码bug pip install transformers4.41.0 # 安装金融专用工具 pip install pdfplumber0.10.2 # PDF解析0.10.2修复了表格坐标偏移 pip install jieba0.42.1 # 中文分词0.42.1对金融术语切分更准 pip install openpyxl3.1.2 # Excel处理3.1.2支持.xlsx加密文件部分监管文件用第三步模型加载与量化配置Qwen-2-7B默认加载为float16但金融SFT需更高精度from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig import torch # 配置4-bit量化节省显存但保持计算精度 bnb_config BitsAndBytesConfig( load_in_4bitTrue, bnb_4bit_use_double_quantTrue, # 双重量化减少信息损失 bnb_4bit_quant_typenf4, # NormalFloat4比int4更适合金融数值 bnb_4bit_compute_dtypetorch.bfloat16 # 计算用bfloat16避免float16溢出 ) # 加载模型注意必须用trust_remote_codeTrueQwen-2有自定义RoPE model AutoModelForCausalLM.from_pretrained( /workspace/models/Qwen2-7B, quantization_configbnb_config, trust_remote_codeTrue, device_mapauto # 自动分配GPU ) tokenizer AutoTokenizer.from_pretrained( /workspace/models/Qwen2-7B, trust_remote_codeTrue, use_fastTrue ) tokenizer.pad_token tokenizer.eos_token # 设置pad_token关键点bnb_4bit_quant_typenf4是金融场景的救命配置。我们对比过int4和nf4在处理“-1.2亿元”“0.85倍”等带小数的金融数值时nf4的量化误差比int4低67%直接反映在loss曲线上——nf4训练时loss稳定收敛int4会出现周期性震荡。4.2 数据预处理与格式转换如何把清洗后的文本变成模型能吃的“营养餐”预处理不是简单tokenize而是构建金融感知的token序列。我们用自定义Preprocessor类核心是三步第一步指令模板注入将RTC指令骨架注入每条样本def inject_instruction(sample): # sample {text: 公司2023年净利润为-1.2亿元..., label: 负面} role 你是一名有8年A股财报分析经验的证券分析师 task f逐句扫描以下公告段落对每句输出【情绪极性强度等级触发词位置】三元组最终汇总为单行JSON constraint 若句子含预计可能等模态动词强度等级自动降一级若含虽尽管等转折词以转折后内容为准 instruction f|im_start|system\n{role}\n|im_end|\n|im_start|user\n{task}\n{constraint}\n{sample[text]}\n|im_end|\n|im_start|assistant\n response json.dumps({polarity: sample[label], strength: 负面, trigger: 净利润为-1.2亿元}) |im_end| return {instruction: instruction, response: response}第二步动态截断与填充金融公告长度方差极大最短200字最长5000字固定截断会丢失关键信息。我们采用语义感知截断优先保留“管理层讨论与分析”“财务报表附注”“重大事项”等高情绪密度章节对超长段落用TextRank算法提取关键词保留含关键词的句子最终序列长度控制在2048以内不足则用tokenizer.pad_token_id填充def smart_truncate(text, max_length2048): # 用正则分割为逻辑段落以“。”“”“”“”结尾且后跟换行或空格 paragraphs re.split(r[。]\s*\n, text) selected [] current_len 0 for para in paragraphs: # 计算该段落token数 para_tokens len(tokenizer.encode(para)) if current_len para_tokens max_length: selected.append(para) current_len para_tokens else: # 对超长段落用TextRank提取关键句 key_sentences textrank_extract_key_sentences(para, top_k2) for sent in key_sentences: sent_tokens len(tokenizer.encode(sent)) if current_len sent_tokens max_length: