mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
Fix:Optimize Agent template page, fix bugs in knowledge base (#9009)
### What problem does this PR solve? Replace Avatar with RAGFlowAvatar component for knowledge base and agent, optimize Agent template page, and modify bugs in knowledge base #3221 ### Type of change - [x] Bug Fix (non-breaking change which fixes an issue)
This commit is contained in:
@ -12,13 +12,6 @@ import {
|
|||||||
type EntityTypesFormFieldProps = {
|
type EntityTypesFormFieldProps = {
|
||||||
name?: string;
|
name?: string;
|
||||||
};
|
};
|
||||||
const initialEntityTypes = [
|
|
||||||
'organization',
|
|
||||||
'person',
|
|
||||||
'geo',
|
|
||||||
'event',
|
|
||||||
'category',
|
|
||||||
];
|
|
||||||
export function EntityTypesFormField({
|
export function EntityTypesFormField({
|
||||||
name = 'parser_config.entity_types',
|
name = 'parser_config.entity_types',
|
||||||
}: EntityTypesFormFieldProps) {
|
}: EntityTypesFormFieldProps) {
|
||||||
@ -29,7 +22,6 @@ export function EntityTypesFormField({
|
|||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name={name}
|
name={name}
|
||||||
defaultValue={initialEntityTypes}
|
|
||||||
render={({ field }) => {
|
render={({ field }) => {
|
||||||
return (
|
return (
|
||||||
<FormItem className=" items-center space-y-0 ">
|
<FormItem className=" items-center space-y-0 ">
|
||||||
|
|||||||
@ -3,9 +3,8 @@ import { useTranslate } from '@/hooks/common-hooks';
|
|||||||
import { useFetchKnowledgeList } from '@/hooks/knowledge-hooks';
|
import { useFetchKnowledgeList } from '@/hooks/knowledge-hooks';
|
||||||
import { UserOutlined } from '@ant-design/icons';
|
import { UserOutlined } from '@ant-design/icons';
|
||||||
import { Avatar as AntAvatar, Form, Select, Space } from 'antd';
|
import { Avatar as AntAvatar, Form, Select, Space } from 'antd';
|
||||||
import { Book } from 'lucide-react';
|
|
||||||
import { useFormContext } from 'react-hook-form';
|
import { useFormContext } from 'react-hook-form';
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from './ui/avatar';
|
import { RAGFlowAvatar } from './ragflow-avatar';
|
||||||
import { FormControl, FormField, FormItem, FormLabel } from './ui/form';
|
import { FormControl, FormField, FormItem, FormLabel } from './ui/form';
|
||||||
import { MultiSelect } from './ui/multi-select';
|
import { MultiSelect } from './ui/multi-select';
|
||||||
|
|
||||||
@ -81,12 +80,7 @@ export function KnowledgeBaseFormField() {
|
|||||||
label: x.name,
|
label: x.name,
|
||||||
value: x.id,
|
value: x.id,
|
||||||
icon: () => (
|
icon: () => (
|
||||||
<Avatar className="size-4 mr-2">
|
<RAGFlowAvatar className="size-4 mr-2" avatar={x.avatar} name={x.name} />
|
||||||
<AvatarImage src={x.avatar} />
|
|
||||||
<AvatarFallback>
|
|
||||||
<Book />
|
|
||||||
</AvatarFallback>
|
|
||||||
</Avatar>
|
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@ 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 { Plus } from 'lucide-react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useEffect } 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 { Button } from '../ui/button';
|
||||||
@ -46,6 +46,10 @@ export const showTagItems = (parserId: DocumentParserType) => {
|
|||||||
|
|
||||||
const UseRaptorField = 'parser_config.raptor.use_raptor';
|
const UseRaptorField = 'parser_config.raptor.use_raptor';
|
||||||
const RandomSeedField = 'parser_config.raptor.random_seed';
|
const RandomSeedField = 'parser_config.raptor.random_seed';
|
||||||
|
const MaxTokenField = 'parser_config.raptor.max_token';
|
||||||
|
const ThresholdField = 'parser_config.raptor.threshold';
|
||||||
|
const MaxCluster = 'parser_config.raptor.max_cluster';
|
||||||
|
const Prompt = 'parser_config.raptor.prompt';
|
||||||
|
|
||||||
// The three types "table", "resume" and "one" do not display this configuration.
|
// The three types "table", "resume" and "one" do not display this configuration.
|
||||||
|
|
||||||
@ -53,6 +57,15 @@ const RaptorFormFields = () => {
|
|||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
const { t } = useTranslate('knowledgeConfiguration');
|
const { t } = useTranslate('knowledgeConfiguration');
|
||||||
const useRaptor = useWatch({ name: UseRaptorField });
|
const useRaptor = useWatch({ name: UseRaptorField });
|
||||||
|
useEffect(() => {
|
||||||
|
if (useRaptor) {
|
||||||
|
form.setValue(MaxTokenField, 256);
|
||||||
|
form.setValue(ThresholdField, 0.1);
|
||||||
|
form.setValue(MaxCluster, 64);
|
||||||
|
form.setValue(RandomSeedField, 0);
|
||||||
|
form.setValue(Prompt, t('promptText'));
|
||||||
|
}
|
||||||
|
}, [form, useRaptor, t]);
|
||||||
|
|
||||||
const handleGenerate = useCallback(() => {
|
const handleGenerate = useCallback(() => {
|
||||||
form.setValue(RandomSeedField, random(10000));
|
form.setValue(RandomSeedField, random(10000));
|
||||||
@ -114,11 +127,7 @@ const RaptorFormFields = () => {
|
|||||||
</FormLabel>
|
</FormLabel>
|
||||||
<div className="w-3/4">
|
<div className="w-3/4">
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Textarea
|
<Textarea {...field} rows={8} />
|
||||||
{...field}
|
|
||||||
rows={8}
|
|
||||||
defaultValue={t('promptText')}
|
|
||||||
/>
|
|
||||||
</FormControl>
|
</FormControl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -134,7 +143,6 @@ const RaptorFormFields = () => {
|
|||||||
name={'parser_config.raptor.max_token'}
|
name={'parser_config.raptor.max_token'}
|
||||||
label={t('maxToken')}
|
label={t('maxToken')}
|
||||||
tooltip={t('maxTokenTip')}
|
tooltip={t('maxTokenTip')}
|
||||||
defaultValue={256}
|
|
||||||
max={2048}
|
max={2048}
|
||||||
min={0}
|
min={0}
|
||||||
layout={FormLayout.Horizontal}
|
layout={FormLayout.Horizontal}
|
||||||
@ -143,7 +151,6 @@ const RaptorFormFields = () => {
|
|||||||
name={'parser_config.raptor.threshold'}
|
name={'parser_config.raptor.threshold'}
|
||||||
label={t('threshold')}
|
label={t('threshold')}
|
||||||
tooltip={t('thresholdTip')}
|
tooltip={t('thresholdTip')}
|
||||||
defaultValue={0.1}
|
|
||||||
step={0.01}
|
step={0.01}
|
||||||
max={1}
|
max={1}
|
||||||
min={0}
|
min={0}
|
||||||
@ -153,7 +160,6 @@ const RaptorFormFields = () => {
|
|||||||
name={'parser_config.raptor.max_cluster'}
|
name={'parser_config.raptor.max_cluster'}
|
||||||
label={t('maxCluster')}
|
label={t('maxCluster')}
|
||||||
tooltip={t('maxClusterTip')}
|
tooltip={t('maxClusterTip')}
|
||||||
defaultValue={64}
|
|
||||||
max={1024}
|
max={1024}
|
||||||
min={1}
|
min={1}
|
||||||
layout={FormLayout.Horizontal}
|
layout={FormLayout.Horizontal}
|
||||||
|
|||||||
@ -143,7 +143,12 @@ export const useComposeLlmOptionsByModelTypes = (
|
|||||||
|
|
||||||
return modelTypes.reduce<
|
return modelTypes.reduce<
|
||||||
(DefaultOptionType & {
|
(DefaultOptionType & {
|
||||||
options: { label: JSX.Element; value: string; disabled: boolean; is_tools: boolean }[];
|
options: {
|
||||||
|
label: JSX.Element;
|
||||||
|
value: string;
|
||||||
|
disabled: boolean;
|
||||||
|
is_tools: boolean;
|
||||||
|
}[];
|
||||||
})[]
|
})[]
|
||||||
>((pre, cur) => {
|
>((pre, cur) => {
|
||||||
const options = allOptions[cur];
|
const options = allOptions[cur];
|
||||||
@ -211,7 +216,6 @@ export const useFetchMyLlmListDetailed = (): ResponseGetType<
|
|||||||
return { data, loading };
|
return { data, loading };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const useSelectLlmList = () => {
|
export const useSelectLlmList = () => {
|
||||||
const { data: myLlmList, loading: myLlmListLoading } = useFetchMyLlmList();
|
const { data: myLlmList, loading: myLlmListLoading } = useFetchMyLlmList();
|
||||||
const { data: factoryList, loading: factoryListLoading } =
|
const { data: factoryList, loading: factoryListLoading } =
|
||||||
@ -262,7 +266,7 @@ export const useSaveApiKey = () => {
|
|||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
message.success(t('message.modified'));
|
message.success(t('message.modified'));
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
||||||
}
|
}
|
||||||
return data.code;
|
return data.code;
|
||||||
@ -314,7 +318,7 @@ export const useAddLlm = () => {
|
|||||||
const { data } = await userService.add_llm(params);
|
const { data } = await userService.add_llm(params);
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
||||||
message.success(t('message.modified'));
|
message.success(t('message.modified'));
|
||||||
}
|
}
|
||||||
@ -338,7 +342,7 @@ export const useDeleteLlm = () => {
|
|||||||
const { data } = await userService.delete_llm(params);
|
const { data } = await userService.delete_llm(params);
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
||||||
message.success(t('message.deleted'));
|
message.success(t('message.deleted'));
|
||||||
}
|
}
|
||||||
@ -362,7 +366,7 @@ export const useDeleteFactory = () => {
|
|||||||
const { data } = await userService.deleteFactory(params);
|
const { data } = await userService.deleteFactory(params);
|
||||||
if (data.code === 0) {
|
if (data.code === 0) {
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmList'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
queryClient.invalidateQueries({ queryKey: ['myLlmListDetailed'] });
|
||||||
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
queryClient.invalidateQueries({ queryKey: ['factoryList'] });
|
||||||
message.success(t('message.deleted'));
|
message.success(t('message.deleted'));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1296,6 +1296,7 @@ This delimiter is used to split the input text into several text pieces echo of
|
|||||||
agentDescription:
|
agentDescription:
|
||||||
'Builds agent components equipped with reasoning, tool usage, and multi-agent collaboration. ',
|
'Builds agent components equipped with reasoning, tool usage, and multi-agent collaboration. ',
|
||||||
maxRecords: 'Max records',
|
maxRecords: 'Max records',
|
||||||
|
createAgent: 'Create Agent',
|
||||||
stringTransform: 'String transform',
|
stringTransform: 'String transform',
|
||||||
userFillUp: 'Input',
|
userFillUp: 'Input',
|
||||||
codeExec: 'Code',
|
codeExec: 'Code',
|
||||||
|
|||||||
@ -1248,6 +1248,7 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
|||||||
agent: 'Agent',
|
agent: 'Agent',
|
||||||
agentDescription: '构建具备推理、工具调用和多智能体协同的智能体组件。',
|
agentDescription: '构建具备推理、工具调用和多智能体协同的智能体组件。',
|
||||||
maxRecords: '最大记录数',
|
maxRecords: '最大记录数',
|
||||||
|
createAgent: 'Create Agent',
|
||||||
stringTransform: '文本处理',
|
stringTransform: '文本处理',
|
||||||
userFillUp: '等待输入',
|
userFillUp: '等待输入',
|
||||||
codeExec: '代码',
|
codeExec: '代码',
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
|
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||||
import { useFetchKnowledgeList } from '@/hooks/knowledge-hooks';
|
import { useFetchKnowledgeList } from '@/hooks/knowledge-hooks';
|
||||||
import { IRetrievalNode } from '@/interfaces/database/flow';
|
import { IRetrievalNode } from '@/interfaces/database/flow';
|
||||||
import { UserOutlined } from '@ant-design/icons';
|
|
||||||
import { NodeProps, Position } from '@xyflow/react';
|
import { NodeProps, Position } from '@xyflow/react';
|
||||||
import { Avatar, Flex } from 'antd';
|
import { Flex } from 'antd';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { memo, useMemo } from 'react';
|
import { memo, useMemo } from 'react';
|
||||||
@ -68,10 +68,11 @@ function InnerRetrievalNode({
|
|||||||
return (
|
return (
|
||||||
<div className={styles.nodeText} key={knowledge.id}>
|
<div className={styles.nodeText} key={knowledge.id}>
|
||||||
<Flex align={'center'} gap={6}>
|
<Flex align={'center'} gap={6}>
|
||||||
<Avatar
|
<RAGFlowAvatar
|
||||||
size={26}
|
className="size-6 rounded-lg"
|
||||||
icon={<UserOutlined />}
|
avatar={knowledge.avatar}
|
||||||
src={knowledge.avatar}
|
name={knowledge.name || 'CN'}
|
||||||
|
isPerson={true}
|
||||||
/>
|
/>
|
||||||
<Flex className={styles.knowledgeNodeName} flex={1}>
|
<Flex className={styles.knowledgeNodeName} flex={1}>
|
||||||
{knowledge.name}
|
{knowledge.name}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ import { useSetModalState } from '@/hooks/common-hooks';
|
|||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { useFetchAgentTemplates, useSetAgent } from '@/hooks/use-agent-request';
|
import { useFetchAgentTemplates, useSetAgent } from '@/hooks/use-agent-request';
|
||||||
import { IFlowTemplate } from '@/interfaces/database/flow';
|
import { IFlowTemplate } from '@/interfaces/database/flow';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useEffect, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { CreateAgentDialog } from './create-agent-dialog';
|
import { CreateAgentDialog } from './create-agent-dialog';
|
||||||
import { TemplateCard } from './template-card';
|
import { TemplateCard } from './template-card';
|
||||||
@ -21,7 +21,11 @@ export default function AgentTemplates() {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const list = useFetchAgentTemplates();
|
const list = useFetchAgentTemplates();
|
||||||
const { loading, setAgent } = useSetAgent();
|
const { loading, setAgent } = useSetAgent();
|
||||||
|
const [templateList, setTemplateList] = useState<IFlowTemplate[]>([]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTemplateList(list);
|
||||||
|
}, [list]);
|
||||||
const {
|
const {
|
||||||
visible: creatingVisible,
|
visible: creatingVisible,
|
||||||
hideModal: hideCreatingModal,
|
hideModal: hideCreatingModal,
|
||||||
@ -62,7 +66,14 @@ export default function AgentTemplates() {
|
|||||||
template?.dsl,
|
template?.dsl,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
const handleSiderBarChange = (keyword: string) => {
|
||||||
|
const tempList = list.filter(
|
||||||
|
(item, index) =>
|
||||||
|
item.title.toLocaleLowerCase().includes(keyword?.toLocaleLowerCase()) ||
|
||||||
|
index === 0,
|
||||||
|
);
|
||||||
|
setTemplateList(tempList);
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<PageHeader>
|
<PageHeader>
|
||||||
|
|||||||
@ -1,47 +1,59 @@
|
|||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { IFlowTemplate } from '@/interfaces/database/flow';
|
import { IFlowTemplate } from '@/interfaces/database/flow';
|
||||||
|
import { Plus } from 'lucide-react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
data: IFlowTemplate;
|
data: IFlowTemplate;
|
||||||
|
isCreate?: boolean;
|
||||||
showModal(record: IFlowTemplate): void;
|
showModal(record: IFlowTemplate): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function TemplateCard({ data, showModal }: IProps) {
|
export function TemplateCard({ data, showModal, isCreate = false }: IProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
const handleClick = useCallback(() => {
|
const handleClick = useCallback(() => {
|
||||||
showModal(data);
|
showModal(data);
|
||||||
}, [data, showModal]);
|
}, [data, showModal]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard group relative">
|
<Card className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard group relative min-h-40">
|
||||||
<CardContent className="p-4 ">
|
<CardContent className="p-4 ">
|
||||||
<div className="flex justify-between mb-4">
|
{isCreate && (
|
||||||
{data.avatar ? (
|
<div
|
||||||
<div
|
className="flex flex-col justify-center items-center gap-4 mb-4 absolute top-0 right-0 left-0 bottom-0 cursor-pointer "
|
||||||
className="w-[70px] h-[70px] rounded-xl bg-cover"
|
onClick={handleClick}
|
||||||
style={{ backgroundImage: `url(${data.avatar})` }}
|
>
|
||||||
/>
|
<Plus size={50} fontWeight={700} />
|
||||||
) : (
|
<div>{t('flow.createAgent')}</div>
|
||||||
<Avatar className="w-[70px] h-[70px]">
|
</div>
|
||||||
<AvatarImage src="https://github.com/shadcn.png" />
|
)}
|
||||||
<AvatarFallback>CN</AvatarFallback>
|
{!isCreate && (
|
||||||
</Avatar>
|
<>
|
||||||
)}
|
<div className="flex justify-start items-center gap-4 mb-4">
|
||||||
</div>
|
<RAGFlowAvatar
|
||||||
<h3 className="text-xl font-bold mb-2">{data.title}</h3>
|
className="w-7 h-7"
|
||||||
<p className="break-words">{data.description}</p>
|
avatar={
|
||||||
<Button
|
data.avatar ? data.avatar : 'https://github.com/shadcn.png'
|
||||||
variant="tertiary"
|
}
|
||||||
className="absolute bottom-4 right-4 left-4 hidden justify-end group-hover:block text-center"
|
name={data?.title || 'CN'}
|
||||||
onClick={handleClick}
|
></RAGFlowAvatar>
|
||||||
>
|
<div className="text-[18px] font-bold ">{data.title}</div>
|
||||||
{t('flow.useTemplate')}
|
</div>
|
||||||
</Button>
|
<p className="break-words">{data.description}</p>
|
||||||
|
<div className="group-hover:bg-gradient-to-t from-black/70 from-10% via-black/0 via-50% to-black/0 w-full h-full group-hover:block absolute top-0 left-0 hidden rounded-xl">
|
||||||
|
<Button
|
||||||
|
variant="default"
|
||||||
|
className="w-1/3 absolute bottom-4 right-4 left-4 justify-center text-center m-auto"
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
|
{t('flow.useTemplate')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|||||||
57
web/src/pages/agents/template-sidebar.tsx
Normal file
57
web/src/pages/agents/template-sidebar.tsx
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { useSecondPathName } from '@/hooks/route-hook';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
import { Banknote, LayoutGrid, User } from 'lucide-react';
|
||||||
|
|
||||||
|
const menuItems = [
|
||||||
|
{
|
||||||
|
section: 'All Templates',
|
||||||
|
items: [
|
||||||
|
{ icon: User, label: 'Assistant', key: 'Assistant' },
|
||||||
|
{ icon: LayoutGrid, label: 'chatbot', key: 'chatbot' },
|
||||||
|
{ icon: Banknote, label: 'generator', key: 'generator' },
|
||||||
|
{ icon: Banknote, label: 'Intel', key: 'Intel' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export function SideBar({ change }: { change: (keyword: string) => void }) {
|
||||||
|
const pathName = useSecondPathName();
|
||||||
|
const handleMenuClick = (key: string) => {
|
||||||
|
change(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<aside className="w-[303px] bg-background border-r flex flex-col">
|
||||||
|
<div className="flex-1 overflow-auto">
|
||||||
|
{menuItems.map((section, idx) => (
|
||||||
|
<div key={idx}>
|
||||||
|
<h2
|
||||||
|
className="p-6 text-sm font-semibold hover:bg-muted/50 cursor-pointer"
|
||||||
|
onClick={() => handleMenuClick('')}
|
||||||
|
>
|
||||||
|
{section.section}
|
||||||
|
</h2>
|
||||||
|
{section.items.map((item, itemIdx) => {
|
||||||
|
const active = pathName === item.key;
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
key={itemIdx}
|
||||||
|
variant={active ? 'secondary' : 'ghost'}
|
||||||
|
className={cn('w-full justify-start gap-2.5 p-6 relative')}
|
||||||
|
onClick={() => handleMenuClick(item.key)}
|
||||||
|
>
|
||||||
|
<item.icon className="w-6 h-6" />
|
||||||
|
<span>{item.label}</span>
|
||||||
|
{active && (
|
||||||
|
<div className="absolute right-0 w-[5px] h-[66px] bg-primary rounded-l-xl shadow-[0_0_5.94px_#7561ff,0_0_11.88px_#7561ff,0_0_41.58px_#7561ff,0_0_83.16px_#7561ff,0_0_142.56px_#7561ff,0_0_249.48px_#7561ff]" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</aside>
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -6,6 +6,11 @@ import {
|
|||||||
DropdownMenuItem,
|
DropdownMenuItem,
|
||||||
DropdownMenuTrigger,
|
DropdownMenuTrigger,
|
||||||
} from '@/components/ui/dropdown-menu';
|
} from '@/components/ui/dropdown-menu';
|
||||||
|
import {
|
||||||
|
HoverCard,
|
||||||
|
HoverCardContent,
|
||||||
|
HoverCardTrigger,
|
||||||
|
} from '@/components/ui/hover-card';
|
||||||
import { Progress } from '@/components/ui/progress';
|
import { Progress } from '@/components/ui/progress';
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { IDocumentInfo } from '@/interfaces/database/document';
|
import { IDocumentInfo } from '@/interfaces/database/document';
|
||||||
@ -13,12 +18,11 @@ import { CircleX, Play, RefreshCw } from 'lucide-react';
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { RunningStatus } from './constant';
|
import { RunningStatus } from './constant';
|
||||||
import { ParsingCard } from './parsing-card';
|
import { ParsingCard, PopoverContent } from './parsing-card';
|
||||||
import { UseChangeDocumentParserShowType } from './use-change-document-parser';
|
import { UseChangeDocumentParserShowType } from './use-change-document-parser';
|
||||||
import { useHandleRunDocumentByIds } from './use-run-document';
|
import { useHandleRunDocumentByIds } from './use-run-document';
|
||||||
import { UseSaveMetaShowType } from './use-save-meta';
|
import { UseSaveMetaShowType } from './use-save-meta';
|
||||||
import { isParserRunning } from './utils';
|
import { isParserRunning } from './utils';
|
||||||
|
|
||||||
const IconMap = {
|
const IconMap = {
|
||||||
[RunningStatus.UNSTART]: <Play />,
|
[RunningStatus.UNSTART]: <Play />,
|
||||||
[RunningStatus.RUNNING]: <CircleX />,
|
[RunningStatus.RUNNING]: <CircleX />,
|
||||||
@ -94,10 +98,17 @@ export function ParsingStatusCell({
|
|||||||
</Button>
|
</Button>
|
||||||
</ConfirmDeleteDialog>
|
</ConfirmDeleteDialog>
|
||||||
{isParserRunning(run) ? (
|
{isParserRunning(run) ? (
|
||||||
<div className="flex items-center gap-1">
|
<HoverCard>
|
||||||
<Progress value={p} className="h-1 flex-1 min-w-10" />
|
<HoverCardTrigger asChild>
|
||||||
{p}%
|
<div className="flex items-center gap-1">
|
||||||
</div>
|
<Progress value={p} className="h-1 flex-1 min-w-10" />
|
||||||
|
{p}%
|
||||||
|
</div>
|
||||||
|
</HoverCardTrigger>
|
||||||
|
<HoverCardContent className="w-[40vw]">
|
||||||
|
<PopoverContent record={record}></PopoverContent>
|
||||||
|
</HoverCardContent>
|
||||||
|
</HoverCard>
|
||||||
) : (
|
) : (
|
||||||
<ParsingCard record={record}></ParsingCard>
|
<ParsingCard record={record}></ParsingCard>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -71,9 +71,13 @@ export const useFetchKnowledgeConfigurationOnMount = (
|
|||||||
knowledgeDetails.avatar,
|
knowledgeDetails.avatar,
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('🚀 ~ useEffect ~ fileList:', fileList);
|
console.log('🚀 ~ useEffect ~ fileList:', fileList, knowledgeDetails);
|
||||||
form.reset({
|
const parser_config = {
|
||||||
...pick(knowledgeDetails, [
|
...form.formState?.defaultValues?.parser_config,
|
||||||
|
...knowledgeDetails.parser_config,
|
||||||
|
};
|
||||||
|
const formValues = {
|
||||||
|
...pick({ ...knowledgeDetails, parser_config: parser_config }, [
|
||||||
'description',
|
'description',
|
||||||
'name',
|
'name',
|
||||||
'permission',
|
'permission',
|
||||||
@ -83,6 +87,9 @@ export const useFetchKnowledgeConfigurationOnMount = (
|
|||||||
'parser_config',
|
'parser_config',
|
||||||
'pagerank',
|
'pagerank',
|
||||||
]),
|
]),
|
||||||
|
};
|
||||||
|
form.reset({
|
||||||
|
...formValues,
|
||||||
avatar: fileList,
|
avatar: fileList,
|
||||||
});
|
});
|
||||||
}, [form, knowledgeDetails]);
|
}, [form, knowledgeDetails]);
|
||||||
|
|||||||
@ -54,10 +54,6 @@ export default function DatasetSettings() {
|
|||||||
topn_tags: 3,
|
topn_tags: 3,
|
||||||
raptor: {
|
raptor: {
|
||||||
use_raptor: false,
|
use_raptor: false,
|
||||||
max_token: 256,
|
|
||||||
threshold: 0.1,
|
|
||||||
max_cluster: 64,
|
|
||||||
random_seed: 0,
|
|
||||||
},
|
},
|
||||||
graphrag: {
|
graphrag: {
|
||||||
use_graphrag: false,
|
use_graphrag: false,
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import { MoreButton } from '@/components/more-button';
|
import { MoreButton } from '@/components/more-button';
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
import { RAGFlowAvatar } from '@/components/ragflow-avatar';
|
||||||
import { Badge } from '@/components/ui/badge';
|
import { Badge } from '@/components/ui/badge';
|
||||||
import { Card, CardContent } from '@/components/ui/card';
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
@ -32,10 +32,11 @@ export function DatasetCard({
|
|||||||
<CardContent className="p-2.5 pt-2 group">
|
<CardContent className="p-2.5 pt-2 group">
|
||||||
<section className="flex justify-between mb-2">
|
<section className="flex justify-between mb-2">
|
||||||
<div className="flex gap-2 items-center">
|
<div className="flex gap-2 items-center">
|
||||||
<Avatar className="size-6 rounded-lg">
|
<RAGFlowAvatar
|
||||||
<AvatarImage src={dataset.avatar} />
|
className="size-6 rounded-lg"
|
||||||
<AvatarFallback className="rounded-lg ">CN</AvatarFallback>
|
avatar={dataset.avatar}
|
||||||
</Avatar>
|
name={dataset.name || 'CN'}
|
||||||
|
></RAGFlowAvatar>
|
||||||
{owner && (
|
{owner && (
|
||||||
<Badge className="h-5 rounded-sm px-1 bg-background-badge text-text-badge">
|
<Badge className="h-5 rounded-sm px-1 bg-background-badge text-text-badge">
|
||||||
{owner}
|
{owner}
|
||||||
|
|||||||
@ -111,7 +111,9 @@ export const useFetchSystemModelSettingOnMount = () => {
|
|||||||
export const useSubmitOllama = () => {
|
export const useSubmitOllama = () => {
|
||||||
const [selectedLlmFactory, setSelectedLlmFactory] = useState<string>('');
|
const [selectedLlmFactory, setSelectedLlmFactory] = useState<string>('');
|
||||||
const [editMode, setEditMode] = useState(false);
|
const [editMode, setEditMode] = useState(false);
|
||||||
const [initialValues, setInitialValues] = useState<Partial<IAddLlmRequestBody> | undefined>();
|
const [initialValues, setInitialValues] = useState<
|
||||||
|
Partial<IAddLlmRequestBody> | undefined
|
||||||
|
>();
|
||||||
const [originalModelName, setOriginalModelName] = useState<string>('');
|
const [originalModelName, setOriginalModelName] = useState<string>('');
|
||||||
const { addLlm, loading } = useAddLlm();
|
const { addLlm, loading } = useAddLlm();
|
||||||
const {
|
const {
|
||||||
@ -137,7 +139,12 @@ export const useSubmitOllama = () => {
|
|||||||
[hideLlmAddingModal, addLlm],
|
[hideLlmAddingModal, addLlm],
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleShowLlmAddingModal = (llmFactory: string, isEdit = false, modelData?: any, detailedData?: any) => {
|
const handleShowLlmAddingModal = (
|
||||||
|
llmFactory: string,
|
||||||
|
isEdit = false,
|
||||||
|
modelData?: any,
|
||||||
|
detailedData?: any,
|
||||||
|
) => {
|
||||||
setSelectedLlmFactory(llmFactory);
|
setSelectedLlmFactory(llmFactory);
|
||||||
setEditMode(isEdit);
|
setEditMode(isEdit);
|
||||||
|
|
||||||
|
|||||||
@ -3,9 +3,17 @@ import { LlmIcon } from '@/components/svg-icon';
|
|||||||
import { useTheme } from '@/components/theme-provider';
|
import { useTheme } from '@/components/theme-provider';
|
||||||
import { LLMFactory } from '@/constants/llm';
|
import { LLMFactory } from '@/constants/llm';
|
||||||
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
import { useSetModalState, useTranslate } from '@/hooks/common-hooks';
|
||||||
import { LlmItem, useSelectLlmList, useFetchMyLlmListDetailed } from '@/hooks/llm-hooks';
|
import {
|
||||||
|
LlmItem,
|
||||||
|
useFetchMyLlmListDetailed,
|
||||||
|
useSelectLlmList,
|
||||||
|
} from '@/hooks/llm-hooks';
|
||||||
import { getRealModelName } from '@/utils/llm-util';
|
import { getRealModelName } from '@/utils/llm-util';
|
||||||
import { CloseCircleOutlined, EditOutlined, SettingOutlined } from '@ant-design/icons';
|
import {
|
||||||
|
CloseCircleOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
SettingOutlined,
|
||||||
|
} from '@ant-design/icons';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
@ -137,7 +145,10 @@ const ModelCard = ({ item, clickApiKey, handleEditModel }: IModelCardProps) => {
|
|||||||
<Tag color="#b8b8b8">{model.type}</Tag>
|
<Tag color="#b8b8b8">{model.type}</Tag>
|
||||||
{isLocalLlmFactory(item.name) && (
|
{isLocalLlmFactory(item.name) && (
|
||||||
<Tooltip title={t('edit', { keyPrefix: 'common' })}>
|
<Tooltip title={t('edit', { keyPrefix: 'common' })}>
|
||||||
<Button type={'text'} onClick={() => handleEditModel(model, item)}>
|
<Button
|
||||||
|
type={'text'}
|
||||||
|
onClick={() => handleEditModel(model, item)}
|
||||||
|
>
|
||||||
<EditOutlined style={{ color: '#1890ff' }} />
|
<EditOutlined style={{ color: '#1890ff' }} />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -304,12 +315,14 @@ const UserSettingModel = () => {
|
|||||||
(model: any, factory: LlmItem) => {
|
(model: any, factory: LlmItem) => {
|
||||||
if (factory) {
|
if (factory) {
|
||||||
const detailedFactory = detailedLlmList[factory.name];
|
const detailedFactory = detailedLlmList[factory.name];
|
||||||
const detailedModel = detailedFactory?.llm?.find((m: any) => m.name === model.name);
|
const detailedModel = detailedFactory?.llm?.find(
|
||||||
|
(m: any) => m.name === model.name,
|
||||||
|
);
|
||||||
|
|
||||||
const editData = {
|
const editData = {
|
||||||
llm_factory: factory.name,
|
llm_factory: factory.name,
|
||||||
llm_name: model.name,
|
llm_name: model.name,
|
||||||
model_type: model.type
|
model_type: model.type,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isLocalLlmFactory(factory.name)) {
|
if (isLocalLlmFactory(factory.name)) {
|
||||||
@ -333,7 +346,11 @@ const UserSettingModel = () => {
|
|||||||
grid={{ gutter: 16, column: 1 }}
|
grid={{ gutter: 16, column: 1 }}
|
||||||
dataSource={llmList}
|
dataSource={llmList}
|
||||||
renderItem={(item) => (
|
renderItem={(item) => (
|
||||||
<ModelCard item={item} clickApiKey={handleAddModel} handleEditModel={handleEditModel}></ModelCard>
|
<ModelCard
|
||||||
|
item={item}
|
||||||
|
clickApiKey={handleAddModel}
|
||||||
|
handleEditModel={handleEditModel}
|
||||||
|
></ModelCard>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
|
|||||||
@ -134,7 +134,11 @@ const OllamaModal = ({
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
title={editMode ? t('editLlmTitle', { name: llmFactory }) : t('addLlmTitle', { name: llmFactory })}
|
title={
|
||||||
|
editMode
|
||||||
|
? t('editLlmTitle', { name: llmFactory })
|
||||||
|
: t('addLlmTitle', { name: llmFactory })
|
||||||
|
}
|
||||||
open={visible}
|
open={visible}
|
||||||
onOk={handleOk}
|
onOk={handleOk}
|
||||||
onCancel={hideModal}
|
onCancel={hideModal}
|
||||||
@ -196,10 +200,7 @@ const OllamaModal = ({
|
|||||||
name="api_key"
|
name="api_key"
|
||||||
rules={[{ required: false, message: t('apiKeyMessage') }]}
|
rules={[{ required: false, message: t('apiKeyMessage') }]}
|
||||||
>
|
>
|
||||||
<Input
|
<Input placeholder={t('apiKeyMessage')} onKeyDown={handleKeyDown} />
|
||||||
placeholder={t('apiKeyMessage')}
|
|
||||||
onKeyDown={handleKeyDown}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item<FieldType>
|
<Form.Item<FieldType>
|
||||||
label={t('maxTokens')}
|
label={t('maxTokens')}
|
||||||
|
|||||||
Reference in New Issue
Block a user