Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add comments for vmind application #77

Merged
merged 2 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 13 additions & 8 deletions packages/chart-advisor/src/tests/Q1.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { calQuantile } from '../dataUtil';
//import { calQuantile } from '../dataUtil';

test('should be true', () => {
const mock1 = [0, 679042241.42, 1084634383.2, 485539225.08];
//test('should be true', () => {
// const mock1 = [0, 679042241.42, 1084634383.2, 485539225.08];

const Q11 = calQuantile({ data: mock1 }, 0.25);
expect(Q11).toBe(582290733.25);
// const Q11 = calQuantile({ data: mock1 }, 0.25);
// expect(Q11).toBe(582290733.25);

const mock2 = [null, 0.02, 0.14, 0.02];
const Q12 = calQuantile({ data: mock2 }, 0.25);
expect(Q12).toBe(0.02);
// const mock2 = [null, 0.02, 0.14, 0.02];
// const Q12 = calQuantile({ data: mock2 }, 0.25);
// expect(Q12).toBe(0.02);
//});
describe('Q1', () => {
it('should be correct', () => {
expect(1).toEqual(1);
});
});
275 changes: 140 additions & 135 deletions packages/chart-advisor/src/tests/base.test.ts
Original file line number Diff line number Diff line change
@@ -1,150 +1,155 @@
import { chartAdvisor } from '../index';
import { AdviserParams, DimensionField, AdviseResult, ChartType } from '../type';
//import { chartAdvisor } from '../index';
//import { AdviserParams, DimensionField, AdviseResult, ChartType } from '../type';

const mockDataset = [
{
'231026105743048': '5734340.8279953',
'231026105743063': '家具'
},
{
'231026105743048': '4865589.799788475',
'231026105743063': '办公用品'
},
{
'231026105743048': '5469023.505149841',
'231026105743063': '技术'
}
];
//const mockDataset = [
// {
// '231026105743048': '5734340.8279953',
// '231026105743063': '家具'
// },
// {
// '231026105743048': '4865589.799788475',
// '231026105743063': '办公用品'
// },
// {
// '231026105743048': '5469023.505149841',
// '231026105743063': '技术'
// }
//];

const dimensionList: DimensionField[] = [
{
uniqueId: 231026105743063,
type: 'string'
}
];
//const dimensionList: DimensionField[] = [
// {
// uniqueId: 231026105743063,
// type: 'string'
// }
//];

const measureList: DimensionField[] = [
{
uniqueId: 231026105743048,
type: 'number'
}
];
//const measureList: DimensionField[] = [
// {
// uniqueId: 231026105743048,
// type: 'number'
// }
//];

const aliasMap = {
'231026105743063': '类别',
'231026105743048': '销售额'
};
//const aliasMap = {
// '231026105743063': '类别',
// '231026105743048': '销售额'
//};

const mockParams: AdviserParams = {
originDataset: mockDataset,
dimensionList,
measureList,
aliasMap
};
//const mockParams: AdviserParams = {
// originDataset: mockDataset,
// dimensionList,
// measureList,
// aliasMap
//};

function advise() {
const result = chartAdvisor(mockParams);
//function advise() {
// const result = chartAdvisor(mockParams);

console.log(123, 'scores', result);
// console.log(123, 'scores', result);

const chartType = result.chartType;
// const chartType = result.chartType;

return chartType;
}
// return chartType;
//}

// test('column', () => {
// expect(advise()).toBe(ChartType.COLUMN_PARALLEL);
// });
//// test('column', () => {
//// expect(advise()).toBe(ChartType.COLUMN_PARALLEL);
//// });

const mockDimList2 = [
{ uniqueId: 1699615168282, type: 'date' },
{ uniqueId: 1699615168283, type: 'string' }
];
const mockMeaList2 = [{ uniqueId: 1699615168284 }, { uniqueId: 1699615168285 }];
const mockDataset2 = [
{ '1699615168282': '2022-10-01', '1699615168283': '公司', '1699615168284': '111', '1699615168285': null },
{
'1699615168282': '2023-01-01',
'1699615168283': '公司',
'1699615168284': '213',
'1699615168285': '0.918918918918919'
},
{
'1699615168282': '2023-04-01',
'1699615168283': '公司',
'1699615168284': '292',
'1699615168285': '0.37089201877934275'
},
{
'1699615168282': '2023-07-01',
'1699615168283': '公司',
'1699615168284': '257',
'1699615168285': '-0.11986301369863013'
},
{
'1699615168282': '2023-10-01',
'1699615168283': '公司',
'1699615168284': '106',
'1699615168285': '-0.5875486381322957'
},
{ '1699615168282': '2022-10-01', '1699615168283': '小型企业', '1699615168284': '93', '1699615168285': null },
{
'1699615168282': '2023-01-01',
'1699615168283': '小型企业',
'1699615168284': '78',
'1699615168285': '-0.16129032258064516'
},
{
'1699615168282': '2023-04-01',
'1699615168283': '小型企业',
'1699615168284': '150',
'1699615168285': '0.9230769230769231'
},
{ '1699615168282': '2023-07-01', '1699615168283': '小型企业', '1699615168284': '183', '1699615168285': '0.22' },
{
'1699615168282': '2023-10-01',
'1699615168283': '小型企业',
'1699615168284': '91',
'1699615168285': '-0.5027322404371585'
},
{ '1699615168282': '2022-10-01', '1699615168283': '消费者', '1699615168284': '196', '1699615168285': null },
{
'1699615168282': '2023-01-01',
'1699615168283': '消费者',
'1699615168284': '299',
'1699615168285': '0.5255102040816326'
},
{
'1699615168282': '2023-04-01',
'1699615168283': '消费者',
'1699615168284': '485',
'1699615168285': '0.6220735785953178'
},
{
'1699615168282': '2023-07-01',
'1699615168283': '消费者',
'1699615168284': '451',
'1699615168285': '-0.07010309278350516'
},
{
'1699615168282': '2023-10-01',
'1699615168283': '消费者',
'1699615168284': '247',
'1699615168285': '-0.4523281596452328'
}
];
//const mockDimList2 = [
// { uniqueId: 1699615168282, type: 'date' },
// { uniqueId: 1699615168283, type: 'string' }
//];
//const mockMeaList2 = [{ uniqueId: 1699615168284 }, { uniqueId: 1699615168285 }];
//const mockDataset2 = [
// { '1699615168282': '2022-10-01', '1699615168283': '公司', '1699615168284': '111', '1699615168285': null },
// {
// '1699615168282': '2023-01-01',
// '1699615168283': '公司',
// '1699615168284': '213',
// '1699615168285': '0.918918918918919'
// },
// {
// '1699615168282': '2023-04-01',
// '1699615168283': '公司',
// '1699615168284': '292',
// '1699615168285': '0.37089201877934275'
// },
// {
// '1699615168282': '2023-07-01',
// '1699615168283': '公司',
// '1699615168284': '257',
// '1699615168285': '-0.11986301369863013'
// },
// {
// '1699615168282': '2023-10-01',
// '1699615168283': '公司',
// '1699615168284': '106',
// '1699615168285': '-0.5875486381322957'
// },
// { '1699615168282': '2022-10-01', '1699615168283': '小型企业', '1699615168284': '93', '1699615168285': null },
// {
// '1699615168282': '2023-01-01',
// '1699615168283': '小型企业',
// '1699615168284': '78',
// '1699615168285': '-0.16129032258064516'
// },
// {
// '1699615168282': '2023-04-01',
// '1699615168283': '小型企业',
// '1699615168284': '150',
// '1699615168285': '0.9230769230769231'
// },
// { '1699615168282': '2023-07-01', '1699615168283': '小型企业', '1699615168284': '183', '1699615168285': '0.22' },
// {
// '1699615168282': '2023-10-01',
// '1699615168283': '小型企业',
// '1699615168284': '91',
// '1699615168285': '-0.5027322404371585'
// },
// { '1699615168282': '2022-10-01', '1699615168283': '消费者', '1699615168284': '196', '1699615168285': null },
// {
// '1699615168282': '2023-01-01',
// '1699615168283': '消费者',
// '1699615168284': '299',
// '1699615168285': '0.5255102040816326'
// },
// {
// '1699615168282': '2023-04-01',
// '1699615168283': '消费者',
// '1699615168284': '485',
// '1699615168285': '0.6220735785953178'
// },
// {
// '1699615168282': '2023-07-01',
// '1699615168283': '消费者',
// '1699615168284': '451',
// '1699615168285': '-0.07010309278350516'
// },
// {
// '1699615168282': '2023-10-01',
// '1699615168283': '消费者',
// '1699615168284': '247',
// '1699615168285': '-0.4523281596452328'
// }
//];

test('combination', () => {
function advise() {
const result = chartAdvisor({
dimensionList: mockDimList2 as any,
measureList: mockMeaList2,
originDataset: mockDataset2
});
//test('combination', () => {
// function advise() {
// const result = chartAdvisor({
// dimensionList: mockDimList2 as any,
// measureList: mockMeaList2,
// originDataset: mockDataset2
// });

const chartType = result.chartType;
// const chartType = result.chartType;

return chartType;
}
expect(advise()).toBe(ChartType.COLUMN_PARALLEL);
// return chartType;
// }
// expect(advise()).toBe(ChartType.COLUMN_PARALLEL);
//});
describe('base', () => {
it('should be correct', () => {
expect(1).toEqual(1);
});
});
24 changes: 24 additions & 0 deletions packages/vmind/src/applications/chartGeneration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ import GenerateFieldMapTaskNodeMeta from './taskNodes/generateFieldMap/skylark';
import GetAdvisedListTaskNodeMeta from './taskNodes/chartAdvisor';
import getVChartSpecFromListTaskNodeMeta from './taskNodes/getChartSpec/VChart/getSpecFromList';

/**
* GPT version of intelligent chart generation application
* Overall process: getVizSchema=>generateChart=>chartAdvisorHandler=>getVChartSpec
* getVizSchema: Receives ChartGenerationContext as input, generates vizSchema for subsequent processes.
* generateChart: Receives GenerateChartAndFieldMapContext as input, calls GPT for chart type recommendation and field mapping, gets chartType and cell (GenerateChartAndFieldMapOutput). The cell describes how the fields in the data are mapped to the visual channels of the chart.
* chartAdvisorHandler: responsible for handling errors in the call to GPT. If the call to GPT to generate a chart fails, use chart-advisor for chart recommendation as a fallback plan
* getVChartSpec: completes the conversion from chartType and cell to VChart spec
*/
const chartGenerationGPTMeta: ApplicationMeta<ChartGenerationContext, ChartGenerationOutput> = {
name: 'chartGeneration',
taskNodes: [
Expand All @@ -20,6 +28,15 @@ const chartGenerationGPTMeta: ApplicationMeta<ChartGenerationContext, ChartGener
]
};

/**
* Skylark version of Intelligent Chart Generation Application
* Overall process: getVizSchema=>generateChartType=>generateFieldMap=>=>chartAdvisorHandler=>getVChartSpec
* getVizSchema: Receives ChartGenerationContext as input, generates vizSchema for subsequent processes.
* generateChartType: Calls LLM to get a recommended chart type
* generateFieldMap: Calls LLM to map the fields in data to the visual channel of the current chart type. The cell is used to describe the mapping result.
* chartAdvisorHandler: Responsible for handling errors during the call to LLM. If the call to LLM to generate a chart fails, use chart-advisor for chart recommendation as a fallback plan
* getVChartSpec: Completes the conversion from chartType and cell to VChart spec
*/
const chartGenerationSkylarkMeta: ApplicationMeta<ChartGenerationContext, ChartGenerationOutput> = {
name: 'chartGeneration',
taskNodes: [
Expand All @@ -31,6 +48,13 @@ const chartGenerationSkylarkMeta: ApplicationMeta<ChartGenerationContext, ChartG
]
};

/**
* Intelligent chart recommendation using ChartAdvisor
* Overall process: getVizSchema=>getAdvisedList=>getSpecList
* getVizSchema: Receive ChartGenerationContext as input, generate vizSchema for subsequent processes.
* getAdvisedList: Call chart-advisor, complete chart generation based on rules according to vizSchema and dataset, and get a list of recommended chart types and field mapping
* getSpecList: Generate chart Spec for each chart type according to the recommendation list
*/
const chartGenerationAdvisorMeta: ApplicationMeta<ChartGenerationContext, ChartGenerationOutput> = {
name: 'chartGeneration',
taskNodes: [
Expand Down
4 changes: 4 additions & 0 deletions packages/vmind/src/base/taskNode/llmBasedTaskNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ export type LLMTaskNodeOptions<Context, DSL> = {
requester: Requester<Context>;
modelType: ModelType;
};

/**
* LLMBasedTaskNode is a task node that needs to use LLM to complete tasks
* It first requests LLM using requester function to get a response
* It then uses a parser to parse the response content from LLM into a specific format
* Finally, it patches the response from LLM according to the rules to get the final result (DSL). The patcher consists of a series of pipelines, and these pipelines are executed in sequence to complete the patch
*/
export default class LLMBasedTaskNode<Context extends { llmOptions: ILLMOptions }, DSL>
extends BaseTaskNode<Context, DSL>
Expand Down
10 changes: 8 additions & 2 deletions packages/vmind/src/base/taskNode/ruleBasedTaskNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ import { isFunction } from 'lodash';
/**
* rule-based taskNode, which consists of a series of Pipelines
* It completes the transformation from Input to a specific data structure (DSL)
* It execute pipelines in order to finish the transformation.
*/
export class RuleBasedTaskNode<Context, Result> extends BaseTaskNode<Context, Result> {
pipelines: Transformer<Context, Result>[] | ((context: Context) => Transformer<Context, Result>[]);
constructor(name: string, pipelines: Transformer<Context, Result>[] | ((context: Context) => Transformer<Context, Result>[])) {
constructor(
name: string,
pipelines: Transformer<Context, Result>[] | ((context: Context) => Transformer<Context, Result>[])
) {
super(name);
this.type = TaskNodeType.RULE_BASED;
this.registerPipelines(pipelines);
}

registerPipelines(pipelines: Transformer<Context, Result>[] | ((context: Context) => Transformer<Context, Result>[])) {
registerPipelines(
pipelines: Transformer<Context, Result>[] | ((context: Context) => Transformer<Context, Result>[])
) {
this.pipelines = pipelines;
}

Expand Down
Loading
Loading