魔搭社区推荐
作者:西二旗马斯克LLM
日前,由中国中文信息学会社会媒体处理专委会主办,智谱 AI、安硕信息、阿里云、魔搭社区、北京交通大学联合承办的「SMP 2023 ChatGLM 金融大模型挑战赛」落下帷幕,该赛事旨在推动大模型在金融垂直行业应用的研究和开发,沉淀大模型落地实践经验。赛后,赛事方第一时间开源开放了赛事相关的代码,目前也开始有开发者小伙伴基于此整理了一些干货笔记,小编特搜罗来向大家分享,希望能给正在关注大模型行业落地的小伙伴们一些帮助。
附开源地址:
Github:https://github.com/MetaGLM/FinGLM魔搭社区:https://modelscope.cn/organization/finglm
SMP 2023 ChatGLM 金融大模型挑战赛后公布的开源项目FinGLM,公布了不少比赛靠前团队的代码,今天就学习一下,做一个笔记,没耐心读代码的可以朋友可以先从本篇文章进行粗读,然后找自己感兴趣的部分再精读。
pdf转txt工具
智能知识库类项目一个脏活累活就是pdf转txt,其中表格部分由于复杂多变,非常麻烦,我把代码拷贝过来,加了一些注释:https://github.com/qq31682216/chatgpt_all/blob/main/huawei_demo/pdf_to_txt/pdf2txt.py,也可以到文末原项目地址中看原始代码学习。
关键依赖库
代码使用pdfplumber库从PDF中提取并加逻辑拼装。安装代码:pip install pdfplumber==0.9.0
主要逻辑
先glob读取文件排序,再送入15个进程的进程池,多进程处理。
按pdf.pages页遍历处理,每页通过page遍历存储
通过extract_text_and_tables函数提取文本和表格
其中表格使用page.find_tables()获取到表格数据,遍历表格开始处理,一旦有表格了,那么表格和文本都需要提取,通过check_lines函数,提取文本,得到按行的文本,通过new_table = table.extract()合并或者去掉一些多余的项,得到表格文本;如果没找到表格,调用check_lines得到文本,并处理页眉页脚。
因为这个是针对年报数据的,所以里边用了很多正则,都是人工看总结出来的,如果你的数据不好使,可以着重改一下这里的代码,具体可以debug跟踪一下执行,看看pdfplumber给你的输入是什么,你需要的输输出是什么。
最后按行保存json格式文本到alltxt2目录中,文件名变为.txt后缀。
输出格式举例:
{"page": 7, "allrow": 165, "type": "excel", "inside": "['受的政府补助除外)', '', '', '', '']"} {"page": 7, "allrow": 166, "type": "excel", "inside": "['委托他人投资或管理资产的损益', '11,983,529.98', '9,660,508.21', '4,469,117.34', '']"} {"page": 7, "allrow": 167, "type": "text", "inside": ""} {"page": 7, "allrow": 168, "type": "页脚", "inside": "7"} {"page": 8, "allrow": 169, "type": "text", "inside": ""} {"page": 8, "allrow": 170, "type": "页眉", "inside": "浙江核新同花顺网络信息股份有限公司2019年年度报告全文"} {"page": 8, "allrow": 171, "type": "excel", "inside": "['除同公司正常经营业务相关的有效套期保', '', '', '', '']"} {"page": 8, "allrow": 172, "type": "excel", "inside": "['值业务外,持有交易性金融资产、衍生金', '', '', '', '']"}
瑕疵
风格方面,因为我长时间在大厂,所以多人合作比较常见,python代码基本上都会有规范,这份代码从规范上讲还差不少,不方便阅读和打团战,例如需要用if '__main__' == __name__:来包一下运行逻辑,这样其他代码引用这个文件时,不会执行这段代码;再比如遍历lines,不用l这个变量,因为和1很像,容易笔误;最大的问题就是几乎没有注释,看起来逻辑很难懂。
接下来读一读各选手代码,精力有限,我先从自己感兴趣的读起
馒头科技
比赛冠军,微调典范,给出了明确的样本条数、改进方法,值得学习。团队成员毕业于不同学校、工作在不同公司、城市都是3个,连做的事情都是医疗、风控、VR,不知道他们怎么碰撞到一起了。
方案
本项目主要采用prompt设计+大模型微调的方式来对用户的问题进行回答。首先会对用户的提向进行分类判断用户是想问基本公司信息和财务报表信息或者是询问公司年报的相关内容或者是想对整体数据进行查询分析。对于查询或询问类的提问,我们会对用户提向进行意图识别,提取用户问题的关键词,然后对报表或者年报进行相关信息召回,通过prompt 设计将召回的报表字段和年报内容交由 GLM 模型进行处理回答。对于统计类分析,我们主要通过模板和大模型改写的方式来构建 SQL 训练数据,对GLM进行微调,增强模型NL2SQL的能力,然后直接执行 SQL 来获取分析结果。
亮点
1、微调意图识别和SQL生成两个模型。
2、构建数据集的方式值得借鉴。
3、数据量少的只有200条,但是泛化能力很强。
4、多用枚举,少用否定句的经验不错,少踩坑。
代码
等待公布,我再补充。
先对问题进行分类,是使用大模型prompt进行,做了微调,构建训练集900+标记,prompt如下:
prompt
分类后续处理
微调经验
1、loss在0.2下不去。相信很多同学遇到这个问题,之前在用友讲座上交流,就有此疑问,一开始的效果比较糟糕,最后发现是训练字段小 于传入的模版+问题的字符串,导致训练过程中的传入字段丢失截断。
2、加更多信息和step是优化关键。从一开始的只 有选项的题目,到有一定信息的选项描述(高频的关键字等),同时对训练step加大到400,对微调训练有很大的帮助,loss下降到0.01,分类能力优秀。
3、尝试调低Learning rate可以获得更快的训练收敛效益。
NL2SQL方面,也是很好的经验可以借鉴
1、早期用公共NL2SQL训练集,4万多条,结果丧失对话能力,SQL生成也很差,这也是大家常遇到的问题,信息覆盖。小规模标注60-100道题对4万多条来说也没法用,放弃了。
2、要想稳定生产准确有效SQL语言,是需要根据实际的任务情况和方向来设定训练目标,他们使用chatGPT/Bard来协助生成不同的提问模板,再通过字段的随机条件填充。200多高质量标注,到后来1000多道高质量标注。这个意义对我们借鉴很有用,在一个特定场景,大概需要200-1000个不同类型的标注样本,这个和本人经验很符合。另外这个地方我以前只是用chatGPT生成标注(self-instruction),他们这里可以借鉴生成模板,这样节省费用。
反卷总局
无微调,LLM提示+各种花式用法,压榨原版LLM能力的典范。
方案
1、基于正则分类与抽取关键词的方式,实现数据库字段高频问题的快速回答
2、基于LLM抽取关键词的方式,实现与数据库字段相似问题的泛化
3、基于LLM文档问答的方式,实现数据库字段外问题的兜底
亮点
1、使用In-Context Learning的方式抽取关键词,无需微调,保留大模型的通用能力
2、通过分块文本增加标题信息,以及LLM关键词的召回增强的方法,显著提升回答公司综合问题的效果
代码
表格数据使用pdfplumber的txt数据提取+html数据提取+基于paddleocr的ocr数据提取,数据互补融合入库。
process_keyword/question_analyse.py 中会对问题进行分类,基本上是正则+判断+LLM判断,对问道的内容做了归一化,计算公式中明确了召回数据,用若干字典配置。
method/calculate.py 做了信息抽取,这里有个小技巧,原来我们放few-shot例子时放在prompt中,他这里直接放在历史记录中,发现效果更好。值得借鉴。
method/com_info.py中利用大模型提取关键字。
method/statistics.py 中用m3e模型做句子向量匹配。
predict.py 中加载之前问题分析的结果,对不同类型问题分别处理。
整体代码读下来,if else,正则等等还是比较多的,这也是当前大模型开发中的trade-off,不能一下子完美完成任务,但是可以借助大模型帮忙做文本处理、相似等工作。
吃辣子
个人觉得总结得最好的一个团队,可惜不公布代码,只能看PPT,首图也是用他们提出的以LLM为核心的系统设计,本人目前做的智能BI项目“说数”demo正是这个架构,不谋而合。
方案
采用chatglm2-6b为核心模型,综合运用意图识别、语义解析、向量检索等技术,构建了金融财务领域的智能问答系统。
亮点
1、使用微调模型进行主体、年份、意图要素识别,同时也分成几类问题分别处理。
2、几个关键识别靠大模型:意图要素、计算意图、统计条件。
3、在泛化性和可靠性上下功夫,比较贴合实际应用场景。
4、利用知识库对特有词汇消歧,例如所有者权益合计vs净资产,应该做了个replace,作为兜底手段没问题。
5、貌似唯一一个使用faiss数据库做向量语义的,之前我用faiss在这个项目里效果较差,不知他们做了什么操作。
6、分级匹配的思路:首先语义匹配数据库字段,再语义匹配文档树中章节标题节点,最后深度向量 语义检索文档树子叶,或全文向量语义检索,保证系统的泛化和可靠。
7、生成SQL带有自动诊断和修复。具体怎么诊断,PPT中没有,我记得会上听是一个格式的修复,例如json少了双引号之类的。
其他
要素识别示例
意图识别微调的数据集,初赛5k + 复赛2k + 合成2k = 9k,训练集 : 测试集 = 17 : 1,合成数据多样化,增强了微调模 型的泛化能力。
SQL微调数据集,初赛复赛6k+合成2k,约8k条样本 训练集:测试集=11.5:1。
这些数字经验可以参考,可以用这些数据作为起点,节省大家实际微调时间。
结婚买房代代韭菜
应该是前9队伍里唯一一个独行侠,代码量大,非常不容易。
方案
亮点
1、对文档结构根据章节做了doctree。
2、微调问题分类模型,准确率99.9%,其中构建数据集做了易混数据和随机替换别名。
3、NL2SQL部分,简化部分问题SQL来降低任务难度,例如开滦股份2019-2020年这两年的法定代表人是否都相同?SQL为select 年份, 法定代表人 from big where 年份 in ('2019年' , '2020年') and 股票简称 in ('开滦股份')。
4、只用1张3090,成本极低,当然我看单条速度也比较慢,不容易。代码中也是分四次加载,我猜测可能是显存不够。
5、格式化输出也使用微调方式。
代码
除去数据处理不谈,predict.py为预测流程,router函数为分流器,读取问题,通过query_type_router函数分流。
query_analyze.py 中的query_type_router函数,先求出问题类型,使用jieba分词,得到公司名称、年份、关键词,接下来就可以用关键词、公司、年份综合判断属于哪些问题了。然后使用微调后模型判断分类。
nl2sql中,nl2sql/nl2sql.py文件里prepare_prompt函数得到查询列,这里去停词、关键词匹配、做编辑距离计算等,然后处理了公式相关。prepare_query_for_sql做了公司名称的小处理。整个SQL按类型分开,简单问题分析Query之后,根据要素和条件拼装出来,复杂的用大模型。
translate_sql函数先找到中文,去掉''不需要转换的,剩下的转换成英文表名,这个很值得我借鉴,之前用LLM生成SQL,经常在中英文这里出错,这里做了个trick,先生成含中文的伪SQL,再替换成英文的字段,并且他取了个巧,用拼音库批量替换。
solve_type1函数用规则或者模型生成答案。
pack_normalize_res格式化结果。
最后
文末,FinGLM开源库地址:https://github.com/MetaGLM/FinGLMLM
我的github库地址:https://https://github.com/qq31682216/chatgpt_all,不断完善中。
点击直达FinGLM 开源https://modelscope.cn/organization/finglm