Skip to content

Commit

Permalink
fix: Optimize field mapping for sequence chart
Browse files Browse the repository at this point in the history
  • Loading branch information
xsy-kucha committed Sep 23, 2024
1 parent d64e451 commit 710539e
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 62 deletions.
14 changes: 7 additions & 7 deletions packages/vmind/__tests__/browser/src/constants/mockData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export const mockUserInput6 = {
比利时,欧洲,53840,2018
挪威,欧洲,48930,2018
`,
input: '帮我展示各国GDP排名变化'
input: '使用动态条形图帮我展示各国GDP排名变化'
};

/*
Expand Down Expand Up @@ -4766,7 +4766,7 @@ export const bubbleCirclePackingData = {
房地产业,73821.3
其他,279918.4
`,
input: '请使用气泡图帮我绘制'
input: '请使用气泡圈图帮我绘制'
};

export const mapChartData = {
Expand Down Expand Up @@ -5076,7 +5076,7 @@ analytics,cluster,HierarchicalCluster,,6714
analytics,cluster,MergeEdge,,743
analytics,optimization,AspectRatioBanker,,7074
flex,FlareVis,,,4116`,
input: '请使用矩形树图渲染数据'
input: '请使用矩形树图渲染数据的层次结构'
};

export const gaugeChartData = {
Expand Down Expand Up @@ -5398,7 +5398,7 @@ export const singleColumnLineCombinationChartData = {
2022-09-01,0.259653267575217,2.040817156148029,2.19857288799284,2.229208371156883
2022-09-02,1.398428414171018,0.071469482611002,0.9048807067534731,0.0022491420541680004
2022-09-03,1.7166677805176591,1.903668070163285,1.866568462888393,1.8648831840830011`,
input: '请使用四个折线的组合图展示不同类别的权重随着时间的变化'
input: '请使用四个独立的折线的组合图展示不同类别的权重随着时间的变化'
};

export const singleColumnLineCombinationChartData1 = {
Expand Down Expand Up @@ -5594,7 +5594,7 @@ east,1027,654,654,830
west,1027,159,2100,532
north,1027,28,1679,498
`,
input: '帮我使用四个柱图的组合展示不同区域各商品销售额'
input: '帮我使用四个不同柱图的组合展示四个区域上不同商品销售额'
};

export const singleColumnBarCombinationChartData1 = {
Expand Down Expand Up @@ -5779,7 +5779,7 @@ export const singleColumnBarCombinationChartData1 = {
2022-09-01,0.259653267575217,2.040817156148029,2.19857288799284,2.229208371156883
2022-09-02,1.398428414171018,0.071469482611002,0.9048807067534731,0.0022491420541680004
2022-09-03,1.7166677805176591,1.903668070163285,1.866568462888393,1.8648831840830011`,
input: '请使用组合图展示不同类别的权重随着时间的变化,用四个柱图。'
input: '请使用四个独立柱图的组合图展示前十天不同类别的权重随着时间的变化。'
};

