更新时间:2024-08-29 GMT+08:00
分享

基于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中的参数对应上。

训练模型

自监督训练:

不涉及

有监督微调:

场景采用了下表中的微调参数进行微调,您可以在平台中参考如下参数进行训练:

表1 微调核心参数设置

训练参数

设置值

数据批量大小(batch_size)

8

训练轮数(epoch)

6

学习率(learning_rate)

7.5e-05

学习率衰减比率(learning_rate_decay_ratio)

0.067

热身比例(warmup)

0.013

评估和优化模型

模型评估:

您可以从平台的训练日志中获取到每一步的Loss,并绘制成Loss曲线。本场景的一个Loss曲线示例如下:

图1 Loss曲线

通过观察Loss曲线随着迭代步数的增加呈下降趋势直至稳定,证明整个训练状态是正常的。

模型持续优化:

本场景采用了下表中的推理参数进行解码,您可以在平台部署后参考如下参数调试:

表2 推理核心参数设置

推理参数

设置值

最大Token限制(max_token)

1024

温度(temperature)

0.3

核采样(top_p)

0.8

话题重复度控制(presence_penalty)

0

部署推理服务后,可以采用人工评测的方案来评估模型效果。如下提供了本场景可能存在的常见问题,若在评测过程中出现如下问题,可以参考解决:

  • 问题一:JSON字段缺失、JSON字段或值错误。

    解决方案:对于这几种情况,需要在微调数据中增大该缺失字段的数据比例,同时也可以在Prompt中加入对该字段的强调。

  • 问题二:JSON格式错误、JSON内容发散。

    解决方案:对于这种情况,可以尝试修改推理参数。例如降低“温度”参数的值,可以起到规范模型输出,使结果不再多样化。

相关文档