Skip to content

Commit

Permalink
Merge pull request #171 from VisActor/feat/vchart_editor_merge_spec
Browse files Browse the repository at this point in the history
feat: merge spec of vchart
  • Loading branch information
666haiwen authored Dec 10, 2024
2 parents 891998b + 6ab0a0a commit 4401658
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
IconUser
} from '@arco-design/web-react/icon';
import VChart from '@visactor/vchart';
import { isArray } from '@visactor/vutils';
import { isArray, isEmpty, merge } from '@visactor/vutils';
import { VChartSpec } from '../../../../../src';

const globalVariables = (import.meta as any).env;
Expand Down Expand Up @@ -59,6 +59,7 @@ const baseSpec = {
};
const vchartSpecAtom = new VChartSpec({ spec: baseSpec }, {});
export function QARag() {
const vchartInstance = React.useRef<any>(null);
const [query, setQuery] = React.useState('');
const [topK, setTopK] = React.useState(5);
const [llmTopKey, setLLmTopKey] = React.useState('');
Expand Down Expand Up @@ -116,9 +117,18 @@ export function QARag() {
});
console.log('res: ', res.data);
const { keyPathRes = [], qaRes = [], topKeys = [], dslRes, parentKeyPath, aliasKeyPath, error } = res.data;
// @todo @xile611 spec update
// vchartSpecAtom.updateContext({});
// const { spec: newSpec } = await vchartSpecAtom.run();

