跳到主要内容

AI 可视化推荐模型算法服务

TODO

AIGC 可视化算法负责人:@韩东明(handongming2@myhexin.com)博士

AI 可视化推荐模型算法服务提供了图表推荐、自然语言微调、数据洞察等能力。

图表推荐

需要理解的是,AI 可视化推荐模型算法服务推荐的结果是组件用例,它与组件(Layer)的实现不一定是一对一的关系

组件与用例?

组件(Layer)是底层能力,代表支持此类图表的渲染实现;而用例则指的是使用该组件(Layer)通过不同参数配置组合实现的可视化效果案例

例如,对于通用的常规折线图类型组件,其用例可以为单折线、多折线、堆叠折线等等。

所以,在训练 AI 可视化推荐模型时,提供的训练集包含的是一个个组件用例的参数配置定义,而不是该类型组件的配置参数定义。因此,对于同样需要 X 与 Y 两个维度数据字段的简单柱状图和折线图的这种情况,我们可以通过人工打标的方式,让 AI 模型更倾向于推荐柱状图或者折线图。

如何构建训练集

每一个组件在开发时均需要定义可视化相关的元信息:

// src/core/layer.ts
interface VisInfo {
/** 组件唯一 id */
id: string;
/** 组件名称,英文 */
name_en: string;
/** 组件名称,中文 */
name_zh: string;
/** 分类标签(AI 模型训练依赖) */
types_en: string[];
/** 可视化目标,英文(AI 模型训练依赖) */
purpose_en: string[];
/** 可视化目标,中文(AI 模型训练依赖) */
purpose_zh: string[];
/**
* (AI 模型训练依赖)
* @example ['echarts','aime','f10'] */
standers: string;
/** (AI 模型训练依赖) */
rules?: unknown;
/** 数据特征参数(AI 模型训练依赖) */
parameters: {
[key: string]: {
/** 枚举该字段值可接受的数据类型 */
itemType: (typeof DEFINE)[keyof typeof DEFINE][];
/** 该字段的集合类型 */
category: (typeof DEFINE)[keyof typeof DEFINE];
/** 优先类型 */
priority?: (typeof DEFINE)[keyof typeof DEFINE];
/** 可选字段 */
optional?: boolean;
};
};
/** 额外辅助信息 */
extra?: {
/** 是否不被用来训练 LLM */
isNotTrainedByLLM: boolean;
};
}

以柱状图为例:

// src/layer/preset/bar.ts
const visInfo: Layer['visInfo'] = {
id: 'bar',
name_en: 'Bar',
name_zh: '柱状图',
types_en: [],
purpose_en: [],
purpose_zh: [],
standers: '',
rules: {
x: amount => amount > 1,
y: amount => amount > 1,
z: amount => amount > 1,
data: amount => amount > 1
},
/** 保证和 Spec.encoding 字段一致 */
parameters: {
x: {
itemType: [DEFINE.STR, DEFINE.DATE],
category: DEFINE.SINGLE,
priority: DEFINE.DATE
},
y: {
itemType: [DEFINE.NUMBER],
category: DEFINE.ARRAY
},
z: {
itemType: [DEFINE.DATE, DEFINE.STR],
category: DEFINE.SINGLE,
priority: DEFINE.STR,
optional: true
}
}
};

const layer = defineStandardChartLayer<Spec>({
type: visInfo.id,
isIndependentLayer: false,
visInfo,
render(api, spec, $dom) {}
});

以上定义意味着我们可以仅提供一个标准的表格数据集和数据编码参数(x/y/z)即可渲染出一个柱状图的可视化效果,具体可参考数据规范一节内容。

但这里需要注意的是,z 被定义为可选参数(optional: true),这就意味着 bar 类型的柱状图组件至少会有两个用例,即一个是仅提供 xy 参数的单柱图,另一个则是提供所有 3 个参数的分组柱状图。

组件用例
  • bar 类型的柱状图组件用例仅有两种吗?

因为以上仅举例了数据编码参数的差异,实际上组件还有样式参数配置,例如在分组柱状图的基础上我们再加一个 dvStacked 参数则形成了一个新的用例,即堆叠柱状图。

组件支持的参数越多,形成的组合就越多,那么对应的用例就越多,通常我们仅根据业务需求构建常用的组件用例即可。

接下来,为了让 AI 可视化推荐模型学习到单柱图和分组柱状图的知识,我们需要提供两个相应的组件用例作为训练语料。

// 单柱图
{
name: "bar",
// ... 引用 bar 组件的 visInfo 定义
parameters: {
x: {
itemType: [DEFINE.STR, DEFINE.DATE],
category: DEFINE.SINGLE,
priority: DEFINE.DATE
},
y: {
itemType: [DEFINE.NUMBER],
category: DEFINE.ARRAY
}
}
}

// 分组柱状图
{
name: "groupedBar",
// ... 引用 bar 组件的 visInfo 定义
parameters: {
x: {
itemType: [DEFINE.STR, DEFINE.DATE],
category: DEFINE.SINGLE,
priority: DEFINE.DATE
},
y: {
itemType: [DEFINE.NUMBER],
category: DEFINE.ARRAY
},
z: {
itemType: [DEFINE.DATE, DEFINE.STR],
category: DEFINE.SINGLE,
priority: DEFINE.STR,
}
}
}

分析以上定义,我们首先可以看到每个组件用例必须要有一个唯一的 name 字段(代表业务抽象,值可以由业务侧自定义),其次需要引用 bar 组件的可视化元信息定义,不过我们需要对 parameters 字段进行调整,仅定义该用例需要的参数即可。

