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