diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts index ccca8d748..2ee7181b5 100644 --- a/web/src/locales/en.ts +++ b/web/src/locales/en.ts @@ -1712,6 +1712,53 @@ This delimiter is used to split the input text into several text pieces echo of questions: 'Questions', metadata: 'Metadata', fieldName: 'Result Destination', + prompts: { + system: { + keywords: `Role +You are a text analyzer. + +Task +Extract the most important keywords/phrases of a given piece of text content. + +Requirements +- Summarize the text content, and give the top 5 important keywords/phrases. +- The keywords MUST be in the same language as the given piece of text content. +- The keywords are delimited by ENGLISH COMMA. +- Output keywords ONLY.`, + questions: `Role +You are a text analyzer. + +Task +Propose 3 questions about a given piece of text content. + +Requirements +- Understand and summarize the text content, and propose the top 3 important questions. +- The questions SHOULD NOT have overlapping meanings. +- The questions SHOULD cover the main content of the text as much as possible. +- The questions MUST be in the same language as the given piece of text content. +- One question per line. +- Output questions ONLY.`, + summary: `Act as a precise summarizer. Your task is to create a summary of the provided content that is both concise and faithful to the original. + +Key Instructions: +1. Accuracy: Strictly base the summary on the information given. Do not introduce any new facts, conclusions, or interpretations that are not explicitly stated. +2. Language: Write the summary in the same language as the source text. +3. Objectivity: Present the key points without bias, preserving the original intent and tone of the content. Do not editorialize. +4. Conciseness: Focus on the most important ideas, omitting minor details and fluff.`, + metadata: `Extract important structured information from the given content. Output ONLY a valid JSON string with no additional text. If no important structured information is found, output an empty JSON object: {}. + +Important structured information may include: names, dates, locations, events, key facts, numerical data, or other extractable entities.`, + }, + user: { + keywords: `Text Content +[Insert text here]`, + questions: `Text Content +[Insert text here]`, + summary: `Text to Summarize: +[Insert text here]`, + metadata: `Content: [INSERT CONTENT HERE]`, + }, + }, }, }, }; diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts index c9e1727e9..7d2269ff0 100644 --- a/web/src/locales/zh.ts +++ b/web/src/locales/zh.ts @@ -1630,6 +1630,53 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于 questions: '问题', metadata: '元数据', fieldName: '结果目的地', + prompts: { + system: { + keywords: `角色 +你是一名文本分析员。 + +任务 +从给定的文本内容中提取最重要的关键词/短语。 + +要求 +- 总结文本内容,并给出最重要的5个关键词/短语。 +- 关键词必须与给定的文本内容使用相同的语言。 +- 关键词之间用英文逗号分隔。 +- 仅输出关键词。`, + questions: `角色 +你是一名文本分析员。 + +任务 +针对给定的文本内容提出3个问题。 + +要求 +- 理解并总结文本内容,并提出最重要的3个问题。 +- 问题的含义不应重叠。 +- 问题应尽可能涵盖文本的主要内容。 +- 问题必须与给定的文本内容使用相同的语言。 +- 每行一个问题。 +- 仅输出问题。`, + summary: `扮演一个精准的摘要者。你的任务是为提供的内容创建一个简洁且忠实于原文的摘要。 + +关键说明: +1. 准确性:摘要必须严格基于所提供的信息。请勿引入任何未明确说明的新事实、结论或解释。 +2. 语言:摘要必须使用与原文相同的语言。 +3. 客观性:不带偏见地呈现要点,保留内容的原始意图和语气。请勿进行编辑。 +4. 简洁性:专注于最重要的思想,省略细节和多余的内容。`, + metadata: `从给定内容中提取重要的结构化信息。仅输出有效的 JSON 字符串,不包含任何附加文本。如果未找到重要的结构化信息,则输出一个空的 JSON 对象:{}。 + +重要的结构化信息可能包括:姓名、日期、地点、事件、关键事实、数字数据或其他可提取实体。`, + }, + user: { + keywords: `文本内容 +[在此处插入文本]`, + questions: `文本内容 +[在此处插入文本]`, + summary: `要总结的文本: +[在此处插入文本]`, + metadata: `内容:[在此处插入内容]`, + }, + }, }, }, }; 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 6e524428b..a97868bdd 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 @@ -131,12 +131,12 @@ export default function VariablePickerMenuPlugin({ baseOptions, }: VariablePickerMenuPluginProps): JSX.Element { const [editor] = useLexicalComposerContext(); - const isFirstRender = useRef(true); - const checkForTriggerMatch = useBasicTypeaheadTriggerMatch('/', { minLength: 0, }); + const previousValue = useRef(); + const [queryString, setQueryString] = React.useState(''); let options = useBuildQueryVariableOptions(); @@ -280,8 +280,8 @@ export default function VariablePickerMenuPlugin({ ); useEffect(() => { - if (editor && value && isFirstRender.current) { - isFirstRender.current = false; + if (editor && value && value !== previousValue.current) { + previousValue.current = value; editor.update( () => { parseTextToVariableNodes(value); diff --git a/web/src/pages/data-flow/constant.tsx b/web/src/pages/data-flow/constant.tsx index 7cd22e311..04d699ba4 100644 --- a/web/src/pages/data-flow/constant.tsx +++ b/web/src/pages/data-flow/constant.tsx @@ -256,6 +256,23 @@ export const initialParserValues = { fields: Object.values(ParserFields), output_format: EmailOutputFormat.Text, }, + { + fileFormat: FileType.TextMarkdown, + output_format: TextMarkdownOutputFormat.Text, + }, + { + fileFormat: FileType.Docx, + output_format: DocxOutputFormat.Json, + }, + { + fileFormat: FileType.PowerPoint, + output_format: PptOutputFormat.Json, + }, + { + fileFormat: FileType.Audio, + llm_id: '', + output_format: AudioOutputFormat.Text, + }, ], }; @@ -289,7 +306,7 @@ export const initialHierarchicalMergerValues = { ], }; -export const initialContextValues = { +export const initialExtractorValues = { ...initialLlmBaseValues, field_name: ContextGeneratorFieldName.Summary, outputs: {}, @@ -318,6 +335,7 @@ export const RestrictedUpstreamMap = { [Operator.Splitter]: [Operator.Begin], [Operator.HierarchicalMerger]: [Operator.Begin], [Operator.Tokenizer]: [Operator.Begin], + [Operator.Extractor]: [Operator.Begin], }; export const NodeMap = { diff --git a/web/src/pages/data-flow/form/extractor-form/index.tsx b/web/src/pages/data-flow/form/extractor-form/index.tsx index 722896e97..8021818b8 100644 --- a/web/src/pages/data-flow/form/extractor-form/index.tsx +++ b/web/src/pages/data-flow/form/extractor-form/index.tsx @@ -6,13 +6,13 @@ import { Form } from '@/components/ui/form'; import { PromptEditor } from '@/pages/agent/form/components/prompt-editor'; import { buildOptions } from '@/utils/form'; import { zodResolver } from '@hookform/resolvers/zod'; -import { memo } from 'react'; +import { memo, useCallback } from 'react'; import { useForm } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { z } from 'zod'; import { ContextGeneratorFieldName, - initialContextValues, + initialExtractorValues, } from '../../constant'; import { useBuildNodeOutputOptions } from '../../hooks/use-build-options'; import { useFormValues } from '../../hooks/use-form-values'; @@ -21,27 +21,48 @@ import { INextOperatorForm } from '../../interface'; import { FormWrapper } from '../components/form-wrapper'; export const FormSchema = z.object({ + field_name: z.string(), sys_prompt: z.string(), prompts: z.string().optional(), ...LlmSettingSchema, - field_name: z.array(z.string()), }); export type ExtractorFormSchemaType = z.infer; const ExtractorForm = ({ node }: INextOperatorForm) => { - const defaultValues = useFormValues(initialContextValues, node); + const defaultValues = useFormValues(initialExtractorValues, node); const { t } = useTranslation(); const form = useForm({ defaultValues, resolver: zodResolver(FormSchema), + // mode: 'onChange', }); const promptOptions = useBuildNodeOutputOptions(node?.id); const options = buildOptions(ContextGeneratorFieldName, t, 'dataflow'); + const setPromptValue = useCallback( + (field: keyof ExtractorFormSchemaType, key: string, value: string) => { + form.setValue(field, t(`dataflow.prompts.${key}.${value}`), { + shouldDirty: true, + shouldValidate: true, + }); + }, + [form, t], + ); + + const handleFieldNameChange = useCallback( + (value: string) => { + if (value) { + setPromptValue('sys_prompt', 'system', value); + setPromptValue('prompts', 'user', value); + } + }, + [setPromptValue], + ); + useWatchFormChange(node?.id, form); return ( @@ -51,7 +72,11 @@ const ExtractorForm = ({ node }: INextOperatorForm) => { {(field) => ( { + field.onChange(value); + handleFieldNameChange(value); + }} + value={field.value} placeholder={t('dataFlowPlaceholder')} options={options} > diff --git a/web/src/pages/data-flow/form/parser-form/index.tsx b/web/src/pages/data-flow/form/parser-form/index.tsx index 7bd05766b..df213e215 100644 --- a/web/src/pages/data-flow/form/parser-form/index.tsx +++ b/web/src/pages/data-flow/form/parser-form/index.tsx @@ -116,7 +116,7 @@ function ParserItem({ name, index, fieldLength, remove }: ParserItemProps) { >
- Parser {index} + Parser {index + 1} {index > 0 && (