### What problem does this PR solve? Feat: Add TavilyExtract operator #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.20.0
| agent: 'Agent', | agent: 'Agent', | ||||
| 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', | |||||
| }, | }, | ||||
| llmTools: { | llmTools: { | ||||
| bad_calculator: { | bad_calculator: { |
| query: '查询变量', | query: '查询变量', | ||||
| agent: 'Agent', | agent: 'Agent', | ||||
| agentDescription: '构建具备推理、工具调用和多智能体协同的智能体组件。', | agentDescription: '构建具备推理、工具调用和多智能体协同的智能体组件。', | ||||
| maxRecords: '最大记录数', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: 'All rights reserved @ React', | profile: 'All rights reserved @ React', |
| import { SideDown } from '@/assets/icon/Icon'; | |||||
| import { Card, CardContent } from '@/components/ui/card'; | |||||
| import { | |||||
| Collapsible, | |||||
| CollapsibleContent, | |||||
| CollapsibleTrigger, | |||||
| } from '@/components/ui/collapsible'; | |||||
| import { | |||||
| Sidebar, | |||||
| SidebarContent, | |||||
| SidebarGroup, | |||||
| SidebarGroupContent, | |||||
| SidebarGroupLabel, | |||||
| SidebarHeader, | |||||
| SidebarMenu, | |||||
| } from '@/components/ui/sidebar'; | |||||
| import { memo, useMemo } from 'react'; | |||||
| import { | |||||
| AgentOperatorList, | |||||
| Operator, | |||||
| componentMenuList, | |||||
| operatorMap, | |||||
| } from './constant'; | |||||
| import { useHandleDrag } from './hooks'; | |||||
| import OperatorIcon from './operator-icon'; | |||||
| type OperatorItem = { | |||||
| name: Operator; | |||||
| }; | |||||
| function OperatorCard({ name }: OperatorItem) { | |||||
| const { handleDragStart } = useHandleDrag(); | |||||
| return ( | |||||
| <Card | |||||
| draggable | |||||
| onDragStart={handleDragStart(name)} | |||||
| className="bg-colors-background-inverse-weak border-colors-outline-neutral-standard cursor-pointer" | |||||
| > | |||||
| <CardContent className="p-2 flex items-center gap-2"> | |||||
| <OperatorIcon | |||||
| name={name} | |||||
| color={operatorMap[name].color} | |||||
| ></OperatorIcon> | |||||
| {name} | |||||
| </CardContent> | |||||
| </Card> | |||||
| ); | |||||
| } | |||||
| type OperatorCollapsibleProps = { operatorList: OperatorItem[]; title: string }; | |||||
| function OperatorCollapsible({ | |||||
| operatorList, | |||||
| title, | |||||
| }: OperatorCollapsibleProps) { | |||||
| return ( | |||||
| <Collapsible defaultOpen className="group/collapsible"> | |||||
| <SidebarGroup> | |||||
| <SidebarGroupLabel asChild className="mb-1"> | |||||
| <CollapsibleTrigger> | |||||
| <span className="font-bold text-base">{title}</span> | |||||
| <SideDown className="ml-auto" /> | |||||
| </CollapsibleTrigger> | |||||
| </SidebarGroupLabel> | |||||
| <CollapsibleContent className="px-2"> | |||||
| <SidebarGroupContent> | |||||
| <SidebarMenu className="gap-2"> | |||||
| {operatorList.map((item) => ( | |||||
| <OperatorCard key={item.name} name={item.name}></OperatorCard> | |||||
| ))} | |||||
| </SidebarMenu> | |||||
| </SidebarGroupContent> | |||||
| </CollapsibleContent> | |||||
| </SidebarGroup> | |||||
| </Collapsible> | |||||
| ); | |||||
| } | |||||
| function InnerAgentSidebar() { | |||||
| const agentOperatorList = useMemo(() => { | |||||
| return componentMenuList.filter((x) => | |||||
| AgentOperatorList.some((y) => y === x.name), | |||||
| ); | |||||
| }, []); | |||||
| const thirdOperatorList = useMemo(() => { | |||||
| return componentMenuList.filter( | |||||
| (x) => !AgentOperatorList.some((y) => y === x.name), | |||||
| ); | |||||
| }, []); | |||||
| return ( | |||||
| <Sidebar variant={'floating'} className="top-16"> | |||||
| <SidebarHeader> | |||||
| <p className="font-bold text-2xl">All nodes</p> | |||||
| </SidebarHeader> | |||||
| <SidebarContent> | |||||
| <OperatorCollapsible | |||||
| title="Agent operator" | |||||
| operatorList={agentOperatorList} | |||||
| ></OperatorCollapsible> | |||||
| <OperatorCollapsible | |||||
| title="Third-party tools" | |||||
| operatorList={thirdOperatorList} | |||||
| ></OperatorCollapsible> | |||||
| </SidebarContent> | |||||
| </Sidebar> | |||||
| ); | |||||
| } | |||||
| export const AgentSidebar = memo(InnerAgentSidebar); |
| <OperatorItemList | <OperatorItemList | ||||
| operators={[ | operators={[ | ||||
| Operator.TavilySearch, | Operator.TavilySearch, | ||||
| Operator.Crawler, | |||||
| Operator.TavilyExtract, | |||||
| Operator.ExeSQL, | Operator.ExeSQL, | ||||
| Operator.Bing, | Operator.Bing, | ||||
| ]} | ]} |
| Agent = 'Agent', | Agent = 'Agent', | ||||
| Tool = 'Tool', | Tool = 'Tool', | ||||
| TavilySearch = 'TavilySearch', | TavilySearch = 'TavilySearch', | ||||
| TavilyExtract = 'TavilyExtract', | |||||
| UserFillUp = 'UserFillUp', | UserFillUp = 'UserFillUp', | ||||
| StringTransform = 'StringTransform', | StringTransform = 'StringTransform', | ||||
| } | } | ||||
| Operator.Agent, | Operator.Agent, | ||||
| ]; | ]; | ||||
| export const operatorMap: Record< | |||||
| Operator, | |||||
| { | |||||
| backgroundColor?: string; | |||||
| color?: string; | |||||
| width?: number; | |||||
| height?: number; | |||||
| fontSize?: number; | |||||
| iconFontSize?: number; | |||||
| iconWidth?: number; | |||||
| moreIconColor?: string; | |||||
| } | |||||
| > = { | |||||
| [Operator.Retrieval]: { | |||||
| backgroundColor: '#cad6e0', | |||||
| color: '#385974', | |||||
| }, | |||||
| [Operator.Generate]: { | |||||
| backgroundColor: '#ebd6d6', | |||||
| width: 150, | |||||
| height: 150, | |||||
| fontSize: 20, | |||||
| iconFontSize: 30, | |||||
| color: '#996464', | |||||
| }, | |||||
| [Operator.Answer]: { | |||||
| backgroundColor: '#f4816d', | |||||
| color: '#f4816d', | |||||
| }, | |||||
| [Operator.Begin]: { | |||||
| backgroundColor: '#4f51d6', | |||||
| }, | |||||
| [Operator.Categorize]: { | |||||
| backgroundColor: '#ffebcd', | |||||
| color: '#cc8a26', | |||||
| }, | |||||
| [Operator.Message]: { | |||||
| backgroundColor: '#c5ddc7', | |||||
| color: 'green', | |||||
| }, | |||||
| [Operator.Relevant]: { | |||||
| backgroundColor: '#9fd94d', | |||||
| color: '#8ef005', | |||||
| width: 70, | |||||
| height: 70, | |||||
| fontSize: 12, | |||||
| iconFontSize: 16, | |||||
| }, | |||||
| [Operator.RewriteQuestion]: { | |||||
| backgroundColor: '#f8c7f8', | |||||
| color: '#f32bf3', | |||||
| width: 70, | |||||
| height: 70, | |||||
| fontSize: 12, | |||||
| iconFontSize: 16, | |||||
| }, | |||||
| [Operator.KeywordExtract]: { | |||||
| width: 70, | |||||
| height: 70, | |||||
| backgroundColor: '#6E5494', | |||||
| color: '#6E5494', | |||||
| fontSize: 12, | |||||
| iconWidth: 16, | |||||
| }, | |||||
| [Operator.DuckDuckGo]: { | |||||
| backgroundColor: '#e7e389', | |||||
| color: '#aea00c', | |||||
| }, | |||||
| [Operator.Baidu]: { | |||||
| backgroundColor: '#d9e0f8', | |||||
| }, | |||||
| [Operator.Wikipedia]: { | |||||
| backgroundColor: '#dee0e2', | |||||
| }, | |||||
| [Operator.PubMed]: { | |||||
| backgroundColor: '#a2ccf0', | |||||
| }, | |||||
| [Operator.ArXiv]: { | |||||
| width: 70, | |||||
| height: 70, | |||||
| fontSize: 12, | |||||
| iconWidth: 16, | |||||
| iconFontSize: 16, | |||||
| moreIconColor: 'white', | |||||
| backgroundColor: '#b31b1b', | |||||
| color: 'white', | |||||
| }, | |||||
| [Operator.Google]: { | |||||
| backgroundColor: 'pink', | |||||
| }, | |||||
| [Operator.Bing]: { | |||||
| backgroundColor: '#c0dcc4', | |||||
| }, | |||||
| [Operator.GoogleScholar]: { | |||||
| backgroundColor: '#b4e4f6', | |||||
| }, | |||||
| [Operator.DeepL]: { | |||||
| backgroundColor: '#f5e8e6', | |||||
| }, | |||||
| [Operator.GitHub]: { | |||||
| backgroundColor: 'purple', | |||||
| color: 'purple', | |||||
| }, | |||||
| [Operator.BaiduFanyi]: { backgroundColor: '#e5f2d3' }, | |||||
| [Operator.QWeather]: { | |||||
| backgroundColor: '#a4bbf3', | |||||
| color: '#a4bbf3', | |||||
| }, | |||||
| [Operator.ExeSQL]: { backgroundColor: '#b9efe8' }, | |||||
| [Operator.Switch]: { backgroundColor: '#dbaff6', color: '#dbaff6' }, | |||||
| [Operator.WenCai]: { backgroundColor: '#faac5b' }, | |||||
| [Operator.AkShare]: { backgroundColor: '#8085f5' }, | |||||
| [Operator.YahooFinance]: { backgroundColor: '#b474ff' }, | |||||
| [Operator.Jin10]: { backgroundColor: '#a0b9f8' }, | |||||
| [Operator.Concentrator]: { | |||||
| backgroundColor: '#32d2a3', | |||||
| color: '#32d2a3', | |||||
| width: 70, | |||||
| height: 70, | |||||
| fontSize: 10, | |||||
| iconFontSize: 16, | |||||
| }, | |||||
| [Operator.TuShare]: { backgroundColor: '#f8cfa0' }, | |||||
| [Operator.Note]: { backgroundColor: '#f8cfa0' }, | |||||
| [Operator.Crawler]: { | |||||
| backgroundColor: '#dee0e2', | |||||
| }, | |||||
| [Operator.Invoke]: { | |||||
| backgroundColor: '#dee0e2', | |||||
| }, | |||||
| [Operator.Template]: { | |||||
| backgroundColor: '#dee0e2', | |||||
| }, | |||||
| [Operator.Email]: { backgroundColor: '#e6f7ff' }, | |||||
| [Operator.Iteration]: { backgroundColor: '#e6f7ff' }, | |||||
| [Operator.IterationStart]: { backgroundColor: '#e6f7ff' }, | |||||
| [Operator.Code]: { backgroundColor: '#4c5458' }, | |||||
| [Operator.WaitingDialogue]: { backgroundColor: '#a5d65c' }, | |||||
| [Operator.Agent]: { backgroundColor: '#a5d65c' }, | |||||
| [Operator.TavilySearch]: { backgroundColor: '#a5d65c' }, | |||||
| }; | |||||
| export const componentMenuList = [ | export const componentMenuList = [ | ||||
| { | { | ||||
| name: Operator.Retrieval, | name: Operator.Retrieval, | ||||
| }; | }; | ||||
| export const initialExeSqlValues = { | export const initialExeSqlValues = { | ||||
| ...initialLlmBaseValues, | |||||
| sql: '', | |||||
| db_type: 'mysql', | db_type: 'mysql', | ||||
| database: '', | database: '', | ||||
| username: '', | username: '', | ||||
| host: '', | host: '', | ||||
| port: 3306, | port: 3306, | ||||
| password: '', | password: '', | ||||
| loop: 3, | |||||
| top_n: 30, | |||||
| query: '', | |||||
| max_records: 1024, | |||||
| }; | }; | ||||
| export const initialSwitchValues = { | export const initialSwitchValues = { | ||||
| type: 'string', | type: 'string', | ||||
| }, | }, | ||||
| json: { | json: { | ||||
| value: {}, | |||||
| type: 'Object', | |||||
| value: [], | |||||
| type: 'Array<Object>', | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| export enum TavilyExtractDepth { | |||||
| Basic = 'basic', | |||||
| Advanced = 'advanced', | |||||
| } | |||||
| export enum TavilyExtractFormat { | |||||
| Text = 'text', | |||||
| Markdown = 'markdown', | |||||
| } | |||||
| export const initialTavilyExtractValues = { | |||||
| urls: '', | |||||
| extract_depth: TavilyExtractDepth.Basic, | |||||
| format: TavilyExtractFormat.Markdown, | |||||
| outputs: { | |||||
| formalized_content: { | |||||
| value: '', | |||||
| type: 'string', | |||||
| }, | |||||
| json: { | |||||
| value: [], | |||||
| type: 'Array<Object>', | |||||
| }, | }, | ||||
| }, | }, | ||||
| }; | }; | ||||
| [Operator.WaitingDialogue]: [Operator.Begin], | [Operator.WaitingDialogue]: [Operator.Begin], | ||||
| [Operator.Agent]: [Operator.Begin], | [Operator.Agent]: [Operator.Begin], | ||||
| [Operator.TavilySearch]: [Operator.Begin], | [Operator.TavilySearch]: [Operator.Begin], | ||||
| [Operator.TavilyExtract]: [Operator.Begin], | |||||
| [Operator.StringTransform]: [Operator.Begin], | [Operator.StringTransform]: [Operator.Begin], | ||||
| [Operator.UserFillUp]: [Operator.Begin], | [Operator.UserFillUp]: [Operator.Begin], | ||||
| }; | }; | ||||
| [Operator.TavilySearch]: 'ragNode', | [Operator.TavilySearch]: 'ragNode', | ||||
| [Operator.UserFillUp]: 'ragNode', | [Operator.UserFillUp]: 'ragNode', | ||||
| [Operator.StringTransform]: 'ragNode', | [Operator.StringTransform]: 'ragNode', | ||||
| [Operator.TavilyExtract]: 'ragNode', | |||||
| }; | }; | ||||
| export enum BeginQueryType { | export enum BeginQueryType { |
| import { z } from 'zod'; | |||||
| import { Operator } from '../constant'; | |||||
| import AgentForm from '../form/agent-form'; | |||||
| import AkShareForm from '../form/akshare-form'; | |||||
| import AnswerForm from '../form/answer-form'; | |||||
| import ArXivForm from '../form/arxiv-form'; | |||||
| import BaiduFanyiForm from '../form/baidu-fanyi-form'; | |||||
| import BaiduForm from '../form/baidu-form'; | |||||
| import BeginForm from '../form/begin-form'; | |||||
| import BingForm from '../form/bing-form'; | |||||
| import CategorizeForm from '../form/categorize-form'; | |||||
| import CodeForm from '../form/code-form'; | |||||
| import CrawlerForm from '../form/crawler-form'; | |||||
| import DeepLForm from '../form/deepl-form'; | |||||
| import DuckDuckGoForm from '../form/duckduckgo-form'; | |||||
| import EmailForm from '../form/email-form'; | |||||
| import ExeSQLForm from '../form/exesql-form'; | |||||
| import GenerateForm from '../form/generate-form'; | |||||
| import GithubForm from '../form/github-form'; | |||||
| import GoogleForm from '../form/google-form'; | |||||
| import GoogleScholarForm from '../form/google-scholar-form'; | |||||
| import InvokeForm from '../form/invoke-form'; | |||||
| import IterationForm from '../form/iteration-form'; | |||||
| import IterationStartForm from '../form/iteration-start-from'; | |||||
| import Jin10Form from '../form/jin10-form'; | |||||
| import KeywordExtractForm from '../form/keyword-extract-form'; | |||||
| import MessageForm from '../form/message-form'; | |||||
| import PubMedForm from '../form/pubmed-form'; | |||||
| import QWeatherForm from '../form/qweather-form'; | |||||
| import RelevantForm from '../form/relevant-form'; | |||||
| import RetrievalForm from '../form/retrieval-form/next'; | |||||
| import RewriteQuestionForm from '../form/rewrite-question-form'; | |||||
| import { StringTransformForm } from '../form/string-transform-form'; | |||||
| import SwitchForm from '../form/switch-form'; | |||||
| import TavilyExtractForm from '../form/tavily-extract-form'; | |||||
| import TavilyForm from '../form/tavily-form'; | |||||
| import TemplateForm from '../form/template-form'; | |||||
| import ToolForm from '../form/tool-form'; | |||||
| import TuShareForm from '../form/tushare-form'; | |||||
| import UserFillUpForm from '../form/user-fill-up-form'; | |||||
| import WenCaiForm from '../form/wencai-form'; | |||||
| import WikipediaForm from '../form/wikipedia-form'; | |||||
| import YahooFinanceForm from '../form/yahoo-finance-form'; | |||||
| export const FormConfigMap = { | |||||
| [Operator.Begin]: { | |||||
| component: BeginForm, | |||||
| }, | |||||
| [Operator.Retrieval]: { | |||||
| component: RetrievalForm, | |||||
| }, | |||||
| [Operator.Generate]: { | |||||
| component: GenerateForm, | |||||
| }, | |||||
| [Operator.Answer]: { | |||||
| component: AnswerForm, | |||||
| }, | |||||
| [Operator.Categorize]: { | |||||
| component: CategorizeForm, | |||||
| }, | |||||
| [Operator.Message]: { | |||||
| component: MessageForm, | |||||
| }, | |||||
| [Operator.Relevant]: { | |||||
| component: RelevantForm, | |||||
| }, | |||||
| [Operator.RewriteQuestion]: { | |||||
| component: RewriteQuestionForm, | |||||
| }, | |||||
| [Operator.Code]: { | |||||
| component: CodeForm, | |||||
| }, | |||||
| [Operator.WaitingDialogue]: { | |||||
| component: CodeForm, | |||||
| }, | |||||
| [Operator.Agent]: { | |||||
| component: AgentForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Baidu]: { | |||||
| component: BaiduForm, | |||||
| }, | |||||
| [Operator.DuckDuckGo]: { | |||||
| component: DuckDuckGoForm, | |||||
| }, | |||||
| [Operator.KeywordExtract]: { | |||||
| component: KeywordExtractForm, | |||||
| }, | |||||
| [Operator.Wikipedia]: { | |||||
| component: WikipediaForm, | |||||
| }, | |||||
| [Operator.PubMed]: { | |||||
| component: PubMedForm, | |||||
| }, | |||||
| [Operator.ArXiv]: { | |||||
| component: ArXivForm, | |||||
| }, | |||||
| [Operator.Google]: { | |||||
| component: GoogleForm, | |||||
| }, | |||||
| [Operator.Bing]: { | |||||
| component: BingForm, | |||||
| }, | |||||
| [Operator.GoogleScholar]: { | |||||
| component: GoogleScholarForm, | |||||
| }, | |||||
| [Operator.DeepL]: { | |||||
| component: DeepLForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.GitHub]: { | |||||
| component: GithubForm, | |||||
| }, | |||||
| [Operator.BaiduFanyi]: { | |||||
| component: BaiduFanyiForm, | |||||
| }, | |||||
| [Operator.QWeather]: { | |||||
| component: QWeatherForm, | |||||
| }, | |||||
| [Operator.ExeSQL]: { | |||||
| component: ExeSQLForm, | |||||
| }, | |||||
| [Operator.Switch]: { | |||||
| component: SwitchForm, | |||||
| }, | |||||
| [Operator.WenCai]: { | |||||
| component: WenCaiForm, | |||||
| }, | |||||
| [Operator.AkShare]: { | |||||
| component: AkShareForm, | |||||
| }, | |||||
| [Operator.YahooFinance]: { | |||||
| component: YahooFinanceForm, | |||||
| }, | |||||
| [Operator.Jin10]: { | |||||
| component: Jin10Form, | |||||
| }, | |||||
| [Operator.TuShare]: { | |||||
| component: TuShareForm, | |||||
| }, | |||||
| [Operator.Crawler]: { | |||||
| component: CrawlerForm, | |||||
| }, | |||||
| [Operator.Invoke]: { | |||||
| component: InvokeForm, | |||||
| }, | |||||
| [Operator.Concentrator]: { | |||||
| component: () => <></>, | |||||
| }, | |||||
| [Operator.Note]: { | |||||
| component: () => <></>, | |||||
| }, | |||||
| [Operator.Template]: { | |||||
| component: TemplateForm, | |||||
| }, | |||||
| [Operator.Email]: { | |||||
| component: EmailForm, | |||||
| }, | |||||
| [Operator.Iteration]: { | |||||
| component: IterationForm, | |||||
| }, | |||||
| [Operator.IterationStart]: { | |||||
| component: IterationStartForm, | |||||
| }, | |||||
| [Operator.Tool]: { | |||||
| component: ToolForm, | |||||
| }, | |||||
| [Operator.TavilySearch]: { | |||||
| component: TavilyForm, | |||||
| }, | |||||
| [Operator.UserFillUp]: { | |||||
| component: UserFillUpForm, | |||||
| }, | |||||
| [Operator.StringTransform]: { | |||||
| component: StringTransformForm, | |||||
| }, | |||||
| [Operator.TavilyExtract]: { | |||||
| component: TavilyExtractForm, | |||||
| }, | |||||
| }; |
| import OperatorIcon from '../operator-icon'; | import OperatorIcon from '../operator-icon'; | ||||
| import useGraphStore from '../store'; | import useGraphStore from '../store'; | ||||
| import { needsSingleStepDebugging } from '../utils'; | import { needsSingleStepDebugging } from '../utils'; | ||||
| import { FormConfigMap } from './form-config-map'; | |||||
| import SingleDebugDrawer from './single-debug-drawer'; | import SingleDebugDrawer from './single-debug-drawer'; | ||||
| import { useFormConfigMap } from './use-form-config-map'; | |||||
| interface IProps { | interface IProps { | ||||
| node?: RAGFlowNodeType; | node?: RAGFlowNodeType; | ||||
| const operatorName: Operator = node?.data.label as Operator; | const operatorName: Operator = node?.data.label as Operator; | ||||
| const clickedToolId = useGraphStore((state) => state.clickedToolId); | const clickedToolId = useGraphStore((state) => state.clickedToolId); | ||||
| const FormConfigMap = useFormConfigMap(); | |||||
| const currentFormMap = FormConfigMap[operatorName]; | const currentFormMap = FormConfigMap[operatorName]; | ||||
| const OperatorForm = currentFormMap?.component ?? EmptyContent; | const OperatorForm = currentFormMap?.component ?? EmptyContent; |
| import { LlmSettingSchema } from '@/components/llm-setting-items/next'; | |||||
| import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; | |||||
| import { useTranslation } from 'react-i18next'; | |||||
| import { z } from 'zod'; | |||||
| import { Operator } from '../constant'; | |||||
| import AgentForm from '../form/agent-form'; | |||||
| import AkShareForm from '../form/akshare-form'; | |||||
| import AnswerForm from '../form/answer-form'; | |||||
| import ArXivForm from '../form/arxiv-form'; | |||||
| import BaiduFanyiForm from '../form/baidu-fanyi-form'; | |||||
| import BaiduForm from '../form/baidu-form'; | |||||
| import BeginForm from '../form/begin-form'; | |||||
| import BingForm from '../form/bing-form'; | |||||
| import CategorizeForm from '../form/categorize-form'; | |||||
| import CodeForm from '../form/code-form'; | |||||
| import CrawlerForm from '../form/crawler-form'; | |||||
| import DeepLForm from '../form/deepl-form'; | |||||
| import DuckDuckGoForm from '../form/duckduckgo-form'; | |||||
| import EmailForm from '../form/email-form'; | |||||
| import ExeSQLForm from '../form/exesql-form'; | |||||
| import GenerateForm from '../form/generate-form'; | |||||
| import GithubForm from '../form/github-form'; | |||||
| import GoogleForm from '../form/google-form'; | |||||
| import GoogleScholarForm from '../form/google-scholar-form'; | |||||
| import InvokeForm from '../form/invoke-form'; | |||||
| import IterationForm from '../form/iteration-form'; | |||||
| import IterationStartForm from '../form/iteration-start-from'; | |||||
| import Jin10Form from '../form/jin10-form'; | |||||
| import KeywordExtractForm from '../form/keyword-extract-form'; | |||||
| import MessageForm from '../form/message-form'; | |||||
| import PubMedForm from '../form/pubmed-form'; | |||||
| import QWeatherForm from '../form/qweather-form'; | |||||
| import RelevantForm from '../form/relevant-form'; | |||||
| import RetrievalForm from '../form/retrieval-form/next'; | |||||
| import RewriteQuestionForm from '../form/rewrite-question-form'; | |||||
| import { StringTransformForm } from '../form/string-transform-form'; | |||||
| import SwitchForm from '../form/switch-form'; | |||||
| import TavilyForm from '../form/tavily-form'; | |||||
| import TemplateForm from '../form/template-form'; | |||||
| import ToolForm from '../form/tool-form'; | |||||
| import TuShareForm from '../form/tushare-form'; | |||||
| import UserFillUpForm from '../form/user-fill-up-form'; | |||||
| import WenCaiForm from '../form/wencai-form'; | |||||
| import WikipediaForm from '../form/wikipedia-form'; | |||||
| import YahooFinanceForm from '../form/yahoo-finance-form'; | |||||
| export function useFormConfigMap() { | |||||
| const { t } = useTranslation(); | |||||
| const FormConfigMap = { | |||||
| [Operator.Begin]: { | |||||
| component: BeginForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({ | |||||
| enablePrologue: z.boolean().optional(), | |||||
| prologue: z | |||||
| .string() | |||||
| .min(1, { | |||||
| message: t('common.namePlaceholder'), | |||||
| }) | |||||
| .trim() | |||||
| .optional(), | |||||
| mode: z.string(), | |||||
| query: z | |||||
| .array( | |||||
| z.object({ | |||||
| key: z.string(), | |||||
| type: z.string(), | |||||
| value: z.string(), | |||||
| optional: z.boolean(), | |||||
| name: z.string(), | |||||
| options: z.array(z.union([z.number(), z.string(), z.boolean()])), | |||||
| }), | |||||
| ) | |||||
| .optional(), | |||||
| }), | |||||
| }, | |||||
| [Operator.Retrieval]: { | |||||
| component: RetrievalForm, | |||||
| defaultValues: { query: [] }, | |||||
| schema: z.object({ | |||||
| name: z | |||||
| .string() | |||||
| .min(1, { | |||||
| message: t('common.namePlaceholder'), | |||||
| }) | |||||
| .trim(), | |||||
| age: z | |||||
| .string() | |||||
| .min(1, { | |||||
| message: t('common.namePlaceholder'), | |||||
| }) | |||||
| .trim(), | |||||
| query: z.array( | |||||
| z.object({ | |||||
| type: z.string(), | |||||
| }), | |||||
| ), | |||||
| }), | |||||
| }, | |||||
| [Operator.Generate]: { | |||||
| component: GenerateForm, | |||||
| defaultValues: { | |||||
| cite: true, | |||||
| prompt: t('flow.promptText'), | |||||
| }, | |||||
| schema: z.object({ | |||||
| prompt: z.string().min(1, { | |||||
| message: t('flow.promptMessage'), | |||||
| }), | |||||
| }), | |||||
| }, | |||||
| [Operator.Answer]: { | |||||
| component: AnswerForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Categorize]: { | |||||
| component: CategorizeForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({ | |||||
| parameter: z.string().optional(), | |||||
| ...LlmSettingSchema, | |||||
| message_history_window_size: z.coerce.number(), | |||||
| items: z.array( | |||||
| z | |||||
| .object({ | |||||
| name: z.string().min(1, t('flow.nameMessage')).trim(), | |||||
| description: z.string().optional(), | |||||
| // examples: z | |||||
| // .array( | |||||
| // z.object({ | |||||
| // value: z.string(), | |||||
| // }), | |||||
| // ) | |||||
| // .optional(), | |||||
| }) | |||||
| .optional(), | |||||
| ), | |||||
| }), | |||||
| }, | |||||
| [Operator.Message]: { | |||||
| component: MessageForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({ | |||||
| content: z | |||||
| .array( | |||||
| z.object({ | |||||
| value: z.string(), | |||||
| }), | |||||
| ) | |||||
| .optional(), | |||||
| }), | |||||
| }, | |||||
| [Operator.Relevant]: { | |||||
| component: RelevantForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.RewriteQuestion]: { | |||||
| component: RewriteQuestionForm, | |||||
| defaultValues: { | |||||
| message_history_window_size: 6, | |||||
| }, | |||||
| schema: z.object({ | |||||
| llm_id: z.string(), | |||||
| message_history_window_size: z.number(), | |||||
| language: z.string(), | |||||
| }), | |||||
| }, | |||||
| [Operator.Code]: { | |||||
| component: CodeForm, | |||||
| defaultValues: { | |||||
| lang: ProgrammingLanguage.Python, | |||||
| script: CodeTemplateStrMap[ProgrammingLanguage.Python], | |||||
| arguments: [], | |||||
| }, | |||||
| schema: z.object({ | |||||
| lang: z.string(), | |||||
| script: z.string(), | |||||
| arguments: z.array( | |||||
| z.object({ name: z.string(), component_id: z.string() }), | |||||
| ), | |||||
| return: z.union([ | |||||
| z | |||||
| .array(z.object({ name: z.string(), component_id: z.string() })) | |||||
| .optional(), | |||||
| z.object({ name: z.string(), component_id: z.string() }), | |||||
| ]), | |||||
| }), | |||||
| }, | |||||
| [Operator.WaitingDialogue]: { | |||||
| component: CodeForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({ | |||||
| arguments: z.array( | |||||
| z.object({ name: z.string(), component_id: z.string() }), | |||||
| ), | |||||
| }), | |||||
| }, | |||||
| [Operator.Agent]: { | |||||
| component: AgentForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Baidu]: { | |||||
| component: BaiduForm, | |||||
| defaultValues: { top_n: 10 }, | |||||
| schema: z.object({ top_n: z.number() }), | |||||
| }, | |||||
| [Operator.DuckDuckGo]: { | |||||
| component: DuckDuckGoForm, | |||||
| defaultValues: { | |||||
| top_n: 10, | |||||
| channel: 'text', | |||||
| }, | |||||
| schema: z.object({ | |||||
| top_n: z.number(), | |||||
| }), | |||||
| }, | |||||
| [Operator.KeywordExtract]: { | |||||
| component: KeywordExtractForm, | |||||
| defaultValues: { top_n: 3 }, | |||||
| schema: z.object({ | |||||
| llm_id: z.string(), | |||||
| top_n: z.number(), | |||||
| }), | |||||
| }, | |||||
| [Operator.Wikipedia]: { | |||||
| component: WikipediaForm, | |||||
| defaultValues: { | |||||
| top_n: 10, | |||||
| }, | |||||
| schema: z.object({ | |||||
| language: z.string(), | |||||
| top_n: z.number(), | |||||
| }), | |||||
| }, | |||||
| [Operator.PubMed]: { | |||||
| component: PubMedForm, | |||||
| defaultValues: { top_n: 10 }, | |||||
| schema: z.object({ | |||||
| top_n: z.number(), | |||||
| email: z.string(), | |||||
| }), | |||||
| }, | |||||
| [Operator.ArXiv]: { | |||||
| component: ArXivForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Google]: { | |||||
| component: GoogleForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Bing]: { | |||||
| component: BingForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.GoogleScholar]: { | |||||
| component: GoogleScholarForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.DeepL]: { | |||||
| component: DeepLForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.GitHub]: { | |||||
| component: GithubForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.BaiduFanyi]: { | |||||
| component: BaiduFanyiForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.QWeather]: { | |||||
| component: QWeatherForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({ | |||||
| web_apikey: z.string(), | |||||
| lang: z.string(), | |||||
| type: z.string(), | |||||
| user_type: z.string(), | |||||
| time_period: z.string().optional(), | |||||
| }), | |||||
| }, | |||||
| [Operator.ExeSQL]: { | |||||
| component: ExeSQLForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Switch]: { | |||||
| component: SwitchForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.WenCai]: { | |||||
| component: WenCaiForm, | |||||
| defaultValues: { | |||||
| top_n: 20, | |||||
| }, | |||||
| schema: z.object({ | |||||
| top_n: z.number(), | |||||
| query_type: z.string(), | |||||
| }), | |||||
| }, | |||||
| [Operator.AkShare]: { | |||||
| component: AkShareForm, | |||||
| defaultValues: { | |||||
| top_n: 10, | |||||
| }, | |||||
| schema: z.object({ | |||||
| top_n: z.number(), | |||||
| }), | |||||
| }, | |||||
| [Operator.YahooFinance]: { | |||||
| component: YahooFinanceForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Jin10]: { | |||||
| component: Jin10Form, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.TuShare]: { | |||||
| component: TuShareForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Crawler]: { | |||||
| component: CrawlerForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Invoke]: { | |||||
| component: InvokeForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Concentrator]: { | |||||
| component: () => <></>, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Note]: { | |||||
| component: () => <></>, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Template]: { | |||||
| component: TemplateForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Email]: { | |||||
| component: EmailForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Iteration]: { | |||||
| component: IterationForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.IterationStart]: { | |||||
| component: IterationStartForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.Tool]: { | |||||
| component: ToolForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.TavilySearch]: { | |||||
| component: TavilyForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.UserFillUp]: { | |||||
| component: UserFillUpForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| [Operator.StringTransform]: { | |||||
| component: StringTransformForm, | |||||
| defaultValues: {}, | |||||
| schema: z.object({}), | |||||
| }, | |||||
| }; | |||||
| return FormConfigMap; | |||||
| } |
| import { RAGFlowNodeType } from '@/interfaces/database/flow'; | |||||
| import { get, isEmpty, isPlainObject, omit } from 'lodash'; | |||||
| import { useMemo, useRef } from 'react'; | |||||
| import { Operator } from '../constant'; | |||||
| import { buildCategorizeListFromObject, convertToObjectArray } from '../utils'; | |||||
| import { useFormConfigMap } from './use-form-config-map'; | |||||
| export function useValues(node?: RAGFlowNodeType, isDirty?: boolean) { | |||||
| const operatorName: Operator = node?.data.label as Operator; | |||||
| const previousId = useRef<string | undefined>(node?.id); | |||||
| const FormConfigMap = useFormConfigMap(); | |||||
| const currentFormMap = FormConfigMap[operatorName]; | |||||
| const values = useMemo(() => { | |||||
| const formData = node?.data?.form; | |||||
| if (operatorName === Operator.Categorize) { | |||||
| const items = buildCategorizeListFromObject( | |||||
| get(node, 'data.form.category_description', {}), | |||||
| ); | |||||
| if (isPlainObject(formData)) { | |||||
| console.info('xxx'); | |||||
| const nextValues = { | |||||
| ...omit(formData, 'category_description'), | |||||
| items, | |||||
| }; | |||||
| return nextValues; | |||||
| } | |||||
| } else if (operatorName === Operator.Message) { | |||||
| return { | |||||
| ...formData, | |||||
| content: convertToObjectArray(formData.content), | |||||
| }; | |||||
| } else { | |||||
| return isEmpty(formData) ? currentFormMap : formData; | |||||
| } | |||||
| }, [currentFormMap, node, operatorName]); | |||||
| return values; | |||||
| } |
| label: 'Search', | label: 'Search', | ||||
| list: [ | list: [ | ||||
| Operator.TavilySearch, | Operator.TavilySearch, | ||||
| Operator.TavilyExtract, | |||||
| Operator.Google, | Operator.Google, | ||||
| Operator.Bing, | Operator.Bing, | ||||
| Operator.DuckDuckGo, | Operator.DuckDuckGo, | ||||
| Operator.GitHub, | Operator.GitHub, | ||||
| Operator.ExeSQL, | Operator.ExeSQL, | ||||
| Operator.Invoke, | Operator.Invoke, | ||||
| Operator.Crawler, | |||||
| Operator.Code, | Operator.Code, | ||||
| Operator.Retrieval, | Operator.Retrieval, | ||||
| ], | ], |
| import { LargeModelFormField } from '@/components/large-model-form-field'; | |||||
| import NumberInput from '@/components/originui/number-input'; | |||||
| import { SelectWithSearch } from '@/components/originui/select-with-search'; | import { SelectWithSearch } from '@/components/originui/select-with-search'; | ||||
| import { TopNFormField } from '@/components/top-n-item'; | |||||
| import { ButtonLoading } from '@/components/ui/button'; | import { ButtonLoading } from '@/components/ui/button'; | ||||
| import { | import { | ||||
| Form, | Form, | ||||
| FormLabel, | FormLabel, | ||||
| FormMessage, | FormMessage, | ||||
| } from '@/components/ui/form'; | } from '@/components/ui/form'; | ||||
| import { Input, NumberInput } from '@/components/ui/input'; | |||||
| import { Input } from '@/components/ui/input'; | |||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { zodResolver } from '@hookform/resolvers/zod'; | import { zodResolver } from '@hookform/resolvers/zod'; | ||||
| import { memo } from 'react'; | import { memo } from 'react'; | ||||
| return ( | return ( | ||||
| <> | <> | ||||
| <LargeModelFormField></LargeModelFormField> | |||||
| <FormField | <FormField | ||||
| control={form.control} | control={form.control} | ||||
| name="db_type" | name="db_type" | ||||
| <FormItem> | <FormItem> | ||||
| <FormLabel>{t('port')}</FormLabel> | <FormLabel>{t('port')}</FormLabel> | ||||
| <FormControl> | <FormControl> | ||||
| <NumberInput {...field}></NumberInput> | |||||
| <NumberInput {...field} className="w-full"></NumberInput> | |||||
| </FormControl> | </FormControl> | ||||
| <FormMessage /> | <FormMessage /> | ||||
| </FormItem> | </FormItem> | ||||
| </FormItem> | </FormItem> | ||||
| )} | )} | ||||
| /> | /> | ||||
| <FormField | <FormField | ||||
| control={form.control} | control={form.control} | ||||
| name="loop" | |||||
| name="max_records" | |||||
| render={({ field }) => ( | render={({ field }) => ( | ||||
| <FormItem> | <FormItem> | ||||
| <FormLabel tooltip={t('loopTip')}>{t('loop')}</FormLabel> | |||||
| <FormLabel>{t('maxRecords')}</FormLabel> | |||||
| <FormControl> | <FormControl> | ||||
| <NumberInput {...field}></NumberInput> | |||||
| <NumberInput {...field} className="w-full"></NumberInput> | |||||
| </FormControl> | </FormControl> | ||||
| <FormMessage /> | <FormMessage /> | ||||
| </FormItem> | </FormItem> | ||||
| )} | )} | ||||
| /> | /> | ||||
| <TopNFormField max={1000}></TopNFormField> | |||||
| <div className="flex justify-end"> | <div className="flex justify-end"> | ||||
| <ButtonLoading loading={loading} type="submit"> | <ButtonLoading loading={loading} type="submit"> | ||||
| Test | Test | ||||
| return ( | return ( | ||||
| <Form {...form}> | <Form {...form}> | ||||
| <FormWrapper onSubmit={form.handleSubmit(onSubmit)}> | <FormWrapper onSubmit={form.handleSubmit(onSubmit)}> | ||||
| <QueryVariable></QueryVariable> | |||||
| <QueryVariable name="sql"></QueryVariable> | |||||
| <ExeSQLFormWidgets loading={loading}></ExeSQLFormWidgets> | <ExeSQLFormWidgets loading={loading}></ExeSQLFormWidgets> | ||||
| </FormWrapper> | </FormWrapper> | ||||
| </Form> | </Form> |
| import { z } from 'zod'; | import { z } from 'zod'; | ||||
| export const ExeSQLFormSchema = { | export const ExeSQLFormSchema = { | ||||
| llm_id: z.string().min(1), | |||||
| sql: z.string(), | |||||
| db_type: z.string().min(1), | db_type: z.string().min(1), | ||||
| database: z.string().min(1), | database: z.string().min(1), | ||||
| username: z.string().min(1), | username: z.string().min(1), | ||||
| host: z.string().min(1), | host: z.string().min(1), | ||||
| port: z.number(), | port: z.number(), | ||||
| password: z.string().min(1), | password: z.string().min(1), | ||||
| loop: z.number(), | |||||
| top_n: z.number(), | |||||
| max_records: z.number(), | |||||
| }; | }; | ||||
| export const FormSchema = z.object({ | export const FormSchema = z.object({ |
| import { FormContainer } from '@/components/form-container'; | |||||
| import { | |||||
| Form, | |||||
| FormControl, | |||||
| FormField, | |||||
| FormItem, | |||||
| FormLabel, | |||||
| FormMessage, | |||||
| } from '@/components/ui/form'; | |||||
| import { Input } from '@/components/ui/input'; | |||||
| import { RAGFlowSelect } from '@/components/ui/select'; | |||||
| import { buildOptions } from '@/utils/form'; | |||||
| import { zodResolver } from '@hookform/resolvers/zod'; | |||||
| import { memo } from 'react'; | |||||
| import { useForm } from 'react-hook-form'; | |||||
| import { z } from 'zod'; | |||||
| import { | |||||
| TavilyExtractDepth, | |||||
| TavilyExtractFormat, | |||||
| initialTavilyExtractValues, | |||||
| } from '../../constant'; | |||||
| import { useFormValues } from '../../hooks/use-form-values'; | |||||
| import { useWatchFormChange } from '../../hooks/use-watch-form-change'; | |||||
| import { INextOperatorForm } from '../../interface'; | |||||
| import { buildOutputList } from '../../utils/build-output-list'; | |||||
| import { FormWrapper } from '../components/form-wrapper'; | |||||
| import { Output } from '../components/output'; | |||||
| import { TavilyApiKeyField, TavilyFormSchema } from '../tavily-form'; | |||||
| const outputList = buildOutputList(initialTavilyExtractValues.outputs); | |||||
| function TavilyExtractForm({ node }: INextOperatorForm) { | |||||
| const values = useFormValues(initialTavilyExtractValues, node); | |||||
| const FormSchema = z.object({ | |||||
| ...TavilyFormSchema, | |||||
| urls: z.string(), | |||||
| extract_depth: z.enum([ | |||||
| TavilyExtractDepth.Advanced, | |||||
| TavilyExtractDepth.Basic, | |||||
| ]), | |||||
| format: z.enum([TavilyExtractFormat.Text, TavilyExtractFormat.Markdown]), | |||||
| }); | |||||
| const form = useForm<z.infer<typeof FormSchema>>({ | |||||
| defaultValues: values, | |||||
| resolver: zodResolver(FormSchema), | |||||
| }); | |||||
| useWatchFormChange(node?.id, form); | |||||
| return ( | |||||
| <Form {...form}> | |||||
| <FormWrapper> | |||||
| <FormContainer> | |||||
| <TavilyApiKeyField></TavilyApiKeyField> | |||||
| </FormContainer> | |||||
| <FormContainer> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="urls" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>URL</FormLabel> | |||||
| <FormControl> | |||||
| <Input {...field} /> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="extract_depth" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>Extract Depth</FormLabel> | |||||
| <FormControl> | |||||
| <RAGFlowSelect | |||||
| placeholder="shadcn" | |||||
| {...field} | |||||
| options={buildOptions(TavilyExtractDepth)} | |||||
| /> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="format" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>Format</FormLabel> | |||||
| <FormControl> | |||||
| <RAGFlowSelect | |||||
| placeholder="shadcn" | |||||
| {...field} | |||||
| options={buildOptions(TavilyExtractFormat)} | |||||
| /> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| </FormContainer> | |||||
| </FormWrapper> | |||||
| <div className="p-5"> | |||||
| <Output list={outputList}></Output> | |||||
| </div> | |||||
| </Form> | |||||
| ); | |||||
| } | |||||
| export default memo(TavilyExtractForm); |
| import { buildOptions } from '@/utils/form'; | import { buildOptions } from '@/utils/form'; | ||||
| import { zodResolver } from '@hookform/resolvers/zod'; | import { zodResolver } from '@hookform/resolvers/zod'; | ||||
| import { memo, useMemo } from 'react'; | import { memo, useMemo } from 'react'; | ||||
| import { useForm } from 'react-hook-form'; | |||||
| import { useForm, useFormContext } from 'react-hook-form'; | |||||
| import { z } from 'zod'; | import { z } from 'zod'; | ||||
| import { | import { | ||||
| TavilySearchDepth, | TavilySearchDepth, | ||||
| initialTavilyValues, | initialTavilyValues, | ||||
| } from '../../constant'; | } from '../../constant'; | ||||
| import { INextOperatorForm } from '../../interface'; | import { INextOperatorForm } from '../../interface'; | ||||
| import { FormWrapper } from '../components/form-wrapper'; | |||||
| import { Output, OutputType } from '../components/output'; | import { Output, OutputType } from '../components/output'; | ||||
| import { QueryVariable } from '../components/query-variable'; | import { QueryVariable } from '../components/query-variable'; | ||||
| import { DynamicDomain } from './dynamic-domain'; | import { DynamicDomain } from './dynamic-domain'; | ||||
| import { useValues } from './use-values'; | import { useValues } from './use-values'; | ||||
| import { useWatchFormChange } from './use-watch-change'; | import { useWatchFormChange } from './use-watch-change'; | ||||
| export function TavilyApiKeyField() { | |||||
| const form = useFormContext(); | |||||
| return ( | |||||
| <FormField | |||||
| control={form.control} | |||||
| name="api_key" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>Api Key</FormLabel> | |||||
| <FormControl> | |||||
| <Input type="password" {...field}></Input> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| ); | |||||
| } | |||||
| export const TavilyFormSchema = { | |||||
| api_key: z.string(), | |||||
| }; | |||||
| function TavilyForm({ node }: INextOperatorForm) { | function TavilyForm({ node }: INextOperatorForm) { | ||||
| const values = useValues(node); | const values = useValues(node); | ||||
| const FormSchema = z.object({ | const FormSchema = z.object({ | ||||
| api_key: z.string(), | |||||
| ...TavilyFormSchema, | |||||
| query: z.string(), | query: z.string(), | ||||
| search_depth: z.enum([TavilySearchDepth.Advanced, TavilySearchDepth.Basic]), | search_depth: z.enum([TavilySearchDepth.Advanced, TavilySearchDepth.Basic]), | ||||
| topic: z.enum([TavilyTopic.News, TavilyTopic.General]), | topic: z.enum([TavilyTopic.News, TavilyTopic.General]), | ||||
| return ( | return ( | ||||
| <Form {...form}> | <Form {...form}> | ||||
| <form | |||||
| className="space-y-5 px-5 " | |||||
| autoComplete="off" | |||||
| onSubmit={(e) => { | |||||
| e.preventDefault(); | |||||
| }} | |||||
| > | |||||
| <FormWrapper> | |||||
| <FormContainer> | <FormContainer> | ||||
| <FormField | |||||
| control={form.control} | |||||
| name="api_key" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>Api Key</FormLabel> | |||||
| <FormControl> | |||||
| <Input type="password" {...field}></Input> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <TavilyApiKeyField></TavilyApiKeyField> | |||||
| </FormContainer> | </FormContainer> | ||||
| <FormContainer> | <FormContainer> | ||||
| <QueryVariable></QueryVariable> | <QueryVariable></QueryVariable> | ||||
| label={'Exclude Domains'} | label={'Exclude Domains'} | ||||
| ></DynamicDomain> | ></DynamicDomain> | ||||
| </FormContainer> | </FormContainer> | ||||
| </form> | |||||
| </FormWrapper> | |||||
| <div className="p-5"> | <div className="p-5"> | ||||
| <Output list={outputList}></Output> | <Output list={outputList}></Output> | ||||
| </div> | </div> |
| useEffect(() => { | useEffect(() => { | ||||
| // Manually triggered form updates are synchronized to the canvas | // Manually triggered form updates are synchronized to the canvas | ||||
| if (id && form?.formState.isDirty) { | |||||
| if (id) { | |||||
| values = form?.getValues(); | values = form?.getValues(); | ||||
| let nextValues: any = { | let nextValues: any = { | ||||
| ...values, | ...values, |
| [Operator.Crawler]: CrawlerForm, | [Operator.Crawler]: CrawlerForm, | ||||
| [Operator.Email]: EmailForm, | [Operator.Email]: EmailForm, | ||||
| [Operator.TavilySearch]: TavilyForm, | [Operator.TavilySearch]: TavilyForm, | ||||
| [Operator.TavilyExtract]: TavilyForm, | |||||
| }; | }; |
| import { FormContainer } from '@/components/form-container'; | import { FormContainer } from '@/components/form-container'; | ||||
| import { | |||||
| Form, | |||||
| FormControl, | |||||
| FormField, | |||||
| FormItem, | |||||
| FormLabel, | |||||
| FormMessage, | |||||
| } from '@/components/ui/form'; | |||||
| import { Input } from '@/components/ui/input'; | |||||
| import { Form } from '@/components/ui/form'; | |||||
| import { zodResolver } from '@hookform/resolvers/zod'; | import { zodResolver } from '@hookform/resolvers/zod'; | ||||
| import { useForm } from 'react-hook-form'; | import { useForm } from 'react-hook-form'; | ||||
| import { z } from 'zod'; | import { z } from 'zod'; | ||||
| import { FormWrapper } from '../../components/form-wrapper'; | |||||
| import { TavilyApiKeyField, TavilyFormSchema } from '../../tavily-form'; | |||||
| import { useValues } from '../use-values'; | import { useValues } from '../use-values'; | ||||
| import { useWatchFormChange } from '../use-watch-change'; | import { useWatchFormChange } from '../use-watch-change'; | ||||
| const TavilyForm = () => { | const TavilyForm = () => { | ||||
| const values = useValues(); | const values = useValues(); | ||||
| const FormSchema = z.object({ | |||||
| api_key: z.string(), | |||||
| }); | |||||
| const FormSchema = z.object(TavilyFormSchema); | |||||
| const form = useForm<z.infer<typeof FormSchema>>({ | const form = useForm<z.infer<typeof FormSchema>>({ | ||||
| defaultValues: values, | defaultValues: values, | ||||
| return ( | return ( | ||||
| <Form {...form}> | <Form {...form}> | ||||
| <form | |||||
| className="space-y-5 px-5 " | |||||
| autoComplete="off" | |||||
| onSubmit={(e) => { | |||||
| e.preventDefault(); | |||||
| }} | |||||
| > | |||||
| <FormWrapper> | |||||
| <FormContainer> | <FormContainer> | ||||
| <FormField | |||||
| control={form.control} | |||||
| name="api_key" | |||||
| render={({ field }) => ( | |||||
| <FormItem> | |||||
| <FormLabel>Api Key</FormLabel> | |||||
| <FormControl> | |||||
| <Input type="password" {...field}></Input> | |||||
| </FormControl> | |||||
| <FormMessage /> | |||||
| </FormItem> | |||||
| )} | |||||
| /> | |||||
| <TavilyApiKeyField></TavilyApiKeyField> | |||||
| </FormContainer> | </FormContainer> | ||||
| </form> | |||||
| </FormWrapper> | |||||
| </Form> | </Form> | ||||
| ); | ); | ||||
| }; | }; |
| initialRewriteQuestionValues, | initialRewriteQuestionValues, | ||||
| initialStringTransformValues, | initialStringTransformValues, | ||||
| initialSwitchValues, | initialSwitchValues, | ||||
| initialTavilyExtractValues, | |||||
| initialTavilyValues, | initialTavilyValues, | ||||
| initialTemplateValues, | initialTemplateValues, | ||||
| initialTuShareValues, | initialTuShareValues, | ||||
| [Operator.GitHub]: initialGithubValues, | [Operator.GitHub]: initialGithubValues, | ||||
| [Operator.BaiduFanyi]: initialBaiduFanyiValues, | [Operator.BaiduFanyi]: initialBaiduFanyiValues, | ||||
| [Operator.QWeather]: initialQWeatherValues, | [Operator.QWeather]: initialQWeatherValues, | ||||
| [Operator.ExeSQL]: { ...initialExeSqlValues, llm_id: llmId }, | |||||
| [Operator.ExeSQL]: initialExeSqlValues, | |||||
| [Operator.Switch]: initialSwitchValues, | [Operator.Switch]: initialSwitchValues, | ||||
| [Operator.WenCai]: initialWenCaiValues, | [Operator.WenCai]: initialWenCaiValues, | ||||
| [Operator.AkShare]: initialAkShareValues, | [Operator.AkShare]: initialAkShareValues, | ||||
| [Operator.TavilySearch]: initialTavilyValues, | [Operator.TavilySearch]: initialTavilyValues, | ||||
| [Operator.UserFillUp]: initialUserFillUpValues, | [Operator.UserFillUp]: initialUserFillUpValues, | ||||
| [Operator.StringTransform]: initialStringTransformValues, | [Operator.StringTransform]: initialStringTransformValues, | ||||
| [Operator.TavilyExtract]: initialTavilyExtractValues, | |||||
| }; | }; | ||||
| }, [llmId]); | }, [llmId]); | ||||
| ...omit(initialValues, 'query'), | ...omit(initialValues, 'query'), | ||||
| description: '', | description: '', | ||||
| }; | }; | ||||
| case Operator.TavilySearch: | |||||
| case (Operator.TavilySearch, Operator.TavilyExtract): | |||||
| return { | return { | ||||
| api_key: '', | api_key: '', | ||||
| }; | }; | ||||
| case Operator.ExeSQL: | case Operator.ExeSQL: | ||||
| return omit(initialValues, 'query'); | |||||
| return omit(initialValues, 'sql'); | |||||
| case Operator.Bing: | case Operator.Bing: | ||||
| return omit(initialValues, 'query'); | return omit(initialValues, 'query'); | ||||