export const dynamicScatterPlotData = {
Expand Down Expand Up @@ -9849,7 +9849,7 @@ Alex Len,-2209016166000,start
Alex Len,-2209015962000,end
DeAndre' Bembry,-2209016547000,start
DeAndre' Bembry,-2209015783000,end`,
input: '帮我展示各运动员在比赛中的行动记录。'
input: '使用时序图帮我展示各运动员在比赛中的行动记录。'
};
export const mockUserTextInput0 = {
text: `快手消失了。快手上市后,市值一度超过2000亿美元,现在只剩200多亿美元。去年快手的营收破了千亿,公司也赚钱了,但市场不买账了。
Expand Down
17 changes: 11 additions & 6 deletions packages/vmind/src/applications/chartGeneration/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,14 @@ export const SUPPORTED_CHART_LIST = Object.values(ChartType);
export const COMBINATION_BASIC_CHART_LIST = Object.values(CombinationBasicChartType);
export const COMBINATION_CHART_LIST = Object.values(CombinationChartType);

export const NEED_COLOR_FIELD_CHART_LIST = [ChartType.PieChart, ChartType.RoseChart, ChartType.LinearProgress];
export const NEED_COLOR_FIELD_CHART_LIST = [
ChartType.PieChart,
ChartType.RoseChart,
ChartType.LinearProgress,
ChartType.CircularProgress
];

export const NEED_SIZE_FIELD_CHART_LIST = [ChartType.ScatterPlot, ChartType.BasicHeatMap, ChartType.LiquidChart];
export const NEED_SIZE_FIELD_CHART_LIST = [ChartType.ScatterPlot, ChartType.BasicHeatMap];

export const NEED_COLOR_AND_SIZE_CHART_LIST = [
ChartType.WordCloud,
Expand All @@ -16,8 +21,7 @@ export const NEED_COLOR_AND_SIZE_CHART_LIST = [
ChartType.VennChart,
ChartType.Gauge,
ChartType.SunburstChart,
ChartType.TreemapChart,
ChartType.CircularProgress
ChartType.TreemapChart
];

export const CARTESIAN_CHART_LIST = [
Expand All @@ -34,10 +38,11 @@ export const CARTESIAN_CHART_LIST = [
ChartType.BasicHeatMap
];

export const DYNAMIC_CHART_LIST = [
export const TIME_SERIES_CHART_LIST = [
ChartType.DynamicBarChart,
ChartType.DynamicScatterPlotChart,
ChartType.DynamicRoseChart
ChartType.DynamicRoseChart,
ChartType.SequenceChart
];

export const DEFAULT_MAP_OPTION: BasemapOption = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,18 @@ export const chartKnowledgeBase: ChartKnowledgeBase = {
},
[ChartType.SunburstChart]: {
knowledge: [
'Sunburst Charts are excellent for visualizing hierarchical data, allowing users to see relationships between categories and subcategories at varying levels of detail.',
'The colors field for sunburst chart and treemap chart must be an array. The order of the elements in the array needs to be sorted from large to small according to the coverage described by the data field.'
'Sunburst Charts are excellent for visualizing hierarchical data, allowing users to see relationships between categories and subcategories at varying levels of detail.'
]
},
[ChartType.TreemapChart]: {
knowledge: [
'Treemap Charts are effective for displaying large amounts of hierarchical data in a compact space, where areas represent the size of each category.',
'The colors field for sunburst chart and treemap chart must be an array. The order of the elements in the array needs to be sorted from large to small according to the coverage described by the data field.'
'Treemap Charts are effective for displaying large amounts of hierarchical data in a compact space, where areas represent the size of each category.'
]
},
[ChartType.Gauge]: {
knowledge: [
'Gauge Charts are useful for displaying performance metrics against a target, providing a quick visual summary at a glance.',
'The gauge chart must contain two fields: size and color.'
'Gauge Charts are useful for displaying performance metrics against a target.',
'If you want to display a dashboard, use a Gauge Chart.'
]
},
[ChartType.BasicHeatMap]: {
Expand All @@ -115,8 +113,7 @@ export const chartKnowledgeBase: ChartKnowledgeBase = {
},
[ChartType.VennChart]: {
knowledge: [
'Venn Charts are useful for displaying the relationships between different groups, emphasizing similarities and differences visually.',
'The color field of the Venn diagram requires an array of length 2. The field with subscript 0 maps to the sets, and the field with subscript 1 maps to the name.'
'Venn Charts are useful for displaying the relationships between different groups, emphasizing similarities and differences visually.'
]
},
[ChartType.SingleColumnCombinationChart]: {
Expand All @@ -134,8 +131,7 @@ export const chartKnowledgeBase: ChartKnowledgeBase = {
},
[ChartType.DynamicRoseChart]: {
knowledge: [
'Dynamic Rose Chart is used to display cyclical or seasonal data over time, with values represented by the length of radial bars.',
'Dynamic Rose Chart highlights changes in categorical data or periodic trends across multiple categories over time.'
'Dynamic Rose Chart is used to display cyclical or seasonal data over time, with values represented by the length of radial bars.'
],
constraints: [
'Use Dynamic Rose Chart if you want to show cyclical data and observe changes in multiple categories over time.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,17 +312,16 @@ export const ChartFieldInfo: ChannelInfo = {
size: 'field assigned to size channel'
},
knowledge: [
'The color field for treemap chart must be an array. The order of the elements in the array needs to be sorted from large to small according to the coverage described by the data field.'
'The color field must be an array sorted from large to small according to the coverage described by the data field.'
]
},
[ChartType.Gauge.toUpperCase()]: {
visualChannels: {
color:
'color channel of gauge chart. Used to represent the current value against a range. Must be a string field.',
color: 'color channel of gauge chart. Must be a string field.',
size: "size channel of gauge chart. Represents a numeric value indicating the current state. Can't be empty."
},
responseDescription: {
color: 'field assigned to color channel',
color: 'field assigned to color channel. Often used to distinguish themes.',
size: 'field assigned to size channel'
},
knowledge: [
Expand Down Expand Up @@ -409,19 +408,19 @@ export const ChartFieldInfo: ChannelInfo = {
},
[ChartType.SequenceChart.toUpperCase()]: {
visualChannels: {
x: "x channel of sequence chart. Represents the initiator of the timeline or event, showing which entity or individual is involved in each sequence. Can't be empty.",
y: "y channel of sequence chart. Represents the timeline or time series, displaying the chronological order of events. This is essential for showing when events occur. Often a numeric value. Can't be empty.",
group:
"group channel of sequence chart. Represents the initiator of the timeline or event, showing which entity or individual is involved in each sequence. Can't be empty.",
time: "time channel of sequence chart. Represents the timeline or time series, displaying the chronological order of events. This is essential for showing when events occur. Often a numeric value. Can't be empty.",
color:
'color channel of sequence chart. Differentiates the types or categories of events within the timeline. It is useful for distinguishing between different types of events in the sequence. For example: start or end'
},
responseDescription: {
x: 'field assigned to x channel, representing the initiator of the timeline or event',
y: 'field assigned to y channel, typically used for time progression',
group: 'field assigned to group channel, representing the initiator of the timeline or event',
time: 'field assigned to time channel, typically used for time progression',
color: 'field assigned to color channel, representing event types'
},
knowledge: [
'All visual channels must be aligned with the structure of the data being visualized.',
'Sequence charts are ideal for displaying event sequences over time, where the y-axis represents time progression, the x-axis shows the initiator of the timeline, and color helps distinguish between event types.',
'Sequence charts are ideal for displaying event sequences over time, where the time-axis represents time progression, the group-axis shows the initiator of the timeline, and color helps distinguish between event types.',
'This chart is useful for visualizing workflows, event timelines, or sequences where time, initiators, and event types need to be clearly represented.'
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Your task is:
1. Filter out useful fields related to user's command.
2. Assign the useful fields to the available visual channels according to field name and type.
3. If the chart type is a combination chart, the above two steps need to be repeated for each sub-chart generation task of the combination chart. The number of mapping relationships of visual channels in the response needs to be consistent with the number of sub-charts generated.
4. The response is an array in YAML format without any additional descriptions.
4. The outermost structure of the response must be an array in YAML format without any additional descriptions. The YAML array must be generated strictly according to the corresponding format at the end of the prompt, and special attention should be paid to the length of the array and the meaning of the elements in the array.
Available visual channels:
${availableChannels}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
NEED_COLOR_FIELD_CHART_LIST,
NEED_SIZE_FIELD_CHART_LIST,
NEED_COLOR_AND_SIZE_CHART_LIST,
DYNAMIC_CHART_LIST
TIME_SERIES_CHART_LIST
} from '../../../../constants';

const getColorKnowledge = (chartTypeList: ChartType[]) => {
Expand Down Expand Up @@ -93,7 +93,7 @@ export const visualChannelInfoMap = {
},
time: (chartTypeList: ChartType[]) => {
return {
singleFieldInfo: `This is usually a date field and cannot be empty in all dynamic chart types. For example, ${DYNAMIC_CHART_LIST.join(
singleFieldInfo: `This is usually a date field and cannot be empty in all dynamic chart types. For example, ${TIME_SERIES_CHART_LIST.join(
','
)}.`
};
Expand All @@ -115,6 +115,12 @@ export const visualChannelInfoMap = {
singleFieldInfo:
"the field mapped to the value channel. Only used in Sankey Chart. Can't be empty in Sankey Chart."
};
},
group: (chartTypeList: ChartType[]) => {
return {
singleFieldInfo:
"the field mapped to the group channel. Only used in Sequence Chart. Can't be empty in Sequence Chart."
};
}
};
export const chartKnowledgeDict: ChartKnowledge = {
Expand Down Expand Up @@ -194,7 +200,7 @@ export const chartKnowledgeDict: ChartKnowledge = {
},
[ChartType.LiquidChart]: {
index: 14,
visualChannels: ['x', 'y'],
visualChannels: ['value'],
examples: [],
knowledge: [
'Liquid chart is used to display a single value, with the value range typically from 0 to 1. The value usually represents progress, completion, or percentage, and is associated with only one field'
Expand All @@ -210,7 +216,7 @@ export const chartKnowledgeDict: ChartKnowledge = {
},
[ChartType.CircularProgress]: {
index: 16,
visualChannels: ['x', 'y'],
visualChannels: ['color', 'value'],
examples: [],
knowledge: [
'Circular progress chart is also used to display progress data, presented in a circular form, with the values on the numerical axis typically ranging from 0 to 1.'
Expand Down Expand Up @@ -279,7 +285,7 @@ export const chartKnowledgeDict: ChartKnowledge = {
visualChannels: ['x', 'y', 'color', 'size', 'time'],
examples: [],
knowledge: [
'The five channels that need to be mapped in the dynamic scatter plot are: x, y, color, size, and time; the x, y, and size channels require numeric data fields; the time field must be mapped.'
'The five channels that need to be mapped in the dynamic scatter plot are: x, y, color, size, and time; the x, y, and size channels require numeric data fields; the color channel is needed to distinguish different categories of scatter points; the time field must be mapped.'
]
},
[ChartType.DynamicRoseChart]: {
Expand All @@ -290,9 +296,12 @@ export const chartKnowledgeDict: ChartKnowledge = {
},
[ChartType.SequenceChart]: {
index: 30,
visualChannels: ['x', 'y', 'color'],
visualChannels: ['group', 'time', 'color'],
examples: [],
knowledge: ['The three channels that need to be mapped in the sequence chart are: x, y, and color;']
knowledge: [
'The three channels that need to be mapped in the sequence chart are: group, time, and color;',
'The sequence chart is used to display information such as time nodes with a sequence.'
]
}
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1304,7 +1304,7 @@ export const liquidField: Transformer<Context, GetChartSpecOutput> = (context: C
const { cells, dataset, spec } = context;
const cell = getCell(cells);

spec.valueField = cell.value;
spec.valueField = (cell.value ?? cell.y ?? cell.size) as string;
spec.indicatorSmartInvert = true;

return { spec };
Expand Down Expand Up @@ -1387,7 +1387,7 @@ export const circularProgressField: Transformer<Context, GetChartSpecOutput> = (
const cell = getCell(cells);

spec.categoryField = cell.color;
spec.valueField = cell.value;
spec.valueField = (cell.value ?? cell.size) as string;
spec.seriesField = cell.color;

spec.radius = 0.8;
Expand All @@ -1414,7 +1414,7 @@ export const indicator: Transformer<Context, GetChartSpecOutput> = (context: Con
if (!firstEntry) {
return { spec };
}
const valueField = (cell.value ?? cell.y) as string;
const valueField = (cell.value ?? cell.y ?? cell.size) as string;
const value = firstEntry[valueField];
const cat = firstEntry[cell.radius ?? cell.x];

Expand Down Expand Up @@ -2308,29 +2308,34 @@ export const dynamicRoseDisplayConf: Transformer<Context, GetChartSpecOutput> =
export const sequenceChartData: Transformer<Context, GetChartSpecOutput> = (context: Context) => {
const { cells, dataset, spec } = context;
const cell = getCell(cells);
const yField = cell.y as string;
const xField = cell.x;
const timeField = cell.time as string;
const groupField = cell.group;
const colorField = cell.color as string;
const dataMap: { [key: string]: DataItem[] } = {};
dataset.forEach(data => {
dataMap[data[xField]] ? dataMap[data[xField]].push(data) : (dataMap[data[xField]] = [data]);
dataMap[data[groupField]]
? dataMap[data[groupField]].push({ ...data })
: (dataMap[data[groupField]] = [{ ...data }]);
});
const dataDot: { [key: string]: DataItem[] | string }[] = [];
const dataLink: { [key: string]: string }[] = [];
const dataLink: { [key: string]: string | number }[] = [];
Object.keys(dataMap).forEach(key => {
const dotList = sortArray(dataMap[key], [{ field: timeField, order: SortOrder.ASC }]).map((data, index, array) => {
const newData = { ...data };
newData.node_name = `${data[groupField]}_${Math.floor(index / 2).toString()}_${data[colorField]}_node`;
return newData;
});
dataDot.push({
[cell.x]: key,
dots: dataMap[key]
[cell.group]: key,
dots: dotList
});
sortArray(dataMap[key], [{ field: yField, order: SortOrder.ASC }]).forEach((data, index, array) => {
dotList.forEach((dot, index, array) => {
if (index % 2 !== 0) {
dataLink.push({
from: `${data[xField]}_${Math.floor(index / 2).toString()}_${array[index - 1][colorField]}_node`,
to: `${data[xField]}_${Math.floor(index / 2).toString()}_${data[colorField]}_node`
from: array[index - 1].node_name,
to: dot.node_name
});
}
data.node_name = `${data[xField]}_${Math.floor(index / 2).toString()}_${data[colorField]}_node`;
return data;
});
});
spec.data = [
Expand Down Expand Up @@ -2360,10 +2365,10 @@ export const sequenceChartSeries: Transformer<Context, GetChartSpecOutput> = (co
{
type: 'dot',
dataId: 'dataDotSeries',
xField: cell.y as string,
yField: cell.x,
xField: cell.time as string,
yField: cell.group,
dotTypeField: cell.color as string,
titleField: cell.x,
titleField: cell.group,
highLightSeriesGroup: '',
height: 500,
clipHeight: 800,
Expand Down Expand Up @@ -2398,12 +2403,12 @@ export const sequenceChartSeries: Transformer<Context, GetChartSpecOutput> = (co
{
hasShape: true,
shapeType: 'square',
key: (datum: any) => datum[cell.x]
key: (datum: any) => datum[cell.group]
},
{
hasShape: false,
key: 'event_time_stamp',
value: (datum: any) => datum[cell.color as string]
value: (datum: any) => datum[cell.group as string]
}
]
}
Expand All @@ -2422,10 +2427,10 @@ export const sequenceChartAxes: Transformer<Context, GetChartSpecOutput> = (cont
type: 'time',
range: {
min: fieldInfo.filter(fieldInfo => {
return fieldInfo.fieldName === cell.y;
return fieldInfo.fieldName === cell.time;
})[0].domain[0],
max: fieldInfo.filter(fieldInfo => {
return fieldInfo.fieldName === cell.y;
return fieldInfo.fieldName === cell.time;
})[0].domain[1]
},
layers: [
Expand Down
1 change: 1 addition & 0 deletions packages/vmind/src/applications/chartGeneration/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ export type Cell = {
target?: string;
value?: string;
category?: string;
group?: string;
};

0 comments on commit 710539e

Please sign in to comment.