vchartSpecAtom.updateContext({
spec: spec,
appendSpec: {
leafSpec: dslRes,
parentKeyPath,
aliasKeyPath
}
});
const { spec: newSpec } = await vchartSpecAtom.run();
console.log('newSpec', newSpec);
setSpec(newSpec);
setLoading(false);
if (error) {
setDialog([
Expand Down Expand Up @@ -183,14 +193,20 @@ export function QARag() {
}, [dialog]);

React.useEffect(() => {
if (spec) {
if (spec && !vchartInstance.current) {
(document.getElementById('chart') as HTMLElement).innerHTML = '';
console.log('new vchart', spec);

const chart = new VChart(spec, {
dom: document.getElementById('chart') as HTMLElement
});
chart.renderAsync();

vchartInstance.current = chart;
} else if (spec && vchartInstance.current) {
vchartInstance.current.updateSpecSync(spec);
}
}, [spec]);
}, [spec, vchartInstance]);

return (
<div className="rag-container">
Expand Down
9 changes: 6 additions & 3 deletions packages/vmind/__tests__/experiment/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// import { result as capcutResult } from './results/dataExtraction/result7';
// import { result as capcutResult, caseResult, capcutV2Result } from './results/dataExtraction/version1';
import { capcutResult, capcutV2Result } from './results/dataExtraction/dataResult';
// import { capcutResult, capcutV2Result } from './results/dataExtraction/dataResult';
// import { result as caseResult } from './results/dataExtraction/commonResult';
// import { result as doubaoResult } from './results/dataExtraction/doubao1';
import { commonAnswer } from './data/dataExtractionData';
import { mergeResult, updateScoreInDataExtraction } from './pages/DataExtraction/verify';
import { AtomName, Schedule, type FieldInfo } from '../../../src';
import { type FieldInfo } from '../../../src';
import { DataType } from '../../../src/common/typings';
import type { SimpleFieldInfo } from '../../../src/common/typings';
import type { DataExtractionResult } from './pages/DataExtraction/type';
import { DataCleanAtom, MultipleDataCleanAtom } from '../../../src/atom';
import { MultipleDataCleanAtom } from '../../../src/atom';

const capcutResult = {};
const capcutV2Result = {};

export function getCurrentFormattedTime() {
const now = new Date();
Expand Down
100 changes: 99 additions & 1 deletion packages/vmind/src/atom/VChartSpec/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,77 @@ import { AtomName } from '../../types/atom';
import type { BaseOptions } from '../type';
import { BaseAtom } from '../base';
import type { VChartSpecCtx } from '../../types';
import { merge } from '@visactor/vutils';
import { set } from '../../utils/set';

const parseRealPath = (path: string, aliasKeyPath: string, spec: any) => {
let appendSpec: any;

if (aliasKeyPath) {
const topKeyPath = aliasKeyPath.split('.')[0];
const subPaths = path.split('.');

if (subPaths[0] === 'axes[0]' || subPaths[0] === 'axes') {
if (topKeyPath === 'xAxis') {
appendSpec = { orient: 'bottom', aliasName: topKeyPath };
} else if (topKeyPath === 'yAxis') {
appendSpec = { orient: 'left', aliasName: topKeyPath };
} else if (topKeyPath === 'radiusAxis') {
appendSpec = { orient: 'radius', aliasName: topKeyPath };
} else if (topKeyPath === 'angleAxis') {
appendSpec = { orient: 'angle', aliasName: topKeyPath };
} else if (topKeyPath === 'leftAxis') {
appendSpec = { orient: 'left', aliasName: topKeyPath };
} else if (topKeyPath === 'rightAxis') {
appendSpec = { orient: 'right', aliasName: topKeyPath };
} else if (topKeyPath === 'topAxis') {
appendSpec = { orient: 'top', aliasName: topKeyPath };
} else if (topKeyPath === 'bottomAxis') {
appendSpec = { orient: 'bottom', aliasName: topKeyPath };
}

if (spec.axes) {
let specifiedAxis = spec.axes.find((axis: any) => axis.aliasName === topKeyPath);

if (!specifiedAxis) {
if (topKeyPath === 'xAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'bottom');
} else if (topKeyPath === 'yAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'left');
} else if (topKeyPath === 'radiusAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'radius');
} else if (topKeyPath === 'angleAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'angle');
} else if (topKeyPath === 'leftAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'left');
} else if (topKeyPath === 'rightAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'right');
} else if (topKeyPath === 'topAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'top');
} else if (topKeyPath === 'bottomAxis') {
specifiedAxis = spec.axes.find((axis: any) => axis.orient === 'bottom');
}
}

if (specifiedAxis) {
const index = spec.axes.indexOf(specifiedAxis);

subPaths[0] = `axes[${index}]`;
} else {
subPaths[0] = `axes[${spec.axes.length}]`;
}
}
}

return {
appendPath: subPaths[0],
appendSpec,
path: subPaths.join('.')
};
}

return { path };
};

export class VChartSpec extends BaseAtom<VChartSpecCtx, BaseOptions> {
name = AtomName.VCHART_SPEC;
Expand All @@ -20,7 +91,34 @@ export class VChartSpec extends BaseAtom<VChartSpecCtx, BaseOptions> {
}

_runWithOutLLM(): VChartSpecCtx {
// @todo @xile611 最终atom执行入口
const { spec, appendSpec } = this.context;

if (!spec) {
this.context.spec = {};

return this.context;
}

if (!appendSpec || !appendSpec.leafSpec) {
return this.context;
}
const { leafSpec, parentKeyPath = '', aliasKeyPath = '' } = appendSpec;
let newSpec = merge({}, this.context.spec);

if (parentKeyPath) {
const aliasResult = parseRealPath(parentKeyPath, aliasKeyPath, newSpec);

if (aliasResult.appendSpec && aliasResult.appendPath) {
set(newSpec, aliasResult.appendPath, aliasResult.appendSpec);
}

set(newSpec, aliasResult.path ?? parentKeyPath, leafSpec);
} else {
newSpec = leafSpec;
}
this.context.prevSpec = this.context.spec;
this.context.spec = newSpec;

return this.context;
}
}
17 changes: 16 additions & 1 deletion packages/vmind/src/types/atom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,24 @@ export interface ChartQAExtractionCtx extends BaseContext {
explanation: string;
}

// @todo @xile611
export interface VChartSpecCtx extends BaseContext {
spec: any;
prevSpec?: any;
// 新增的spec相关配置
appendSpec?: {
/**
* 大模型返回的叶子节点的配置内容
*/
leafSpec: any;
/**
* 配置父路径
*/
parentKeyPath: string;
/**
* 父路径的别名
*/
aliasKeyPath?: string;
};
}

export interface DialogueChartCtx extends BaseContext {
Expand Down
78 changes: 78 additions & 0 deletions packages/vmind/src/utils/set.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { isObject, isValid, merge } from '@visactor/vutils';

export function set(object: any, path: string, value: any) {
return object == null ? object : baseSet(object, path, value);
}

/**
* Casts `value` to a path array if it's not one.
*
* @private
* @param {*} value The value to inspect.
* @param {Object} [object] The object to query keys on.
* @returns {Array} Returns the cast property path array.
*/
function castPath(path: string, object: any) {
if (object[path]) {
return [path];
}
const arr: string[] = [];

path.split('.').forEach(entry => {
const res = /\[(\d)\]/g.exec(entry);

if (res) {
arr.push(entry.replace(res[0], ''));
arr.push(res[1]);
} else {
arr.push(entry);
}
});

return arr;
}

function isIndex(key: string) {
return /\d/.exec(key);
}

/**
* The base implementation of `_.set`.
*
* @private
* @param {Object} object The object to modify.
* @param {Array|string} pathString The path of the property to set.
* @param {*} value The value to set.
* @param {Function} [customizer] The function to customize path creation.
* @returns {Object} Returns `object`.
*/
function baseSet(object: any, pathString: string, value: any) {
if (!isObject(object)) {
return object;
}
const path = castPath(pathString, object);

let index = -1;
const length = path.length;
const lastIndex = length - 1;
let nested: any = object;

while (nested != null && ++index < length) {
const key = path[index];
let newValue = value;

if (index !== lastIndex) {
const objValue = (nested as any)[key];

newValue = isValid(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
}

if (isValid(nested[key])) {
merge(nested[key], newValue);
} else {
nested[key] = newValue;
}
nested = nested[key];
}
return object;
}

0 comments on commit 4401658

Please sign in to comment.