基于NL2JSON助力金融精细化运营
场景介绍
在金融场景中,客户日常业务依赖大量报表数据来支持精细化运营,但手工定制开发往往耗费大量人力。因此,希望借助大模型消除语义歧义性,识别用户查询意图,并直接生成支持下游操作的结构化JSON信息。大模型的NL2JSON能力可以从自然语言输入抽取关键信息并转换为JSON格式输出,以供下游操作,从而满足该场景下客户需求。
金融场景下,NL2JSON能力可以有效消除用户语义歧义性,提高数据处理的灵活性和便利性,降低人力开发成本、提升交付效率和查询性能,同时赋能精细化运营。
选择基模型/基础功能模型
盘古-NLP-N2-基础功能模型
准备训练数据
本场景不涉及自监督训练,无需准备自监督数据。
微调数据来源:
- 来源一:真实业务场景数据。
- 来源二:基于人工泛化的真实业务场景数据。
- 来源三:基于简单规则槽位泛化的真实业务场景数据。示例如下:
科技行业公司的平均利润和市值是多少?
识别原始问题中的槽位:
科技行业公司的[metric]利润和市值是多少?
采用简单的逻辑规则进行替换,获取更多数据。此处将[metric]替换为“最大”、“最小”、“中位”、“总”等,示例如下:
科技行业公司的最大利润和市值是多少? 科技行业公司的最小利润和市值是多少? 科技行业公司的中位利润和市值是多少? 科技行业公司的总利润和市值是多少? …
- 来源四:基于大模型的数据泛化。基于目标场任务的分析,通过人工标注部分数据样例,再基于大模型(比如盘古提供的任意一个规格的基础功能模型)采用self-instruct等方式泛化出更多的业务场景数据。示例如下:
请改写命令案例,生成10个相似命令,保证每个命令都可以调用正确的指标接口。 请注意: 1. 命令必须契合人类常见的提问方式,命令方式必须保证多样化 2. 生成的命令只能改写命令案例中文表达部分的内容 指标接口名称:利润的平均值、市值的平均值 命令案例:科技行业公司的平均利润和市值是多少
通过调用大模型,获取更多数据:
1. "请给我科技行业公司的利润平均值和市值平均值。" 2. "科技行业的公司平均利润和市值都是多少?" 3. "我需要知道科技行业公司的平均利润和平均市值。" 4. "能告诉我一下科技行业公司的平均利润和市值是多少吗?" 5. "请问科技行业的公司,他们的平均利润和市值是多少?" ……
微调数据要求:
- 数据格式样例:JSONL格式,每行是一条JSON,包含“context”和“target”两个字段。示例如下:
{"context": "今天是2023-11-20,你是一个银行智能助理,现在需要根据用户问题、指标-解释表、参数-类型-解释表,生成符合要求格式的json。\n\n请学习并记住以下背景知识:\n1.json格式:{\"metrics\":[{\"caption\":\"指标名称\"}],\"dimensions\":[{\"caption\":\"维度名称\"}],\"filters\":{\"query_filters\":[{\"value\":[\"值内容\"],\"caption\":\"度量名称\",\"relation_operator\":\"名称与内容的逻辑关系\"}],\"having_filters\":[{\"value\":[\"值内容\"],\"caption\":\"度量名称\",\"relation_operator\":\"名称与内容的逻辑关系\"}]},\"orders\":[{\"caption\":\"名称,caption和formula二选一\",\"order\":\"升序还是降序,枚举值:DESC, ASC\"}],\"limit\":1000}。\n2.relation_operator的取值要限定在:[\"EQUAL-TO\",\"NOT-EQUAL\",\"GREATER-THAN\",\"LESS-THAN\",\"BETWEEN\",\"NOT-BETWEEN\",\"IN\",\"NOT-IN\",\"NULL\",\"NOT-NULL\",\"CONTAIN\",\"GREATER-THAN-OR-EQUAL-TO\"]。\n3.order的取值要限定在[\"ASC\",\"DESC\"]。\n4.dimensions-caption中的值要限定在参数-类型-解释表中\n\n以下是你的思考过程:\n步骤1.根据用户问题从指标-解释表中得到metrics中caption的值,格式为:\"metrics\":[{\"caption\":\"xx\"}],不要超过两个\n步骤2.根据用户问题从参数-类型-解释表中得到dimensions、query_filters、orders中caption的值,格式为:\"dimensions\":[{\"caption\":\"xx\"}],\"filters\":{\"query_filters\":[{\"value\":[\"xx\"],\"caption\":\"xx\",\"relation_operator\":\"xx\"}],\"orders\":[{\"caption\":\"xx\",\"order\":\"xx\"}]\n步骤3.根据用户问题从metrics和dimensions中caption的值得到having_filters中caption的值,格式为:\"having_filters\":[{\"value\":[\"xx\"],\"caption\":\"xx\",\"relation_operator\":\"xx\"}]}\n步骤4.综合以上内容和json格式,输出json,格式为{\"result\":{\"metrics\":[\"XXX\"],\"dimensions\":[\"XXX\"],\"filters\":{\"XXX\":\"xxx\"},\"orders\":[\"XXX\"],\"limit\":1000}}\n\n请根据以上背景知识、参考案例按照步骤生成符合需求格式的json。\n\n用户问题:科技行业公司的平均利润和市值是多少?\n指标-解释表:[['利润的平均值', '利润的平均值'], ['市值的平均值', '市值的平均值']]\n参数-类型-解释表:[['id', 'NUMBER', '标识'], ['name', 'ENUM', '名称'], ['City', 'ENUM', '城市'], ['Height', 'NUMBER', '高度'], ['Stories', 'NUMBER', '故事'], ['Status', 'ENUM', '状态'], ['Headquarters', 'ENUM', '总部'], ['Industry', 'ENUM', '行业'], ['Sales_billion', 'NUMBER', '销售十亿'], ['Profits_billion', 'NUMBER', '利润(十亿)'], ['Assets_billion', 'NUMBER', '资产(十亿)'], ['Market_Value_billion', 'ENUM', '市值(十亿)'], ['building_id', 'NUMBER', '建筑编号'], ['company_id', 'NUMBER', '公司编号'], ['move_in_year', 'NUMBER', '搬入年份']]\n请按照要求将结果json写在\"result\"中: ", "target": "{\"metrics\":[{'caption': '利润的平均值'}, {'caption': '市值的平均值'}],\"filters\":{'query_filters': [{'value': ['technology'], 'caption': 'Industry', 'relation_operator': 'EQUAL-TO'}]}}"}
- 数据量级要求:本场景使用了30000条数据进行微调。
类似场景需要的微调数据量视具体情况而定,从经验上来说,若实际场景相对简单和通用,使用几千条数据即可;若场景复杂或专业,则需要上万条数据。
- 数据质量要求:
- 保证数据的分布和目标需要与实际场景匹配。
- 保证数据的覆盖度:数据需要尽可能覆盖产品所提供的功能;数据需要覆盖难易度、长短度,包含参数丰富等场景;数据在长短、扁平与深层嵌套、对接客户api接口数量上全覆盖。
- 数据中需要提供JSON的字段解释,以及Query和JSON生成逻辑解释。这些信息需要拼入Prompt,并确保人以及大模型可以根据Query、字段解释、Query到JSON的生成逻辑生成符合客户要求的JSON。Prompt会作为输入(context字段)的内容组成训练数据,同时也是模型调用时的Prompt。JSON字段解释示例如下:
["metrics":"指标列表","caption":"维度/度量/指标名称","dimensions":"维度列表","query_filters":"where中的过滤条件,所有条件为AND关系","having_filters":"having中的过滤条件,所有条件为AND关系","value":"值内容","relation_operator":"字段与值的逻辑关系,枚举值","orders":"排序列表","order":"升序还是降序,枚举值:DESC, ASC","limit":"返回数量"]
参数字段解释示例:[['id', 'int', '标识'], ['name', 'text', '名称'], ['City', 'text', '城市'], ['Height', 'int', '高度'], ['Stories', 'int', '故事'], ['Status', 'text', '状态'], ['Headquarters', 'text', '总部'], ['Industry', 'text', '行业'], ['Sales_billion', 'int', '销售十亿'], ['Profits_billion', 'int', '利润(十亿)'], ['Assets_billion', 'int', '资产(十亿)'], ['Market_Value_billion', 'text', '市值(十亿)'], ['building_id', 'int', '建筑编号'], ['company_id', 'int', '公司编号'], ['move_in_year', 'int', '搬入年份']]
Query和JSON生成逻辑解释示例:步骤1.根据用户问题从指标-解释表中得到metrics中caption的值,格式为:"metrics":[{"caption":"xx"}],不要超过两个 步骤2.根据用户问题从参数-类型-解释表中得到dimensions、query_filters、orders中caption的值,格式为:"dimensions":[{"caption":"xx"},{"caption":"xx"},{"caption":"xx"}],"filters":{"query_filters":[{"value":["xx"],"caption":"xx","relation_operator":"xx"},{"value":["xx"],"caption":"xx","relation_operator":"xx"}],"orders":[{"caption":"xx","order":"xx"},{"caption":"xx","order":"xx"}] 步骤3.根据用户问题从metrics和dimensions中caption的值得到having_filters中caption的值,格式为:"having_filters":[{"value":["xx"],"caption":"xx","relation_operator":"xx"}]} 步骤4.综合以上内容和json格式,输出json
微调数据清洗:
如下提供了该场景实际使用的数清洗策略,供您参考:
- 判断数据中的JSON结构是否符合预先定义的接口结构。
{"context": "…", "target": "{\"metrics\":['AvgProfits', 'AvgMarketValue'],\"filters\":{'query_filters': [{'value': ['technology'], 'caption': 'Industry', 'relation_operator': 'EQUAL-TO'}]}}"}
预先定义的JSON结构如下:
{"metrics":[{"caption":"xx"}],"dimensions":[{"caption":"xx"}],"filters":{"query_filters":[{"value":["xx"],"caption":"xx","relation_operator":"xx"}],"having_filters":[{"value":["xx"],"caption":"xx","relation_operator":"xx"}]},"orders":[{"caption":"xx","order":"xx"}],"limit":1000}
编写清洗脚本,清洗后的数据如下:
{"context": "…", "target": "{\"metrics\":[{'caption': 'AvgProfits'}, {'caption': 'AvgMarketValue'}],\"filters\":{'query_filters': [{'value': ['technology'], 'caption': 'Industry', 'relation_operator': 'EQUAL-TO'}]}}"}
- 判断数据中JSON的生成逻辑是否符合预先要求。
{"context": "… 请根据以上背景知识、参考案例按照步骤生成符合需求格式的json。\n\n用户问题:科技行业公司的平均利润和市值是多少?\n指标-解释表:[['利润的平均值', '利润的平均值'], ['市值的平均值', '市值的平均值']]\n参数-类型-解释表:[['id', 'NUMBER', '标识'], ['name', 'ENUM', '名称'], ['City', 'ENUM', '城市'], ['Height', 'NUMBER', '高度'], ['Stories', 'NUMBER', '故事'], ['Status', 'ENUM', '状态'], ['Headquarters', 'ENUM', '总部'], ['Industry', 'ENUM', '行业'], ['Sales_billion', 'NUMBER', '销售十亿'], ['Profits_billion', 'NUMBER', '利润(十亿)'], ['Assets_billion', 'NUMBER', '资产(十亿)'], ['Market_Value_billion', 'ENUM', '市值(十亿)'], ['building_id', 'NUMBER', '建筑编号'], ['company_id', 'NUMBER', '公司编号'], ['move_in_year', 'NUMBER', '搬入年份']]\n请按照要求将结果json写在\"result\"中: ", "target": "{\"metrics\":[{'caption': 'AvgProfits'}, {'caption': 'AvgMarketValue'}],\"filters\":{'query_filters': [{'value': ['technology'], 'caption': 'Industry', 'relation_operator': 'EQUAL-TO'}]}}"}
预先要求如下:
步骤1.根据用户问题从指标-解释表中得到metrics中caption的值,格式为:"metrics":[{"caption":"xx"}],不要超过两个
编写清洗脚本,清洗后的数据如下:
{"context": "… 请根据以上背景知识、参考案例按照步骤生成符合需求格式的json。\n\n用户问题:科技行业公司的平均利润和市值是多少?\n指标-解释表:[['利润的平均值', '利润的平均值'], ['市值的平均值', '市值的平均值']]\n参数-类型-解释表:[['id', 'NUMBER', '标识'], ['name', 'ENUM', '名称'], ['City', 'ENUM', '城市'], ['Height', 'NUMBER', '高度'], ['Stories', 'NUMBER', '故事'], ['Status', 'ENUM', '状态'], ['Headquarters', 'ENUM', '总部'], ['Industry', 'ENUM', '行业'], ['Sales_billion', 'NUMBER', '销售十亿'], ['Profits_billion', 'NUMBER', '利润(十亿)'], ['Assets_billion', 'NUMBER', '资产(十亿)'], ['Market_Value_billion', 'ENUM', '市值(十亿)'], ['building_id', 'NUMBER', '建筑编号'], ['company_id', 'NUMBER', '公司编号'], ['move_in_year', 'NUMBER', '搬入年份']]\n请按照要求将结果json写在\"result\"中: ", "target": "{\"metrics\":[{'caption': '利润的平均值'}, {'caption': '市值的平均值'}],\"filters\":{'query_filters': [{'value': ['technology'], 'caption': 'Industry', 'relation_operator': 'EQUAL-TO'}]}}"}
- 判断数据中的JSON参数是否与Query中的参数对应上。
训练模型
自监督训练:
不涉及
有监督微调:
该场景采用了下表中的微调参数进行微调,您可以在平台中参考如下参数进行训练:
训练参数 |
设置值 |
---|---|
数据批量大小(batch_size) |
8 |
训练轮数(epoch) |
6 |
学习率(learning_rate) |
7.5e-05 |
学习率衰减比率(learning_rate_decay_ratio) |
0.067 |
热身比例(warmup) |
0.013 |
评估和优化模型
模型评估:
您可以从平台的训练日志中获取到每一步的Loss,并绘制成Loss曲线。本场景的一个Loss曲线示例如下:
![](https://support.huaweicloud.com/bestpractice-pangulm/zh-cn_image_0000001726224856.png)
通过观察,Loss曲线随着迭代步数的增加呈下降趋势直至稳定,证明整个训练状态是正常的。
模型持续优化:
本场景采用了下表中的推理参数进行解码,您可以在平台部署后参考如下参数调试:
推理参数 |
设置值 |
---|---|
最大Token限制(max_token) |
1024 |
温度(temperature) |
0.3 |
核采样(top_p) |
0.8 |
话题重复度控制(presence_penalty) |
0 |
部署推理服务后,可以采用人工评测的方案来评估模型效果。如下提供了本场景可能存在的常见问题,若在评测过程中出现如下问题,可以参考解决:
- 问题一:JSON字段缺失、JSON字段或值错误。
解决方案:对于这几种情况,需要在微调数据中增大该缺失字段的数据比例,同时也可以在Prompt中加入对该字段的强调。
- 问题二:JSON格式错误、JSON内容发散。
解决方案:对于这种情况,可以尝试修改推理参数。例如降低“温度”参数的值,可以起到规范模型输出,使结果不再多样化。