注意

训练集的数据结构是和算法组同事 @韩东明 约定好的,所以这里的 name 字段命名也可以更改为 type 或者 case 等,只需要双方约定好即可。

另外,在旧版本的前端组件库渲染时需要指定 type 参数字段,该字段实际上对应的是这里组件用例定义的 name 字段,而不是组件(Layer)内部实现定义的 type 字段,具体可参考了解 AI 可视化推荐模型算法服务数据协议一节的内容。

组件用例
  • 训练集是由谁来构建?

理论上来说,训练集和组件标注均是与业务相关的,不同的业务由于差异化需求要实现定制化,应该由业务开发人员来构建训练集。

另一方面,我们可以预见的是,不同的业务对于可视化组件用例的需求应该是有大部分重叠的,例如对于单折线、多折线、单柱图、分组柱状图等等比较常见的用例,每一个业务几乎都会用到,这也意味着不同业务的训练集中存在交集且占比很高,而这部分交集则可以由组件库来构建并维护,减少各个业务的重复工作量,同时用统一的 name 定义也更容易在对接多个业务时进行调试。

各个业务的开发仅需要负责构建自己业务定制需求的训练集数据即可。

当 AI 可视化推荐模型学习到训练集的知识后,就可以针对用户的问句和数据集推荐出可视化结果,这里给出推荐单柱图的结果案例:

const dataset = [
{ date: '2022-12-01', value: 10 },
{ date: '2023-12-01', value: 5 },
{ date: '2024-12-01', value: 18 },
];

// AI 可视化推荐模型的响应结果
{
name: "bar",
parameters: {
x: "date",
y: "value"
}
}

根据上述结果来看,AI 可视化推荐模型在学习到单柱图的知识后,根据参数的定义和对数据集特征分析,成功输出了可以渲染单柱图组件的 xy 参数值。

此时,业务前端可以将 AI 模型的输出结果经过业务侧处理后传递给组件库即可渲染出可视化效果。

图表推荐到底推荐的是什么?

如果类比 Github Copilot 这样的产品,我们可以认为 AI 模型以编程语言、库、框架的 APIs 文档再附加各种应用案例代码片段为训练语料,最终实现了给定一个目标任务其可以根据学习到的基础知识输出结果的能力。例如,我们让其用 JavaScript 实现一个快速排序算法,询问多次可能得到功能等效但实现略微有所差异的代码,正是这种差异的不确定性为业务落地带来了挑战。

这种模式更像是开发者通过学习基础知识,然后给出自己的实现方案来完成任务,不同的开发者解决同一个问题思路总会有差异,其中更关键的是开发者可以自己或者通过测试流程进行验证,而 AI 模型目前无法验证自己推理的结果。

在可视化代码生成的场景中,我们也可以用相同的思路让 AI 可视化推荐模型学习组件库的 APIs 文档和应用案例知识,我们抛出一个问题后 AI 模型给出推荐的图表类型及其代码片段。同样的,如果我们多次询问同一个问题,可能会得到有差异的结果(比如同一种图表类型但不同的实现代码),还可能因为生成结果的不准确导致前端渲染失败,不确定性和容错处理在业务落地过程中是个极大的挑战。

我们现在所采用的方案则是让 AI 可视化推荐模型学习具体的组件用例而不是底层的 APIs 文档知识,这也意味着 AI 模型实际上是在我们提供的可枚举的组件用例集合中进行分类匹配,并结合组件用例的参数定义和数据集特征生成最终的代码片段。这种模式使得 AI 模型缺乏“创造力”,但输出更具备确定性和稳定性,可满足现阶段产品/设计的预期。

自然语言微调

通常,我们会给组件库配置一套默认的业务主题风格,但考虑到在具体的业务场景中实现更加智能、丰富的交互设计,提供了支持基于自然语言对话的可视化效果微调能力。

AI 可视化推荐模型通过学习组件库的 APIs 文档和微调指令案例知识,可以根据用户针对可视化效果的微调问句生成对应的配置参数,实现对可视化效果的更新。

给出 AI 模型输出的微调结果案例:

{
name: "bar",
parameters: {
x: "date",
y: "value"
},
style: {
series: {
itemStyle: {
color: 'red'
}
}
}
}

上述结果会将当前单柱图的柱子颜色更新为红色。

注意

AIGC 可视化组件库底层依赖了多个库,例如范式组件库、行情图组件库等,目前仅针对基于范式组件库开发的组件实现微调支持。

信息

在前端组件库中,业务开发手动编码的组件配置参数和 AI 模型输出的微调指令配置参数结构是一致的,这降低了业务侧的复杂性,同时为业务侧实现可视化效果的持久化保存提供了支持。

数据洞察

常规的可视化效果仅能向用户传递数据集的基础信息,通过提供数据洞察能力,可以挖掘数据集的潜在信息,并结合统计学知识对数据集的多个维度进行分析总结,帮助用户更好的理解数据集并做出决策。

AI 可视化推荐模型需要基于推荐的图表结果(上下文)输出洞察结果,这是因为数据洞察的内容与当前可视化效果密切相关。例如,当一个数据集中有多个维度的字段时,当前可视化效果仅引用了其中两个字段,那么数据洞察也应该以这两个字段为分析的依据。

注意

由于数据洞察的业务复杂性,我们对其进行分类,并逐步实现及适配不同类型的组件。

信息

在前端组件库中,数据洞察被设计为一个全局组件,类似 dataZoomtooltip 等,保证了参数结构的统一性,不额外引入多余的概念来增加业务开发的学习门槛。