mirror of
https://github.com/infiniflow/ragflow.git
synced 2026-02-06 18:45:08 +08:00
Compare commits
3 Commits
cf1f523d03
...
5c1791d7f0
| Author | SHA1 | Date | |
|---|---|---|---|
| 5c1791d7f0 | |||
| e82617f6de | |||
| a7abc57f68 |
@ -1,5 +1,6 @@
|
|||||||
(window._iconfont_svg_string_4909832 =
|
(window._iconfont_svg_string_4909832 =
|
||||||
'<svg>' +
|
'<svg>' +
|
||||||
|
'<symbol id="icon-Pipeline" viewBox="0 0 1024 1024"><path d="M610.9184 729.6a59.392 59.392 0 0 1 59.3408 59.392v79.104a59.3408 59.3408 0 0 1-59.392 59.3408H413.1328a59.392 59.392 0 0 1-59.3408-59.392V788.992a59.392 59.392 0 0 1 59.392-59.3408h197.7856z m0-316.4672a59.392 59.392 0 0 1 59.3408 59.3408v79.104a59.3408 59.3408 0 0 1-59.392 59.392H413.1328a59.3408 59.3408 0 0 1-59.3408-59.392V472.4736a59.392 59.392 0 0 1 59.392-59.392h197.7856z m0-316.5184a59.392 59.392 0 0 1 59.3408 59.3408V235.008a59.3408 59.3408 0 0 1-59.392 59.392H413.1328A59.3408 59.3408 0 0 1 353.792 235.008V155.9552a59.392 59.392 0 0 1 59.392-59.392h197.7856z" fill="#00BEB4" ></path><path d="M749.3632 472.4224a197.8368 197.8368 0 0 1 0 395.6224l-4.608-0.256a39.5776 39.5776 0 0 1 4.608-78.848l6.9632-0.2048a118.6816 118.6816 0 0 0-6.9632-237.2096l-4.608-0.256a39.5776 39.5776 0 0 1 4.608-78.848zM274.6368 155.904l4.608 0.256a39.5776 39.5776 0 0 1-4.608 78.848 118.6816 118.6816 0 1 0 0 237.4144 39.5776 39.5776 0 1 1 0 79.104 197.7856 197.7856 0 1 1 0-395.6224z" fill="#1177D7" ></path></symbol>' +
|
||||||
'<symbol id="icon-dataflow-01" viewBox="0 0 1024 1024"><path d="M636.202667 214.954667c-18.688 1.493333-28.288 4.266667-34.944 7.68a85.333333 85.333333 0 0 0-37.290667 37.290666c-3.413333 6.656-6.186667 16.213333-7.68 34.944C554.666667 314.069333 554.666667 338.901333 554.666667 375.466667V469.333333h135.253333a128.042667 128.042667 0 1 1 0 85.333334H554.666667v93.866666c0 36.565333 0 61.397333 1.621333 80.597334 1.493333 18.688 4.266667 28.288 7.68 34.944a85.333333 85.333333 0 0 0 37.290667 37.290666c6.656 3.413333 16.213333 6.186667 34.944 7.68 14.08 1.152 31.232 1.493333 53.76 1.578667A128.042667 128.042667 0 0 1 938.666667 853.333333a128 128 0 0 1-248.746667 42.666667 814.037333 814.037333 0 0 1-60.672-1.877333c-23.978667-1.962667-46.037333-6.186667-66.730667-16.725334a170.666667 170.666667 0 0 1-74.581333-74.581333c-10.538667-20.693333-14.762667-42.752-16.725333-66.730667C469.333333 712.96 469.333333 684.629333 469.333333 650.325333V554.666667H334.08a128.042667 128.042667 0 1 1 0-85.333334H469.333333V373.717333c0-34.346667 0-62.72 1.877334-85.76 1.962667-24.021333 6.186667-46.08 16.725333-66.773333a170.666667 170.666667 0 0 1 74.581333-74.581333c20.693333-10.538667 42.752-14.762667 66.730667-16.725334a813.653333 813.653333 0 0 1 60.714667-1.834666 128.042667 128.042667 0 1 1 0 85.333333c-22.528 0.085333-39.68 0.426667-53.76 1.578667z" ></path></symbol>' +
|
'<symbol id="icon-dataflow-01" viewBox="0 0 1024 1024"><path d="M636.202667 214.954667c-18.688 1.493333-28.288 4.266667-34.944 7.68a85.333333 85.333333 0 0 0-37.290667 37.290666c-3.413333 6.656-6.186667 16.213333-7.68 34.944C554.666667 314.069333 554.666667 338.901333 554.666667 375.466667V469.333333h135.253333a128.042667 128.042667 0 1 1 0 85.333334H554.666667v93.866666c0 36.565333 0 61.397333 1.621333 80.597334 1.493333 18.688 4.266667 28.288 7.68 34.944a85.333333 85.333333 0 0 0 37.290667 37.290666c6.656 3.413333 16.213333 6.186667 34.944 7.68 14.08 1.152 31.232 1.493333 53.76 1.578667A128.042667 128.042667 0 0 1 938.666667 853.333333a128 128 0 0 1-248.746667 42.666667 814.037333 814.037333 0 0 1-60.672-1.877333c-23.978667-1.962667-46.037333-6.186667-66.730667-16.725334a170.666667 170.666667 0 0 1-74.581333-74.581333c-10.538667-20.693333-14.762667-42.752-16.725333-66.730667C469.333333 712.96 469.333333 684.629333 469.333333 650.325333V554.666667H334.08a128.042667 128.042667 0 1 1 0-85.333334H469.333333V373.717333c0-34.346667 0-62.72 1.877334-85.76 1.962667-24.021333 6.186667-46.08 16.725333-66.773333a170.666667 170.666667 0 0 1 74.581333-74.581333c20.693333-10.538667 42.752-14.762667 66.730667-16.725334a813.653333 813.653333 0 0 1 60.714667-1.834666 128.042667 128.042667 0 1 1 0 85.333333c-22.528 0.085333-39.68 0.426667-53.76 1.578667z" ></path></symbol>' +
|
||||||
'<symbol id="icon-knowledgegraph" viewBox="0 0 1024 1024"><path d="M190.464 489.472h327.68v40.96h-327.68z" ></path><path d="M482.34496 516.5056l111.26784-308.20352 38.54336 13.9264L520.86784 530.432z" ></path><path d="M620.544 196.608m-122.88 0a122.88 122.88 0 1 0 245.76 0 122.88 122.88 0 1 0-245.76 0Z" ></path><path d="M182.272 509.952m-122.88 0a122.88 122.88 0 1 0 245.76 0 122.88 122.88 0 1 0-245.76 0Z" ></path><path d="M558.65344 520.9088l283.77088 163.84-20.48 35.47136-283.77088-163.84z" ></path><path d="M841.728 686.08m-122.88 0a122.88 122.88 0 1 0 245.76 0 122.88 122.88 0 1 0-245.76 0Z" ></path><path d="M448.67584 803.77856l49.60256-323.91168 40.48896 6.20544-49.60256 323.91168z" ></path><path d="M512 530.432m-143.36 0a143.36 143.36 0 1 0 286.72 0 143.36 143.36 0 1 0-286.72 0Z" ></path><path d="M462.848 843.776m-102.4 0a102.4 102.4 0 1 0 204.8 0 102.4 102.4 0 1 0-204.8 0Z"></path></symbol>' +
|
'<symbol id="icon-knowledgegraph" viewBox="0 0 1024 1024"><path d="M190.464 489.472h327.68v40.96h-327.68z" ></path><path d="M482.34496 516.5056l111.26784-308.20352 38.54336 13.9264L520.86784 530.432z" ></path><path d="M620.544 196.608m-122.88 0a122.88 122.88 0 1 0 245.76 0 122.88 122.88 0 1 0-245.76 0Z" ></path><path d="M182.272 509.952m-122.88 0a122.88 122.88 0 1 0 245.76 0 122.88 122.88 0 1 0-245.76 0Z" ></path><path d="M558.65344 520.9088l283.77088 163.84-20.48 35.47136-283.77088-163.84z" ></path><path d="M841.728 686.08m-122.88 0a122.88 122.88 0 1 0 245.76 0 122.88 122.88 0 1 0-245.76 0Z" ></path><path d="M448.67584 803.77856l49.60256-323.91168 40.48896 6.20544-49.60256 323.91168z" ></path><path d="M512 530.432m-143.36 0a143.36 143.36 0 1 0 286.72 0 143.36 143.36 0 1 0-286.72 0Z" ></path><path d="M462.848 843.776m-102.4 0a102.4 102.4 0 1 0 204.8 0 102.4 102.4 0 1 0-204.8 0Z"></path></symbol>' +
|
||||||
'<symbol id="icon-mcp" viewBox="0 0 1024 1024"><path d="M171.84 477.184l296.192-296.128q39.808-39.808 96.064-39.808 56.32 0 96.128 39.808t39.808 96.064q0 7.488-0.704 14.72 6.848-0.64 13.888-0.64 57.152 0 97.536 40.32 40.32 40.448 40.32 97.536t-40.32 97.472l-269.696 269.696q-4.928 4.928 0 9.856l57.152 57.152a30.464 30.464 0 0 1-43.072 43.072l-57.152-57.152q-19.84-19.84-19.84-48t19.84-48l269.696-269.696q22.528-22.528 22.528-54.4t-22.528-54.4q-22.592-22.592-54.4-22.592-31.936 0-54.464 22.592l-17.28 17.216L435.2 598.336a30.464 30.464 0 0 1-43.008-0.064l-0.192-0.128a30.272 30.272 0 0 1 0.128-42.88L599.68 347.52l17.408-17.408q21.952-22.016 21.952-53.056t-21.952-52.992q-22.016-22.016-53.056-22.016t-52.992 22.016L214.912 520.256a30.464 30.464 0 0 1-43.072-43.072z m567.104-29.44L513.92 672.96q-39.808 39.808-96.128 39.808t-96.128-39.808q-39.808-39.808-39.808-96.128t39.808-96.128l225.088-225.024a30.464 30.464 0 0 1 43.008 43.008L364.8 523.712q-21.952 22.016-21.952 53.056t21.952 53.056q22.016 21.952 53.056 21.952t52.992-21.952l225.088-225.088a30.464 30.464 0 0 1 43.072 43.072z" ></path></symbol>' +
|
'<symbol id="icon-mcp" viewBox="0 0 1024 1024"><path d="M171.84 477.184l296.192-296.128q39.808-39.808 96.064-39.808 56.32 0 96.128 39.808t39.808 96.064q0 7.488-0.704 14.72 6.848-0.64 13.888-0.64 57.152 0 97.536 40.32 40.32 40.448 40.32 97.536t-40.32 97.472l-269.696 269.696q-4.928 4.928 0 9.856l57.152 57.152a30.464 30.464 0 0 1-43.072 43.072l-57.152-57.152q-19.84-19.84-19.84-48t19.84-48l269.696-269.696q22.528-22.528 22.528-54.4t-22.528-54.4q-22.592-22.592-54.4-22.592-31.936 0-54.464 22.592l-17.28 17.216L435.2 598.336a30.464 30.464 0 0 1-43.008-0.064l-0.192-0.128a30.272 30.272 0 0 1 0.128-42.88L599.68 347.52l17.408-17.408q21.952-22.016 21.952-53.056t-21.952-52.992q-22.016-22.016-53.056-22.016t-52.992 22.016L214.912 520.256a30.464 30.464 0 0 1-43.072-43.072z m567.104-29.44L513.92 672.96q-39.808 39.808-96.128 39.808t-96.128-39.808q-39.808-39.808-39.808-96.128t39.808-96.128l225.088-225.024a30.464 30.464 0 0 1 43.008 43.008L364.8 523.712q-21.952 22.016-21.952 53.056t21.952 53.056q22.016 21.952 53.056 21.952t52.992-21.952l225.088-225.088a30.464 30.464 0 0 1 43.072 43.072z" ></path></symbol>' +
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
|
import { useFetchAgentList } from '@/hooks/use-agent-request';
|
||||||
import { buildSelectOptions } from '@/utils/component-util';
|
import { buildSelectOptions } from '@/utils/component-util';
|
||||||
import { ArrowUpRight } from 'lucide-react';
|
import { ArrowUpRight } from 'lucide-react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import { useFormContext } from 'react-hook-form';
|
import { useFormContext } from 'react-hook-form';
|
||||||
|
import { SelectWithSearch } from '../originui/select-with-search';
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormField,
|
FormField,
|
||||||
@ -9,11 +12,12 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '../ui/form';
|
} from '../ui/form';
|
||||||
import { RAGFlowSelect } from '../ui/select';
|
import { MultiSelect } from '../ui/multi-select';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
toDataPipeline?: () => void;
|
toDataPipeline?: () => void;
|
||||||
formFieldName: string;
|
formFieldName: string;
|
||||||
|
isMult?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = [
|
const data = [
|
||||||
@ -22,16 +26,25 @@ const data = [
|
|||||||
{ id: '3', name: 'data-pipeline-3' },
|
{ id: '3', name: 'data-pipeline-3' },
|
||||||
{ id: '4', name: 'data-pipeline-4' },
|
{ id: '4', name: 'data-pipeline-4' },
|
||||||
];
|
];
|
||||||
export function DataFlowItem(props: IProps) {
|
export function DataFlowSelect(props: IProps) {
|
||||||
const { toDataPipeline, formFieldName } = props;
|
const { toDataPipeline, formFieldName, isMult = true } = props;
|
||||||
const { t } = useTranslate('knowledgeConfiguration');
|
const { t } = useTranslate('knowledgeConfiguration');
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
|
console.log('data-pipline form', form);
|
||||||
const toDataPipLine = () => {
|
const toDataPipLine = () => {
|
||||||
// window.open('/data-pipeline');
|
|
||||||
|
|
||||||
toDataPipeline?.();
|
toDataPipeline?.();
|
||||||
};
|
};
|
||||||
const options = buildSelectOptions(data, 'id', 'name');
|
const { data: dataPipelineOptions, loading } = useFetchAgentList({
|
||||||
|
canvas_category: 'dataflow_canvas',
|
||||||
|
});
|
||||||
|
const options = useMemo(() => {
|
||||||
|
const option = buildSelectOptions(
|
||||||
|
dataPipelineOptions?.canvas,
|
||||||
|
'id',
|
||||||
|
'title',
|
||||||
|
);
|
||||||
|
return option || [];
|
||||||
|
}, [dataPipelineOptions]);
|
||||||
return (
|
return (
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
@ -57,16 +70,27 @@ export function DataFlowItem(props: IProps) {
|
|||||||
|
|
||||||
<div className="text-muted-foreground">
|
<div className="text-muted-foreground">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<RAGFlowSelect
|
<>
|
||||||
|
{!isMult && (
|
||||||
|
<SelectWithSearch
|
||||||
{...field}
|
{...field}
|
||||||
placeholder={t('dataFlowPlaceholder')}
|
placeholder={t('dataFlowPlaceholder')}
|
||||||
options={options}
|
options={options}
|
||||||
/>
|
/>
|
||||||
|
)}
|
||||||
|
{isMult && (
|
||||||
|
<MultiSelect
|
||||||
|
{...field}
|
||||||
|
onValueChange={field.onChange}
|
||||||
|
placeholder={t('dataFlowPlaceholder')}
|
||||||
|
options={options}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex pt-1">
|
<div className="flex pt-1">
|
||||||
<div className="w-1/4"></div>
|
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export function EntityTypesFormField({
|
|||||||
return (
|
return (
|
||||||
<FormItem className=" items-center space-y-0 ">
|
<FormItem className=" items-center space-y-0 ">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<FormLabel className="text-sm text-muted-foreground whitespace-nowrap w-1/4">
|
<FormLabel className="text-sm whitespace-nowrap w-1/4">
|
||||||
<span className="text-red-600">*</span> {t('entityTypes')}
|
<span className="text-red-600">*</span> {t('entityTypes')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<div className="w-3/4">
|
<div className="w-3/4">
|
||||||
|
|||||||
@ -39,8 +39,8 @@ 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">
|
<section className="flex justify-between w-full">
|
||||||
<section className="flex gap-1 items-center">
|
<section className="flex gap-1 items-center w-full">
|
||||||
<div className="text-[20px] font-bold w-80% leading-5 text-ellipsis overflow-hidden">
|
<div className="text-[20px] font-bold w-80% leading-5 text-ellipsis overflow-hidden">
|
||||||
{data.name}
|
{data.name}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -45,6 +45,8 @@ export type SelectWithSearchFlagProps = {
|
|||||||
onChange?(value: string): void;
|
onChange?(value: string): void;
|
||||||
triggerClassName?: string;
|
triggerClassName?: string;
|
||||||
allowClear?: boolean;
|
allowClear?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
placeholder?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SelectWithSearch = forwardRef<
|
export const SelectWithSearch = forwardRef<
|
||||||
@ -58,6 +60,8 @@ export const SelectWithSearch = forwardRef<
|
|||||||
options = [],
|
options = [],
|
||||||
triggerClassName,
|
triggerClassName,
|
||||||
allowClear = false,
|
allowClear = false,
|
||||||
|
disabled = false,
|
||||||
|
placeholder = t('common.selectPlaceholder'),
|
||||||
},
|
},
|
||||||
ref,
|
ref,
|
||||||
) => {
|
) => {
|
||||||
@ -105,6 +109,7 @@ export const SelectWithSearch = forwardRef<
|
|||||||
role="combobox"
|
role="combobox"
|
||||||
aria-expanded={open}
|
aria-expanded={open}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
disabled={disabled}
|
||||||
className={cn(
|
className={cn(
|
||||||
'bg-background hover:bg-background border-input w-full justify-between px-3 font-normal outline-offset-0 outline-none focus-visible:outline-[3px] [&_svg]:pointer-events-auto',
|
'bg-background hover:bg-background border-input w-full justify-between px-3 font-normal outline-offset-0 outline-none focus-visible:outline-[3px] [&_svg]:pointer-events-auto',
|
||||||
triggerClassName,
|
triggerClassName,
|
||||||
@ -115,9 +120,7 @@ export const SelectWithSearch = forwardRef<
|
|||||||
<span className="leading-none truncate">{selectLabel}</span>
|
<span className="leading-none truncate">{selectLabel}</span>
|
||||||
</span>
|
</span>
|
||||||
) : (
|
) : (
|
||||||
<span className="text-muted-foreground">
|
<span className="text-muted-foreground">{placeholder}</span>
|
||||||
{t('common.selectPlaceholder')}
|
|
||||||
</span>
|
|
||||||
)}
|
)}
|
||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
{value && allowClear && (
|
{value && allowClear && (
|
||||||
|
|||||||
@ -62,7 +62,7 @@ export function UseGraphRagFormField() {
|
|||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
tooltip={t('useGraphRagTip')}
|
tooltip={t('useGraphRagTip')}
|
||||||
className="text-sm text-muted-foreground whitespace-break-spaces w-1/4"
|
className="text-sm whitespace-break-spaces w-1/4"
|
||||||
>
|
>
|
||||||
{t('useGraphRag')}
|
{t('useGraphRag')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
@ -125,7 +125,7 @@ const GraphRagItems = ({
|
|||||||
<FormItem className=" items-center space-y-0 ">
|
<FormItem className=" items-center space-y-0 ">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
className="text-sm text-muted-foreground whitespace-nowrap w-1/4"
|
className="text-sm whitespace-nowrap w-1/4"
|
||||||
tooltip={renderWideTooltip(
|
tooltip={renderWideTooltip(
|
||||||
<div
|
<div
|
||||||
dangerouslySetInnerHTML={{
|
dangerouslySetInnerHTML={{
|
||||||
@ -161,7 +161,7 @@ const GraphRagItems = ({
|
|||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
tooltip={renderWideTooltip('resolutionTip')}
|
tooltip={renderWideTooltip('resolutionTip')}
|
||||||
className="text-sm text-muted-foreground whitespace-nowrap w-1/4"
|
className="text-sm whitespace-nowrap w-1/4"
|
||||||
>
|
>
|
||||||
{t('resolution')}
|
{t('resolution')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
@ -190,7 +190,7 @@ const GraphRagItems = ({
|
|||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
tooltip={renderWideTooltip('communityTip')}
|
tooltip={renderWideTooltip('communityTip')}
|
||||||
className="text-sm text-muted-foreground whitespace-nowrap w-1/4"
|
className="text-sm whitespace-nowrap w-1/4"
|
||||||
>
|
>
|
||||||
{t('community')}
|
{t('community')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
|||||||
@ -2,11 +2,10 @@ import { FormLayout } from '@/constants/form';
|
|||||||
import { DocumentParserType } from '@/constants/knowledge';
|
import { DocumentParserType } from '@/constants/knowledge';
|
||||||
import { useTranslate } from '@/hooks/common-hooks';
|
import { useTranslate } from '@/hooks/common-hooks';
|
||||||
import random from 'lodash/random';
|
import random from 'lodash/random';
|
||||||
import { Plus } from 'lucide-react';
|
import { Shuffle } from 'lucide-react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useFormContext, useWatch } from 'react-hook-form';
|
import { useFormContext, useWatch } from 'react-hook-form';
|
||||||
import { SliderInputFormField } from '../slider-input-form-field';
|
import { SliderInputFormField } from '../slider-input-form-field';
|
||||||
import { Button } from '../ui/button';
|
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormField,
|
FormField,
|
||||||
@ -14,7 +13,7 @@ import {
|
|||||||
FormLabel,
|
FormLabel,
|
||||||
FormMessage,
|
FormMessage,
|
||||||
} from '../ui/form';
|
} from '../ui/form';
|
||||||
import { Input } from '../ui/input';
|
import { ExpandedInput } from '../ui/input';
|
||||||
import { Switch } from '../ui/switch';
|
import { Switch } from '../ui/switch';
|
||||||
import { Textarea } from '../ui/textarea';
|
import { Textarea } from '../ui/textarea';
|
||||||
|
|
||||||
@ -93,7 +92,7 @@ const RaptorFormFields = () => {
|
|||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
tooltip={t('useRaptorTip')}
|
tooltip={t('useRaptorTip')}
|
||||||
className="text-sm text-muted-foreground w-1/4 whitespace-break-spaces"
|
className="text-sm w-1/4 whitespace-break-spaces"
|
||||||
>
|
>
|
||||||
<div className="w-auto xl:w-20 2xl:w-24 3xl:w-28 4xl:w-auto ">
|
<div className="w-auto xl:w-20 2xl:w-24 3xl:w-28 4xl:w-auto ">
|
||||||
{t('useRaptor')}
|
{t('useRaptor')}
|
||||||
@ -130,7 +129,7 @@ const RaptorFormFields = () => {
|
|||||||
<div className="flex items-start">
|
<div className="flex items-start">
|
||||||
<FormLabel
|
<FormLabel
|
||||||
tooltip={t('promptTip')}
|
tooltip={t('promptTip')}
|
||||||
className="text-sm text-muted-foreground whitespace-nowrap w-1/4"
|
className="text-sm whitespace-nowrap w-1/4"
|
||||||
>
|
>
|
||||||
{t('prompt')}
|
{t('prompt')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
@ -185,21 +184,23 @@ const RaptorFormFields = () => {
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className=" items-center space-y-0 ">
|
<FormItem className=" items-center space-y-0 ">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<FormLabel className="text-sm text-muted-foreground whitespace-wrap w-1/4">
|
<FormLabel className="text-sm whitespace-wrap w-1/4">
|
||||||
{t('randomSeed')}
|
{t('randomSeed')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<div className="w-3/4">
|
<div className="w-3/4">
|
||||||
<FormControl defaultValue={0}>
|
<FormControl defaultValue={0}>
|
||||||
<div className="flex gap-4 items-center">
|
<ExpandedInput
|
||||||
<Input {...field} defaultValue={0} type="number" />
|
{...field}
|
||||||
<Button
|
className="w-full"
|
||||||
size={'sm'}
|
defaultValue={0}
|
||||||
|
type="number"
|
||||||
|
suffix={
|
||||||
|
<Shuffle
|
||||||
|
className="size-3.5 cursor-pointer"
|
||||||
onClick={handleGenerate}
|
onClick={handleGenerate}
|
||||||
type={'button'}
|
/>
|
||||||
>
|
}
|
||||||
<Plus />
|
/>
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { ControllerRenderProps, useFormContext } from 'react-hook-form';
|
|||||||
|
|
||||||
type RAGFlowFormItemProps = {
|
type RAGFlowFormItemProps = {
|
||||||
name: string;
|
name: string;
|
||||||
label: ReactNode;
|
label?: ReactNode;
|
||||||
tooltip?: ReactNode;
|
tooltip?: ReactNode;
|
||||||
children: ReactNode | ((field: ControllerRenderProps) => ReactNode);
|
children: ReactNode | ((field: ControllerRenderProps) => ReactNode);
|
||||||
horizontal?: boolean;
|
horizontal?: boolean;
|
||||||
@ -39,6 +39,7 @@ export function RAGFlowFormItem({
|
|||||||
'flex items-center': horizontal,
|
'flex items-center': horizontal,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
|
{label && (
|
||||||
<FormLabel
|
<FormLabel
|
||||||
required={required}
|
required={required}
|
||||||
tooltip={tooltip}
|
tooltip={tooltip}
|
||||||
@ -46,6 +47,7 @@ export function RAGFlowFormItem({
|
|||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
)}
|
||||||
<FormControl>
|
<FormControl>
|
||||||
{typeof children === 'function'
|
{typeof children === 'function'
|
||||||
? children(field)
|
? children(field)
|
||||||
|
|||||||
@ -54,8 +54,7 @@ export function SliderInputFormField({
|
|||||||
<FormLabel
|
<FormLabel
|
||||||
tooltip={tooltip}
|
tooltip={tooltip}
|
||||||
className={cn({
|
className={cn({
|
||||||
'text-sm text-muted-foreground whitespace-break-spaces w-1/4':
|
'text-sm whitespace-break-spaces w-1/4': isHorizontal,
|
||||||
isHorizontal,
|
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{label}
|
{label}
|
||||||
|
|||||||
@ -18,7 +18,7 @@ export const useNavigatePage = () => {
|
|||||||
|
|
||||||
const navigateToDataset = useCallback(
|
const navigateToDataset = useCallback(
|
||||||
(id: string) => () => {
|
(id: string) => () => {
|
||||||
navigate(`${Routes.Dataset}/${id}`);
|
navigate(`${Routes.DatasetBase}${Routes.DataSetOverview}/${id}`);
|
||||||
},
|
},
|
||||||
[navigate],
|
[navigate],
|
||||||
);
|
);
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
IAgentLogsResponse,
|
IAgentLogsResponse,
|
||||||
IFlow,
|
IFlow,
|
||||||
IFlowTemplate,
|
IFlowTemplate,
|
||||||
|
IPipeLineListRequest,
|
||||||
ITraceData,
|
ITraceData,
|
||||||
} from '@/interfaces/database/agent';
|
} from '@/interfaces/database/agent';
|
||||||
import { IDebugSingleRequestBody } from '@/interfaces/request/agent';
|
import { IDebugSingleRequestBody } from '@/interfaces/request/agent';
|
||||||
@ -16,6 +17,7 @@ import { IInputs } from '@/pages/agent/interface';
|
|||||||
import { useGetSharedChatSearchParams } from '@/pages/chat/shared-hooks';
|
import { useGetSharedChatSearchParams } from '@/pages/chat/shared-hooks';
|
||||||
import agentService, {
|
import agentService, {
|
||||||
fetchAgentLogsByCanvasId,
|
fetchAgentLogsByCanvasId,
|
||||||
|
fetchPipeLineList,
|
||||||
fetchTrace,
|
fetchTrace,
|
||||||
} from '@/services/agent-service';
|
} from '@/services/agent-service';
|
||||||
import api from '@/utils/api';
|
import api from '@/utils/api';
|
||||||
@ -123,7 +125,12 @@ export const useFetchAgentListByPage = () => {
|
|||||||
...pagination,
|
...pagination,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
initialData: { canvas: [], total: 0 },
|
placeholderData: (previousData) => {
|
||||||
|
if (previousData === undefined) {
|
||||||
|
return { canvas: [], total: 0 };
|
||||||
|
}
|
||||||
|
return previousData;
|
||||||
|
},
|
||||||
gcTime: 0,
|
gcTime: 0,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } = await agentService.listCanvasTeam(
|
const { data } = await agentService.listCanvasTeam(
|
||||||
@ -150,7 +157,7 @@ export const useFetchAgentListByPage = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: data.canvas,
|
data: data?.canvas ?? [],
|
||||||
loading,
|
loading,
|
||||||
searchString,
|
searchString,
|
||||||
handleInputChange: onInputChange,
|
handleInputChange: onInputChange,
|
||||||
@ -648,3 +655,26 @@ export const useFetchPrompt = () => {
|
|||||||
|
|
||||||
return { data, loading, refetch };
|
return { data, loading, refetch };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useFetchAgentList = ({
|
||||||
|
canvas_category = 'agent_canvas',
|
||||||
|
}: IPipeLineListRequest): {
|
||||||
|
data: {
|
||||||
|
canvas: IFlow[];
|
||||||
|
total: number;
|
||||||
|
};
|
||||||
|
loading: boolean;
|
||||||
|
} => {
|
||||||
|
const { data, isFetching: loading } = useQuery({
|
||||||
|
queryKey: ['fetchPipeLineList'],
|
||||||
|
initialData: [],
|
||||||
|
gcTime: 0,
|
||||||
|
queryFn: async () => {
|
||||||
|
const { data } = await fetchPipeLineList({ canvas_category });
|
||||||
|
|
||||||
|
return data?.data ?? [];
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return { data, loading };
|
||||||
|
};
|
||||||
|
|||||||
@ -236,7 +236,11 @@ export const useUpdateKnowledge = (shouldFetchList = false) => {
|
|||||||
return { data, loading, saveKnowledgeConfiguration: mutateAsync };
|
return { data, loading, saveKnowledgeConfiguration: mutateAsync };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFetchKnowledgeBaseConfiguration = (refreshCount?: number) => {
|
export const useFetchKnowledgeBaseConfiguration = (props?: {
|
||||||
|
isEdit?: boolean;
|
||||||
|
refreshCount?: number;
|
||||||
|
}) => {
|
||||||
|
const { isEdit = true, refreshCount } = props || { isEdit: true };
|
||||||
const { id } = useParams();
|
const { id } = useParams();
|
||||||
const [searchParams] = useSearchParams();
|
const [searchParams] = useSearchParams();
|
||||||
const knowledgeBaseId = searchParams.get('id') || id;
|
const knowledgeBaseId = searchParams.get('id') || id;
|
||||||
@ -253,10 +257,14 @@ export const useFetchKnowledgeBaseConfiguration = (refreshCount?: number) => {
|
|||||||
initialData: {} as IKnowledge,
|
initialData: {} as IKnowledge,
|
||||||
gcTime: 0,
|
gcTime: 0,
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
|
if (isEdit) {
|
||||||
const { data } = await kbService.get_kb_detail({
|
const { data } = await kbService.get_kb_detail({
|
||||||
kb_id: knowledgeBaseId,
|
kb_id: knowledgeBaseId,
|
||||||
});
|
});
|
||||||
return data?.data ?? {};
|
return data?.data ?? {};
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -266,3 +266,12 @@ export interface IAgentLogMessage {
|
|||||||
role: 'user' | 'assistant';
|
role: 'user' | 'assistant';
|
||||||
id: string;
|
id: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPipeLineListRequest {
|
||||||
|
page?: number;
|
||||||
|
page_size?: number;
|
||||||
|
keywords?: string;
|
||||||
|
orderby?: string;
|
||||||
|
desc?: boolean;
|
||||||
|
canvas_category?: 'agent_canvas' | 'dataflow_canvas';
|
||||||
|
}
|
||||||
|
|||||||
@ -1636,6 +1636,10 @@ This delimiter is used to split the input text into several text pieces echo of
|
|||||||
chunkerDescription: 'Chunker',
|
chunkerDescription: 'Chunker',
|
||||||
tokenizer: 'Tokenizer',
|
tokenizer: 'Tokenizer',
|
||||||
tokenizerDescription: 'Tokenizer',
|
tokenizerDescription: 'Tokenizer',
|
||||||
|
splitter: 'Splitter',
|
||||||
|
splitterDescription: 'Splitter',
|
||||||
|
hierarchicalMergerDescription: 'Hierarchical merger',
|
||||||
|
hierarchicalMerger: 'Hierarchical merger',
|
||||||
outputFormat: 'Output format',
|
outputFormat: 'Output format',
|
||||||
lang: 'Language',
|
lang: 'Language',
|
||||||
fileFormats: 'File formats',
|
fileFormats: 'File formats',
|
||||||
|
|||||||
@ -1544,6 +1544,10 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
|||||||
chunkerDescription: '分块器',
|
chunkerDescription: '分块器',
|
||||||
tokenizer: '分词器',
|
tokenizer: '分词器',
|
||||||
tokenizerDescription: '分词器',
|
tokenizerDescription: '分词器',
|
||||||
|
splitter: '拆分器',
|
||||||
|
splitterDescription: '拆分器',
|
||||||
|
hierarchicalMergerDesription: '分层合并',
|
||||||
|
hierarchicalMerger: '分层合并',
|
||||||
outputFormat: '输出格式',
|
outputFormat: '输出格式',
|
||||||
lang: '语言',
|
lang: '语言',
|
||||||
fileFormats: '文件格式',
|
fileFormats: '文件格式',
|
||||||
|
|||||||
@ -86,7 +86,7 @@ export function FileUploadDirectUpload({
|
|||||||
</div>
|
</div>
|
||||||
<p className="font-medium text-sm">Drag & drop files here</p>
|
<p className="font-medium text-sm">Drag & drop files here</p>
|
||||||
<p className="text-muted-foreground text-xs">
|
<p className="text-muted-foreground text-xs">
|
||||||
Or click to browse (max 2 files)
|
Or click to browse (max 1 files)
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<FileUploadTrigger asChild>
|
<FileUploadTrigger asChild>
|
||||||
|
|||||||
@ -51,7 +51,7 @@ const RunSheet = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sheet onOpenChange={hideModal} open>
|
<Sheet onOpenChange={hideModal} open modal={false}>
|
||||||
<SheetContent className={cn('top-20 p-2')}>
|
<SheetContent className={cn('top-20 p-2')}>
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
<SheetTitle>{t('flow.testRun')}</SheetTitle>
|
<SheetTitle>{t('flow.testRun')}</SheetTitle>
|
||||||
|
|||||||
@ -69,7 +69,7 @@ export function RegularExpressions({
|
|||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader className="flex-row justify-between items-center">
|
<CardHeader className="flex-row justify-between items-center">
|
||||||
<CardTitle>H{index}</CardTitle>
|
<CardTitle>H{index + 1}</CardTitle>
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant={'ghost'}
|
variant={'ghost'}
|
||||||
|
|||||||
34
web/src/pages/data-flow/hooks/use-run-dataflow.ts
Normal file
34
web/src/pages/data-flow/hooks/use-run-dataflow.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import { useSendMessageBySSE } from '@/hooks/use-send-message';
|
||||||
|
import api from '@/utils/api';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
import { useParams } from 'umi';
|
||||||
|
import { useSaveGraphBeforeOpeningDebugDrawer } from './use-save-graph';
|
||||||
|
|
||||||
|
export function useRunDataflow(showLogSheet: () => void) {
|
||||||
|
const { send } = useSendMessageBySSE(api.runCanvas);
|
||||||
|
const { id } = useParams();
|
||||||
|
|
||||||
|
const { handleRun: saveGraph, loading } =
|
||||||
|
useSaveGraphBeforeOpeningDebugDrawer(showLogSheet!);
|
||||||
|
|
||||||
|
const run = useCallback(
|
||||||
|
async (fileResponseData: Record<string, any>) => {
|
||||||
|
const success = await saveGraph();
|
||||||
|
if (!success) return;
|
||||||
|
const res = await send({
|
||||||
|
id,
|
||||||
|
query: '',
|
||||||
|
session_id: null,
|
||||||
|
inputs: fileResponseData,
|
||||||
|
});
|
||||||
|
console.log('🚀 ~ useRunDataflow ~ res:', res);
|
||||||
|
|
||||||
|
if (res && res?.response.status === 200 && res?.data?.code === 0) {
|
||||||
|
// fetch canvas
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[id, saveGraph, send],
|
||||||
|
);
|
||||||
|
|
||||||
|
return { run, loading: loading };
|
||||||
|
}
|
||||||
@ -1,8 +1,4 @@
|
|||||||
import {
|
import { useFetchAgent, useSetAgent } from '@/hooks/use-agent-request';
|
||||||
useFetchAgent,
|
|
||||||
useResetAgent,
|
|
||||||
useSetAgent,
|
|
||||||
} from '@/hooks/use-agent-request';
|
|
||||||
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||||
import { formatDate } from '@/utils/date';
|
import { formatDate } from '@/utils/date';
|
||||||
import { useDebounceEffect } from 'ahooks';
|
import { useDebounceEffect } from 'ahooks';
|
||||||
@ -34,21 +30,22 @@ export const useSaveGraph = (showMessage: boolean = true) => {
|
|||||||
|
|
||||||
export const useSaveGraphBeforeOpeningDebugDrawer = (show: () => void) => {
|
export const useSaveGraphBeforeOpeningDebugDrawer = (show: () => void) => {
|
||||||
const { saveGraph, loading } = useSaveGraph();
|
const { saveGraph, loading } = useSaveGraph();
|
||||||
const { resetAgent } = useResetAgent();
|
// const { resetAgent } = useResetAgent();
|
||||||
|
|
||||||
const handleRun = useCallback(
|
const handleRun = useCallback(
|
||||||
async (nextNodes?: RAGFlowNodeType[]) => {
|
async (nextNodes?: RAGFlowNodeType[]) => {
|
||||||
const saveRet = await saveGraph(nextNodes);
|
const saveRet = await saveGraph(nextNodes);
|
||||||
if (saveRet?.code === 0) {
|
if (saveRet?.code === 0) {
|
||||||
// Call the reset api before opening the run drawer each time
|
// Call the reset api before opening the run drawer each time
|
||||||
const resetRet = await resetAgent();
|
// const resetRet = await resetAgent();
|
||||||
// After resetting, all previous messages will be cleared.
|
// After resetting, all previous messages will be cleared.
|
||||||
if (resetRet?.code === 0) {
|
// if (resetRet?.code === 0) {
|
||||||
show();
|
show();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
return saveRet?.code === 0;
|
||||||
},
|
},
|
||||||
[saveGraph, resetAgent, show],
|
[saveGraph, show],
|
||||||
);
|
);
|
||||||
|
|
||||||
return { handleRun, loading };
|
return { handleRun, loading };
|
||||||
|
|||||||
@ -91,13 +91,7 @@ export function useShowDrawer({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (drawerVisible) {
|
if (drawerVisible) {
|
||||||
if (inputs.length > 0) {
|
|
||||||
showRunModal();
|
showRunModal();
|
||||||
hideChatModal();
|
|
||||||
} else {
|
|
||||||
showChatModal();
|
|
||||||
hideRunModal();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}, [
|
}, [
|
||||||
hideChatModal,
|
hideChatModal,
|
||||||
|
|||||||
@ -6,60 +6,21 @@ import {
|
|||||||
} from '@/components/ui/sheet';
|
} from '@/components/ui/sheet';
|
||||||
import { IModalProps } from '@/interfaces/common';
|
import { IModalProps } from '@/interfaces/common';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
import { useCallback } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { BeginId } from '../constant';
|
import { useRunDataflow } from '../hooks/use-run-dataflow';
|
||||||
import DebugContent from '../debug-content';
|
import { UploaderForm } from './uploader';
|
||||||
import { useGetBeginNodeDataInputs } from '../hooks/use-get-begin-query';
|
|
||||||
import { useSaveGraphBeforeOpeningDebugDrawer } from '../hooks/use-save-graph';
|
|
||||||
import { BeginQuery } from '../interface';
|
|
||||||
import useGraphStore from '../store';
|
|
||||||
import { buildBeginQueryWithObject } from '../utils';
|
|
||||||
|
|
||||||
const RunSheet = ({
|
const RunSheet = ({ hideModal, showModal: showLogSheet }: IModalProps<any>) => {
|
||||||
hideModal,
|
|
||||||
showModal: showChatModal,
|
|
||||||
}: IModalProps<any>) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { updateNodeForm, getNode } = useGraphStore((state) => state);
|
|
||||||
|
|
||||||
const inputs = useGetBeginNodeDataInputs();
|
const { run, loading } = useRunDataflow(() => {});
|
||||||
|
|
||||||
const { handleRun, loading } = useSaveGraphBeforeOpeningDebugDrawer(
|
|
||||||
showChatModal!,
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleRunAgent = useCallback(
|
|
||||||
(nextValues: BeginQuery[]) => {
|
|
||||||
const beginNode = getNode(BeginId);
|
|
||||||
const inputs: Record<string, BeginQuery> = beginNode?.data.form.inputs;
|
|
||||||
|
|
||||||
const nextInputs = buildBeginQueryWithObject(inputs, nextValues);
|
|
||||||
|
|
||||||
const currentNodes = updateNodeForm(BeginId, nextInputs, ['inputs']);
|
|
||||||
handleRun(currentNodes);
|
|
||||||
hideModal?.();
|
|
||||||
},
|
|
||||||
[getNode, handleRun, hideModal, updateNodeForm],
|
|
||||||
);
|
|
||||||
|
|
||||||
const onOk = useCallback(
|
|
||||||
async (nextValues: any[]) => {
|
|
||||||
handleRunAgent(nextValues);
|
|
||||||
},
|
|
||||||
[handleRunAgent],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Sheet onOpenChange={hideModal} open>
|
<Sheet onOpenChange={hideModal} open modal={false}>
|
||||||
<SheetContent className={cn('top-20 p-2')}>
|
<SheetContent className={cn('top-20 p-2')}>
|
||||||
<SheetHeader>
|
<SheetHeader>
|
||||||
<SheetTitle>{t('flow.testRun')}</SheetTitle>
|
<SheetTitle>{t('flow.testRun')}</SheetTitle>
|
||||||
<DebugContent
|
<UploaderForm ok={run} loading={loading}></UploaderForm>
|
||||||
ok={onOk}
|
|
||||||
parameters={inputs}
|
|
||||||
loading={loading}
|
|
||||||
></DebugContent>
|
|
||||||
</SheetHeader>
|
</SheetHeader>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
|
|||||||
57
web/src/pages/data-flow/run-sheet/uploader.tsx
Normal file
57
web/src/pages/data-flow/run-sheet/uploader.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||||
|
import { ButtonLoading } from '@/components/ui/button';
|
||||||
|
import { Form } from '@/components/ui/form';
|
||||||
|
import { FileUploadDirectUpload } from '@/pages/agent/debug-content/uploader';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
const formSchema = z.object({
|
||||||
|
file: z.record(z.any()),
|
||||||
|
});
|
||||||
|
|
||||||
|
export type FormSchemaType = z.infer<typeof formSchema>;
|
||||||
|
|
||||||
|
type UploaderFormProps = {
|
||||||
|
ok: (values: FormSchemaType) => void;
|
||||||
|
loading: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function UploaderForm({ ok, loading }: UploaderFormProps) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const form = useForm<FormSchemaType>({
|
||||||
|
resolver: zodResolver(formSchema),
|
||||||
|
defaultValues: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(ok)} className="space-y-8">
|
||||||
|
<RAGFlowFormItem name="file">
|
||||||
|
{(field) => {
|
||||||
|
return (
|
||||||
|
<FileUploadDirectUpload
|
||||||
|
value={field.value}
|
||||||
|
onChange={field.onChange}
|
||||||
|
></FileUploadDirectUpload>
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
</RAGFlowFormItem>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<ButtonLoading
|
||||||
|
type="submit"
|
||||||
|
loading={loading}
|
||||||
|
className="w-full mt-1"
|
||||||
|
>
|
||||||
|
{t('flow.run')}
|
||||||
|
</ButtonLoading>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -1,17 +1,21 @@
|
|||||||
|
import { IconFont } from '@/components/icon-font';
|
||||||
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Link, Route, Settings2, Unlink } from 'lucide-react';
|
import { Link, Settings2, Unlink } from 'lucide-react';
|
||||||
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import LinkDataPipelineModal from './link-data-pipline-modal';
|
||||||
|
|
||||||
interface DataPipelineItemProps {
|
interface DataPipelineItemProps {
|
||||||
name: string;
|
name: string;
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
isDefault?: boolean;
|
isDefault?: boolean;
|
||||||
linked?: boolean;
|
linked?: boolean;
|
||||||
|
openLinkModalFunc?: (open: boolean) => void;
|
||||||
}
|
}
|
||||||
const DataPipelineItem = (props: DataPipelineItemProps) => {
|
const DataPipelineItem = (props: DataPipelineItemProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { name, avatar, isDefault, linked } = props;
|
const { name, avatar, isDefault, linked, openLinkModalFunc } = props;
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-between gap-1 px-2 rounded-lg border">
|
<div className="flex items-center justify-between gap-1 px-2 rounded-lg border">
|
||||||
<div className="flex items-center gap-1">
|
<div className="flex items-center gap-1">
|
||||||
@ -27,15 +31,24 @@ const DataPipelineItem = (props: DataPipelineItemProps) => {
|
|||||||
<Button variant={'transparent'} className="border-none">
|
<Button variant={'transparent'} className="border-none">
|
||||||
<Settings2 />
|
<Settings2 />
|
||||||
</Button>
|
</Button>
|
||||||
<Button variant={'transparent'} className="border-none">
|
{!isDefault && (
|
||||||
|
<Button
|
||||||
|
variant={'transparent'}
|
||||||
|
className="border-none"
|
||||||
|
onClick={() => {
|
||||||
|
openLinkModalFunc?.(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
{linked ? <Link /> : <Unlink />}
|
{linked ? <Link /> : <Unlink />}
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
const LinkDataPipeline = () => {
|
const LinkDataPipeline = () => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
const [openLinkModal, setOpenLinkModal] = useState(false);
|
||||||
const testNode = [
|
const testNode = [
|
||||||
{
|
{
|
||||||
name: 'Data Pipeline 1',
|
name: 'Data Pipeline 1',
|
||||||
@ -49,11 +62,14 @@ const LinkDataPipeline = () => {
|
|||||||
linked: false,
|
linked: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const openLinkModalFunc = (open: boolean) => {
|
||||||
|
setOpenLinkModal(open);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
<section className="flex flex-col">
|
<section className="flex flex-col">
|
||||||
<div className="flex items-center gap-1 text-text-primary text-sm">
|
<div className="flex items-center gap-1 text-text-primary text-sm">
|
||||||
<Route className="size-4" />
|
<IconFont name="Pipeline" />
|
||||||
{t('knowledgeConfiguration.dataPipeline')}
|
{t('knowledgeConfiguration.dataPipeline')}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
@ -70,9 +86,19 @@ const LinkDataPipeline = () => {
|
|||||||
</section>
|
</section>
|
||||||
<section className="flex flex-col gap-2">
|
<section className="flex flex-col gap-2">
|
||||||
{testNode.map((item) => (
|
{testNode.map((item) => (
|
||||||
<DataPipelineItem key={item.name} {...item} />
|
<DataPipelineItem
|
||||||
|
key={item.name}
|
||||||
|
openLinkModalFunc={openLinkModalFunc}
|
||||||
|
{...item}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
<LinkDataPipelineModal
|
||||||
|
open={openLinkModal}
|
||||||
|
setOpen={(open: boolean) => {
|
||||||
|
openLinkModalFunc(open);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -0,0 +1,95 @@
|
|||||||
|
import { DataFlowSelect } from '@/components/data-pipeline-select';
|
||||||
|
import Input from '@/components/originui/input';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from '@/components/ui/form';
|
||||||
|
import { Modal } from '@/components/ui/modal/modal';
|
||||||
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { t } from 'i18next';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { linkPiplineFormSchema } from '../form-schema';
|
||||||
|
|
||||||
|
const LinkDataPipelineModal = ({
|
||||||
|
open,
|
||||||
|
setOpen,
|
||||||
|
}: {
|
||||||
|
open: boolean;
|
||||||
|
setOpen: (open: boolean) => void;
|
||||||
|
}) => {
|
||||||
|
const form = useForm<z.infer<typeof linkPiplineFormSchema>>({
|
||||||
|
resolver: zodResolver(linkPiplineFormSchema),
|
||||||
|
defaultValues: { data_flow: ['888'], file_filter: '' },
|
||||||
|
});
|
||||||
|
// const [open, setOpen] = useState(false);
|
||||||
|
const { navigateToAgents } = useNavigatePage();
|
||||||
|
const handleFormSubmit = (values: any) => {
|
||||||
|
console.log(values);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
title={t('knowledgeConfiguration.linkDataPipeline')}
|
||||||
|
open={open}
|
||||||
|
onOpenChange={setOpen}
|
||||||
|
showfooter={false}
|
||||||
|
>
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(handleFormSubmit)}>
|
||||||
|
<div className="flex flex-col gap-4 ">
|
||||||
|
<DataFlowSelect
|
||||||
|
toDataPipeline={navigateToAgents}
|
||||||
|
formFieldName="data_flow"
|
||||||
|
/>
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name={'file_filter'}
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem className=" items-center space-y-0 ">
|
||||||
|
<div className="flex flex-col gap-1">
|
||||||
|
<div className="flex gap-2 justify-between ">
|
||||||
|
<FormLabel
|
||||||
|
tooltip={t('knowledgeConfiguration.fileFilterTip')}
|
||||||
|
className="text-sm text-text-primary whitespace-wrap "
|
||||||
|
>
|
||||||
|
{t('knowledgeConfiguration.fileFilter')}
|
||||||
|
</FormLabel>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="text-muted-foreground">
|
||||||
|
<FormControl>
|
||||||
|
<Input
|
||||||
|
placeholder={t('dataFlowPlaceholder')}
|
||||||
|
{...field}
|
||||||
|
/>
|
||||||
|
</FormControl>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex pt-1">
|
||||||
|
<div className="w-full"></div>
|
||||||
|
<FormMessage />
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="flex justify-end gap-1">
|
||||||
|
<Button type="reset" variant={'outline'} className="btn-primary">
|
||||||
|
{t('modal.cancelText')}
|
||||||
|
</Button>
|
||||||
|
<Button type="submit" variant={'default'} className="btn-primary">
|
||||||
|
{t('modal.okText')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default LinkDataPipelineModal;
|
||||||
@ -9,6 +9,9 @@ export function ConfigurationFormContainer({
|
|||||||
return <section className={cn('space-y-4', className)}>{children}</section>;
|
return <section className={cn('space-y-4', className)}>{children}</section>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MainContainer({ children }: PropsWithChildren) {
|
export function MainContainer({
|
||||||
return <section className="space-y-5">{children}</section>;
|
children,
|
||||||
|
className,
|
||||||
|
}: PropsWithChildren & { className?: string }) {
|
||||||
|
return <section className={cn('space-y-5', className)}>{children}</section>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { SelectWithSearch } from '@/components/originui/select-with-search';
|
||||||
import {
|
import {
|
||||||
FormControl,
|
FormControl,
|
||||||
FormField,
|
FormField,
|
||||||
@ -16,8 +17,12 @@ import {
|
|||||||
useSelectChunkMethodList,
|
useSelectChunkMethodList,
|
||||||
useSelectEmbeddingModelOptions,
|
useSelectEmbeddingModelOptions,
|
||||||
} from '../hooks';
|
} from '../hooks';
|
||||||
|
interface IProps {
|
||||||
export function ChunkMethodItem() {
|
line?: 1 | 2;
|
||||||
|
isEdit?: boolean;
|
||||||
|
}
|
||||||
|
export function ChunkMethodItem(props: IProps) {
|
||||||
|
const { line } = props;
|
||||||
const { t } = useTranslate('knowledgeConfiguration');
|
const { t } = useTranslate('knowledgeConfiguration');
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
// const handleChunkMethodSelectChange = useHandleChunkMethodSelectChange(form);
|
// const handleChunkMethodSelectChange = useHandleChunkMethodSelectChange(form);
|
||||||
@ -28,28 +33,29 @@ export function ChunkMethodItem() {
|
|||||||
control={form.control}
|
control={form.control}
|
||||||
name={'parser_id'}
|
name={'parser_id'}
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className=" items-center space-y-0 ">
|
<FormItem className=" items-center space-y-1">
|
||||||
<div className="flex items-center">
|
<div className={line === 1 ? 'flex items-center' : ''}>
|
||||||
<FormLabel
|
<FormLabel
|
||||||
required
|
required
|
||||||
tooltip={t('chunkMethodTip')}
|
tooltip={t('chunkMethodTip')}
|
||||||
className="text-sm text-muted-foreground whitespace-wrap w-1/4"
|
className={cn('text-sm', {
|
||||||
|
'w-1/4 whitespace-pre-wrap': line === 1,
|
||||||
|
})}
|
||||||
>
|
>
|
||||||
{t('chunkMethod')}
|
{t('chunkMethod')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<div className="w-3/4 ">
|
<div className={line === 1 ? 'w-3/4 ' : 'w-full'}>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<RAGFlowSelect
|
<RAGFlowSelect
|
||||||
{...field}
|
{...field}
|
||||||
options={parserList}
|
options={parserList}
|
||||||
placeholder={t('chunkMethodPlaceholder')}
|
placeholder={t('chunkMethodPlaceholder')}
|
||||||
// onChange={handleChunkMethodSelectChange}
|
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex pt-1">
|
<div className="flex pt-1">
|
||||||
<div className="w-1/4"></div>
|
<div className={line === 1 ? 'w-1/4' : ''}></div>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
@ -57,14 +63,13 @@ export function ChunkMethodItem() {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
export function EmbeddingModelItem({ line = 1, isEdit = true }: IProps) {
|
||||||
export function EmbeddingModelItem({ line = 1 }: { line?: 1 | 2 }) {
|
|
||||||
const { t } = useTranslate('knowledgeConfiguration');
|
const { t } = useTranslate('knowledgeConfiguration');
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
const embeddingModelOptions = useSelectEmbeddingModelOptions();
|
const embeddingModelOptions = useSelectEmbeddingModelOptions();
|
||||||
const disabled = useHasParsedDocument();
|
const disabled = useHasParsedDocument(isEdit);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={'embd_id'}
|
name={'embd_id'}
|
||||||
@ -89,22 +94,24 @@ export function EmbeddingModelItem({ line = 1 }: { line?: 1 | 2 }) {
|
|||||||
className={cn('text-muted-foreground', { 'w-3/4': line === 1 })}
|
className={cn('text-muted-foreground', { 'w-3/4': line === 1 })}
|
||||||
>
|
>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<RAGFlowSelect
|
<SelectWithSearch
|
||||||
{...field}
|
onChange={field.onChange}
|
||||||
|
value={field.value}
|
||||||
options={embeddingModelOptions}
|
options={embeddingModelOptions}
|
||||||
disabled={disabled}
|
disabled={isEdit ? disabled : false}
|
||||||
placeholder={t('embeddingModelPlaceholder')}
|
placeholder={t('embeddingModelPlaceholder')}
|
||||||
/>
|
/>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex pt-1">
|
<div className="flex pt-1">
|
||||||
<div className="w-1/4"></div>
|
<div className={line === 1 ? 'w-1/4' : ''}></div>
|
||||||
<FormMessage />
|
<FormMessage />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -71,3 +71,8 @@ export const formSchema = z.object({
|
|||||||
pagerank: z.number(),
|
pagerank: z.number(),
|
||||||
// icon: z.array(z.instanceof(File)),
|
// icon: z.array(z.instanceof(File)),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const linkPiplineFormSchema = z.object({
|
||||||
|
data_flow: z.array(z.string()),
|
||||||
|
file_filter: z.string().optional(),
|
||||||
|
});
|
||||||
|
|||||||
@ -24,7 +24,7 @@ export function GeneralForm() {
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="items-center space-y-0">
|
<FormItem className="items-center space-y-0">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<FormLabel className="text-sm text-muted-foreground whitespace-nowrap w-1/4">
|
<FormLabel className="text-sm whitespace-nowrap w-1/4">
|
||||||
<span className="text-red-600">*</span>
|
<span className="text-red-600">*</span>
|
||||||
{t('common.name')}
|
{t('common.name')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
@ -45,7 +45,7 @@ export function GeneralForm() {
|
|||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem className="items-center space-y-0">
|
<FormItem className="items-center space-y-0">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<FormLabel className="text-sm text-muted-foreground whitespace-nowrap w-1/4">
|
<FormLabel className="text-sm whitespace-nowrap w-1/4">
|
||||||
{t('setting.avatar')}
|
{t('setting.avatar')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl className="w-3/4">
|
<FormControl className="w-3/4">
|
||||||
@ -70,7 +70,7 @@ export function GeneralForm() {
|
|||||||
return (
|
return (
|
||||||
<FormItem className="items-center space-y-0">
|
<FormItem className="items-center space-y-0">
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<FormLabel className="text-sm text-muted-foreground whitespace-nowrap w-1/4">
|
<FormLabel className="text-sm whitespace-nowrap w-1/4">
|
||||||
{t('flow.description')}
|
{t('flow.description')}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl className="w-3/4">
|
<FormControl className="w-3/4">
|
||||||
|
|||||||
@ -25,8 +25,10 @@ export function useSelectEmbeddingModelOptions() {
|
|||||||
return allOptions[LlmModelType.Embedding];
|
return allOptions[LlmModelType.Embedding];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useHasParsedDocument() {
|
export function useHasParsedDocument(isEdit?: boolean) {
|
||||||
const { data: knowledgeDetails } = useFetchKnowledgeBaseConfiguration();
|
const { data: knowledgeDetails } = useFetchKnowledgeBaseConfiguration({
|
||||||
|
isEdit,
|
||||||
|
});
|
||||||
return knowledgeDetails.chunk_num > 0;
|
return knowledgeDetails.chunk_num > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +54,7 @@ export const useFetchKnowledgeConfigurationOnMount = (
|
|||||||
'pagerank',
|
'pagerank',
|
||||||
'avatar',
|
'avatar',
|
||||||
]),
|
]),
|
||||||
};
|
} as z.infer<typeof formSchema>;
|
||||||
form.reset(formValues);
|
form.reset(formValues);
|
||||||
}, [form, knowledgeDetails]);
|
}, [form, knowledgeDetails]);
|
||||||
|
|
||||||
|
|||||||
@ -82,7 +82,7 @@ export default function DatasetSettings() {
|
|||||||
className="space-y-6 flex-1"
|
className="space-y-6 flex-1"
|
||||||
>
|
>
|
||||||
<div className="w-[768px] h-[calc(100vh-240px)] pr-1 overflow-y-auto scrollbar-auto">
|
<div className="w-[768px] h-[calc(100vh-240px)] pr-1 overflow-y-auto scrollbar-auto">
|
||||||
<MainContainer>
|
<MainContainer className="text-text-secondary">
|
||||||
<GeneralForm></GeneralForm>
|
<GeneralForm></GeneralForm>
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
|
|||||||
@ -28,7 +28,7 @@ export function SideBar({ refreshCount }: PropType) {
|
|||||||
const pathName = useSecondPathName();
|
const pathName = useSecondPathName();
|
||||||
const { handleMenuClick } = useHandleMenuClick();
|
const { handleMenuClick } = useHandleMenuClick();
|
||||||
// refreshCount: be for avatar img sync update on top left
|
// refreshCount: be for avatar img sync update on top left
|
||||||
const { data } = useFetchKnowledgeBaseConfiguration(refreshCount);
|
const { data } = useFetchKnowledgeBaseConfiguration({ refreshCount });
|
||||||
const { data: routerData } = useFetchKnowledgeGraph();
|
const { data: routerData } = useFetchKnowledgeGraph();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ export function SideBar({ refreshCount }: PropType) {
|
|||||||
{
|
{
|
||||||
icon: Banknote,
|
icon: Banknote,
|
||||||
label: t(`knowledgeDetails.configuration`),
|
label: t(`knowledgeDetails.configuration`),
|
||||||
key: Routes.DatasetSetting,
|
key: Routes.DataSetSetting,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
if (!isEmpty(routerData?.graph)) {
|
if (!isEmpty(routerData?.graph)) {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { DataFlowItem } from '@/components/data-pipeline-select';
|
import { DataFlowSelect } from '@/components/data-pipeline-select';
|
||||||
import { ButtonLoading } from '@/components/ui/button';
|
import { ButtonLoading } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
@ -23,6 +23,7 @@ import { useForm, useWatch } from 'react-hook-form';
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import {
|
import {
|
||||||
|
ChunkMethodItem,
|
||||||
EmbeddingModelItem,
|
EmbeddingModelItem,
|
||||||
ParseTypeItem,
|
ParseTypeItem,
|
||||||
} from '../dataset/dataset-setting/configuration/common-item';
|
} from '../dataset/dataset-setting/configuration/common-item';
|
||||||
@ -32,7 +33,8 @@ const FormId = 'dataset-creating-form';
|
|||||||
export function InputForm({ onOk }: IModalProps<any>) {
|
export function InputForm({ onOk }: IModalProps<any>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z
|
||||||
|
.object({
|
||||||
name: z
|
name: z
|
||||||
.string()
|
.string()
|
||||||
.min(1, {
|
.min(1, {
|
||||||
@ -40,6 +42,37 @@ export function InputForm({ onOk }: IModalProps<any>) {
|
|||||||
})
|
})
|
||||||
.trim(),
|
.trim(),
|
||||||
parseType: z.number().optional(),
|
parseType: z.number().optional(),
|
||||||
|
embd_id: z
|
||||||
|
.string()
|
||||||
|
.min(1, {
|
||||||
|
message: t('knowledgeConfiguration.embeddingModelPlaceholder'),
|
||||||
|
})
|
||||||
|
.trim(),
|
||||||
|
parser_id: z.string().optional(),
|
||||||
|
pipline_id: z.string().optional(),
|
||||||
|
})
|
||||||
|
.superRefine((data, ctx) => {
|
||||||
|
// When parseType === 1, parser_id is required
|
||||||
|
if (
|
||||||
|
data.parseType === 1 &&
|
||||||
|
(!data.parser_id || data.parser_id.trim() === '')
|
||||||
|
) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: t('knowledgeList.parserRequired'),
|
||||||
|
path: ['parser_id'],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('form-data', data);
|
||||||
|
// When parseType === 1, pipline_id required
|
||||||
|
if (data.parseType === 2 && !data.pipline_id) {
|
||||||
|
ctx.addIssue({
|
||||||
|
code: z.ZodIssueCode.custom,
|
||||||
|
message: t('knowledgeList.dataFlowRequired'),
|
||||||
|
path: ['pipline_id'],
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
@ -47,17 +80,21 @@ export function InputForm({ onOk }: IModalProps<any>) {
|
|||||||
defaultValues: {
|
defaultValues: {
|
||||||
name: '',
|
name: '',
|
||||||
parseType: 1,
|
parseType: 1,
|
||||||
|
parser_id: '',
|
||||||
|
embd_id: '',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function onSubmit(data: z.infer<typeof FormSchema>) {
|
function onSubmit(data: z.infer<typeof FormSchema>) {
|
||||||
onOk?.(data.name);
|
console.log('submit', data);
|
||||||
|
onOk?.(data);
|
||||||
}
|
}
|
||||||
const parseType = useWatch({
|
const parseType = useWatch({
|
||||||
control: form.control,
|
control: form.control,
|
||||||
name: 'parseType',
|
name: 'parseType',
|
||||||
});
|
});
|
||||||
const { navigateToAgents } = useNavigatePage();
|
const { navigateToAgents } = useNavigatePage();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form {...form}>
|
<Form {...form}>
|
||||||
<form
|
<form
|
||||||
@ -84,13 +121,19 @@ export function InputForm({ onOk }: IModalProps<any>) {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
<EmbeddingModelItem line={2} />
|
<EmbeddingModelItem line={2} isEdit={false} />
|
||||||
<ParseTypeItem />
|
<ParseTypeItem />
|
||||||
|
{parseType === 1 && (
|
||||||
|
<>
|
||||||
|
<ChunkMethodItem></ChunkMethodItem>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
{parseType === 2 && (
|
{parseType === 2 && (
|
||||||
<>
|
<>
|
||||||
<DataFlowItem
|
<DataFlowSelect
|
||||||
|
isMult={false}
|
||||||
toDataPipeline={navigateToAgents}
|
toDataPipeline={navigateToAgents}
|
||||||
formFieldName="data_flow"
|
formFieldName="pipline_id"
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -108,7 +151,7 @@ export function DatasetCreatingDialog({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open onOpenChange={hideModal}>
|
<Dialog open onOpenChange={hideModal}>
|
||||||
<DialogContent className="sm:max-w-[425px]">
|
<DialogContent className="sm:max-w-[425px] focus-visible:!outline-none">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>{t('knowledgeList.createKnowledgeBase')}</DialogTitle>
|
<DialogTitle>{t('knowledgeList.createKnowledgeBase')}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import { useSetModalState } from '@/hooks/common-hooks';
|
|||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { useCreateKnowledge } from '@/hooks/use-knowledge-request';
|
import { useCreateKnowledge } from '@/hooks/use-knowledge-request';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
|
||||||
export const useSearchKnowledge = () => {
|
export const useSearchKnowledge = () => {
|
||||||
const [searchString, setSearchString] = useState<string>('');
|
const [searchString, setSearchString] = useState<string>('');
|
||||||
|
|
||||||
@ -15,16 +14,19 @@ export const useSearchKnowledge = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export interface Iknowledge {
|
||||||
|
name: string;
|
||||||
|
embd_id: string;
|
||||||
|
parser_id: string;
|
||||||
|
}
|
||||||
export const useSaveKnowledge = () => {
|
export const useSaveKnowledge = () => {
|
||||||
const { visible: visible, hideModal, showModal } = useSetModalState();
|
const { visible: visible, hideModal, showModal } = useSetModalState();
|
||||||
const { loading, createKnowledge } = useCreateKnowledge();
|
const { loading, createKnowledge } = useCreateKnowledge();
|
||||||
const { navigateToDataset } = useNavigatePage();
|
const { navigateToDataset } = useNavigatePage();
|
||||||
|
|
||||||
const onCreateOk = useCallback(
|
const onCreateOk = useCallback(
|
||||||
async (name: string) => {
|
async (data: Iknowledge) => {
|
||||||
const ret = await createKnowledge({
|
const ret = await createKnowledge(data);
|
||||||
name,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (ret?.code === 0) {
|
if (ret?.code === 0) {
|
||||||
hideModal();
|
hideModal();
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
import { IAgentLogsRequest } from '@/interfaces/database/agent';
|
import {
|
||||||
|
IAgentLogsRequest,
|
||||||
|
IPipeLineListRequest,
|
||||||
|
} from '@/interfaces/database/agent';
|
||||||
import api from '@/utils/api';
|
import api from '@/utils/api';
|
||||||
import { registerNextServer } from '@/utils/register-server';
|
import { registerNextServer } from '@/utils/register-server';
|
||||||
import request from '@/utils/request';
|
import request from '@/utils/request';
|
||||||
@ -131,4 +134,8 @@ export const fetchAgentLogsByCanvasId = (
|
|||||||
return request.get(methods.fetchAgentLogs.url(canvasId), { params: params });
|
return request.get(methods.fetchAgentLogs.url(canvasId), { params: params });
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fetchPipeLineList = (params: IPipeLineListRequest) => {
|
||||||
|
return request.get(api.listCanvas, { params: params });
|
||||||
|
};
|
||||||
|
|
||||||
export default agentService;
|
export default agentService;
|
||||||
|
|||||||
171
web/src/stories/slider-input-form-field.stories.tsx
Normal file
171
web/src/stories/slider-input-form-field.stories.tsx
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import { Form } from '@/components/ui/form';
|
||||||
|
import type { Meta, StoryObj } from '@storybook/react-webpack5';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
|
||||||
|
import { SliderInputFormField } from '@/components/slider-input-form-field';
|
||||||
|
import { FormLayout } from '@/constants/form';
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
|
||||||
|
const meta = {
|
||||||
|
title: 'Example/SliderInputFormField',
|
||||||
|
component: SliderInputFormField,
|
||||||
|
parameters: {
|
||||||
|
layout: 'centered',
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
component: `
|
||||||
|
## Component Description
|
||||||
|
|
||||||
|
SliderInputFormField is a form field component that combines a slider and a numeric input field.
|
||||||
|
It provides a user-friendly way to select numeric values within a specified range. `,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tags: ['autodocs'],
|
||||||
|
argTypes: {
|
||||||
|
name: { control: 'text' },
|
||||||
|
label: { control: 'text' },
|
||||||
|
min: { control: 'number' },
|
||||||
|
max: { control: 'number' },
|
||||||
|
step: { control: 'number' },
|
||||||
|
defaultValue: { control: 'number' },
|
||||||
|
layout: {
|
||||||
|
control: 'select',
|
||||||
|
options: [FormLayout.Vertical, FormLayout.Horizontal],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
args: {
|
||||||
|
name: 'sliderValue',
|
||||||
|
label: 'Slider Value',
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 1,
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
} satisfies Meta<typeof SliderInputFormField>;
|
||||||
|
|
||||||
|
// Form wrapper decorator
|
||||||
|
const WithFormProvider = ({ children }: { children: React.ReactNode }) => {
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {},
|
||||||
|
resolver: zodResolver(z.object({})),
|
||||||
|
});
|
||||||
|
return <Form {...form}>{children}</Form>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const withFormProvider = (Story: any) => (
|
||||||
|
<WithFormProvider>
|
||||||
|
<Story />
|
||||||
|
</WithFormProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof meta>;
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
|
||||||
|
export const Default: Story = {
|
||||||
|
decorators: [withFormProvider],
|
||||||
|
args: {
|
||||||
|
name: 'sliderValue',
|
||||||
|
label: 'Slider Value',
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
step: 1,
|
||||||
|
defaultValue: 50,
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
story: `
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
\`\`\`tsx
|
||||||
|
import { SliderInputFormField } from '@/components/slider-input-form-field';
|
||||||
|
|
||||||
|
<SliderInputFormField
|
||||||
|
name="sliderValue"
|
||||||
|
label="Slider Value"
|
||||||
|
min={0}
|
||||||
|
max={100}
|
||||||
|
step={1}
|
||||||
|
defaultValue={50}
|
||||||
|
/>
|
||||||
|
\`\`\`
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const HorizontalLayout: Story = {
|
||||||
|
decorators: [withFormProvider],
|
||||||
|
args: {
|
||||||
|
name: 'horizontalSlider',
|
||||||
|
label: 'Horizontal Slider',
|
||||||
|
min: 0,
|
||||||
|
max: 200,
|
||||||
|
step: 5,
|
||||||
|
defaultValue: 100,
|
||||||
|
layout: FormLayout.Horizontal,
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
story: `
|
||||||
|
### Horizontal Layout
|
||||||
|
|
||||||
|
\`\`\`tsx
|
||||||
|
import { SliderInputFormField } from '@/components/slider-input-form-field';
|
||||||
|
import { FormLayout } from '@/constants/form';
|
||||||
|
|
||||||
|
<SliderInputFormField
|
||||||
|
name="horizontalSlider"
|
||||||
|
label="Horizontal Slider"
|
||||||
|
min={0}
|
||||||
|
max={200}
|
||||||
|
step={5}
|
||||||
|
defaultValue={100}
|
||||||
|
layout={FormLayout.Horizontal}
|
||||||
|
/>
|
||||||
|
\`\`\`
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const CustomRange: Story = {
|
||||||
|
decorators: [withFormProvider],
|
||||||
|
args: {
|
||||||
|
name: 'customRange',
|
||||||
|
label: 'Custom Range (0-1000)',
|
||||||
|
min: 0,
|
||||||
|
max: 1000,
|
||||||
|
step: 10,
|
||||||
|
defaultValue: 500,
|
||||||
|
},
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
story: `
|
||||||
|
### Custom Range
|
||||||
|
|
||||||
|
\`\`\`tsx
|
||||||
|
import { SliderInputFormField } from '@/components/slider-input-form-field';
|
||||||
|
|
||||||
|
<SliderInputFormField
|
||||||
|
name="customRange"
|
||||||
|
label="Custom Range (0-1000)"
|
||||||
|
min={0}
|
||||||
|
max={1000}
|
||||||
|
step={10}
|
||||||
|
defaultValue={500}
|
||||||
|
/>
|
||||||
|
\`\`\`
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@ -3,6 +3,9 @@ export function buildSelectOptions(
|
|||||||
keyName?: string,
|
keyName?: string,
|
||||||
valueName?: string,
|
valueName?: string,
|
||||||
) {
|
) {
|
||||||
|
if (!Array.isArray(list) || !list.length) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
if (keyName && valueName) {
|
if (keyName && valueName) {
|
||||||
return list.map((x) => ({ label: x[valueName], value: x[keyName] }));
|
return list.map((x) => ({ label: x[valueName], value: x[keyName] }));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user