mirror of
https://github.com/tencentmusic/supersonic.git
synced 2025-12-20 06:34:55 +00:00
[feature](webapp) add copilot and modify domain to model
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal, Select, Form, Input, InputNumber, message, Button, Radio } from 'antd';
|
||||
import { getDimensionList, getDomainList, savePlugin } from './service';
|
||||
import { getDimensionList, getModelList, savePlugin } from './service';
|
||||
import {
|
||||
DimensionType,
|
||||
DomainType,
|
||||
ModelType,
|
||||
ParamTypeEnum,
|
||||
ParseModeEnum,
|
||||
PluginType,
|
||||
@@ -26,10 +26,8 @@ type Props = {
|
||||
};
|
||||
|
||||
const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
const [domainList, setDomainList] = useState<DomainType[]>([]);
|
||||
const [domainDimensionList, setDomainDimensionList] = useState<Record<number, DimensionType[]>>(
|
||||
{},
|
||||
);
|
||||
const [modelList, setModelList] = useState<ModelType[]>([]);
|
||||
const [modelDimensionList, setModelDimensionList] = useState<Record<number, DimensionType[]>>({});
|
||||
const [confirmLoading, setConfirmLoading] = useState(false);
|
||||
const [pluginType, setPluginType] = useState<PluginTypeEnum>();
|
||||
const [functionName, setFunctionName] = useState<string>();
|
||||
@@ -38,28 +36,25 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
const [filters, setFilters] = useState<any[]>([]);
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const initDomainList = async () => {
|
||||
const res = await getDomainList();
|
||||
setDomainList([{ id: -1, name: '全部' }, ...getLeafList(res.data)]);
|
||||
const initModelList = async () => {
|
||||
const res = await getModelList();
|
||||
setModelList([{ id: -1, name: '默认' }, ...getLeafList(res.data)]);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initDomainList();
|
||||
initModelList();
|
||||
}, []);
|
||||
|
||||
const initDomainDimensions = async (params: any) => {
|
||||
const domainIds = params
|
||||
.filter((param: any) => !!param.domainId)
|
||||
.map((param: any) => param.domainId);
|
||||
const res = await Promise.all(domainIds.map((domainId: number) => getDimensionList(domainId)));
|
||||
setDomainDimensionList(
|
||||
domainIds.reduce(
|
||||
(result: Record<number, DimensionType[]>, domainId: number, index: number) => {
|
||||
result[domainId] = res[index].data.list;
|
||||
return result;
|
||||
},
|
||||
{},
|
||||
),
|
||||
const initModelDimensions = async (params: any) => {
|
||||
const modelIds = params
|
||||
.filter((param: any) => !!param.modelId)
|
||||
.map((param: any) => param.modelId);
|
||||
const res = await Promise.all(modelIds.map((modelId: number) => getDimensionList(modelId)));
|
||||
setModelDimensionList(
|
||||
modelIds.reduce((result: Record<number, DimensionType[]>, modelId: number, index: number) => {
|
||||
result[modelId] = res[index].data.list;
|
||||
return result;
|
||||
}, {}),
|
||||
);
|
||||
};
|
||||
|
||||
@@ -79,7 +74,7 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
(option: any) => option.paramType !== ParamTypeEnum.FORWARD,
|
||||
);
|
||||
setFilters(params);
|
||||
initDomainDimensions(params);
|
||||
initModelDimensions(params);
|
||||
}
|
||||
setPluginType(detail.type);
|
||||
const parseModeObj = JSON.parse(detail.parseModeConfig || '{}');
|
||||
@@ -159,7 +154,7 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
await savePlugin({
|
||||
...values,
|
||||
id: detail?.id,
|
||||
domainList: isArray(values.domainList) ? values.domainList : [values.domainList],
|
||||
modelList: isArray(values.modelList) ? values.modelList : [values.modelList],
|
||||
config: JSON.stringify(config),
|
||||
parseModeConfig: JSON.stringify(getFunctionParam(values.pattern)),
|
||||
});
|
||||
@@ -169,11 +164,11 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
};
|
||||
|
||||
const updateDimensionList = async (value: number) => {
|
||||
if (domainDimensionList[value]) {
|
||||
if (modelDimensionList[value]) {
|
||||
return;
|
||||
}
|
||||
const res = await getDimensionList(value);
|
||||
setDomainDimensionList({ ...domainDimensionList, [value]: res.data.list });
|
||||
setModelDimensionList({ ...modelDimensionList, [value]: res.data.list });
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -186,12 +181,12 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
onCancel={onCancel}
|
||||
>
|
||||
<Form {...layout} form={form} style={{ maxWidth: 820 }}>
|
||||
<FormItem name="domainList" label="主题域">
|
||||
<FormItem name="modelList" label="主题域">
|
||||
<Select
|
||||
placeholder="请选择主题域"
|
||||
options={domainList.map((domain) => ({
|
||||
label: domain.name,
|
||||
value: domain.id,
|
||||
options={modelList.map((model) => ({
|
||||
label: model.name,
|
||||
value: model.id,
|
||||
}))}
|
||||
showSearch
|
||||
filterOption={(input, option) =>
|
||||
@@ -223,7 +218,6 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
setPluginType(value);
|
||||
if (value === PluginTypeEnum.DSL) {
|
||||
form.setFieldsValue({ parseMode: ParseModeEnum.FUNCTION_CALL });
|
||||
// setFunctionName('DSL');
|
||||
setFunctionParams([
|
||||
{
|
||||
id: uuid(),
|
||||
@@ -236,47 +230,6 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
}}
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem
|
||||
name="pattern"
|
||||
label="插件描述"
|
||||
rules={[{ required: true, message: '请输入插件描述' }]}
|
||||
>
|
||||
<TextArea placeholder="请输入插件描述,多个描述换行分隔" allowClear />
|
||||
</FormItem>
|
||||
<FormItem name="exampleQuestions" label="示例问题">
|
||||
<div className={styles.paramsSection}>
|
||||
{examples.map((example) => {
|
||||
const { id, question } = example;
|
||||
return (
|
||||
<div className={styles.filterRow} key={id}>
|
||||
<Input
|
||||
placeholder="示例问题"
|
||||
value={question}
|
||||
className={styles.questionExample}
|
||||
onChange={(e) => {
|
||||
example.question = e.target.value;
|
||||
setExamples([...examples]);
|
||||
}}
|
||||
allowClear
|
||||
/>
|
||||
<DeleteOutlined
|
||||
onClick={() => {
|
||||
setExamples(examples.filter((item) => item.id !== id));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setExamples([...examples, { id: uuid() }]);
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
新增示例问题
|
||||
</Button>
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem label="函数名称">
|
||||
<Input
|
||||
value={functionName}
|
||||
@@ -287,6 +240,9 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
allowClear
|
||||
/>
|
||||
</FormItem>
|
||||
<FormItem name="pattern" label="函数描述">
|
||||
<TextArea placeholder="请输入函数描述,多个描述换行分隔" allowClear />
|
||||
</FormItem>
|
||||
<FormItem name="params" label="函数参数" hidden={pluginType === PluginTypeEnum.DSL}>
|
||||
<div className={styles.paramsSection}>
|
||||
{functionParams.map((functionParam: FunctionParamFormItemType) => {
|
||||
@@ -345,6 +301,40 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
</Button>
|
||||
</div>
|
||||
</FormItem>
|
||||
<FormItem name="exampleQuestions" label="示例问题">
|
||||
<div className={styles.paramsSection}>
|
||||
{examples.map((example) => {
|
||||
const { id, question } = example;
|
||||
return (
|
||||
<div className={styles.filterRow} key={id}>
|
||||
<Input
|
||||
placeholder="示例问题"
|
||||
value={question}
|
||||
className={styles.questionExample}
|
||||
onChange={(e) => {
|
||||
example.question = e.target.value;
|
||||
setExamples([...examples]);
|
||||
}}
|
||||
allowClear
|
||||
/>
|
||||
<DeleteOutlined
|
||||
onClick={() => {
|
||||
setExamples(examples.filter((item) => item.id !== id));
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
<Button
|
||||
onClick={() => {
|
||||
setExamples([...examples, { id: uuid() }]);
|
||||
}}
|
||||
>
|
||||
<PlusOutlined />
|
||||
新增示例问题
|
||||
</Button>
|
||||
</div>
|
||||
</FormItem>
|
||||
{(pluginType === PluginTypeEnum.WEB_PAGE || pluginType === PluginTypeEnum.WEB_SERVICE) && (
|
||||
<>
|
||||
<FormItem name="url" label="地址" rules={[{ required: true, message: '请输入地址' }]}>
|
||||
@@ -391,9 +381,9 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
<>
|
||||
<Select
|
||||
placeholder="主题域"
|
||||
options={domainList.map((domain) => ({
|
||||
label: domain.name,
|
||||
value: domain.id,
|
||||
options={modelList.map((model) => ({
|
||||
label: model.name,
|
||||
value: model.id,
|
||||
}))}
|
||||
showSearch
|
||||
filterOption={(input, option) =>
|
||||
@@ -403,16 +393,16 @@ const DetailModal: React.FC<Props> = ({ detail, onSubmit, onCancel }) => {
|
||||
}
|
||||
className={styles.filterParamName}
|
||||
allowClear
|
||||
value={filter.domainId}
|
||||
value={filter.modelId}
|
||||
onChange={(value) => {
|
||||
filter.domainId = value;
|
||||
filter.modelId = value;
|
||||
setFilters([...filters]);
|
||||
updateDimensionList(value);
|
||||
}}
|
||||
/>
|
||||
<Select
|
||||
placeholder="请选择维度,需先选择主题域"
|
||||
options={(domainDimensionList[filter.domainId] || []).map(
|
||||
options={(modelDimensionList[filter.modelId] || []).map(
|
||||
(dimension) => ({
|
||||
label: dimension.name,
|
||||
value: `${dimension.id}`,
|
||||
|
||||
@@ -5,9 +5,9 @@ import moment from 'moment';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { PARSE_MODE_MAP, PLUGIN_TYPE_MAP } from './constants';
|
||||
import DetailModal from './DetailModal';
|
||||
import { deletePlugin, getDomainList, getPluginList } from './service';
|
||||
import { deletePlugin, getModelList, getPluginList } from './service';
|
||||
import styles from './style.less';
|
||||
import { DomainType, ParseModeEnum, PluginType, PluginTypeEnum } from './type';
|
||||
import { ModelType, ParseModeEnum, PluginType, PluginTypeEnum } from './type';
|
||||
|
||||
const { Search } = Input;
|
||||
|
||||
@@ -15,27 +15,27 @@ const PluginManage = () => {
|
||||
const [name, setName] = useState<string>();
|
||||
const [type, setType] = useState<PluginTypeEnum>();
|
||||
const [pattern, setPattern] = useState<string>();
|
||||
const [domain, setDomain] = useState<string>();
|
||||
const [model, setModel] = useState<string>();
|
||||
const [data, setData] = useState<PluginType[]>([]);
|
||||
const [domainList, setDomainList] = useState<DomainType[]>([]);
|
||||
const [modelList, setModelList] = useState<ModelType[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [currentPluginDetail, setCurrentPluginDetail] = useState<PluginType>();
|
||||
const [detailModalVisible, setDetailModalVisible] = useState(false);
|
||||
|
||||
const initDomainList = async () => {
|
||||
const res = await getDomainList();
|
||||
setDomainList(getLeafList(res.data));
|
||||
const initModelList = async () => {
|
||||
const res = await getModelList();
|
||||
setModelList(getLeafList(res.data));
|
||||
};
|
||||
|
||||
const updateData = async (filters?: any) => {
|
||||
setLoading(true);
|
||||
const res = await getPluginList({ name, type, pattern, domain, ...(filters || {}) });
|
||||
const res = await getPluginList({ name, type, pattern, model, ...(filters || {}) });
|
||||
setLoading(false);
|
||||
setData(res.data.map((item) => ({ ...item, config: JSON.parse(item.config || '{}') })));
|
||||
setData(res.data?.map((item) => ({ ...item, config: JSON.parse(item.config || '{}') })) || []);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
initDomainList();
|
||||
initModelList();
|
||||
updateData();
|
||||
}, []);
|
||||
|
||||
@@ -58,17 +58,17 @@ const PluginManage = () => {
|
||||
},
|
||||
{
|
||||
title: '主题域',
|
||||
dataIndex: 'domainList',
|
||||
key: 'domainList',
|
||||
dataIndex: 'modelList',
|
||||
key: 'modelList',
|
||||
width: 200,
|
||||
render: (value: number[]) => {
|
||||
if (value?.includes(-1)) {
|
||||
return '全部';
|
||||
return '默认';
|
||||
}
|
||||
return value ? (
|
||||
<div className={styles.domainColumn}>
|
||||
<div className={styles.modelColumn}>
|
||||
{value.map((id, index) => {
|
||||
const name = domainList.find((domain) => domain.id === +id)?.name;
|
||||
const name = modelList.find((model) => model.id === +id)?.name;
|
||||
return name ? <Tag key={id}>{name}</Tag> : null;
|
||||
})}
|
||||
</div>
|
||||
@@ -90,7 +90,7 @@ const PluginManage = () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '插件描述',
|
||||
title: '函数描述',
|
||||
dataIndex: 'pattern',
|
||||
key: 'pattern',
|
||||
width: 450,
|
||||
@@ -139,9 +139,9 @@ const PluginManage = () => {
|
||||
},
|
||||
];
|
||||
|
||||
const onDomainChange = (value: string) => {
|
||||
setDomain(value);
|
||||
updateData({ domain: value });
|
||||
const onModelChange = (value: string) => {
|
||||
setModel(value);
|
||||
updateData({ model: value });
|
||||
};
|
||||
|
||||
const onTypeChange = (value: PluginTypeEnum) => {
|
||||
@@ -171,10 +171,10 @@ const PluginManage = () => {
|
||||
<Select
|
||||
className={styles.filterItemControl}
|
||||
placeholder="请选择主题域"
|
||||
options={domainList.map((domain) => ({ label: domain.name, value: domain.id }))}
|
||||
value={domain}
|
||||
options={modelList.map((model) => ({ label: model.name, value: model.id }))}
|
||||
value={model}
|
||||
allowClear
|
||||
onChange={onDomainChange}
|
||||
onChange={onModelChange}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.filterItem}>
|
||||
@@ -190,10 +190,10 @@ const PluginManage = () => {
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.filterItem}>
|
||||
<div className={styles.filterItemTitle}>插件描述</div>
|
||||
<div className={styles.filterItemTitle}>函数描述</div>
|
||||
<Search
|
||||
className={styles.filterItemControl}
|
||||
placeholder="请输入插件描述"
|
||||
placeholder="请输入函数描述"
|
||||
value={pattern}
|
||||
onChange={(e) => {
|
||||
setPattern(e.target.value);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { request } from "umi";
|
||||
import { DimensionType, DomainType, PluginType } from "./type";
|
||||
import { DimensionType, ModelType, PluginType } from "./type";
|
||||
|
||||
export function savePlugin(params: Partial<PluginType>) {
|
||||
return request<Result<any>>('/api/chat/plugin', {
|
||||
@@ -21,17 +21,17 @@ export function deletePlugin(id: number) {
|
||||
});
|
||||
}
|
||||
|
||||
export function getDomainList() {
|
||||
return request<Result<DomainType[]>>('/api/chat/conf/domainList', {
|
||||
export function getModelList() {
|
||||
return request<Result<ModelType[]>>('/api/chat/conf/modelList', {
|
||||
method: 'GET',
|
||||
});
|
||||
}
|
||||
|
||||
export function getDimensionList(domainId: number) {
|
||||
export function getDimensionList(modelId: number) {
|
||||
return request<Result<{list: DimensionType[]}>>('/api/semantic/dimension/queryDimension', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
domainIds: [domainId],
|
||||
modelIds: [modelId],
|
||||
current: 1,
|
||||
pageSize: 2000
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.domainColumn {
|
||||
.modelColumn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
column-gap: 2px;
|
||||
|
||||
@@ -26,7 +26,7 @@ export enum ParamTypeEnum {
|
||||
export type PluginType = {
|
||||
id: number;
|
||||
type: PluginTypeEnum;
|
||||
domainList: number[];
|
||||
modelList: number[];
|
||||
pattern: string;
|
||||
parseMode: ParseModeEnum;
|
||||
parseModeConfig: string;
|
||||
@@ -34,7 +34,7 @@ export type PluginType = {
|
||||
config: PluginConfigType;
|
||||
}
|
||||
|
||||
export type DomainType = {
|
||||
export type ModelType = {
|
||||
id: number | string;
|
||||
parentId: number;
|
||||
name: string;
|
||||
|
||||
Reference in New Issue
Block a user