mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Fix: Fixed an issue where parser configurations could be added infinitely #9869 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -39,9 +39,9 @@ export function HomeCard({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col justify-between gap-1 flex-1 h-full w-[calc(100%-50px)]">
|
<div className="flex flex-col justify-between gap-1 flex-1 h-full w-[calc(100%-50px)]">
|
||||||
<section className="flex justify-between w-full">
|
<section className="flex justify-between">
|
||||||
<section className="flex gap-1 items-center w-full">
|
<section className="flex flex-1 min-w-0 gap-1 items-center">
|
||||||
<div className="text-base font-bold w-80% text-ellipsis overflow-hidden leading-snug">
|
<div className="text-base font-bold leading-snug truncate">
|
||||||
{data.name}
|
{data.name}
|
||||||
</div>
|
</div>
|
||||||
{icon}
|
{icon}
|
||||||
|
|||||||
@ -106,7 +106,7 @@ export function Header() {
|
|||||||
}, [navigate]);
|
}, [navigate]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="p-5 pr-14 flex justify-between items-center ">
|
<section className="py-5 px-10 flex justify-between items-center ">
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
<img
|
<img
|
||||||
src={'/logo.svg'}
|
src={'/logo.svg'}
|
||||||
|
|||||||
@ -1729,13 +1729,15 @@ This delimiter is used to split the input text into several text pieces echo of
|
|||||||
regularExpressions: 'Regular Expressions',
|
regularExpressions: 'Regular Expressions',
|
||||||
overlappedPercent: 'Overlapped percent',
|
overlappedPercent: 'Overlapped percent',
|
||||||
searchMethod: 'Search method',
|
searchMethod: 'Search method',
|
||||||
|
searchMethodTip: `Defines how the content can be searched — by full-text, embedding, or both.
|
||||||
|
The Tokenizer will store the content in the corresponding data structures for the selected methods.`,
|
||||||
begin: 'File',
|
begin: 'File',
|
||||||
parserMethod: 'Parsing method',
|
parserMethod: 'Parsing method',
|
||||||
systemPrompt: 'System Prompt',
|
systemPrompt: 'System Prompt',
|
||||||
systemPromptPlaceholder:
|
systemPromptPlaceholder:
|
||||||
'Enter system prompt for image analysis, if empty the system default value will be used',
|
'Enter system prompt for image analysis, if empty the system default value will be used',
|
||||||
exportJson: 'Export JSON',
|
exportJson: 'Export JSON',
|
||||||
viewResult: 'View Result',
|
viewResult: 'View result',
|
||||||
running: 'Running',
|
running: 'Running',
|
||||||
summary: 'Augmented Context',
|
summary: 'Augmented Context',
|
||||||
keywords: 'Keywords',
|
keywords: 'Keywords',
|
||||||
|
|||||||
@ -1634,6 +1634,8 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
|||||||
regularExpressions: '正则表达式',
|
regularExpressions: '正则表达式',
|
||||||
overlappedPercent: '重叠百分比',
|
overlappedPercent: '重叠百分比',
|
||||||
searchMethod: '搜索方法',
|
searchMethod: '搜索方法',
|
||||||
|
searchMethodTip: `决定该数据集启用的搜索方式,可选择全文、向量,或两者兼有。
|
||||||
|
Tokenizer 会根据所选方式将内容存储为对应的数据结构。`,
|
||||||
filenameEmbdWeight: '文件名嵌入权重',
|
filenameEmbdWeight: '文件名嵌入权重',
|
||||||
begin: '文件',
|
begin: '文件',
|
||||||
parserMethod: '解析方法',
|
parserMethod: '解析方法',
|
||||||
|
|||||||
@ -9,18 +9,29 @@ import {
|
|||||||
SelectWithSearchFlagOptionType,
|
SelectWithSearchFlagOptionType,
|
||||||
} from '@/components/originui/select-with-search';
|
} from '@/components/originui/select-with-search';
|
||||||
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||||
import { upperFirst } from 'lodash';
|
import { upperCase, upperFirst } from 'lodash';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { FileType, OutputFormatMap, PdfOutputFormat } from '../../constant';
|
import {
|
||||||
|
FileType,
|
||||||
|
OutputFormatMap,
|
||||||
|
SpreadsheetOutputFormat,
|
||||||
|
} from '../../constant';
|
||||||
import { CommonProps } from './interface';
|
import { CommonProps } from './interface';
|
||||||
import { buildFieldNameWithPrefix } from './utils';
|
import { buildFieldNameWithPrefix } from './utils';
|
||||||
|
|
||||||
|
const UppercaseFields = [
|
||||||
|
SpreadsheetOutputFormat.Html,
|
||||||
|
SpreadsheetOutputFormat.Json,
|
||||||
|
];
|
||||||
|
|
||||||
function buildOutputOptionsFormatMap() {
|
function buildOutputOptionsFormatMap() {
|
||||||
return Object.entries(OutputFormatMap).reduce<
|
return Object.entries(OutputFormatMap).reduce<
|
||||||
Record<string, SelectWithSearchFlagOptionType[]>
|
Record<string, SelectWithSearchFlagOptionType[]>
|
||||||
>((pre, [key, value]) => {
|
>((pre, [key, value]) => {
|
||||||
pre[key] = Object.values(value).map((v) => ({
|
pre[key] = Object.values(value).map((v) => ({
|
||||||
label: v === PdfOutputFormat.Json ? 'JSON' : upperFirst(v),
|
label: UppercaseFields.some((x) => x === v)
|
||||||
|
? upperCase(v)
|
||||||
|
: upperFirst(v),
|
||||||
value: v,
|
value: v,
|
||||||
}));
|
}));
|
||||||
return pre;
|
return pre;
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
import {
|
||||||
|
SelectWithSearch,
|
||||||
|
SelectWithSearchFlagOptionType,
|
||||||
|
} from '@/components/originui/select-with-search';
|
||||||
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||||
import { BlockButton, Button } from '@/components/ui/button';
|
import { BlockButton, Button } from '@/components/ui/button';
|
||||||
import { Form } from '@/components/ui/form';
|
import { Form } from '@/components/ui/form';
|
||||||
@ -49,6 +52,7 @@ type ParserItemProps = {
|
|||||||
index: number;
|
index: number;
|
||||||
fieldLength: number;
|
fieldLength: number;
|
||||||
remove: UseFieldArrayRemove;
|
remove: UseFieldArrayRemove;
|
||||||
|
fileFormatOptions: SelectWithSearchFlagOptionType[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const FormSchema = z.object({
|
export const FormSchema = z.object({
|
||||||
@ -67,7 +71,13 @@ export const FormSchema = z.object({
|
|||||||
|
|
||||||
export type ParserFormSchemaType = z.infer<typeof FormSchema>;
|
export type ParserFormSchemaType = z.infer<typeof FormSchema>;
|
||||||
|
|
||||||
function ParserItem({ name, index, fieldLength, remove }: ParserItemProps) {
|
function ParserItem({
|
||||||
|
name,
|
||||||
|
index,
|
||||||
|
fieldLength,
|
||||||
|
remove,
|
||||||
|
fileFormatOptions,
|
||||||
|
}: ParserItemProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const form = useFormContext<ParserFormSchemaType>();
|
const form = useFormContext<ParserFormSchemaType>();
|
||||||
const ref = useRef(null);
|
const ref = useRef(null);
|
||||||
@ -79,23 +89,15 @@ function ParserItem({ name, index, fieldLength, remove }: ParserItemProps) {
|
|||||||
const values = form.getValues();
|
const values = form.getValues();
|
||||||
const parserList = values.setups.slice(); // Adding, deleting, or modifying the parser array will not change the reference.
|
const parserList = values.setups.slice(); // Adding, deleting, or modifying the parser array will not change the reference.
|
||||||
|
|
||||||
const FileFormatOptions = buildOptions(
|
|
||||||
FileType,
|
|
||||||
t,
|
|
||||||
'dataflow.fileFormatOptions',
|
|
||||||
).filter(
|
|
||||||
(x) => x.value !== FileType.Video, // Temporarily hide the video option
|
|
||||||
);
|
|
||||||
|
|
||||||
const filteredFileFormatOptions = useMemo(() => {
|
const filteredFileFormatOptions = useMemo(() => {
|
||||||
const otherFileFormatList = parserList
|
const otherFileFormatList = parserList
|
||||||
.filter((_, idx) => idx !== index)
|
.filter((_, idx) => idx !== index)
|
||||||
.map((x) => x.fileFormat);
|
.map((x) => x.fileFormat);
|
||||||
|
|
||||||
return FileFormatOptions.filter((x) => {
|
return fileFormatOptions.filter((x) => {
|
||||||
return !otherFileFormatList.includes(x.value);
|
return !otherFileFormatList.includes(x.value);
|
||||||
});
|
});
|
||||||
}, [FileFormatOptions, index, parserList]);
|
}, [fileFormatOptions, index, parserList]);
|
||||||
|
|
||||||
const Widget =
|
const Widget =
|
||||||
typeof fileFormat === 'string' && fileFormat in FileFormatWidgetMap
|
typeof fileFormat === 'string' && fileFormat in FileFormatWidgetMap
|
||||||
@ -158,6 +160,14 @@ const ParserForm = ({ node }: INextOperatorForm) => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const defaultValues = useFormValues(initialParserValues, node);
|
const defaultValues = useFormValues(initialParserValues, node);
|
||||||
|
|
||||||
|
const FileFormatOptions = buildOptions(
|
||||||
|
FileType,
|
||||||
|
t,
|
||||||
|
'dataflow.fileFormatOptions',
|
||||||
|
).filter(
|
||||||
|
(x) => x.value !== FileType.Video, // Temporarily hide the video option
|
||||||
|
);
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
defaultValues,
|
defaultValues,
|
||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
@ -194,12 +204,15 @@ const ParserForm = ({ node }: INextOperatorForm) => {
|
|||||||
index={index}
|
index={index}
|
||||||
fieldLength={fields.length}
|
fieldLength={fields.length}
|
||||||
remove={remove}
|
remove={remove}
|
||||||
|
fileFormatOptions={FileFormatOptions}
|
||||||
></ParserItem>
|
></ParserItem>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
{fields.length < FileFormatOptions.length && (
|
||||||
<BlockButton onClick={add} type="button" className="mt-2.5">
|
<BlockButton onClick={add} type="button" className="mt-2.5">
|
||||||
{t('dataflow.addParser')}
|
{t('dataflow.addParser')}
|
||||||
</BlockButton>
|
</BlockButton>
|
||||||
|
)}
|
||||||
</form>
|
</form>
|
||||||
<div className="p-5">
|
<div className="p-5">
|
||||||
<Output list={outputList}></Output>
|
<Output list={outputList}></Output>
|
||||||
|
|||||||
@ -58,6 +58,7 @@ const TokenizerForm = ({ node }: INextOperatorForm) => {
|
|||||||
<RAGFlowFormItem
|
<RAGFlowFormItem
|
||||||
name="search_method"
|
name="search_method"
|
||||||
label={t('dataflow.searchMethod')}
|
label={t('dataflow.searchMethod')}
|
||||||
|
tooltip={t('dataflow.searchMethodTip')}
|
||||||
>
|
>
|
||||||
{(field) => (
|
{(field) => (
|
||||||
<MultiSelect
|
<MultiSelect
|
||||||
|
|||||||
@ -162,9 +162,7 @@ export default function DataFlow() {
|
|||||||
onClick={handleRunAgent}
|
onClick={handleRunAgent}
|
||||||
loading={running}
|
loading={running}
|
||||||
>
|
>
|
||||||
<CirclePlay
|
<CirclePlay className={isParsing ? 'animate-spin' : ''} />
|
||||||
className={isParsing || isLogEmpty ? 'animate-spin' : ''}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{isParsing || running ? t('dataflow.running') : t('flow.run')}
|
{isParsing || running ? t('dataflow.running') : t('flow.run')}
|
||||||
</ButtonLoading>
|
</ButtonLoading>
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export function DataflowTimeline({ traceList }: DataflowTimelineProps) {
|
|||||||
<div className="flex-1 flex items-center gap-5">
|
<div className="flex-1 flex items-center gap-5">
|
||||||
<Progress value={progress} className="h-1 flex-1" />
|
<Progress value={progress} className="h-1 flex-1" />
|
||||||
<span className="text-accent-primary text-xs">
|
<span className="text-accent-primary text-xs">
|
||||||
{progress}%
|
{progress.toFixed(2)}%
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -55,10 +55,10 @@ export function LogSheet({
|
|||||||
return (
|
return (
|
||||||
<Sheet open onOpenChange={hideModal} modal={false}>
|
<Sheet open onOpenChange={hideModal} modal={false}>
|
||||||
<SheetContent
|
<SheetContent
|
||||||
className={cn('top-20')}
|
className={cn('top-20 h-auto flex flex-col p-0 gap-0')}
|
||||||
onInteractOutside={(e) => e.preventDefault()}
|
onInteractOutside={(e) => e.preventDefault()}
|
||||||
>
|
>
|
||||||
<SheetHeader>
|
<SheetHeader className="p-5">
|
||||||
<SheetTitle className="flex items-center gap-2.5">
|
<SheetTitle className="flex items-center gap-2.5">
|
||||||
<Logs className="size-4" /> {t('flow.log')}
|
<Logs className="size-4" /> {t('flow.log')}
|
||||||
{isCompleted && (
|
{isCompleted && (
|
||||||
@ -82,13 +82,14 @@ export function LogSheet({
|
|||||||
)}
|
)}
|
||||||
</SheetTitle>
|
</SheetTitle>
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
<section className="max-h-[82vh] overflow-auto mt-6">
|
<section className="flex-1 overflow-auto px-5 pt-5">
|
||||||
{isLogEmpty ? (
|
{isLogEmpty ? (
|
||||||
<SkeletonCard className="mt-2" />
|
<SkeletonCard className="mt-2" />
|
||||||
) : (
|
) : (
|
||||||
<DataflowTimeline traceList={logs}></DataflowTimeline>
|
<DataflowTimeline traceList={logs}></DataflowTimeline>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
<div className="px-5 pb-5">
|
||||||
{isParsing ? (
|
{isParsing ? (
|
||||||
<Button
|
<Button
|
||||||
className="w-full mt-8 bg-state-error/10 text-state-error hover:bg-state-error hover:text-bg-base"
|
className="w-full mt-8 bg-state-error/10 text-state-error hover:bg-state-error hover:text-bg-base"
|
||||||
@ -106,6 +107,7 @@ export function LogSheet({
|
|||||||
{t('dataflow.exportJson')}
|
{t('dataflow.exportJson')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
</div>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -42,7 +42,7 @@ export function Banner() {
|
|||||||
export function NextBanner() {
|
export function NextBanner() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<section className="text-5xl pt-10 pb-14 font-bold">
|
<section className="text-5xl pt-10 pb-14 font-bold px-10">
|
||||||
<span className="text-text-primary">{t('header.welcome')}</span>
|
<span className="text-text-primary">{t('header.welcome')}</span>
|
||||||
<span className="pl-3 text-transparent bg-clip-text bg-gradient-to-l from-[#40EBE3] to-[#4A51FF]">
|
<span className="pl-3 text-transparent bg-clip-text bg-gradient-to-l from-[#40EBE3] to-[#4A51FF]">
|
||||||
RAGFlow
|
RAGFlow
|
||||||
|
|||||||
@ -4,15 +4,13 @@ import { Datasets } from './datasets';
|
|||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
return (
|
return (
|
||||||
<div className="mx-8">
|
|
||||||
<section>
|
<section>
|
||||||
<NextBanner></NextBanner>
|
<NextBanner></NextBanner>
|
||||||
<section className="h-[calc(100dvh-260px)] overflow-auto scrollbar-thin">
|
<section className="h-[calc(100dvh-260px)] overflow-auto px-10">
|
||||||
<Datasets></Datasets>
|
<Datasets></Datasets>
|
||||||
<Applications></Applications>
|
<Applications></Applications>
|
||||||
</section>
|
</section>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user