소스 검색

chore: enchance auto generate prompt (#6564)

Joel 9 달 전
부모
커밋
0f6a064c08
24개의 변경된 파일566개의 추가작업 그리고 294개의 파일을 삭제
  1. 3 0
      web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx
  2. 14 0
      web/app/components/app/configuration/config-prompt/index.tsx
  3. 52 24
      web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx
  4. 3 11
      web/app/components/app/configuration/config/automatic/automatic-btn.tsx
  5. 174 103
      web/app/components/app/configuration/config/automatic/get-automatic-res.tsx
  6. 7 0
      web/app/components/app/configuration/config/automatic/style.module.css
  7. 4 0
      web/app/components/base/icons/assets/vender/other/generator.svg
  8. 37 0
      web/app/components/base/icons/src/vender/other/Generator.json
  9. 16 0
      web/app/components/base/icons/src/vender/other/Generator.tsx
  10. 1 0
      web/app/components/base/icons/src/vender/other/index.ts
  11. 1 1
      web/app/components/base/icons/src/vender/solid/general/QuestionTriangle.json
  12. 12 0
      web/app/components/workflow/nodes/_base/components/prompt/editor.tsx
  13. 17 2
      web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx
  14. 17 3
      web/app/components/workflow/nodes/llm/components/config-prompt.tsx
  15. 48 0
      web/app/components/workflow/nodes/llm/components/prompt-generator-btn.tsx
  16. 1 0
      web/app/components/workflow/nodes/llm/panel.tsx
  17. 1 18
      web/i18n/de-DE/app-debug.ts
  18. 50 14
      web/i18n/en-US/app-debug.ts
  19. 1 18
      web/i18n/fr-FR/app-debug.ts
  20. 0 17
      web/i18n/ja-JP/app-debug.ts
  21. 49 12
      web/i18n/zh-Hans/app-debug.ts
  22. 1 18
      web/i18n/zh-Hant/app-debug.ts
  23. 1 0
      web/service/debug.ts
  24. 56 53
      web/types/app.ts

+ 3 - 0
web/app/components/app/configuration/config-prompt/advanced-prompt-input.tsx

@@ -43,6 +43,7 @@ type Props = {
   promptVariables: PromptVariable[]
   isContextMissing: boolean
   onHideContextMissingTip: () => void
+  noResize?: boolean
 }
 
 const AdvancedPromptInput: FC<Props> = ({
@@ -56,6 +57,7 @@ const AdvancedPromptInput: FC<Props> = ({
   promptVariables,
   isContextMissing,
   onHideContextMissingTip,
+  noResize,
 }) => {
   const { t } = useTranslation()
   const { eventEmitter } = useEventEmitterContextContext()
@@ -207,6 +209,7 @@ const AdvancedPromptInput: FC<Props> = ({
               <div className="h-[18px] leading-[18px] px-1 rounded-md bg-gray-100 text-xs text-gray-500">{value.length}</div>
             </div>
           )}
+          hideResize={noResize}
         >
           <PromptEditor
             className='min-h-[84px]'

+ 14 - 0
web/app/components/app/configuration/config-prompt/index.tsx

@@ -19,6 +19,10 @@ export type IPromptProps = {
   promptTemplate: string
   promptVariables: PromptVariable[]
   readonly?: boolean
+  noTitle?: boolean
+  gradientBorder?: boolean
+  editorHeight?: number
+  noResize?: boolean
   onChange?: (prompt: string, promptVariables: PromptVariable[]) => void
 }
 
@@ -26,7 +30,11 @@ const Prompt: FC<IPromptProps> = ({
   mode,
   promptTemplate,
   promptVariables,
+  noTitle,
+  gradientBorder,
   readonly = false,
+  editorHeight,
+  noResize,
   onChange,
 }) => {
   const { t } = useTranslation()
@@ -99,6 +107,10 @@ const Prompt: FC<IPromptProps> = ({
         promptVariables={promptVariables}
         readonly={readonly}
         onChange={onChange}
+        noTitle={noTitle}
+        gradientBorder={gradientBorder}
+        editorHeight={editorHeight}
+        noResize={noResize}
       />
     )
   }
@@ -121,6 +133,7 @@ const Prompt: FC<IPromptProps> = ({
                 promptVariables={promptVariables}
                 isContextMissing={isContextMissing && !isHideContextMissTip}
                 onHideContextMissingTip={() => setIsHideContextMissTip(true)}
+                noResize={noResize}
               />
             ))
           )
@@ -136,6 +149,7 @@ const Prompt: FC<IPromptProps> = ({
               promptVariables={promptVariables}
               isContextMissing={isContextMissing && !isHideContextMissTip}
               onHideContextMissingTip={() => setIsHideContextMissTip(true)}
+              noResize={noResize}
             />
           )
         }

+ 52 - 24
web/app/components/app/configuration/config-prompt/simple-prompt-input.tsx

@@ -14,6 +14,7 @@ import PromptEditorHeightResizeWrap from './prompt-editor-height-resize-wrap'
 import cn from '@/utils/classnames'
 import { type PromptVariable } from '@/models/debug'
 import Tooltip from '@/app/components/base/tooltip'
+import type { CompletionParams } from '@/types/app'
 import { AppType } from '@/types/app'
 import { getNewVar, getVars } from '@/utils/var'
 import AutomaticBtn from '@/app/components/app/configuration/config/automatic/automatic-btn'
@@ -28,6 +29,7 @@ import { useEventEmitterContextContext } from '@/context/event-emitter'
 import { ADD_EXTERNAL_DATA_TOOL } from '@/app/components/app/configuration/config-var'
 import { INSERT_VARIABLE_VALUE_BLOCK_COMMAND } from '@/app/components/base/prompt-editor/plugins/variable-block'
 import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '@/app/components/base/prompt-editor/plugins/update-block'
+import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
 
 export type ISimplePromptInput = {
   mode: AppType
@@ -35,6 +37,10 @@ export type ISimplePromptInput = {
   promptVariables: PromptVariable[]
   readonly?: boolean
   onChange?: (promp: string, promptVariables: PromptVariable[]) => void
+  noTitle?: boolean
+  gradientBorder?: boolean
+  editorHeight?: number
+  noResize?: boolean
 }
 
 const Prompt: FC<ISimplePromptInput> = ({
@@ -43,11 +49,19 @@ const Prompt: FC<ISimplePromptInput> = ({
   promptVariables,
   readonly = false,
   onChange,
+  noTitle,
+  gradientBorder,
+  editorHeight: initEditorHeight,
+  noResize,
 }) => {
   const { t } = useTranslation()
+  const media = useBreakpoints()
+  const isMobile = media === MediaType.mobile
+
   const { eventEmitter } = useEventEmitterContextContext()
   const {
     modelConfig,
+    completionParams,
     dataSets,
     setModelConfig,
     setPrevPromptConfig,
@@ -116,6 +130,11 @@ const Prompt: FC<ISimplePromptInput> = ({
 
   const [showAutomatic, { setTrue: showAutomaticTrue, setFalse: showAutomaticFalse }] = useBoolean(false)
   const handleAutomaticRes = (res: AutomaticRes) => {
+    // put eventEmitter in first place to prevent overwrite the configs.prompt_variables.But another problem is that prompt won't hight the prompt_variables.
+    eventEmitter?.emit({
+      type: PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER,
+      payload: res.prompt,
+    } as any)
     const newModelConfig = produce(modelConfig, (draft) => {
       draft.configs.prompt_template = res.prompt
       draft.configs.prompt_variables = res.variables.map(key => ({ key, name: key, type: 'string', required: true }))
@@ -125,41 +144,41 @@ const Prompt: FC<ISimplePromptInput> = ({
     if (mode !== AppType.completion)
       setIntroduction(res.opening_statement)
     showAutomaticFalse()
-    eventEmitter?.emit({
-      type: PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER,
-      payload: res.prompt,
-    } as any)
   }
-  const minHeight = 228
+  const minHeight = initEditorHeight || 228
   const [editorHeight, setEditorHeight] = useState(minHeight)
 
   return (
-    <div className={cn(!readonly ? `${s.gradientBorder}` : 'bg-gray-50', ' relative shadow-md')}>
+    <div className={cn((!readonly || gradientBorder) ? `${s.gradientBorder}` : 'bg-gray-50', ' relative shadow-md')}>
       <div className='rounded-xl bg-[#EEF4FF]'>
-        <div className="flex justify-between items-center h-11 px-3">
-          <div className="flex items-center space-x-1">
-            <div className='h2'>{mode !== AppType.completion ? t('appDebug.chatSubTitle') : t('appDebug.completionSubTitle')}</div>
-            {!readonly && (
-              <Tooltip
-                htmlContent={<div className='w-[180px]'>
-                  {t('appDebug.promptTip')}
-                </div>}
-                selector='config-prompt-tooltip'>
-                <RiQuestionLine className='w-[14px] h-[14px] text-indigo-400' />
-              </Tooltip>
-            )}
-          </div>
-          <div className='flex items-center'>
-            {!isAgent && !readonly && (
-              <AutomaticBtn onClick={showAutomaticTrue} />
-            )}
+        {!noTitle && (
+          <div className="flex justify-between items-center h-11 pl-3 pr-6">
+            <div className="flex items-center space-x-1">
+              <div className='h2'>{mode !== AppType.completion ? t('appDebug.chatSubTitle') : t('appDebug.completionSubTitle')}</div>
+              {!readonly && (
+                <Tooltip
+                  htmlContent={<div className='w-[180px]'>
+                    {t('appDebug.promptTip')}
+                  </div>}
+                  selector='config-prompt-tooltip'>
+                  <RiQuestionLine className='w-[14px] h-[14px] text-indigo-400' />
+                </Tooltip>
+              )}
+            </div>
+            <div className='flex items-center'>
+              {!isAgent && !readonly && !isMobile && (
+                <AutomaticBtn onClick={showAutomaticTrue} />
+              )}
+            </div>
           </div>
-        </div>
+        )}
+
         <PromptEditorHeightResizeWrap
           className='px-4 pt-2 min-h-[228px] bg-white rounded-t-xl text-sm text-gray-700'
           height={editorHeight}
           minHeight={minHeight}
           onHeightChange={setEditorHeight}
+          hideResize={noResize}
           footer={(
             <div className='pl-4 pb-2 flex bg-white rounded-b-xl'>
               <div className="h-[18px] leading-[18px] px-1 rounded-md bg-gray-100 text-xs text-gray-500">{promptTemplate.length}</div>
@@ -216,6 +235,7 @@ const Prompt: FC<ISimplePromptInput> = ({
             onBlur={() => {
               handleChange(promptTemplate, getVars(promptTemplate))
             }}
+            editable={!readonly}
           />
         </PromptEditorHeightResizeWrap>
       </div>
@@ -232,6 +252,14 @@ const Prompt: FC<ISimplePromptInput> = ({
       {showAutomatic && (
         <GetAutomaticResModal
           mode={mode as AppType}
+          model={
+            {
+              provider: modelConfig.provider,
+              name: modelConfig.model_id,
+              mode: modelConfig.mode,
+              completion_params: completionParams as CompletionParams,
+            }
+          }
           isShow={showAutomatic}
           onClose={showAutomaticFalse}
           onFinished={handleAutomaticRes}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 3 - 11
web/app/components/app/configuration/config/automatic/automatic-btn.tsx


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 174 - 103
web/app/components/app/configuration/config/automatic/get-automatic-res.tsx


+ 7 - 0
web/app/components/app/configuration/config/automatic/style.module.css

@@ -0,0 +1,7 @@
+.textGradient {
+  background: linear-gradient(92deg, #2250F2 -29.55%, #0EBCF3 75.22%);
+  -webkit-background-clip: text;
+  -webkit-text-fill-color: transparent;
+  background-clip: text;
+  text-fill-color: transparent;
+}

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 4 - 0
web/app/components/base/icons/assets/vender/other/generator.svg


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 37 - 0
web/app/components/base/icons/src/vender/other/Generator.json


+ 16 - 0
web/app/components/base/icons/src/vender/other/Generator.tsx

@@ -0,0 +1,16 @@
+// GENERATE BY script
+// DON NOT EDIT IT MANUALLY
+
+import * as React from 'react'
+import data from './Generator.json'
+import IconBase from '@/app/components/base/icons/IconBase'
+import type { IconBaseProps, IconData } from '@/app/components/base/icons/IconBase'
+
+const Icon = React.forwardRef<React.MutableRefObject<SVGElement>, Omit<IconBaseProps, 'data'>>((
+  props,
+  ref,
+) => <IconBase {...props} ref={ref} data={data as IconData} />)
+
+Icon.displayName = 'Generator'
+
+export default Icon

+ 1 - 0
web/app/components/base/icons/src/vender/other/index.ts

@@ -0,0 +1 @@
+export { default as Generator } from './Generator'

+ 1 - 1
web/app/components/base/icons/src/vender/solid/general/QuestionTriangle.json

@@ -33,7 +33,7 @@
 						"attributes": {
 							"d": "M6.96353 1.5547C7.40657 0.890144 6.93018 0 6.13148 0H0V12L6.96353 1.5547Z",
 							"fill": "currentColor",
-							"fill-opacity": "0"
+							"fill-opacity": "0.5"
 						},
 						"children": []
 					}

+ 12 - 0
web/app/components/workflow/nodes/_base/components/prompt/editor.tsx

@@ -9,6 +9,7 @@ import { useTranslation } from 'react-i18next'
 import { useBoolean } from 'ahooks'
 import { BlockEnum, EditionType } from '../../../../types'
 import type {
+  ModelConfig,
   Node,
   NodeOutPutVar,
   Variable,
@@ -16,6 +17,7 @@ import type {
 
 import Wrap from '../editor/wrap'
 import { CodeLanguage } from '../../../code/types'
+import PromptGeneratorBtn from '../../../llm/components/prompt-generator-btn'
 import cn from '@/utils/classnames'
 import ToggleExpandBtn from '@/app/components/workflow/nodes/_base/components/toggle-expand-btn'
 import useToggleExpend from '@/app/components/workflow/nodes/_base/hooks/use-toggle-expend'
@@ -55,6 +57,9 @@ type Props = {
   }
   nodesOutputVars?: NodeOutPutVar[]
   availableNodes?: Node[]
+  isSupportPromptGenerator?: boolean
+  onGenerated?: (prompt: string) => void
+  modelConfig?: ModelConfig
   // for jinja
   isSupportJinja?: boolean
   editionType?: EditionType
@@ -80,11 +85,14 @@ const Editor: FC<Props> = ({
   hasSetBlockStatus,
   nodesOutputVars,
   availableNodes = [],
+  isSupportPromptGenerator,
   isSupportJinja,
   editionType,
   onEditionTypeChange,
   varList = [],
   handleAddVariable,
+  onGenerated,
+  modelConfig,
 }) => {
   const { t } = useTranslation()
   const { eventEmitter } = useEventEmitterContextContext()
@@ -124,6 +132,10 @@ const Editor: FC<Props> = ({
             <div className='leading-4 text-xs font-semibold text-gray-700 uppercase'>{title}</div>
             <div className='flex items-center'>
               <div className='leading-[18px] text-xs font-medium text-gray-500'>{value?.length || 0}</div>
+              {isSupportPromptGenerator && (
+                <PromptGeneratorBtn className='ml-[5px]' onGenerated={onGenerated} modelConfig={modelConfig} />
+              )}
+
               <div className='w-px h-3 ml-2 mr-2 bg-gray-200'></div>
               {/* Operations */}
               <div className='flex items-center space-x-2'>

+ 17 - 2
web/app/components/workflow/nodes/llm/components/config-prompt-item.tsx

@@ -1,11 +1,12 @@
 'use client'
 import type { FC } from 'react'
-import React, { useEffect, useState } from 'react'
+import React, { useCallback, useEffect, useState } from 'react'
 import { uniqueId } from 'lodash-es'
 import { useTranslation } from 'react-i18next'
 import { RiQuestionLine } from '@remixicon/react'
-import type { PromptItem, Variable } from '../../../types'
+import type { ModelConfig, PromptItem, Variable } from '../../../types'
 import { EditionType } from '../../../types'
+import { useWorkflowStore } from '../../../store'
 import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
 import TypeSelector from '@/app/components/workflow/nodes/_base/components/selector'
 import TooltipPlus from '@/app/components/base/tooltip-plus'
@@ -37,6 +38,7 @@ type Props = {
   availableNodes: any
   varList: Variable[]
   handleAddVariable: (payload: any) => void
+  modelConfig?: ModelConfig
 }
 
 const roleOptions = [
@@ -76,13 +78,23 @@ const ConfigPromptItem: FC<Props> = ({
   availableNodes,
   varList,
   handleAddVariable,
+  modelConfig,
 }) => {
   const { t } = useTranslation()
+  const workflowStore = useWorkflowStore()
+  const {
+    setControlPromptEditorRerenderKey,
+  } = workflowStore.getState()
   const [instanceId, setInstanceId] = useState(uniqueId())
   useEffect(() => {
     setInstanceId(`${id}-${uniqueId()}`)
   }, [id])
 
+  const handleGenerated = useCallback((prompt: string) => {
+    onPromptChange(prompt)
+    setTimeout(() => setControlPromptEditorRerenderKey(Date.now()))
+  }, [onPromptChange, setControlPromptEditorRerenderKey])
+
   return (
     <Editor
       className={className}
@@ -126,6 +138,9 @@ const ConfigPromptItem: FC<Props> = ({
       hasSetBlockStatus={hasSetBlockStatus}
       nodesOutputVars={availableVars}
       availableNodes={availableNodes}
+      isSupportPromptGenerator={payload.role === PromptRole.system}
+      onGenerated={handleGenerated}
+      modelConfig={modelConfig}
       isSupportJinja
       editionType={payload.edition_type}
       onEditionTypeChange={onEditionTypeChange}

+ 17 - 3
web/app/components/workflow/nodes/llm/components/config-prompt.tsx

@@ -5,9 +5,10 @@ import { useTranslation } from 'react-i18next'
 import produce from 'immer'
 import { ReactSortable } from 'react-sortablejs'
 import { v4 as uuid4 } from 'uuid'
-import type { PromptItem, ValueSelector, Var, Variable } from '../../../types'
+import type { ModelConfig, PromptItem, ValueSelector, Var, Variable } from '../../../types'
 import { EditionType, PromptRole } from '../../../types'
 import useAvailableVarList from '../../_base/hooks/use-available-var-list'
+import { useWorkflowStore } from '../../../store'
 import ConfigPromptItem from './config-prompt-item'
 import cn from '@/utils/classnames'
 import Editor from '@/app/components/workflow/nodes/_base/components/prompt/editor'
@@ -32,6 +33,7 @@ type Props = {
   }
   varList?: Variable[]
   handleAddVariable: (payload: any) => void
+  modelConfig: ModelConfig
 }
 
 const ConfigPrompt: FC<Props> = ({
@@ -46,8 +48,13 @@ const ConfigPrompt: FC<Props> = ({
   hasSetBlockStatus,
   varList = [],
   handleAddVariable,
+  modelConfig,
 }) => {
   const { t } = useTranslation()
+  const workflowStore = useWorkflowStore()
+  const {
+    setControlPromptEditorRerenderKey,
+  } = workflowStore.getState()
   const payloadWithIds = (isChatModel && Array.isArray(payload))
     ? payload.map((item) => {
       const id = uuid4()
@@ -124,6 +131,11 @@ const ConfigPrompt: FC<Props> = ({
     onChange(newPrompt)
   }, [onChange, payload])
 
+  const handleGenerated = useCallback((prompt: string) => {
+    handleCompletionPromptChange(prompt)
+    setTimeout(() => setControlPromptEditorRerenderKey(Date.now()))
+  }, [handleCompletionPromptChange, setControlPromptEditorRerenderKey])
+
   const handleCompletionEditionTypeChange = useCallback((editionType: EditionType) => {
     const newPrompt = produce(payload as PromptItem, (draft) => {
       draft.edition_type = editionType
@@ -189,12 +201,11 @@ const ConfigPrompt: FC<Props> = ({
                           availableNodes={availableNodesWithParent}
                           varList={varList}
                           handleAddVariable={handleAddVariable}
+                          modelConfig={modelConfig}
                         />
                       </div>
-
                     )
                   })
-
                 }
               </ReactSortable>
             </div>
@@ -219,11 +230,14 @@ const ConfigPrompt: FC<Props> = ({
               hasSetBlockStatus={hasSetBlockStatus}
               nodesOutputVars={availableVars}
               availableNodes={availableNodesWithParent}
+              isSupportPromptGenerator
               isSupportJinja
               editionType={(payload as PromptItem).edition_type}
               varList={varList}
               onEditionTypeChange={handleCompletionEditionTypeChange}
               handleAddVariable={handleAddVariable}
+              onGenerated={handleGenerated}
+              modelConfig={modelConfig}
             />
           </div>
         )}

+ 48 - 0
web/app/components/workflow/nodes/llm/components/prompt-generator-btn.tsx

@@ -0,0 +1,48 @@
+'use client'
+import type { FC } from 'react'
+import React, { useCallback } from 'react'
+import { useBoolean } from 'ahooks'
+import cn from 'classnames'
+import { Generator } from '@/app/components/base/icons/src/vender/other'
+import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
+import { AppType } from '@/types/app'
+import type { AutomaticRes } from '@/service/debug'
+import type { ModelConfig } from '@/app/components/workflow/types'
+import type { Model } from '@/types/app'
+
+type Props = {
+  className?: string
+  onGenerated?: (prompt: string) => void
+  modelConfig?: ModelConfig
+}
+
+const PromptGeneratorBtn: FC<Props> = ({
+  className,
+  onGenerated,
+  modelConfig,
+}) => {
+  const [showAutomatic, { setTrue: showAutomaticTrue, setFalse: showAutomaticFalse }] = useBoolean(false)
+  const handleAutomaticRes = useCallback((res: AutomaticRes) => {
+    onGenerated?.(res.prompt)
+    showAutomaticFalse()
+  }, [onGenerated, showAutomaticFalse])
+  return (
+    <div className={cn(className)}>
+      <div className='p-[5px] rounded-md hover:bg-[#155EEF]/8 cursor-pointer' onClick={showAutomaticTrue}>
+        <Generator className='w-3.5 h-3.5 text-primary-600' />
+      </div>
+      {showAutomatic && (
+        <GetAutomaticResModal
+          mode={AppType.chat}
+          isShow={showAutomatic}
+          onClose={showAutomaticFalse}
+          onFinished={handleAutomaticRes}
+          model={modelConfig as Model}
+          isInLLMNode
+        />
+      )}
+    </div>
+  )
+}
+
+export default React.memo(PromptGeneratorBtn)

+ 1 - 0
web/app/components/workflow/nodes/llm/panel.tsx

@@ -178,6 +178,7 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
             hasSetBlockStatus={hasSetBlockStatus}
             varList={inputs.prompt_config?.jinja2_variables || []}
             handleAddVariable={handleAddVariable}
+            modelConfig={model}
           />
         )}
 

+ 1 - 18
web/i18n/de-DE/app-debug.ts

@@ -24,7 +24,7 @@ const translation = {
     resetConfig: 'Zurücksetzen',
     debugConfig: 'Debuggen',
     addFeature: 'Funktion hinzufügen',
-    automatic: 'Automatisch',
+    automatic: 'Generieren',
     stopResponding: 'Antworten stoppen',
     agree: 'gefällt mir',
     disagree: 'gefällt mir nicht',
@@ -199,23 +199,6 @@ const translation = {
       },
     },
   },
-  automatic: {
-    title: 'Automatisierte Anwendungsorchestrierung',
-    description: 'Beschreiben Sie Ihr Szenario, Dify wird eine Anwendung für Sie orchestrieren.',
-    intendedAudience: 'Wer ist die Zielgruppe?',
-    intendedAudiencePlaceHolder: 'z.B. Student',
-    solveProblem: 'Welche Probleme hoffen sie, dass KI für sie lösen kann?',
-    solveProblemPlaceHolder: 'z.B. Erkenntnisse extrahieren und Informationen aus langen Berichten und Artikeln zusammenfassen',
-    generate: 'Generieren',
-    audiencesRequired: 'Zielgruppe erforderlich',
-    problemRequired: 'Problem erforderlich',
-    resTitle: 'Wir haben die folgende Anwendung für Sie orchestriert.',
-    apply: 'Diese Orchestrierung anwenden',
-    noData: 'Beschreiben Sie Ihren Anwendungsfall links, die Orchestrierungsvorschau wird hier angezeigt.',
-    loading: 'Orchestrieren der Anwendung für Sie...',
-    overwriteTitle: 'Bestehende Konfiguration überschreiben?',
-    overwriteMessage: 'Das Anwenden dieser Orchestrierung wird die bestehende Konfiguration überschreiben.',
-  },
   resetConfig: {
     title: 'Zurücksetzen bestätigen?',
     message:

+ 50 - 14
web/i18n/en-US/app-debug.ts

@@ -24,7 +24,7 @@ const translation = {
     resetConfig: 'Reset',
     debugConfig: 'Debug',
     addFeature: 'Add Feature',
-    automatic: 'Automatic',
+    automatic: 'Generate',
     stopResponding: 'Stop responding',
     agree: 'like',
     disagree: 'dislike',
@@ -199,22 +199,58 @@ const translation = {
       },
     },
   },
-  automatic: {
-    title: 'Automated application orchestration',
-    description: 'Describe your scenario, Dify will orchestrate an application for you.',
-    intendedAudience: 'Who is the intended audience?',
-    intendedAudiencePlaceHolder: 'e.g. Student',
-    solveProblem: 'What problems do they hope AI can solve for them?',
-    solveProblemPlaceHolder: 'e.g. Extract insights and summarize information from long reports and articles',
+  generate: {
+    title: 'Prompt Generator',
+    description: 'The Prompt Generator uses the configured model to optimize prompts for higher quality and better structure. Please write clear and detailed instructions.',
+    tryIt: 'Try it',
+    instruction: 'Instructions',
+    instructionPlaceHolder: 'Write clear and specific instructions.',
     generate: 'Generate',
-    audiencesRequired: 'Audiences required',
-    problemRequired: 'Problem required',
-    resTitle: 'We have orchestrated the following application for you.',
-    apply: 'Apply this orchestration',
-    noData: 'Describe your use case on the left, the orchestration preview will show here.',
+    resTitle: 'Generated Prompt',
+    noDataLine1: 'Describe your use case on the left,',
+    noDataLine2: 'the orchestration preview will show here.',
+    apply: 'Apply',
     loading: 'Orchestrating the application for you...',
     overwriteTitle: 'Override existing configuration?',
-    overwriteMessage: 'Applying this orchestration will override existing configuration.',
+    overwriteMessage: 'Applying this prompt will override existing configuration.',
+    template: {
+      pythonDebugger: {
+        name: 'Python debugger',
+        instruction: 'A bot that can generate and debug your code based on your instruction',
+      },
+      translation: {
+        name: 'Translation',
+        instruction: 'A translator that can translate multiple languages',
+      },
+      professionalAnalyst: {
+        name: 'Professional analyst',
+        instruction: 'Extract insights, identify risk and distill key information from long reports into single memo',
+      },
+      excelFormulaExpert: {
+        name: 'Excel formula expert',
+        instruction: 'A chatbot that can help novice users understand, use and create Excel formulas based on user instructions',
+      },
+      travelPlanning: {
+        name: 'Travel planning',
+        instruction: 'The Travel Planning Assistant is an intelligent tool designed to help users effortlessly plan their trips',
+      },
+      SQLSorcerer: {
+        name: 'SQL sorcerer',
+        instruction: 'Transform everyday language into SQL queries',
+      },
+      GitGud: {
+        name: 'Git gud',
+        instruction: 'Generate appropriate Git commands based on user described version control actions',
+      },
+      meetingTakeaways: {
+        name: 'Meeting takeaways',
+        instruction: 'Distill meetings into concise summaries including discussion topics, key takeaways, and action items',
+      },
+      writingsPolisher: {
+        name: 'Writing polisher',
+        instruction: 'Use advanced copyediting techniques to improve your writings',
+      },
+    },
   },
   resetConfig: {
     title: 'Confirm reset?',

+ 1 - 18
web/i18n/fr-FR/app-debug.ts

@@ -24,7 +24,7 @@ const translation = {
     resetConfig: 'Réinitialiser',
     debugConfig: 'Déboguer',
     addFeature: 'Ajouter une fonctionnalité',
-    automatic: 'Automatique',
+    automatic: 'Générer',
     stopResponding: 'Arrêtez de répondre',
     agree: 'comme',
     disagree: 'déteste',
@@ -199,23 +199,6 @@ const translation = {
       },
     },
   },
-  automatic: {
-    title: 'Orchestration automatique d\'application',
-    description: 'Décrivez votre scénario, Dify orchestrera une application pour vous.',
-    intendedAudience: 'Qui est le public cible ?',
-    intendedAudiencePlaceHolder: 'par exemple. Étudiant',
-    solveProblem: 'Quels problèmes espèrent-ils que l\'IA peut résoudre pour eux ?',
-    solveProblemPlaceHolder: 'par exemple, Évaluation des performances académiques',
-    generate: 'Générer',
-    audiencesRequired: 'Audiences requises',
-    problemRequired: 'Problème requis',
-    resTitle: 'Nous avons orchestré l\'application suivante pour vous.',
-    apply: 'Appliquez cette orchestration',
-    noData: 'Décrivez votre cas d\'utilisation sur la gauche, l\'aperçu de l\'orchestration s\'affichera ici.',
-    loading: 'Orchestration de l\'application pour vous...',
-    overwriteTitle: 'Remplacer la configuration existante ?',
-    overwriteMessage: 'L\'application de cette orchestration remplacera la configuration existante.',
-  },
   resetConfig: {
     title: 'Confirmer la réinitialisation ?',
     message:

+ 0 - 17
web/i18n/ja-JP/app-debug.ts

@@ -202,23 +202,6 @@ const translation = {
     },
 
   },
-  automatic: {
-    title: '自動アプリケーションオーケストレーション',
-    description: 'シナリオを説明してください。Difyがアプリケーションをあなたのためにオーケストレートします。',
-    intendedAudience: '誰が想定されるターゲットですか?',
-    intendedAudiencePlaceHolder: '例:学生',
-    solveProblem: 'どのような問題をAIが解決できると期待していますか?',
-    solveProblemPlaceHolder: '例:学業成績の評価',
-    generate: '生成',
-    audiencesRequired: 'ターゲットが必要です',
-    problemRequired: '問題が必要です',
-    resTitle: '次のアプリケーションをあなたのためにオーケストレートしました。',
-    apply: 'このオーケストレーションを適用する',
-    noData: '左側にユースケースを記述し、オーケストレーションプレビューがここに表示されます。',
-    loading: 'アプリケーションのオーケストレーションを実行しています...',
-    overwriteTitle: '既存の構成を上書きしますか?',
-    overwriteMessage: 'このオーケストレーションを適用すると、既存の構成が上書きされます。',
-  },
   resetConfig: {
     title: 'リセットを確認しますか?',
     message: '変更が破棄され、最後に公開された構成が復元されます。',

+ 49 - 12
web/i18n/zh-Hans/app-debug.ts

@@ -24,7 +24,7 @@ const translation = {
     resetConfig: '重置',
     debugConfig: '调试',
     addFeature: '添加功能',
-    automatic: '自动编排',
+    automatic: '生成',
     stopResponding: '停止响应',
     agree: '赞同',
     disagree: '反对',
@@ -199,22 +199,59 @@ const translation = {
       },
     },
   },
-  automatic: {
-    title: '自动编排',
-    description: '描述您的场景,Dify 将为您编排一个应用。',
-    intendedAudience: '目标用户是谁?',
-    intendedAudiencePlaceHolder: '例如:学生',
-    solveProblem: '希望 AI 为他们解决什么问题?',
-    solveProblemPlaceHolder: '例如:评估学业水平',
+  generate: {
+    title: '提示词生成器',
+    description: '提示词生成器使用配置的模型来优化提示词,以获得更高的质量和更好的结构。请写出清晰详细的说明。',
+    tryIt: '试一试',
+    instruction: '指令',
+    instructionPlaceHolder: '写下清晰、具体的说明。',
     generate: '生成',
-    audiencesRequired: '目标用户必填',
-    problemRequired: '解决问题必填',
-    resTitle: '我们为您编排了以下应用程序',
+    resTitle: '生成的提示词',
+    noDataLine1: '在左侧描述您的用例,',
+    noDataLine2: '编排预览将在此处显示。',
     apply: '应用',
     noData: '在左侧描述您的用例,编排预览将在此处显示。',
     loading: '为您编排应用程序中…',
     overwriteTitle: '覆盖现有配置?',
-    overwriteMessage: '应用此编排将覆盖现有配置。',
+    overwriteMessage: '应用此提示将覆盖现有配置。',
+    template: {
+      pythonDebugger: {
+        name: 'Python 代码助手',
+        instruction: '一个帮你写和纠错程序的机器人',
+      },
+      translation: {
+        name: '翻译机器人',
+        instruction: '一个可以翻译多种语言的翻译器',
+      },
+      professionalAnalyst: {
+        name: '职业分析师',
+        instruction: ' 从长篇报告中提取洞察、识别风险并提炼关键信息',
+      },
+      excelFormulaExpert: {
+        name: 'Excel 公式专家',
+        instruction: '一个可以让小白用户理解、使用和创建 Excel 公式的对话机器人',
+      },
+      travelPlanning: {
+        name: '旅行规划助手',
+        instruction: '旅行规划助手是一个智能工具,旨在帮助用户轻松规划他们的旅行',
+      },
+      SQLSorcerer: {
+        name: 'SQL 生成',
+        instruction: '把自然语言转换成 SQL 查询语句',
+      },
+      GitGud: {
+        name: 'Git 大师',
+        instruction: '从用户提出的版本管理需求生成合适的 Git 命令',
+      },
+      meetingTakeaways: {
+        name: '总结会议纪要',
+        instruction: '将会议内容提炼总结,包括讨论主题、关键要点和待办事项',
+      },
+      writingsPolisher: {
+        name: '润色文章',
+        instruction: '用地道的编辑技巧改进我的文章',
+      },
+    },
   },
   resetConfig: {
     title: '确认重置?',

+ 1 - 18
web/i18n/zh-Hant/app-debug.ts

@@ -24,7 +24,7 @@ const translation = {
     resetConfig: '重置',
     debugConfig: '除錯',
     addFeature: '新增功能',
-    automatic: '自動編排',
+    automatic: '產生',
     stopResponding: '停止響應',
     agree: '贊同',
     disagree: '反對',
@@ -199,23 +199,6 @@ const translation = {
       },
     },
   },
-  automatic: {
-    title: '自動編排',
-    description: '描述您的場景,Dify 將為您編排一個應用。',
-    intendedAudience: '目標使用者是誰?',
-    intendedAudiencePlaceHolder: '例如:學生',
-    solveProblem: '希望 AI 為他們解決什麼問題?',
-    solveProblemPlaceHolder: '例如:評估學業水平',
-    generate: '生成',
-    audiencesRequired: '目標使用者必填',
-    problemRequired: '解決問題必填',
-    resTitle: '我們為您編排了以下應用程式',
-    apply: '應用',
-    noData: '在左側描述您的用例,編排預覽將在此處顯示。',
-    loading: '為您編排應用程式中…',
-    overwriteTitle: '覆蓋現有配置?',
-    overwriteMessage: '應用此編排將覆蓋現有配置。',
-  },
   resetConfig: {
     title: '確認重置?',
     message: '重置將丟失當前頁面所有修改,恢復至上次釋出時的配置',

+ 1 - 0
web/service/debug.ts

@@ -7,6 +7,7 @@ export type AutomaticRes = {
   prompt: string
   variables: string[]
   opening_statement: string
+  error?: string
 }
 
 export const sendChatMessage = async (appId: string, body: Record<string, any>, { onData, onCompleted, onThought, onFile, onError, getAbortController, onMessageEnd, onMessageReplace }: {

+ 56 - 53
web/types/app.ts

@@ -140,9 +140,64 @@ export enum AgentStrategy {
   react = 'react',
 }
 
+export type CompletionParams = {
+  /** Maximum number of tokens in the answer message returned by Completion */
+  max_tokens: number
+  /**
+   * A number between 0 and 2.
+   * The larger the number, the more random the result;
+   * otherwise, the more deterministic.
+   * When in use, choose either `temperature` or `top_p`.
+   * Default is 1.
+   */
+  temperature: number
+  /**
+   * Represents the proportion of probability mass samples to take,
+   * e.g., 0.1 means taking the top 10% probability mass samples.
+   * The determinism between the samples is basically consistent.
+   * Among these results, the `top_p` probability mass results are taken.
+   * When in use, choose either `temperature` or `top_p`.
+   * Default is 1.
+   */
+  top_p: number
+  /** When enabled, the Completion Text will concatenate the Prompt content together and return it. */
+  echo: boolean
+  /**
+   * Specify up to 4 to automatically stop generating before the text specified in `stop`.
+   * Suitable for use in chat mode.
+   * For example, specify "Q" and "A",
+   * and provide some Q&A examples as context,
+   * and the model will give out in Q&A format and stop generating before Q&A.
+   */
+  stop: string[]
+  /**
+   * A number between -2.0 and 2.0.
+   * The larger the value, the less the model will repeat topics and the more it will provide new topics.
+   */
+  presence_penalty: number
+  /**
+   * A number between -2.0 and 2.0.
+   * A lower setting will make the model appear less cultured,
+   * always repeating expressions.
+   * The difference between `frequency_penalty` and `presence_penalty`
+   * is that `frequency_penalty` penalizes a word based on its frequency in the training data,
+   * while `presence_penalty` penalizes a word based on its occurrence in the input text.
+   */
+  frequency_penalty: number
+}
 /**
  * Model configuration. The backend type.
  */
+export type Model = {
+  /** LLM provider, e.g., OPENAI */
+  provider: string
+  /** Model name, e.g, gpt-3.5.turbo */
+  name: string
+  mode: ModelModeType
+  /** Default Completion call parameters */
+  completion_params: CompletionParams
+}
+
 export type ModelConfig = {
   opening_statement: string
   suggested_questions?: string[]
@@ -179,59 +234,7 @@ export type ModelConfig = {
     strategy?: AgentStrategy
     tools: ToolItem[]
   }
-  model: {
-    /** LLM provider, e.g., OPENAI */
-    provider: string
-    /** Model name, e.g, gpt-3.5.turbo */
-    name: string
-    mode: ModelModeType
-    /** Default Completion call parameters */
-    completion_params: {
-      /** Maximum number of tokens in the answer message returned by Completion */
-      max_tokens: number
-      /**
-       * A number between 0 and 2.
-       * The larger the number, the more random the result;
-       * otherwise, the more deterministic.
-       * When in use, choose either `temperature` or `top_p`.
-       * Default is 1.
-       */
-      temperature: number
-      /**
-       * Represents the proportion of probability mass samples to take,
-       * e.g., 0.1 means taking the top 10% probability mass samples.
-       * The determinism between the samples is basically consistent.
-       * Among these results, the `top_p` probability mass results are taken.
-       * When in use, choose either `temperature` or `top_p`.
-       * Default is 1.
-       */
-      top_p: number
-      /** When enabled, the Completion Text will concatenate the Prompt content together and return it. */
-      echo: boolean
-      /**
-       * Specify up to 4 to automatically stop generating before the text specified in `stop`.
-       * Suitable for use in chat mode.
-       * For example, specify "Q" and "A",
-       * and provide some Q&A examples as context,
-       * and the model will give out in Q&A format and stop generating before Q&A.
-       */
-      stop: string[]
-      /**
-       * A number between -2.0 and 2.0.
-       * The larger the value, the less the model will repeat topics and the more it will provide new topics.
-       */
-      presence_penalty: number
-      /**
-       * A number between -2.0 and 2.0.
-       * A lower setting will make the model appear less cultured,
-       * always repeating expressions.
-       * The difference between `frequency_penalty` and `presence_penalty`
-       * is that `frequency_penalty` penalizes a word based on its frequency in the training data,
-       * while `presence_penalty` penalizes a word based on its occurrence in the input text.
-       */
-      frequency_penalty: number
-    }
-  }
+  model: Model
   dataset_configs: DatasetConfigs
   file_upload?: {
     image: VisionSettings