import type { LLMNodeType } from '../types' import type { PromptItem, RolePrefix } from '@/app/components/workflow/types' import { produce } from 'immer' import { useCallback, useEffect, useRef, useState } from 'react' type CompletionPromptTemplate = { prompt: PromptItem conversation_histories_role: { user_prefix: string assistant_prefix: string } } export type LLMDefaultConfig = { prompt_templates?: { chat_model: { prompts: PromptItem[] } completion_model: CompletionPromptTemplate } } type Params = { inputs: LLMNodeType doSetInputs: (inputs: LLMNodeType) => void defaultConfig?: LLMDefaultConfig isChatModel: boolean } const useLLMInputManager = ({ inputs, doSetInputs, defaultConfig, isChatModel }: Params) => { const [defaultRolePrefix, setDefaultRolePrefix] = useState({ user: '', assistant: '', }) const inputRef = useRef(inputs) useEffect(() => { inputRef.current = inputs }, [inputs]) const setInputs = useCallback( (newInputs: LLMNodeType) => { if (newInputs.memory && !newInputs.memory.role_prefix) { const payloadWithRolePrefix = produce(newInputs, (draft) => { draft.memory!.role_prefix = defaultRolePrefix }) doSetInputs(payloadWithRolePrefix) inputRef.current = payloadWithRolePrefix return } doSetInputs(newInputs) inputRef.current = newInputs }, [defaultRolePrefix, doSetInputs], ) const appendDefaultPromptConfig = useCallback( (draft: LLMNodeType, nextDefaultConfig: LLMDefaultConfig, passInIsChatMode?: boolean) => { const promptTemplates = nextDefaultConfig.prompt_templates if (!promptTemplates) return if (passInIsChatMode === undefined ? isChatModel : passInIsChatMode) { draft.prompt_template = promptTemplates.chat_model.prompts return } draft.prompt_template = promptTemplates.completion_model.prompt setDefaultRolePrefix({ user: promptTemplates.completion_model.conversation_histories_role.user_prefix, assistant: promptTemplates.completion_model.conversation_histories_role.assistant_prefix, }) }, [isChatModel], ) useEffect(() => { const isReady = defaultConfig && Object.keys(defaultConfig).length > 0 if (!isReady || inputs.prompt_template) return const nextInputs = produce(inputs, (draft) => { appendDefaultPromptConfig(draft, defaultConfig) }) setInputs(nextInputs) }, [appendDefaultPromptConfig, defaultConfig, inputs, setInputs]) return { inputRef, setInputs, appendDefaultPromptConfig, } } export default useLLMInputManager