Skip to content

Commit

Permalink
feat: LLM tool answer sort
Browse files Browse the repository at this point in the history
  • Loading branch information
lixinghua123 authored and lihqi committed Sep 24, 2024
1 parent 07a3928 commit bb960eb
Show file tree
Hide file tree
Showing 6 changed files with 278 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ interface IProps {
sortList: IAnswerSort[][];
waitSortList: IWaitAnswerSort[];
disabeledAll?: boolean;
header?: HTMLElement | string;
title?: string;
prefixId?: string;
}
enum EDirection {
Top = 'Top',
Expand All @@ -41,14 +44,16 @@ interface ITagPoints {

const contentBoxCls = `${prefix}-LLMSidebar-contentBox`;

const SEGMENTATION_OF_KEY = '@';

const Navigation = () => {
const { t } = useTranslation();
return (
<div className={`${contentBoxCls}__navigation`}>
<span>{t('Best')}</span>
<div style={{ display: 'flex', alignItems: 'center' }}>
<div style={{ display: 'flex', alignItems: 'center', flex: 1, margin: '0px 20px' }}>
<LeftOutlined />
<div style={{ height: 0, border: '1px solid #999999', width: '450px' }} />
<div style={{ height: 0, border: '1px solid #999999', width: '100%' }} />
</div>
<span>{t('Worst')}</span>
</div>
Expand All @@ -57,7 +62,18 @@ const Navigation = () => {

const AnswerSort = (props: IProps) => {
const [, forceUpdate] = useReducer((x) => x + 1, 0);
const { sortList, setSortList, waitSortList, disabeledAll } = props;
const {
sortList,
setSortList,
waitSortList,
disabeledAll,
header,
title,
prefixId = 'answer',
} = props;

const waitBoxId = `${prefixId}-waitBox`;
const sortBoxId = `${prefixId}-sortBox`;
const { setHoverKey } = useContext(LLMContext);
const [activateDirection, setActivateDirection] = useState<EDirection | undefined>(undefined);
const [targetTagKey, setTargetTagKey] = useState<number | undefined>(undefined);
Expand Down Expand Up @@ -165,7 +181,7 @@ const AnswerSort = (props: IProps) => {
};

const formatSortList = () => {
const sortBox = document.getElementById('sortBox');
const sortBox = document.getElementById(sortBoxId);

if (sortBox?.childNodes) {
let newSortList: IAnswerSort[][] = [];
Expand Down Expand Up @@ -250,14 +266,14 @@ const AnswerSort = (props: IProps) => {
let formatList = cloneDeep(sortList);

tagIndex = formatList.findIndex((i: IAnswerSort[]) => i[0].id === Number(targetTagKey));
if (target?.parentNode?.parentNode.id === 'sortBox') {
if (target?.parentNode?.parentNode.id === sortBoxId) {
key = getAttributeIndex(target.parentNode.id); // 父级
const curKey = getAttributeIndex(target.id); // 拖动tag
newList = formatList[~~key].filter((i: IAnswerSort) => i.id === ~~curKey);
const removeIndex = formatList[~~key].findIndex((i: IAnswerSort) => i.id === ~~curKey);
formatList[~~key].splice(removeIndex, 1);
}
if (target?.parentNode.id === 'sortBox') {
if (target?.parentNode.id === sortBoxId) {
if (!targetTagKey) {
return;
}
Expand All @@ -270,7 +286,7 @@ const AnswerSort = (props: IProps) => {
formatList.splice(oldIndex, 1);
tagIndex = formatList.findIndex((i: IAnswerSort[]) => i[0].id === ~~targetTagKey);
}
if (target.parentNode.id === 'waitBox') {
if (target.parentNode.id === waitBoxId) {
key = getAttributeIndex(target.id);
oldIndex = answers.findIndex((i: IWaitAnswerSort) => i.id === key);
newList = [answers[oldIndex]];
Expand Down Expand Up @@ -298,29 +314,33 @@ const AnswerSort = (props: IProps) => {
};

const getAttributeIndex = (str: string) => {
const index = str.indexOf('-');
const index = str.indexOf(SEGMENTATION_OF_KEY);
return Number(str.substring(index + 1, str.length));
};

const headerContainer = header ?? (
<div className={`${contentBoxCls}__title`}>
<span>{title ?? t('RankingQualityOfAnswers')}</span>
{answers.length > 0 && (
<Tag color='#FFD9D9' style={{ color: '#F26549', marginLeft: 8 }}>
{t('Unfinished')}
</Tag>
)}
</div>
);

return (
<div style={{ padding: '0px 16px', marginBottom: '16px' }}>
<div className={`${contentBoxCls}__title`}>
<span>{t('RankingQualityOfAnswers')}</span>
{answers.length > 0 && (
<Tag color='#FFD9D9' style={{ color: '#F26549', marginLeft: 8 }}>
{t('Unfinished')}
</Tag>
)}
</div>
<div style={{ padding: '0px 16px', marginBottom: '16px', width: '100%' }}>
{headerContainer}
<div>
<div style={{ display: 'flex', alignItems: 'center' }}>
<span style={{ marginRight: '16px' }}>{t('ToBeSorted')}</span>
<div id='waitBox' className={`${contentBoxCls}__answerBox`}>
<div id={waitBoxId} className={`${contentBoxCls}__answerBox`}>
{answers.length > 0 &&
answers.map((i: IWaitAnswerSort) =>
singleAnswerItem({
item: i,
id: `waitBoxItem-${i?.id}`,
id: `waitBoxItem${SEGMENTATION_OF_KEY}${i?.id}`,
operation: {
onDrag: onDrag,
onDragEnd: onDragEnd,
Expand All @@ -330,15 +350,19 @@ const AnswerSort = (props: IProps) => {
</div>
</div>
<Navigation />
<div id='sortBox' className={`${contentBoxCls}__answerBox`}>
<div id={sortBoxId} className={`${contentBoxCls}__answerBox`}>
{sortList.map((i: IAnswerSort[], index: number) => {
if (i.length > 1) {
return (
<div key={`item-${index}`} id={`sortBox-${index}`}>
<div
key={`item-${index}`}
id={`${sortBoxId}${SEGMENTATION_OF_KEY}${index}`}
style={{ border: '1px dashed #d9d9d9' }}
>
{i.map((item: IAnswerSort) =>
singleAnswerItem({
item,
id: `sortBoxItem-${item?.id}`,
id: `sortBoxItem${SEGMENTATION_OF_KEY}${item?.id}`,
operation: {
onDrag: onDrag,
onDragEnd: onDragEnd,
Expand All @@ -350,7 +374,7 @@ const AnswerSort = (props: IProps) => {
}
return singleAnswerItem({
item: i[0],
id: `sortBox-${i[0]?.id}`,
id: `${sortBoxId}${SEGMENTATION_OF_KEY}${i[0]?.id}`,
operation: {
onDrag: onDrag,
onDragEnd: onDragEnd,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useState, useEffect, useContext, useMemo } from 'react';
import { prefix } from '@/constant';
import { Button, Empty, Tag } from 'antd';
import AnswerSort from '../answerSort';
import { IWaitAnswerSort } from '@/components/LLMToolView/types';
import { getWaitSortList } from '@/components/LLMToolView/utils/data';
import { isArray } from 'lodash';
import ModelSort from '../modelSort';
import { useTranslation } from 'react-i18next';

interface IAnswerSort {
[key: string]: number[][];
}

interface IModelList {
id: number;
answerList: IAnswerList[];
}

interface IAnswerList {
id: string;
answer: string;
}

interface IProps {
selectedSort?: IAnswerSort;
maxAnswerList: IAnswerList[];
modelData: IModelList[];
}

const ModelAnswerSort = (props: IProps) => {
const { selectedSort, maxAnswerList, modelData } = props;
const [answerSortData, setAnswerSortData] = useState({ waitSorts: [], selecteds: selectedSort });
const { t } = useTranslation();

const modelDatas = useMemo(
() =>
modelData.map((i, itemIndex) => ({
...i,
title: itemIndex + 1,
})),
[modelData],
);

const getModelList = (id: string) => {
const values = modelDatas.filter((i) => i.answerList.some((item) => item.id === id)) || [];
return values.map((i) => ({ id: i.id, title: i.title }));
};

const exportSort = (id: string, value: number[][]) => {
// TODO 当拖动一个答案的时,多次调用
// 因为answerSort组件useEffect(() => {formatSortList();}, [JSON.stringify(sortList)])
};

return (
<div>
<div
style={{
fontWeight: 500,
fontSize: '16px',
width: '100%',
lineHeight: '46px',
padding: '0px 16px',
}}
>
<span>{t('RankingQualityOfAnswers')}</span>
{answerSortData?.waitSorts?.length > 0 && (
<Tag color='#FFD9D9' style={{ color: '#F26549', marginLeft: 8 }}>
{t('Unfinished')}
</Tag>
)}
</div>
{maxAnswerList.map((i: IAnswerList, index: number) => {
return (
<div key={index} style={{ display: 'flex' }}>
<div
style={{
fontSize: '16px',
fontWeight: 500,
width: '80px',
lineHeight: '50px',
textAlign: 'center',
}}
>{`${t('Answer')}${index + 1}`}</div>
<ModelSort
setSort={(value) => {
exportSort(i.id, value);
}}
modelList={getModelList(i.id)}
selectedSort={answerSortData.selecteds?.[i.id] ?? []}
header={''}
prefixId={`modelAnswer${index}`}
/>
</div>
);
})}
</div>
);
};
export default ModelAnswerSort;
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import React, { useState, useEffect, useContext, useMemo } from 'react';
import { prefix } from '@/constant';
import { Button, Empty } from 'antd';
import AnswerSort from '../answerSort';
import { IAnswerSort, IWaitAnswerSort } from '@/components/LLMToolView/types';
import { getWaitSortList } from '@/components/LLMToolView/utils/data';
import { isArray } from 'lodash';

interface IModelList {
id: number;
title: number;
}

interface ISortData {
newSort?: IAnswerSort[][];
waitSorts?: IWaitAnswerSort[];
}

interface IProps {
modelList: IModelList[];
selectedSort?: number[][];
disabeledAll?: boolean;
setSort: (sort: number[][]) => void;
header?: HTMLElement | string;
title?: string;
prefixId?: string;
}

const ModelSort = (props: IProps) => {
const { disabeledAll, modelList, selectedSort, setSort, header, title,prefixId } = props;
const [sortData, setSortData] = useState<ISortData>({});

useEffect(() => {
initSortData();
}, []);

const initSortData = () => {
let newSort: any[] = [];
const waitSorts = modelList.filter((i) => {
const selectedIds = selectedSort && selectedSort?.length > 0 ? selectedSort.flat() : [];
if (selectedIds.includes(i.id)) {
return false;
}
return true;
});
if (selectedSort && selectedSort?.length > 0) {
newSort = selectedSort.map((i: number[]) =>
i.map((item) => modelList.find((j) => j.id === item)),
);
}
setSortData({ waitSorts, newSort });
};

const exportSort = (list: IAnswerSort[][]) => {
const sort = list.map((i) => i.map((item) => item.id));
setSort(sort);
};

return (
<AnswerSort
waitSortList={sortData?.waitSorts || []}
sortList={sortData?.newSort || []}
setSortList={(value) => {
setSortData({ ...sortData, newSort: value });
exportSort(value);
}}
disabeledAll={disabeledAll}
header={header}
title={title}
prefixId={prefixId}
/>
);
};

export default ModelSort;
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ import LongText from '@/components/longText';
interface IProps {
textAttribute: ITextList[];
disabeledAll?: boolean;
LLMConfig?: ILLMToolConfig;
setText: (value: ITextList[]) => void;
textConfig: ITextList[];
}

const TextInputBox = (props: IProps) => {
const { disabeledAll, LLMConfig, textAttribute, setText } = props;
const textConfig = LLMConfig?.text && isArray(LLMConfig.text) ? LLMConfig?.text : [];
const { disabeledAll, textConfig, textAttribute, setText } = props;
const { TextArea } = Input;
const [form] = Form.useForm();
const { t } = useTranslation();
Expand Down
Loading

0 comments on commit bb960eb

Please sign in to comment.