mirror of
https://github.com/tencentmusic/supersonic.git
synced 2026-01-07 18:08:58 +08:00
(feature)(webapp) modify model to view (#719)
This commit is contained in:
@@ -135,18 +135,6 @@ const AgentsSection: React.FC<Props> = ({
|
||||
<PlusOutlined />
|
||||
新建助理
|
||||
</Button>
|
||||
<div className={styles.switchShowType}>
|
||||
<span className={styles.switchShowTypeLabel}>切换为卡片</span>
|
||||
<Switch
|
||||
size="small"
|
||||
checked={showType === 'card'}
|
||||
onChange={(value) => {
|
||||
const showTypeValue = value ? 'card' : 'list';
|
||||
setShowType(showTypeValue);
|
||||
localStorage.setItem('AGENT_SHOW_TYPE', showTypeValue);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{showType === 'list' ? (
|
||||
<Table columns={columns} dataSource={showAgents} />
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import { Form, Modal, Input, Select, Button } from 'antd';
|
||||
import { Form, Modal, Input, Select, Button, TreeSelect } from 'antd';
|
||||
import {
|
||||
AgentToolType,
|
||||
AgentToolTypeEnum,
|
||||
AGENT_TOOL_TYPE_LIST,
|
||||
MetricOptionType,
|
||||
MetricType,
|
||||
ModelType,
|
||||
QUERY_MODE_LIST,
|
||||
} from './type';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import styles from './style.less';
|
||||
import { getLeafList, uuid } from '@/utils/utils';
|
||||
import { getMetricList, getModelList } from './service';
|
||||
import { traverseTree, uuid } from '@/utils/utils';
|
||||
import { getModelList } from './service';
|
||||
import { PluginType } from '../ChatPlugin/type';
|
||||
import { getPluginList } from '../ChatPlugin/service';
|
||||
|
||||
@@ -26,17 +24,22 @@ type Props = {
|
||||
|
||||
const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
||||
const [toolType, setToolType] = useState<AgentToolTypeEnum>();
|
||||
const [modelList, setModelList] = useState<ModelType[]>([]);
|
||||
const [modelList, setModelList] = useState<any[]>([]);
|
||||
const [saveLoading, setSaveLoading] = useState(false);
|
||||
const [examples, setExamples] = useState<{ id: string; question?: string }[]>([]);
|
||||
const [metricOptions, setMetricOptions] = useState<MetricOptionType[]>([]);
|
||||
const [modelMetricList, setModelMetricList] = useState<MetricType[]>([]);
|
||||
const [plugins, setPlugins] = useState<PluginType[]>([]);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const initModelList = async () => {
|
||||
const res = await getModelList();
|
||||
setModelList([{ id: -1, name: '默认' }, ...getLeafList(res.data)]);
|
||||
const treeData = traverseTree(res.data, (node: any) => {
|
||||
node.title = node.name;
|
||||
node.value = node.type === 'DOMAIN' ? `DOMAIN_${node.id}` : node.id;
|
||||
node.checkable =
|
||||
node.type === 'VIEW' || (node.type === 'DOMAIN' && node.children?.length > 0);
|
||||
});
|
||||
setModelList([{ title: '默认', value: -1, type: 'VIEW' }, ...treeData]);
|
||||
};
|
||||
|
||||
const initPluginList = async () => {
|
||||
@@ -49,11 +52,6 @@ const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
||||
initPluginList();
|
||||
}, []);
|
||||
|
||||
const initModelMetrics = async (params: any) => {
|
||||
const res = await getMetricList(params[0].modelId);
|
||||
setModelMetricList(res.data.list);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (editTool) {
|
||||
form.setFieldsValue({ ...editTool, plugins: editTool.plugins?.[0] });
|
||||
@@ -62,9 +60,6 @@ const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
||||
(editTool.exampleQuestions || []).map((item) => ({ id: uuid(), question: item })),
|
||||
);
|
||||
setMetricOptions(editTool.metricOptions || []);
|
||||
if (editTool.metricOptions && editTool.metricOptions.length > 0) {
|
||||
initModelMetrics(editTool.metricOptions || []);
|
||||
}
|
||||
} else {
|
||||
form.resetFields();
|
||||
}
|
||||
@@ -88,11 +83,6 @@ const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
||||
setSaveLoading(false);
|
||||
};
|
||||
|
||||
const updateMetricList = async (value: number) => {
|
||||
const res = await getMetricList(value);
|
||||
setModelMetricList(res.data.list);
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open
|
||||
@@ -115,11 +105,13 @@ const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
||||
</FormItem>
|
||||
{(toolType === AgentToolTypeEnum.NL2SQL_RULE ||
|
||||
toolType === AgentToolTypeEnum.NL2SQL_LLM) && (
|
||||
<FormItem name="modelIds" label="主题域">
|
||||
<Select
|
||||
options={modelList.map((model) => ({ label: model.name, value: model.id }))}
|
||||
placeholder="请选择主题域"
|
||||
mode="multiple"
|
||||
<FormItem name="viewIds" label="视图">
|
||||
<TreeSelect
|
||||
treeData={modelList}
|
||||
placeholder="请选择视图"
|
||||
multiple
|
||||
treeCheckable
|
||||
allowClear
|
||||
/>
|
||||
</FormItem>
|
||||
)}
|
||||
@@ -159,70 +151,6 @@ const ToolModal: React.FC<Props> = ({ editTool, onSaveTool, onCancel }) => {
|
||||
</div>
|
||||
</FormItem>
|
||||
)}
|
||||
{toolType === AgentToolTypeEnum.ANALYTICS && (
|
||||
<>
|
||||
<FormItem name="modelId" label="主题域">
|
||||
<Select
|
||||
options={modelList.map((model) => ({ label: model.name, value: model.id }))}
|
||||
showSearch
|
||||
filterOption={(input, option) =>
|
||||
((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
|
||||
}
|
||||
placeholder="请选择主题域"
|
||||
onChange={(value) => {
|
||||
setMetricOptions([...metricOptions]);
|
||||
updateMetricList(value);
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="params" label="指标">
|
||||
<div className={styles.paramsSection}>
|
||||
{metricOptions.map((filter: any) => {
|
||||
return (
|
||||
<div className={styles.filterRow} key={filter.id}>
|
||||
<Select
|
||||
placeholder="请选择指标,需先选择主题域"
|
||||
options={(modelMetricList || []).map((metric) => ({
|
||||
label: metric.name,
|
||||
value: `${metric.id}`,
|
||||
}))}
|
||||
showSearch
|
||||
className={styles.filterParamValueField}
|
||||
filterOption={(input, option) =>
|
||||
((option?.label ?? '') as string)
|
||||
.toLowerCase()
|
||||
.includes(input.toLowerCase())
|
||||
}
|
||||
allowClear
|
||||
value={filter.metricId}
|
||||
onChange={(value) => {
|
||||
filter.metricId = value;
|
||||
setMetricOptions([...metricOptions]);
|
||||
}}
|
||||
/>
|
||||
<DeleteOutlined
|
||||
onClick={() => {
|
||||
setMetricOptions(metricOptions.filter((item) => item.id !== filter.id));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setMetricOptions([
|
||||
...metricOptions,
|
||||
{ id: uuid(), metricId: undefined, modelId: undefined },
|
||||
]);
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
新增指标
|
||||
</Button>
|
||||
</div>
|
||||
</FormItem>
|
||||
</>
|
||||
)}
|
||||
{toolType === AgentToolTypeEnum.PLUGIN && (
|
||||
<FormItem name="plugins" label="插件">
|
||||
<Select
|
||||
|
||||
@@ -19,7 +19,7 @@ export function deleteAgent(id: number) {
|
||||
}
|
||||
|
||||
export function getModelList() {
|
||||
return request<Result<ModelType[]>>('/api/chat/conf/viewList', {
|
||||
return request<Result<ModelType[]>>('/api/chat/conf/getDomainViewTree', {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ export enum AgentToolTypeEnum {
|
||||
NL2SQL_RULE = 'NL2SQL_RULE',
|
||||
NL2SQL_LLM = 'NL2SQL_LLM',
|
||||
PLUGIN = 'PLUGIN',
|
||||
ANALYTICS = 'ANALYTICS',
|
||||
}
|
||||
|
||||
export const AGENT_TOOL_TYPE_LIST = [
|
||||
@@ -76,6 +75,7 @@ export type ModelType = {
|
||||
parentId: number;
|
||||
name: string;
|
||||
bizName: string;
|
||||
type: 'DOMAIN' | 'VIEW';
|
||||
};
|
||||
|
||||
export type MetricType = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal, Select, Form, Input, InputNumber, message, Button, Radio } from 'antd';
|
||||
import { Modal, Select, Form, Input, InputNumber, message, Button, Radio, TreeSelect } from 'antd';
|
||||
import { getDimensionList, getModelList, savePlugin } from './service';
|
||||
import {
|
||||
DimensionType,
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
FunctionParamFormItemType,
|
||||
PluginTypeEnum,
|
||||
} from './type';
|
||||
import { getLeafList, uuid } from '@/utils/utils';
|
||||
import { getLeafList, traverseTree, uuid } from '@/utils/utils';
|
||||
import styles from './style.less';
|
||||
import { PLUGIN_TYPE_MAP } from './constants';
|
||||
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
@@ -38,7 +38,13 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
|
||||
const initModelList = async () => {
|
||||
const res = await getModelList();
|
||||
setModelList([{ id: -1, name: '默认' }, ...getLeafList(res.data)]);
|
||||
const treeData = traverseTree(res.data, (node: any) => {
|
||||
node.title = node.name;
|
||||
node.value = node.type === 'DOMAIN' ? `DOMAIN_${node.id}` : node.id;
|
||||
node.checkable =
|
||||
node.type === 'VIEW' || (node.type === 'DOMAIN' && node.children?.length > 0);
|
||||
});
|
||||
setModelList([{ title: '默认', value: -1, type: 'VIEW' }, ...treeData]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -181,18 +187,12 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Form {...layout} form={form} style={{ maxWidth: 820 }}>
|
||||
<FormItem name="modelList" label="主题域">
|
||||
<Select
|
||||
placeholder="请选择主题域"
|
||||
options={modelList.map((model) => ({
|
||||
label: model.name,
|
||||
value: model.id,
|
||||
}))}
|
||||
showSearch
|
||||
filterOption={(input, option) =>
|
||||
((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
|
||||
}
|
||||
mode="multiple"
|
||||
<FormItem name="viewList" label="视图">
|
||||
<TreeSelect
|
||||
treeData={modelList}
|
||||
placeholder="请选择视图"
|
||||
multiple
|
||||
treeCheckable
|
||||
allowClear
|
||||
/>
|
||||
</FormItem>
|
||||
|
||||
@@ -3,11 +3,11 @@ import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button, Input, message, Popconfirm, Select, Table, Tag } from 'antd';
|
||||
import moment from 'moment';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { PARSE_MODE_MAP, PLUGIN_TYPE_MAP } from './constants';
|
||||
import { PLUGIN_TYPE_MAP } from './constants';
|
||||
import DetailModal from './DetailModal';
|
||||
import { deletePlugin, getModelList, getPluginList } from './service';
|
||||
import styles from './style.less';
|
||||
import { ModelType, ParseModeEnum, PluginType, PluginTypeEnum } from './type';
|
||||
import { ModelType, PluginType, PluginTypeEnum } from './type';
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
@@ -57,9 +57,9 @@ const PluginManage = () => {
|
||||
key: 'name',
|
||||
},
|
||||
{
|
||||
title: '主题域',
|
||||
dataIndex: 'modelList',
|
||||
key: 'modelList',
|
||||
title: '视图',
|
||||
dataIndex: 'viewList',
|
||||
key: 'viewList',
|
||||
width: 200,
|
||||
render: (value: number[]) => {
|
||||
if (value?.includes(-1)) {
|
||||
@@ -67,7 +67,7 @@ const PluginManage = () => {
|
||||
}
|
||||
return value ? (
|
||||
<div className={styles.modelColumn}>
|
||||
{value.map((id, index) => {
|
||||
{value.map((id) => {
|
||||
const name = modelList.find((model) => model.id === +id)?.name;
|
||||
return name ? <Tag key={id}>{name}</Tag> : null;
|
||||
})}
|
||||
|
||||
@@ -22,7 +22,7 @@ export function deletePlugin(id: number) {
|
||||
}
|
||||
|
||||
export function getModelList() {
|
||||
return request<Result<ModelType[]>>('/api/chat/conf/viewList', {
|
||||
return request<Result<ModelType[]>>('/api/chat/conf/getDomainViewTree', {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user