feat: gener instrument left

feat/enchance-prompt-and-code-fe
Joel 9 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 { useFeaturesStore } from '@/app/components/base/features/hooks'
import { noop } from 'lodash-es'
import { GeneratorType } from '../config/automatic/types'
export type ISimplePromptInput = {
mode: AppType
@ -276,6 +277,8 @@ const Prompt: FC<ISimplePromptInput> = ({
isShow={showAutomatic}
onClose={showAutomaticFalse}
onFinished={handleAutomaticRes}
isBasicMode
generatorType={GeneratorType.prompt}
/>
)}
</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 type { ModelModeType } from '@/types/app'
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 = {
mode: AppType
isShow: boolean
onClose: () => void
onFinished: (res: AutomaticRes) => void
isInLLMNode?: boolean
nodesOutputVars?: NodeOutPutVar[]
availableNodes?: Node[]
generatorType: GeneratorType
isBasicMode?: boolean
}
const TryLabel: FC<{
@ -68,7 +75,10 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
mode,
isShow,
onClose,
isInLLMNode,
nodesOutputVars,
availableNodes,
generatorType,
isBasicMode,
onFinished,
}) => {
const { t } = useTranslation()
@ -124,6 +134,11 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
]
const [instruction, setInstruction] = useState<string>('')
const [ideaOutput, setIdeaOutput] = useState<string>('')
const [isFoldIdeaOutput, {
toggle: toggleFoldIdeaOutput,
}] = useBoolean(true)
const handleChooseTemplate = useCallback((key: string) => {
return () => {
const template = t(`appDebug.generate.template.${key}.instruction`)
@ -210,7 +225,6 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
const { error, ...res } = await generateRule({
instruction,
model_config: model,
no_variable: !!isInLLMNode,
})
setRes(res)
if (error) {
@ -240,11 +254,11 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
>
<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='mb-8'>
<div className='mb-4'>
<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>
<div className='mb-8'>
<div>
<ModelParameterModal
popupClassName='!w-[520px]'
portalToFollowElemContentClassName='z-[1000]'
@ -258,36 +272,60 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
hideDebugWithMultipleModel
/>
</div>
<div >
<div className='flex items-center'>
<div className='mr-3 shrink-0 text-xs font-semibold uppercase leading-[18px] text-text-tertiary'>{t('appDebug.generate.tryIt')}</div>
<div className='h-px grow' style={{
background: 'linear-gradient(to right, rgba(243, 244, 246, 1), rgba(243, 244, 246, 0))',
}}></div>
</div>
<div className='flex flex-wrap'>
{tryList.map(item => (
<TryLabel
key={item.key}
Icon={item.icon}
text={t(`appDebug.generate.template.${item.key}.name`)}
onClick={handleChooseTemplate(item.key)}
/>
))}
{isBasicMode && (
<div className='mt-4'>
<div className='flex items-center'>
<div className='mr-3 shrink-0 text-xs font-semibold uppercase leading-[18px] text-text-tertiary'>{t('appDebug.generate.tryIt')}</div>
<div className='h-px grow' style={{
background: 'linear-gradient(to right, rgba(243, 244, 246, 1), rgba(243, 244, 246, 0))',
}}></div>
</div>
<div className='flex flex-wrap'>
{tryList.map(item => (
<TryLabel
key={item.key}
Icon={item.icon}
text={t(`appDebug.generate.template.${item.key}.name`)}
onClick={handleChooseTemplate(item.key)}
/>
))}
</div>
</div>
</div>
)}
{/* inputs */}
<div className='mt-6'>
<div className='text-[0px]'>
<div className='mb-2 text-sm font-medium leading-5 text-text-primary'>{t('appDebug.generate.instruction')}</div>
<Textarea
className="h-[200px] resize-none"
placeholder={t('appDebug.generate.instructionPlaceHolder') as string}
<div className='mt-4'>
<div>
<div className='system-sm-semibold-uppercase mb-1.5 text-text-secondary'>{t('appDebug.generate.instruction')}</div>
<InstructionEditor
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 className='mt-5 flex justify-end'>
<div className='mt-7 flex justify-end space-x-2'>
<Button>Dismiss(i18n)</Button>
<Button
className='flex space-x-1'
variant='primary'
@ -304,18 +342,18 @@ const GetAutomaticRes: FC<IGetAutomaticResProps> = ({
{(!isLoading && res) && (
<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={cn('max-h-[555px] overflow-y-auto', !isInLLMNode && 'pb-2')}>
<div className={cn('max-h-[555px] overflow-y-auto', isBasicMode && 'pb-2')}>
<ConfigPrompt
mode={mode}
promptTemplate={res?.prompt || ''}
promptVariables={[]}
readonly
noTitle={isInLLMNode}
noTitle={!isBasicMode}
gradientBorder
editorHeight={isInLLMNode ? 524 : 0}
noResize={isInLLMNode}
editorHeight={!isBasicMode ? 524 : 0}
noResize={!isBasicMode}
/>
{!isInLLMNode && (
{isBasicMode && (
<>
{(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'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import cn from '@/utils/classnames'
import { GeneratorType } from '../../app/configuration/config/automatic/types'
export type PromptEditorProps = {
instanceId?: string
@ -125,16 +124,9 @@ const PromptEditor: FC<PromptEditorProps> = ({
variableBlock,
externalToolBlock,
workflowVariableBlock,
currentBlock = {
show: true,
generatorType: GeneratorType.code,
},
errorMessageBlock = {
show: true,
},
lastRunBlock = {
show: true,
},
currentBlock,
errorMessageBlock,
lastRunBlock,
isSupportFileVar,
}) => {
const { eventEmitter } = useEventEmitterContextContext()

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

@ -159,7 +159,13 @@ const Editor: FC<Props> = ({
<div className='flex items-center'>
<div className='text-xs font-medium leading-[18px] text-text-tertiary'>{value?.length || 0}</div>
{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>

@ -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 { AppType } from '@/types/app'
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 = {
className?: string
onGenerated?: (prompt: string) => void
modelConfig?: ModelConfig
nodesOutputVars?: NodeOutPutVar[]
availableNodes?: Node[]
}
const PromptGeneratorBtn: FC<Props> = ({
className,
onGenerated,
nodesOutputVars,
availableNodes,
}) => {
const [showAutomatic, { setTrue: showAutomaticTrue, setFalse: showAutomaticFalse }] = useBoolean(false)
const handleAutomaticRes = useCallback((res: AutomaticRes) => {
@ -38,7 +43,9 @@ const PromptGeneratorBtn: FC<Props> = ({
isShow={showAutomatic}
onClose={showAutomaticFalse}
onFinished={handleAutomaticRes}
isInLLMNode
generatorType={GeneratorType.prompt}
nodesOutputVars={nodesOutputVars}
availableNodes={availableNodes}
/>
)}
</div>

Loading…
Cancel
Save