Przeglądaj źródła

Feat: Add retrieval tool #3221 (#8491)

### What problem does this PR solve?

Feat: Add retrieval tool #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
tags/v0.20.0
balibabu 4 miesięcy temu
rodzic
commit
c4bfd9fa2c
No account linked to committer's email address

+ 48
- 2207
web/src/pages/agent/constant.tsx
Plik diff jest za duży
Wyświetl plik


+ 2
- 15
web/src/pages/agent/form/agent-form/index.tsx Wyświetl plik

FormItem, FormItem,
FormLabel, FormLabel,
} from '@/components/ui/form'; } from '@/components/ui/form';
import { Textarea } from '@/components/ui/textarea';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { Position } from '@xyflow/react'; import { Position } from '@xyflow/react';
import { useContext, useMemo } from 'react'; import { useContext, useMemo } from 'react';
import { INextOperatorForm } from '../../interface'; import { INextOperatorForm } from '../../interface';
import useGraphStore from '../../store'; import useGraphStore from '../../store';
import { isBottomSubAgent } from '../../utils'; import { isBottomSubAgent } from '../../utils';
import { DescriptionField } from '../components/description-field';
import { Output } from '../components/output'; import { Output } from '../components/output';
import { PromptEditor } from '../components/prompt-editor'; import { PromptEditor } from '../components/prompt-editor';
import { AgentTools } from './agent-tools'; import { AgentTools } from './agent-tools';
}} }}
> >
<FormContainer> <FormContainer>
{isSubAgent && (
<FormField
control={form.control}
name={`description`}
render={({ field }) => (
<FormItem className="flex-1">
<FormLabel>Description</FormLabel>
<FormControl>
<Textarea {...field}></Textarea>
</FormControl>
</FormItem>
)}
/>
)}
{isSubAgent && <DescriptionField></DescriptionField>}
<LargeModelFormField></LargeModelFormField> <LargeModelFormField></LargeModelFormField>
<FormField <FormField
control={form.control} control={form.control}

+ 1
- 0
web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx Wyświetl plik

Operator.Invoke, Operator.Invoke,
Operator.Crawler, Operator.Crawler,
Operator.Code, Operator.Code,
Operator.Retrieval,
], ],
}, },
]; ];

+ 12
- 1
web/src/pages/agent/form/agent-form/tool-popover/use-update-tools.ts Wyświetl plik

