From c5e4684b4434bcdc766224548959e579d6259166 Mon Sep 17 00:00:00 2001 From: balibabu Date: Tue, 10 Jun 2025 17:06:30 +0800 Subject: [PATCH] Feat: Let system variables appear in operator prompts #3221 (#8154) ### What problem does this PR solve? Feat: Let system variables appear in operator prompts #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- web/src/components/top-n-item.tsx | 28 ++++--------------- web/src/constants/agent.ts | 7 +++++ web/src/hooks/use-agent-request.ts | 9 +++--- web/src/interfaces/database/flow.ts | 1 + web/src/pages/agent/canvas/index.tsx | 9 ++++-- web/src/pages/agent/chat/box.tsx | 2 +- web/src/pages/agent/chat/hooks.ts | 12 +------- web/src/pages/agent/constant.tsx | 13 +++++++-- .../pages/agent/form/agent-form/constant.ts | 4 --- .../agent/form/agent-form/dynamic-prompt.tsx | 2 +- .../agent/form/agent-form/use-watch-change.ts | 2 +- .../prompt-editor/variable-picker-plugin.tsx | 15 ++-------- .../agent/form/components/query-variable.tsx | 20 ++----------- .../pages/agent/hooks/use-get-begin-query.tsx | 23 ++++++++++++++- web/src/pages/agent/hooks/use-show-drawer.tsx | 10 +++++++ web/src/pages/agent/log-sheet/index.tsx | 24 ++++++++++++++++ web/src/pages/chat/utils.ts | 6 ++-- 17 files changed, 105 insertions(+), 82 deletions(-) delete mode 100644 web/src/pages/agent/form/agent-form/constant.ts create mode 100644 web/src/pages/agent/log-sheet/index.tsx diff --git a/web/src/components/top-n-item.tsx b/web/src/components/top-n-item.tsx index 3fd760233..f433771d2 100644 --- a/web/src/components/top-n-item.tsx +++ b/web/src/components/top-n-item.tsx @@ -1,14 +1,6 @@ import { useTranslate } from '@/hooks/common-hooks'; import { Form, Slider } from 'antd'; -import { useFormContext } from 'react-hook-form'; -import { SingleFormSlider } from './ui/dual-range-slider'; -import { - FormControl, - FormField, - FormItem, - FormLabel, - FormMessage, -} from './ui/form'; +import { SliderInputFormField } from './slider-input-form-field'; type FieldType = { top_n?: number; @@ -41,22 +33,14 @@ interface SimilaritySliderFormFieldProps { } export function TopNFormField({ max = 30 }: SimilaritySliderFormFieldProps) { - const form = useFormContext(); const { t } = useTranslate('chat'); return ( - ( - - {t('topN')} - - - - - - )} - /> + label={t('topN')} + max={max} + tooltip={t('topNTip')} + > ); } diff --git a/web/src/constants/agent.ts b/web/src/constants/agent.ts index 91c128804..28a34111b 100644 --- a/web/src/constants/agent.ts +++ b/web/src/constants/agent.ts @@ -20,3 +20,10 @@ async function main(args) { module.exports = { main }; `, }; + +export enum AgentGlobals { + SysQuery = 'sys.query', + SysUserId = 'sys.user_id', + SysConversationTurns = 'sys.conversation_turns', + SysFiles = 'sys.files', +} diff --git a/web/src/hooks/use-agent-request.ts b/web/src/hooks/use-agent-request.ts index c372b4c32..016718af8 100644 --- a/web/src/hooks/use-agent-request.ts +++ b/web/src/hooks/use-agent-request.ts @@ -1,3 +1,4 @@ +import { AgentGlobals } from '@/constants/agent'; import { DSL, IFlow, IFlowTemplate } from '@/interfaces/database/flow'; import i18n from '@/locales/config'; import { BeginId } from '@/pages/agent/constant'; @@ -61,10 +62,10 @@ export const EmptyDsl = { history: [], path: [], globals: { - 'sys.query': '', - 'sys.user_id': '', - 'sys.conversation_turns': 0, - 'sys.files': [], + [AgentGlobals.SysQuery]: '', + [AgentGlobals.SysUserId]: '', + [AgentGlobals.SysConversationTurns]: 0, + [AgentGlobals.SysFiles]: [], }, }; diff --git a/web/src/interfaces/database/flow.ts b/web/src/interfaces/database/flow.ts index f59f647ad..4ad847d16 100644 --- a/web/src/interfaces/database/flow.ts +++ b/web/src/interfaces/database/flow.ts @@ -12,6 +12,7 @@ export interface DSL { messages: Message[]; reference: IReference[]; globals: Record; + retrieval: IReference[]; } export interface IOperator { diff --git a/web/src/pages/agent/canvas/index.tsx b/web/src/pages/agent/canvas/index.tsx index 9fbd7177b..06c351963 100644 --- a/web/src/pages/agent/canvas/index.tsx +++ b/web/src/pages/agent/canvas/index.tsx @@ -16,7 +16,8 @@ import { } from '../hooks'; import { useAddNode } from '../hooks/use-add-node'; import { useBeforeDelete } from '../hooks/use-before-delete'; -import { useShowDrawer } from '../hooks/use-show-drawer'; +import { useShowDrawer, useShowLogSheet } from '../hooks/use-show-drawer'; +import { LogSheet } from '../log-sheet'; import RunSheet from '../run-sheet'; import { ButtonEdge } from './edge'; import styles from './index.less'; @@ -100,6 +101,8 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { hideDrawer, }); + const { showLogSheet, logSheetVisible, hideLogSheet } = useShowLogSheet(); + const { handleBeforeDelete } = useBeforeDelete(); useWatchNodeFormDataChange(); @@ -178,13 +181,15 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { hideModal={hideRunOrChatDrawer} > )} - {runVisible && ( )} + {logSheetVisible && ( + + )} ); } diff --git a/web/src/pages/agent/chat/box.tsx b/web/src/pages/agent/chat/box.tsx index 1ccece7e1..fa6aed660 100644 --- a/web/src/pages/agent/chat/box.tsx +++ b/web/src/pages/agent/chat/box.tsx @@ -35,7 +35,7 @@ const AgentChatBox = () => { return ( <>
-
+
{derivedMessages?.map((message, i) => { diff --git a/web/src/pages/agent/chat/hooks.ts b/web/src/pages/agent/chat/hooks.ts index f4d6f459b..13bb3003c 100644 --- a/web/src/pages/agent/chat/hooks.ts +++ b/web/src/pages/agent/chat/hooks.ts @@ -27,7 +27,7 @@ const antMessage = message; export const useSelectNextMessages = () => { const { data: flowDetail, loading } = useFetchAgent(); - const reference = flowDetail.dsl.reference; + const reference = flowDetail.dsl.retrieval; const { derivedMessages, ref, @@ -134,11 +134,6 @@ export const useSendNextMessage = () => { addNewestAnswer({ answer: content, id: id, - reference: { - chunks: [], - doc_aggs: [], - total: 0, - }, }); } }, [answerList, addNewestAnswer]); @@ -161,11 +156,6 @@ export const useSendNextMessage = () => { if (prologue) { addNewestAnswer({ answer: prologue, - reference: { - chunks: [], - doc_aggs: [], - total: 0, - }, }); } }, [addNewestAnswer, prologue]); diff --git a/web/src/pages/agent/constant.tsx b/web/src/pages/agent/constant.tsx index bd83dff9b..2776b0c22 100644 --- a/web/src/pages/agent/constant.tsx +++ b/web/src/pages/agent/constant.tsx @@ -31,7 +31,11 @@ import { initialKeywordsSimilarityWeightValue, initialSimilarityThresholdValue, } from '@/components/similarity-slider'; -import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; +import { + AgentGlobals, + CodeTemplateStrMap, + ProgrammingLanguage, +} from '@/constants/agent'; export enum AgentDialogueMode { Conversational = 'conversational', @@ -52,6 +56,11 @@ export enum Channel { News = 'news', } +export enum PromptRole { + User = 'user', + Assistant = 'assistant', +} + import { BranchesOutlined, DatabaseOutlined, @@ -707,7 +716,7 @@ export const initialWaitingDialogueValues = {}; export const initialAgentValues = { ...initialLlmBaseValues, sys_prompt: ``, - prompts: [], + prompts: [{ role: PromptRole.User, content: `{${AgentGlobals.SysQuery}}` }], message_history_window_size: 12, tools: [], outputs: { diff --git a/web/src/pages/agent/form/agent-form/constant.ts b/web/src/pages/agent/form/agent-form/constant.ts deleted file mode 100644 index bcbfb33dd..000000000 --- a/web/src/pages/agent/form/agent-form/constant.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum PromptRole { - User = 'user', - Assistant = 'assistant', -} diff --git a/web/src/pages/agent/form/agent-form/dynamic-prompt.tsx b/web/src/pages/agent/form/agent-form/dynamic-prompt.tsx index 4eda67c0a..1cda9fbd5 100644 --- a/web/src/pages/agent/form/agent-form/dynamic-prompt.tsx +++ b/web/src/pages/agent/form/agent-form/dynamic-prompt.tsx @@ -11,8 +11,8 @@ import { X } from 'lucide-react'; import { memo } from 'react'; import { useFieldArray, useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; +import { PromptRole } from '../../constant'; import { PromptEditor } from '../components/prompt-editor'; -import { PromptRole } from './constant'; const options = [ { label: 'User', value: PromptRole.User }, diff --git a/web/src/pages/agent/form/agent-form/use-watch-change.ts b/web/src/pages/agent/form/agent-form/use-watch-change.ts index 2ef81432a..8640a4518 100644 --- a/web/src/pages/agent/form/agent-form/use-watch-change.ts +++ b/web/src/pages/agent/form/agent-form/use-watch-change.ts @@ -1,7 +1,7 @@ import { useEffect } from 'react'; import { UseFormReturn, useWatch } from 'react-hook-form'; +import { PromptRole } from '../../constant'; import useGraphStore from '../../store'; -import { PromptRole } from './constant'; export function useWatchFormChange(id?: string, form?: UseFormReturn) { let values = useWatch({ control: form?.control }); diff --git a/web/src/pages/agent/form/components/prompt-editor/variable-picker-plugin.tsx b/web/src/pages/agent/form/components/prompt-editor/variable-picker-plugin.tsx index c059c2acb..afa54d477 100644 --- a/web/src/pages/agent/form/components/prompt-editor/variable-picker-plugin.tsx +++ b/web/src/pages/agent/form/components/prompt-editor/variable-picker-plugin.tsx @@ -20,19 +20,12 @@ import { $isRangeSelection, TextNode, } from 'lexical'; -import React, { - ReactElement, - useCallback, - useContext, - useEffect, - useRef, -} from 'react'; +import React, { ReactElement, useCallback, useEffect, useRef } from 'react'; import * as ReactDOM from 'react-dom'; import { $createVariableNode } from './variable-node'; -import { AgentFormContext } from '@/pages/agent/context'; -import { useBuildComponentIdSelectOptions } from '@/pages/agent/hooks/use-get-begin-query'; +import { useBuildQueryVariableOptions } from '@/pages/agent/hooks/use-get-begin-query'; import { ProgrammaticTag } from './constant'; import './index.css'; class VariableInnerOption extends MenuOption { @@ -109,15 +102,13 @@ export default function VariablePickerMenuPlugin({ const [editor] = useLexicalComposerContext(); const isFirstRender = useRef(true); - const node = useContext(AgentFormContext); - const checkForTriggerMatch = useBasicTypeaheadTriggerMatch('/', { minLength: 0, }); const [queryString, setQueryString] = React.useState(''); - const options = useBuildComponentIdSelectOptions(node?.id, node?.parentId); + const options = useBuildQueryVariableOptions(); const buildNextOptions = useCallback(() => { let filteredOptions = options; diff --git a/web/src/pages/agent/form/components/query-variable.tsx b/web/src/pages/agent/form/components/query-variable.tsx index 299282dc0..8cb49b5cc 100644 --- a/web/src/pages/agent/form/components/query-variable.tsx +++ b/web/src/pages/agent/form/components/query-variable.tsx @@ -6,31 +6,15 @@ import { FormLabel, FormMessage, } from '@/components/ui/form'; -import { useFetchAgent } from '@/hooks/use-agent-request'; -import { useContext, useMemo } from 'react'; import { useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; -import { AgentFormContext } from '../../context'; -import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query'; +import { useBuildQueryVariableOptions } from '../../hooks/use-get-begin-query'; export function QueryVariable() { const { t } = useTranslation(); const form = useFormContext(); - const { data } = useFetchAgent(); - const node = useContext(AgentFormContext); - const options = useBuildComponentIdSelectOptions(node?.id, node?.parentId); - - const nextOptions = useMemo(() => { - const globalOptions = Object.keys(data?.dsl?.globals ?? {}).map((x) => ({ - label: x, - value: x, - })); - return [ - { ...options[0], options: [...options[0]?.options, ...globalOptions] }, - ...options.slice(1), - ]; - }, [data.dsl.globals, options]); + const nextOptions = useBuildQueryVariableOptions(); return ( { ); return getLabel; }; + +export function useBuildQueryVariableOptions() { + const { data } = useFetchAgent(); + const node = useContext(AgentFormContext); + const options = useBuildComponentIdSelectOptions(node?.id, node?.parentId); + + const nextOptions = useMemo(() => { + const globalOptions = Object.keys(data?.dsl?.globals ?? {}).map((x) => ({ + label: x, + value: x, + })); + return [ + { ...options[0], options: [...options[0]?.options, ...globalOptions] }, + ...options.slice(1), + ]; + }, [data.dsl.globals, options]); + + return nextOptions; +} diff --git a/web/src/pages/agent/hooks/use-show-drawer.tsx b/web/src/pages/agent/hooks/use-show-drawer.tsx index efc4cf32a..f0693980f 100644 --- a/web/src/pages/agent/hooks/use-show-drawer.tsx +++ b/web/src/pages/agent/hooks/use-show-drawer.tsx @@ -151,3 +151,13 @@ export function useShowDrawer({ showChatModal, }; } + +export function useShowLogSheet() { + const { visible, showModal, hideModal } = useSetModalState(); + + return { + logSheetVisible: visible, + hideLogSheet: hideModal, + showLogSheet: showModal, + }; +} diff --git a/web/src/pages/agent/log-sheet/index.tsx b/web/src/pages/agent/log-sheet/index.tsx new file mode 100644 index 000000000..0d70fcd66 --- /dev/null +++ b/web/src/pages/agent/log-sheet/index.tsx @@ -0,0 +1,24 @@ +import { + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, +} from '@/components/ui/sheet'; +import { IModalProps } from '@/interfaces/common'; + +export function LogSheet({ hideModal }: IModalProps) { + return ( + + + + Are you absolutely sure? + + This action cannot be undone. This will permanently delete your + account and remove your data from our servers. + + + + + ); +} diff --git a/web/src/pages/chat/utils.ts b/web/src/pages/chat/utils.ts index ba44e3c6f..a36f08f3e 100644 --- a/web/src/pages/chat/utils.ts +++ b/web/src/pages/chat/utils.ts @@ -29,9 +29,9 @@ export const buildMessageItemReference = ( conversation: { message: IMessage[]; reference: IReference[] }, message: IMessage, ) => { - const assistantMessages = conversation.message - ?.filter((x) => x.role === MessageType.Assistant) - .slice(1); + const assistantMessages = conversation.message?.filter( + (x) => x.role === MessageType.Assistant, + ); const referenceIndex = assistantMessages.findIndex( (x) => x.id === message.id, );