文章目录
- 项目背景
- 技术选型
- 架构设计
- 核心实现
- 踩坑记录
- 效果对比
项目背景
这几年做AI项目,一个很深的感触是:技术必须找到真实的商业场景,才能产生价值。前阵子,一个做金融投资的朋友找到我,说他们现在做ESG(环境、社会、治理)投资,但评估企业报告太主观、效率太低,问我能不能用AI帮上忙。这不就是典型的“AI+垂直领域”的机会吗?我立刻来了兴趣。
ESG投资现在有多火?看看数据就知道了。全球ESG资产规模已经超过40万亿美元,国内“双碳”目标更是把绿色金融推上了风口。但核心痛点在于:如何客观、高效、规模化地评估一家公司的ESG表现?传统方法依赖分析师手动阅读几百页的PDF报告,既慢又容易带主观偏见。这正是AI,特别是自然语言处理(NLP)技术大显身手的地方。
技术选型
接到需求后,我首先盘点了技术栈。这个项目的核心是从非结构化的文本中,结构化地提取ESG相关信息并量化评分。这本质上是一个信息抽取(Information Extraction, IE)和文本分类问题。
- 核心模型:我放弃了从零训练的想法,时间成本和数据要求都太高。预训练语言模型(PLM)是必然选择。考虑到我们需要处理中文企业报告(社会责任报告、年报),我选择了ERNIE 3.0和RoBERTa-wwm-ext作为基座模型。ERNIE对中文实体和知识理解有增强,而RoBERTa在通用语义表征上很稳健。
- 任务框架:ESG评估是个复合任务。我将其拆解为:
- 文本分类:判断一段文本是否属于E、S、G的某个具体议题(如“碳排放”、“员工福利”、“董事会多样性”)。这用Fine-tuning预训练模型做分类头即可。
- 命名实体识别(NER)与关系抽取:从相关文本中提取具体数据(如“二氧化碳减排量:10万吨”)和因果关系(如“因投入污水处理设备,减少了污染物排放”)。这里我采用了基于提示学习(Prompt-Tuning)的方法,在少样本场景下效果比传统Fine-tuning更好。
- 情感/立场分析:判断文本中企业对某项ESG议题的描述是“积极”、“消极”还是“中性”。这对评估企业态度至关重要。
- 数据处理与工程:报告都是PDF,需要先做OCR和文本解析。我用了
pdfplumber和paddleOCR的组合。解析后的文本需要分句、分段,并构建成适合模型输入的格式。 - 辅助工具:为了快速验证想法和构建标注数据,我用了
Doccano进行文本标注。向量数据库Milvus用来存储和管理企业报告的文本向量,方便后续的语义检索和比对。
架构设计
整个系统的架构,我设计成了一条清晰的流水线,目标是高内聚、低耦合,便于迭代和维护。
[原始PDF报告] -> (解析层) -> [结构化文本] [结构化文本] -> (AI处理层) -> [结构化ESG数据] [结构化ESG数据] -> (评分与聚合层) -> [ESG评分与洞察报告]- 数据接入与解析层:负责处理不同格式的输入(PDF/Word/TXT),统一输出清洁的、带基础结构(章节、段落)的文本。
- AI模型处理层:这是核心。
- 议题识别模块:使用微调后的文本分类模型,为每个文本片段打上E/S/G二级议题标签。
- 信息抽取模块:对于关键议题片段,触发相应的NER或Prompt-Tuning模型,抽取出量化指标和关键事实。
- 情感分析模块:对描述性文本进行分析,输出情感极性。
- 业务逻辑与评分层:根据抽取出的量化数据(如减排量、女性高管比例)和定性情感,结合预定义的行业特定权重和评分规则,计算企业在各个议题上的得分,并汇总成总ESG评分。
- 数据存储与API层:使用PostgreSQL存储结构化结果,Milvus存储文本向量。通过FastAPI提供RESTful API,供前端或投资分析系统调用。
核心实现
这里我拿“环境(E)”议题下的“碳排放管理”子项为例,展示核心代码逻辑。
第一步:构建议题分类模型
importtorchfromtransformersimportBertTokenizer,BertForSequenceClassification,Trainer,TrainingArguments# 加载预训练模型和分词器model_name="hfl/chinese-roberta-wwm-ext"tokenizer=BertTokenizer.from_pretrained(model_name)model=BertForSequenceClassification.from_pretrained(model_name,num_labels=10)# 假设有10个ESG子议题# 准备训练数据(示例)train_texts=["公司通过技术改造,年度碳排放强度下降5%","我们致力于为员工提供平等的职业发展机会..."]train_labels=[0,5]# 0代表“碳排放”,5代表“员工平等”# 编码train_encodings=tokenizer(train_texts,truncation=True,padding=True,max_length=128)classESGDataset(torch.utils.data.Dataset):def__init__(self,encodings,labels):self.encodings=encodings self.labels=labelsdef__getitem__(self,idx):item={key:torch.tensor(val[idx])forkey,valinself.encodings.items()}item['labels']=torch.tensor(self.labels[idx])returnitemdef__len__(self):returnlen(self.labels)train_dataset=ESGDataset(train_encodings,train_labels)# 配置训练参数并训练training_args=TrainingArguments(output_dir='./results',num_train_epochs=3,per_device_train_batch_size=16,logging_dir='./logs',)trainer=Trainer(model=model,args=training_args,train_dataset=train_dataset,)trainer.train()第二步:基于Prompt的信息抽取(关键指标)
对于“碳排放强度下降5%”这样的句子,我们想结构化地提取“指标:碳排放强度”、“变化:下降”、“数值:5%”。传统NER需要大量标注“下降”这样的词为“变化”,成本高。我采用Prompt方法。
fromtransformersimportpipeline# 使用一个简单的文本生成模型(如ChatGLM或可在本地部署的模型),通过设计Prompt来抽取prompt_template=""" 请从以下句子中提取关于环境指标的信息。以JSON格式输出,包含“指标”、“变化方向”、“数值”三个键。 句子:{sentence} """sentence="公司通过技术改造,年度碳排放强度下降5%。"# 假设我们有一个本地运行的文本生成APIdefextract_with_prompt(model_api,prompt):response=model_api.generate(prompt)# 解析response中的JSONreturnparsed_json# 期望输出: {"指标": "碳排放强度", "变化方向": "下降", "数值": "5%"}这种方法在少样本时更灵活,但需要模型有较强的指令遵循能力。
第三步:评分逻辑
defcalculate_carbon_score(extracted_data,industry_baseline):""" extracted_data: 从报告中抽取的多个相关数据点列表 industry_baseline: 该行业的平均碳排放强度 """score=50# 基础分fordatainextracted_data:ifdata["指标"]=="碳排放强度"anddata["变化方向"]=="下降":reduction=float(data["数值"].strip('%'))/100.0# 简单的线性加分规则,实际会更复杂,可能包含对数、阈值等score+=reduction*20# 检查是否有碳中和目标if"碳中和"indata.get("描述",""):score+=10# 与行业基准比较ifcompany_carbon_intensity<industry_baseline:score+=15returnmin(100,max(0,score))# 限制在0-100分踩坑记录
这个项目踩的坑,比预想的要多。
- 数据质量“黑洞”:企业ESG报告格式千奇百怪,有图片型PDF、扫描件、表格混杂。最初的OCR准确率只有70%,导致后续AI模型“垃圾进,垃圾出”。解决方案:我们建立了一个预处理管道,包含PDF类型判断、高质量OCR引擎选择(PaddleOCR对中文印刷体效果好)、以及基于规则和简单模型的表格修复模块,将文本清洁度提升到了95%以上。
- 标注数据稀缺与不一致:ESG领域缺乏公开的高质量标注数据。不同分析师对同一段文本的议题归类可能有分歧。解决方案:我们采用了“专家标注+模型预标注+人工校验”的主动学习循环。先由专家标注少量高质量数据训练一个初始模型,再用模型去预标注新数据,人工只需修正模型不确定的部分,大大提升了标注效率。
- 模型“幻觉”与过度泛化:在信息抽取时,模型有时会“创造”报告中不存在的数字或关系。比如,报告只说“减少了排放”,模型可能输出“减少了10%的排放”。解决方案:a) 在Prompt中明确加入“如未明确提及,则输出‘未提及’”;b) 引入后处理规则,对抽取的关键数值进行合理性校验(如与往年数据对比);c) 对于关键指标,采用“抽取+问答”双模型验证。
- 评分规则的动态性:不同行业(如高耗能的钢铁 vs 轻资产的互联网)的ESG评分标准截然不同。一套固定权重行不通。解决方案:我们将评分规则设计成可配置的“权重模板”,并与行业分类数据库联动,实现动态权重调整。同时,评分系统后端支持投资经理根据政策变化手动微调权重。
效果对比
项目上线后,我们与传统的分析师人工评估进行了一次盲测对比。
- 效率:AI系统处理一份100页的报告,平均时间从人工的8-10小时缩短到5分钟以内,实现了百倍级的效率提升。
- 覆盖度:AI可以无差别地扫描报告全文,而人工可能会因疲劳忽略某些段落。AI在“治理(G)”中关于“风险管理体系”等细节条款的发现率上显著高于人工。
- 一致性:AI对同一份报告多次评估,结果完全一致。而不同分析师对同一家公司的评分差异有时可达15分以上。
- 难点:在处理模糊、含蓄或需要深度推理的文本时,AI仍不如经验丰富的分析师。例如,报告中说“公司注重与社区的沟通”,这可能是真实的社区投入,也可能只是公关话术。AI目前更擅长“硬指标”抽取,对“软性表述”的深度解读还有局限。
结论:这个AI系统不是一个“替代者”,而是一个强大的“增强工具”。它把分析师从繁琐的文档阅读中解放出来,让他们能更专注于高层次的逻辑判断、行业对比和投资决策。目前,该系统已作为辅助工具集成到朋友公司的投研平台中,覆盖了A股和港股上千家公司,形成了初步的数据资产。
这个项目让我深刻体会到,将AI落地到ESG这样的专业领域,技术只占一半,另一半是对业务逻辑的深度理解、对数据脏活累活的耐心,以及灵活务实的问题解决能力。希望这个实战分享对你有启发。
如有问题欢迎评论区交流,持续更新中…