import { IAgentForm } from '@/interfaces/database/agent'; import { IAgentForm } from '@/interfaces/database/agent';
import { DefaultAgentToolValuesMap } from '@/pages/agent/constant';
import { AgentFormContext } from '@/pages/agent/context'; import { AgentFormContext } from '@/pages/agent/context';
import useGraphStore from '@/pages/agent/store'; import useGraphStore from '@/pages/agent/store';
import { get } from 'lodash'; import { get } from 'lodash';
if (node?.id) { if (node?.id) {
const nextValue = value.reduce<IAgentForm['tools']>((pre, cur) => { const nextValue = value.reduce<IAgentForm['tools']>((pre, cur) => {
const tool = tools.find((x) => x.component_name === cur); const tool = tools.find((x) => x.component_name === cur);
pre.push(tool ? tool : { component_name: cur, params: {} });
pre.push(
tool
? tool
: {
component_name: cur,
params:
DefaultAgentToolValuesMap[
cur as keyof typeof DefaultAgentToolValuesMap
] || {},
},
);
return pre; return pre;
}, []); }, []);



+ 2
- 2
web/src/pages/agent/form/baidu-fanyi-form/index.tsx Wyświetl plik

import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { Form, Input, Select } from 'antd'; import { Form, Input, Select } from 'antd';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { IOperatorForm } from '../../interface';
import { import {
BaiduFanyiDomainOptions, BaiduFanyiDomainOptions,
BaiduFanyiSourceLangOptions, BaiduFanyiSourceLangOptions,
} from '../../constant';
import { IOperatorForm } from '../../interface';
} from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';


const BaiduFanyiForm = ({ onValuesChange, form, node }: IOperatorForm) => { const BaiduFanyiForm = ({ onValuesChange, form, node }: IOperatorForm) => {

+ 1
- 1
web/src/pages/agent/form/bing-form/index.tsx Wyświetl plik

import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { Form, Input, Select } from 'antd'; import { Form, Input, Select } from 'antd';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { BingCountryOptions, BingLanguageOptions } from '../../constant';
import { IOperatorForm } from '../../interface'; import { IOperatorForm } from '../../interface';
import { BingCountryOptions, BingLanguageOptions } from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';


const BingForm = ({ onValuesChange, form, node }: IOperatorForm) => { const BingForm = ({ onValuesChange, form, node }: IOperatorForm) => {

+ 26
- 0
web/src/pages/agent/form/components/description-field.tsx Wyświetl plik

import {
FormControl,
FormField,
FormItem,
FormLabel,
} from '@/components/ui/form';
import { Textarea } from '@/components/ui/textarea';
import { useFormContext } from 'react-hook-form';

export function DescriptionField() {
const form = useFormContext();
return (
<FormField
control={form.control}
name={`description`}
render={({ field }) => (
<FormItem className="flex-1">
<FormLabel>Description</FormLabel>
<FormControl>
<Textarea {...field}></Textarea>
</FormControl>
</FormItem>
)}
/>
);
}

+ 1
- 1
web/src/pages/agent/form/crawler-form/index.tsx Wyświetl plik

import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { Form, Input, Select } from 'antd'; import { Form, Input, Select } from 'antd';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { CrawlerResultOptions } from '../../constant';
import { IOperatorForm } from '../../interface'; import { IOperatorForm } from '../../interface';
import { CrawlerResultOptions } from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';
const CrawlerForm = ({ onValuesChange, form, node }: IOperatorForm) => { const CrawlerForm = ({ onValuesChange, form, node }: IOperatorForm) => {
const { t } = useTranslate('flow'); const { t } = useTranslate('flow');

+ 1
- 1
web/src/pages/agent/form/deepl-form/index.tsx Wyświetl plik

import TopNItem from '@/components/top-n-item'; import TopNItem from '@/components/top-n-item';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { Form, Select } from 'antd'; import { Form, Select } from 'antd';
import { DeepLSourceLangOptions, DeepLTargetLangOptions } from '../../constant';
import { useBuildSortOptions } from '../../form-hooks'; import { useBuildSortOptions } from '../../form-hooks';
import { IOperatorForm } from '../../interface'; import { IOperatorForm } from '../../interface';
import { DeepLSourceLangOptions, DeepLTargetLangOptions } from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';


const DeepLForm = ({ onValuesChange, form, node }: IOperatorForm) => { const DeepLForm = ({ onValuesChange, form, node }: IOperatorForm) => {

+ 1
- 1
web/src/pages/agent/form/exesql-form/index.tsx Wyświetl plik

import { useTestDbConnect } from '@/hooks/flow-hooks'; import { useTestDbConnect } from '@/hooks/flow-hooks';
import { Button, Flex, Form, Input, InputNumber, Select } from 'antd'; import { Button, Flex, Form, Input, InputNumber, Select } from 'antd';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { ExeSQLOptions } from '../../constant';
import { IOperatorForm } from '../../interface'; import { IOperatorForm } from '../../interface';
import { ExeSQLOptions } from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';


const ExeSQLForm = ({ onValuesChange, form, node }: IOperatorForm) => { const ExeSQLForm = ({ onValuesChange, form, node }: IOperatorForm) => {

+ 1
- 1
web/src/pages/agent/form/google-form/index.tsx Wyświetl plik

import TopNItem from '@/components/top-n-item'; import TopNItem from '@/components/top-n-item';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { Form, Input, Select } from 'antd'; import { Form, Input, Select } from 'antd';
import { GoogleCountryOptions, GoogleLanguageOptions } from '../../constant';
import { IOperatorForm } from '../../interface'; import { IOperatorForm } from '../../interface';
import { GoogleCountryOptions, GoogleLanguageOptions } from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';


const GoogleForm = ({ onValuesChange, form, node }: IOperatorForm) => { const GoogleForm = ({ onValuesChange, form, node }: IOperatorForm) => {

+ 2
- 2
web/src/pages/agent/form/jin10-form/index.tsx Wyświetl plik

import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { Form, Input, Select } from 'antd'; import { Form, Input, Select } from 'antd';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { IOperatorForm } from '../../interface';
import { import {
Jin10CalendarDatashapeOptions, Jin10CalendarDatashapeOptions,
Jin10CalendarTypeOptions, Jin10CalendarTypeOptions,
Jin10SymbolsDatatypeOptions, Jin10SymbolsDatatypeOptions,
Jin10SymbolsTypeOptions, Jin10SymbolsTypeOptions,
Jin10TypeOptions, Jin10TypeOptions,
} from '../../constant';
import { IOperatorForm } from '../../interface';
} from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';


const Jin10Form = ({ onValuesChange, form, node }: IOperatorForm) => { const Jin10Form = ({ onValuesChange, form, node }: IOperatorForm) => {

+ 2
- 2
web/src/pages/agent/form/qweather-form/index.tsx Wyświetl plik

import { RAGFlowSelect } from '@/components/ui/select'; import { RAGFlowSelect } from '@/components/ui/select';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { INextOperatorForm } from '../../interface';
import { import {
QWeatherLangOptions, QWeatherLangOptions,
QWeatherTimePeriodOptions, QWeatherTimePeriodOptions,
QWeatherTypeOptions, QWeatherTypeOptions,
QWeatherUserTypeOptions, QWeatherUserTypeOptions,
} from '../../constant';
import { INextOperatorForm } from '../../interface';
} from '../../options';
import { DynamicInputVariable } from '../components/next-dynamic-input-variable'; import { DynamicInputVariable } from '../components/next-dynamic-input-variable';


enum FormFieldName { enum FormFieldName {

+ 33
- 23
web/src/pages/agent/form/retrieval-form/next.tsx Wyświetl plik

import { Textarea } from '@/components/ui/textarea'; import { Textarea } from '@/components/ui/textarea';
import { zodResolver } from '@hookform/resolvers/zod'; import { zodResolver } from '@hookform/resolvers/zod';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useForm } from 'react-hook-form';
import { useForm, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { z } from 'zod'; import { z } from 'zod';
import { initialRetrievalValues } from '../../constant'; import { initialRetrievalValues } from '../../constant';
import { QueryVariable } from '../components/query-variable'; import { QueryVariable } from '../components/query-variable';
import { useValues } from './use-values'; import { useValues } from './use-values';


const FormSchema = z.object({
query: z.string().optional(),
export const RetrievalPartialSchema = {
similarity_threshold: z.coerce.number(), similarity_threshold: z.coerce.number(),
keywords_similarity_weight: z.coerce.number(), keywords_similarity_weight: z.coerce.number(),
top_n: z.coerce.number(), top_n: z.coerce.number(),
kb_ids: z.array(z.string()), kb_ids: z.array(z.string()),
rerank_id: z.string(), rerank_id: z.string(),
empty_response: z.string(), empty_response: z.string(),
};

export const FormSchema = z.object({
query: z.string().optional(),
...RetrievalPartialSchema,
}); });


const RetrievalForm = ({ node }: INextOperatorForm) => {
export function EmptyResponseField() {
const { t } = useTranslation(); const { t } = useTranslation();
const form = useFormContext();


return (
<FormField
control={form.control}
name="empty_response"
render={({ field }) => (
<FormItem>
<FormLabel>{t('chat.emptyResponse')}</FormLabel>
<FormControl>
<Textarea
placeholder={t('common.namePlaceholder')}
{...field}
autoComplete="off"
rows={4}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
);
}

const RetrievalForm = ({ node }: INextOperatorForm) => {
const outputList = useMemo(() => { const outputList = useMemo(() => {
return [ return [
{ {
></SimilaritySliderFormField> ></SimilaritySliderFormField>
<TopNFormField></TopNFormField> <TopNFormField></TopNFormField>
<RerankFormFields></RerankFormFields> <RerankFormFields></RerankFormFields>

<FormField
control={form.control}
name="empty_response"
render={({ field }) => (
<FormItem>
<FormLabel>{t('chat.emptyResponse')}</FormLabel>
<FormControl>
<Textarea
placeholder={t('common.namePlaceholder')}
{...field}
autoComplete="off"
rows={4}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<EmptyResponseField></EmptyResponseField>
</FormContainer> </FormContainer>
<Output list={outputList}></Output> <Output list={outputList}></Output>
</form> </form>

+ 1
- 1
web/src/pages/agent/form/rewrite-question-form/index.tsx Wyświetl plik

} from '@/components/ui/form'; } from '@/components/ui/form';
import { RAGFlowSelect } from '@/components/ui/select'; import { RAGFlowSelect } from '@/components/ui/select';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { GoogleLanguageOptions } from '../../constant';
import { INextOperatorForm } from '../../interface'; import { INextOperatorForm } from '../../interface';
import { GoogleLanguageOptions } from '../../options';


const RewriteQuestionForm = ({ form }: INextOperatorForm) => { const RewriteQuestionForm = ({ form }: INextOperatorForm) => {
const { t } = useTranslation(); const { t } = useTranslation();

+ 1
- 1
web/src/pages/agent/form/tool-form/constant.ts Wyświetl plik

import GoogleForm from '../google-form'; import GoogleForm from '../google-form';
import GoogleScholarForm from '../google-scholar-form'; import GoogleScholarForm from '../google-scholar-form';
import PubMedForm from '../pubmed-form'; import PubMedForm from '../pubmed-form';
import RetrievalForm from '../retrieval-form/next';
import WikipediaForm from '../wikipedia-form'; import WikipediaForm from '../wikipedia-form';
import YahooFinanceForm from '../yahoo-finance-form'; import YahooFinanceForm from '../yahoo-finance-form';
import RetrievalForm from './retrieval-form';
import TavilyForm from './tavily-form'; import TavilyForm from './tavily-form';


export const ToolFormConfigMap = { export const ToolFormConfigMap = {

+ 59
- 0
web/src/pages/agent/form/tool-form/retrieval-form/index.tsx Wyświetl plik

import { FormContainer } from '@/components/form-container';
import { KnowledgeBaseFormField } from '@/components/knowledge-base-item';
import { RerankFormFields } from '@/components/rerank';
import { SimilaritySliderFormField } from '@/components/similarity-slider';
import { TopNFormField } from '@/components/top-n-item';
import { Form } from '@/components/ui/form';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { DescriptionField } from '../../components/description-field';
import {
EmptyResponseField,
RetrievalPartialSchema,
} from '../../retrieval-form/next';
import { useValues } from '../use-values';
import { useWatchFormChange } from '../use-watch-change';

export const FormSchema = z.object({
...RetrievalPartialSchema,
description: z.string().optional(),
});

const RetrievalForm = () => {
const defaultValues = useValues();

const form = useForm({
defaultValues: defaultValues,
resolver: zodResolver(FormSchema),
});

useWatchFormChange(form);

return (
<Form {...form}>
<form
className="space-y-6 p-4"
onSubmit={(e) => {
e.preventDefault();
}}
>
<FormContainer>
<DescriptionField></DescriptionField>
<KnowledgeBaseFormField></KnowledgeBaseFormField>
</FormContainer>
<FormContainer>
<SimilaritySliderFormField
vectorSimilarityWeightName="keywords_similarity_weight"
isTooltipShown
></SimilaritySliderFormField>
<TopNFormField></TopNFormField>
<RerankFormFields></RerankFormFields>
<EmptyResponseField></EmptyResponseField>
</FormContainer>
</form>
</Form>
);
};

export default RetrievalForm;

+ 6
- 4
web/src/pages/agent/form/tool-form/use-values.ts Wyświetl plik

import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { DefaultAgentToolValuesMap } from '../../constant';
import useGraphStore from '../../store'; import useGraphStore from '../../store';
import { getAgentNodeTools } from '../../utils'; import { getAgentNodeTools } from '../../utils';


General = 'general', General = 'general',
} }


export const defaultValues = {
api_key: '',
};

export function useValues() { export function useValues() {
const { clickedToolId, clickedNodeId, findUpstreamNodeById } = useGraphStore( const { clickedToolId, clickedNodeId, findUpstreamNodeById } = useGraphStore(
(state) => state, (state) => state,
)?.params; )?.params;


if (isEmpty(formData)) { if (isEmpty(formData)) {
const defaultValues =
DefaultAgentToolValuesMap[
clickedToolId as keyof typeof DefaultAgentToolValuesMap
];

return defaultValues; return defaultValues;
} }



+ 1
- 1
web/src/pages/agent/form/tushare-form/index.tsx Wyświetl plik

import { DatePicker, DatePickerProps, Form, Input, Select } from 'antd'; import { DatePicker, DatePickerProps, Form, Input, Select } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { TuShareSrcOptions } from '../../constant';
import { IOperatorForm } from '../../interface'; import { IOperatorForm } from '../../interface';
import { TuShareSrcOptions } from '../../options';
import DynamicInputVariable from '../components/dynamic-input-variable'; import DynamicInputVariable from '../components/dynamic-input-variable';


const DateTimePicker = ({ const DateTimePicker = ({

+ 1
- 1
web/src/pages/agent/form/wencai-form/index.tsx Wyświetl plik

import { RAGFlowSelect } from '@/components/ui/select'; import { RAGFlowSelect } from '@/components/ui/select';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { WenCaiQueryTypeOptions } from '../../constant';
import { INextOperatorForm } from '../../interface'; import { INextOperatorForm } from '../../interface';
import { WenCaiQueryTypeOptions } from '../../options';
import { DynamicInputVariable } from '../components/next-dynamic-input-variable'; import { DynamicInputVariable } from '../components/next-dynamic-input-variable';


const WenCaiForm = ({ form, node }: INextOperatorForm) => { const WenCaiForm = ({ form, node }: INextOperatorForm) => {

+ 1
- 1
web/src/pages/agent/form/wikipedia-form/index.tsx Wyświetl plik

} from '@/components/ui/form'; } from '@/components/ui/form';
import { RAGFlowSelect } from '@/components/ui/select'; import { RAGFlowSelect } from '@/components/ui/select';
import { useTranslate } from '@/hooks/common-hooks'; import { useTranslate } from '@/hooks/common-hooks';
import { LanguageOptions } from '../../constant';
import { INextOperatorForm } from '../../interface'; import { INextOperatorForm } from '../../interface';
import { LanguageOptions } from '../../options';
import { DynamicInputVariable } from '../components/next-dynamic-input-variable'; import { DynamicInputVariable } from '../components/next-dynamic-input-variable';


const WikipediaForm = ({ form, node }: INextOperatorForm) => { const WikipediaForm = ({ form, node }: INextOperatorForm) => {

+ 3
- 5
web/src/pages/agent/hooks/use-add-node.ts Wyświetl plik

} }


function useAddToolNode() { function useAddToolNode() {
const addNode = useGraphStore((state) => state.addNode);
const getNode = useGraphStore((state) => state.getNode);
const addEdge = useGraphStore((state) => state.addEdge);
const edges = useGraphStore((state) => state.edges);
const nodes = useGraphStore((state) => state.nodes);
const { nodes, edges, addEdge, getNode, addNode } = useGraphStore(
(state) => state,
);


const addToolNode = useCallback( const addToolNode = useCallback(
(newNode: Node<any>, nodeId?: string) => { (newNode: Node<any>, nodeId?: string) => {

+ 2170
- 0
web/src/pages/agent/options.ts
Plik diff jest za duży
Wyświetl plik


Ładowanie…
Anuluj
Zapisz