feat: gener instrument left

feat/enchance-prompt-and-code-fe
Joel 10 months ago
parent 5d232ac1bc
commit 7907235124

@ -27,6 +27,7 @@ import { PROMPT_EDITOR_UPDATE_VALUE_BY_EVENT_EMITTER } from '@/app/components/ba
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import { useFeaturesStore } from '@/app/components/base/features/hooks' import { useFeaturesStore } from '@/app/components/base/features/hooks'
import { noop } from 'lodash-es' import { noop } from 'lodash-es'
import { GeneratorType } from '../config/automatic/types'
export type ISimplePromptInput = { export type ISimplePromptInput = {
mode: AppType mode: AppType
@ -276,6 +277,8 @@ const Prompt: FC<ISimplePromptInput> = ({
isShow={showAutomatic} isShow={showAutomatic}
onClose={showAutomaticFalse} onClose={showAutomaticFalse}
onFinished={handleAutomaticRes} onFinished={handleAutomaticRes}
isBasicMode
generatorType={GeneratorType.prompt}
/> />
)} )}
</div> </div>

@ -39,13 +39,20 @@ import { ModelTypeEnum } from '@/app/components/header/account-setting/model-pro
import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' import { useModelListAndDefaultModelAndCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks'
import type { ModelModeType } from '@/types/app' import type { ModelModeType } from '@/types/app'
import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations' import type { FormValue } from '@/app/components/header/account-setting/model-provider-page/declarations'
import InstructionEditor from './instruction-editor'
import type { Node, NodeOutPutVar } from '@/app/components/workflow/types'
import type { GeneratorType } from './types'
import { ArrowDownRoundFill } from '@/app/components/base/icons/src/vender/solid/general'
export type IGetAutomaticResProps = { export type IGetAutomaticResProps = {
mode: AppType mode: AppType
isShow: boolean isShow: boolean
onClose: () => void onClose: () => void
onFinished: (res: AutomaticRes) => void onFinished: (res: AutomaticRes) => void
isInLLMNode?: boolean nodesOutputVars?: NodeOutPutVar[]
availableNodes?: Node[]
generatorType: GeneratorType
isBasicMode?: boolean
} }
const TryLabel: FC<{ const TryLabel: FC<{
@ -68,7 +75,10 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
mode, mode,
isShow, isShow,
onClose, onClose,
isInLLMNode, nodesOutputVars,
availableNodes,
generatorType,
isBasicMode,
onFinished, onFinished,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
@ -124,6 +134,11 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
] ]
const [instruction, setInstruction] = useState<string>('') const [instruction, setInstruction] = useState<string>('')
const [ideaOutput, setIdeaOutput] = useState<string>('')
const [isFoldIdeaOutput, {
toggle: toggleFoldIdeaOutput,
}] = useBoolean(true)
const handleChooseTemplate = useCallback((key: string) => { const handleChooseTemplate = useCallback((key: string) => {
return () => { return () => {
const template = t(`appDebug.generate.template.${key}.instruction`) const template = t(`appDebug.generate.template.${key}.instruction`)
@ -210,7 +225,6 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
const { error, ...res } = await generateRule({ const { error, ...res } = await generateRule({
instruction, instruction,
model_config: model, model_config: model,
no_variable: !!isInLLMNode,
}) })
setRes(res) setRes(res)
if (error) { if (error) {
@ -240,11 +254,11 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
> >
<div className='flex h-[680px] flex-wrap'> <div className='flex h-[680px] flex-wrap'>
<div className='h-full w-[570px] shrink-0 overflow-y-auto border-r border-divider-regular p-6'> <div className='h-full w-[570px] shrink-0 overflow-y-auto border-r border-divider-regular p-6'>
<div className='mb-8'> <div className='mb-4'>
<div className={`text-lg font-bold leading-[28px] ${s.textGradient}`}>{t('appDebug.generate.title')}</div> <div className={`text-lg font-bold leading-[28px] ${s.textGradient}`}>{t('appDebug.generate.title')}</div>
<div className='mt-1 text-[13px] font-normal text-text-tertiary'>{t('appDebug.generate.description')}</div> <div className='mt-1 text-[13px] font-normal text-text-tertiary'>{t('appDebug.generate.description')}</div>
</div> </div>
<div className='mb-8'> <div>
<ModelParameterModal <ModelParameterModal
popupClassName='!w-[520px]' popupClassName='!w-[520px]'
portalToFollowElemContentClassName='z-[1000]' portalToFollowElemContentClassName='z-[1000]'
@ -258,36 +272,60 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
hideDebugWithMultipleModel hideDebugWithMultipleModel
/> />
</div> </div>
<div > {isBasicMode && (
<div className='flex items-center'> <div className='mt-4'>
<div className='mr-3 shrink-0 text-xs font-semibold uppercase leading-[18px] text-text-tertiary'>{t('appDebug.generate.tryIt')}</div> <div className='flex items-center'>
<div className='h-px grow' style={{ <div className='mr-3 shrink-0 text-xs font-semibold uppercase leading-[18px] text-text-tertiary'>{t('appDebug.generate.tryIt')}</div>
background: 'linear-gradient(to right, rgba(243, 244, 246, 1), rgba(243, 244, 246, 0))', <div className='h-px grow' style={{
}}></div> background: 'linear-gradient(to right, rgba(243, 244, 246, 1), rgba(243, 244, 246, 0))',
</div> }}></div>
<div className='flex flex-wrap'> </div>
{tryList.map(item => ( <div className='flex flex-wrap'>
<TryLabel {tryList.map(item => (
key={item.key} <TryLabel
Icon={item.icon} key={item.key}
text={t(`appDebug.generate.template.${item.key}.name`)} Icon={item.icon}
onClick={handleChooseTemplate(item.key)} text={t(`appDebug.generate.template.${item.key}.name`)}
/> onClick={handleChooseTemplate(item.key)}
))} />
))}
</div>
</div> </div>
</div> )}
{/* inputs */} {/* inputs */}
<div className='mt-6'> <div className='mt-4'>
<div className='text-[0px]'> <div>
<div className='mb-2 text-sm font-medium leading-5 text-text-primary'>{t('appDebug.generate.instruction')}</div> <div className='system-sm-semibold-uppercase mb-1.5 text-text-secondary'>{t('appDebug.generate.instruction')}</div>
<Textarea <InstructionEditor
className="h-[200px] resize-none"
placeholder={t('appDebug.generate.instructionPlaceHolder') as string}
value={instruction} value={instruction}
onChange={e => setInstruction(e.target.value)} /> onChange={setInstruction}
nodesOutputVars={nodesOutputVars}
availableNodes={availableNodes}
generatorType={generatorType}
/>
</div>
<div className='mt-4 text-[0px]'>
<div
className='mb-1.5 flex cursor-pointer items-center text-sm font-medium leading-5 text-text-primary'
onClick={toggleFoldIdeaOutput}
>
<div className='system-sm-semibold-uppercase mr-1 text-text-secondary'>Idea output</div>
<div className='system-xs-regular text-text-tertiary'>(option)</div>
<ArrowDownRoundFill className={cn('size text-text-quaternary', isFoldIdeaOutput && 'relative top-[1px] rotate-[-90deg]')} />
</div>
{ !isFoldIdeaOutput && (
<Textarea
className="h-[80px]"
placeholder={'Describe your ideal response format, length, tone, and content requirements...'}
value={ideaOutput}
onChange={e => setIdeaOutput(e.target.value)}
/>
)}
</div> </div>
<div className='mt-5 flex justify-end'> <div className='mt-7 flex justify-end space-x-2'>
<Button>Dismiss(i18n)</Button>
<Button <Button
className='flex space-x-1' className='flex space-x-1'
variant='primary' variant='primary'
@ -304,18 +342,18 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
{(!isLoading && res) && ( {(!isLoading && res) && (
<div className='h-full w-0 grow p-6 pb-0'> <div className='h-full w-0 grow p-6 pb-0'>
<div className='mb-3 shrink-0 text-base font-semibold leading-[160%] text-text-secondary'>{t('appDebug.generate.resTitle')}</div> <div className='mb-3 shrink-0 text-base font-semibold leading-[160%] text-text-secondary'>{t('appDebug.generate.resTitle')}</div>
<div className={cn('max-h-[555px] overflow-y-auto', !isInLLMNode && 'pb-2')}> <div className={cn('max-h-[555px] overflow-y-auto', isBasicMode && 'pb-2')}>
<ConfigPrompt <ConfigPrompt
mode={mode} mode={mode}
promptTemplate={res?.prompt || ''} promptTemplate={res?.prompt || ''}
promptVariables={[]} promptVariables={[]}
readonly readonly
noTitle={isInLLMNode} noTitle={!isBasicMode}
gradientBorder gradientBorder
editorHeight={isInLLMNode ? 524 : 0} editorHeight={!isBasicMode ? 524 : 0}
noResize={isInLLMNode} noResize={!isBasicMode}
/> />
{!isInLLMNode && ( {isBasicMode && (
<> <>
{(res?.variables?.length && res?.variables?.length > 0) {(res?.variables?.length && res?.variables?.length > 0)
? ( ? (

@ -0,0 +1,94 @@
'use client'
import type { FC } from 'react'
import React from 'react'
import PromptEditor from '@/app/components/base/prompt-editor'
import type { GeneratorType } from './types'
import cn from '@/utils/classnames'
import { useStore } from '@/app/components/workflow/store'
import type { Node, NodeOutPutVar } from '@/app/components/workflow/types'
import { BlockEnum } from '@/app/components/workflow/types'
import { useWorkflowVariableType } from '@/app/components/workflow/hooks'
import { useTranslation } from 'react-i18next'
type Props = {
value: string
onChange: (text: string) => void
nodesOutputVars?: NodeOutPutVar[]
availableNodes?: Node[]
generatorType: GeneratorType
}
const placeholder = `
`
const InstructionEditor: FC<Props> = ({
generatorType,
nodesOutputVars = [],
availableNodes = [],
value,
onChange,
}) => {
const { t } = useTranslation()
const controlPromptEditorRerenderKey = useStore(s => s.controlPromptEditorRerenderKey)
const getVarType = useWorkflowVariableType()
const placeholder = (
<div className='system-sm-regular text-text-placeholder'>
<div className='leading-6'>Describe how you would like to improve this Prompt. For example:</div>
<div className='mt-2'>
<div>Make the output more concise, retaining the core points.</div>
<div>The output format is incorrect, please strictly follow the JSON format.</div>
<div>The tone is too harsh, please make it more friendly.</div>
</div>
</div>
)
return (
<div>
<PromptEditor
wrapperClassName='border !border-components-input-bg-normal bg-components-input-bg-normal hover:!border-components-input-bg-hover rounded-[10px] px-4 pt-3'
key={controlPromptEditorRerenderKey}
placeholder={placeholder}
placeholderClassName='px-4 pt-3'
// compact
className={cn('min-h-[240px] ')}
value={value}
workflowVariableBlock={{
show: true,
variables: nodesOutputVars,
getVarType,
workflowNodesMap: availableNodes.reduce((acc, node) => {
acc[node.id] = {
title: node.data.title,
type: node.data.type,
width: node.width,
height: node.height,
position: node.position,
}
if (node.data.type === BlockEnum.Start) {
acc.sys = {
title: t('workflow.blocks.start'),
type: BlockEnum.Start,
}
}
return acc
}, {} as any),
}}
currentBlock = {{
show: true,
generatorType,
}}
errorMessageBlock = {{
show: true,
}}
lastRunBlock = {{
show: true,
}}
onChange={onChange}
editable
isSupportFileVar={false}
/>
</div>
)
}
export default React.memo(InstructionEditor)

@ -79,7 +79,6 @@ import {
} from './constants' } from './constants'
import { useEventEmitterContextContext } from '@/context/event-emitter' import { useEventEmitterContextContext } from '@/context/event-emitter'
import cn from '@/utils/classnames' import cn from '@/utils/classnames'
import { GeneratorType } from '../../app/configuration/config/automatic/types'
export type PromptEditorProps = { export type PromptEditorProps = {
instanceId?: string instanceId?: string
@ -125,16 +124,9 @@ const PromptEditor: FC<PromptEditorProps> = ({
variableBlock, variableBlock,
externalToolBlock, externalToolBlock,
workflowVariableBlock, workflowVariableBlock,
currentBlock = { currentBlock,
show: true, errorMessageBlock,
generatorType: GeneratorType.code, lastRunBlock,
},
errorMessageBlock = {
show: true,
},
lastRunBlock = {
show: true,
},
isSupportFileVar, isSupportFileVar,
}) => { }) => {
const { eventEmitter } = useEventEmitterContextContext() const { eventEmitter } = useEventEmitterContextContext()

@ -10,6 +10,7 @@ import type {
} from '@/app/components/workflow/types' } from '@/app/components/workflow/types'
import { useIsChatMode } from './use-workflow' import { useIsChatMode } from './use-workflow'
import { useStoreApi } from 'reactflow' import { useStoreApi } from 'reactflow'
import type { Type } from '../nodes/llm/types'
export const useWorkflowVariables = () => { export const useWorkflowVariables = () => {
const { t } = useTranslation() const { t } = useTranslation()
@ -106,7 +107,7 @@ export const useWorkflowVariableType = () => {
isChatMode, isChatMode,
isConstant: false, isConstant: false,
}) })
return type return type as unknown as Type
} }
return getVarType return getVarType

@ -159,7 +159,13 @@ const Editor: FC<Props> = ({
<div className='flex items-center'> <div className='flex items-center'>
<div className='text-xs font-medium leading-[18px] text-text-tertiary'>{value?.length || 0}</div> <div className='text-xs font-medium leading-[18px] text-text-tertiary'>{value?.length || 0}</div>
{isSupportPromptGenerator && ( {isSupportPromptGenerator && (
<PromptGeneratorBtn className='ml-[5px]' onGenerated={onGenerated} modelConfig={modelConfig} /> <PromptGeneratorBtn
className='ml-[5px]'
onGenerated={onGenerated}
modelConfig={modelConfig}
nodesOutputVars={nodesOutputVars}
availableNodes={availableNodes}
/>
)} )}
<div className='ml-2 mr-2 h-3 w-px bg-divider-regular'></div> <div className='ml-2 mr-2 h-3 w-px bg-divider-regular'></div>

@ -8,17 +8,22 @@ import { ActionButton } from '@/app/components/base/action-button'
import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res' import GetAutomaticResModal from '@/app/components/app/configuration/config/automatic/get-automatic-res'
import { AppType } from '@/types/app' import { AppType } from '@/types/app'
import type { AutomaticRes } from '@/service/debug' import type { AutomaticRes } from '@/service/debug'
import type { ModelConfig } from '@/app/components/workflow/types' import type { ModelConfig, Node, NodeOutPutVar } from '@/app/components/workflow/types'
import { GeneratorType } from '@/app/components/app/configuration/config/automatic/types'
type Props = { type Props = {
className?: string className?: string
onGenerated?: (prompt: string) => void onGenerated?: (prompt: string) => void
modelConfig?: ModelConfig modelConfig?: ModelConfig
nodesOutputVars?: NodeOutPutVar[]
availableNodes?: Node[]
} }
const PromptGeneratorBtn: FC<Props> = ({ const PromptGeneratorBtn: FC<Props> = ({
className, className,
onGenerated, onGenerated,
nodesOutputVars,
availableNodes,
}) => { }) => {
const [showAutomatic, { setTrue: showAutomaticTrue, setFalse: showAutomaticFalse }] = useBoolean(false) const [showAutomatic, { setTrue: showAutomaticTrue, setFalse: showAutomaticFalse }] = useBoolean(false)
const handleAutomaticRes = useCallback((res: AutomaticRes) => { const handleAutomaticRes = useCallback((res: AutomaticRes) => {
@ -38,7 +43,9 @@ const PromptGeneratorBtn: FC<Props> = ({
isShow={showAutomatic} isShow={showAutomatic}
onClose={showAutomaticFalse} onClose={showAutomaticFalse}
onFinished={handleAutomaticRes} onFinished={handleAutomaticRes}
isInLLMNode generatorType={GeneratorType.prompt}
nodesOutputVars={nodesOutputVars}
availableNodes={availableNodes}
/> />
)} )}
</div> </div>

Loading…
Cancel
Save