| | |
| | | import type { FC } from 'react' |
| | | import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' |
| | | import useSWR from 'swr' |
| | | import { basePath } from '@/utils/var' |
| | | import { useTranslation } from 'react-i18next' |
| | | import { useContext } from 'use-context-selector' |
| | | import { usePathname } from 'next/navigation' |
| | |
| | | } from '@/app/components/app/configuration/debug/hooks' |
| | | import type { ModelAndParameter } from '@/app/components/app/configuration/debug/types' |
| | | import Button from '@/app/components/base/button' |
| | | import Divider from '@/app/components/base/divider' |
| | | import Loading from '@/app/components/base/loading' |
| | | import AppPublisher from '@/app/components/app/app-publisher/features-wrapper' |
| | | import type { |
| | |
| | | useTextGenerationCurrentProviderAndModelAndModelList, |
| | | } from '@/app/components/header/account-setting/model-provider-page/hooks' |
| | | import { fetchCollectionList } from '@/service/tools' |
| | | import type { Collection } from '@/app/components/tools/types' |
| | | import { type Collection } from '@/app/components/tools/types' |
| | | import { useStore as useAppStore } from '@/app/components/app/store' |
| | | import { |
| | | getMultipleRetrievalConfig, |
| | |
| | | import { SupportUploadFileTypes } from '@/app/components/workflow/types' |
| | | import NewFeaturePanel from '@/app/components/base/features/new-feature-panel' |
| | | import { fetchFileUploadConfig } from '@/service/common' |
| | | import { |
| | | correctModelProvider, |
| | | correctToolProvider, |
| | | } from '@/utils' |
| | | import PluginDependency from '@/app/components/workflow/plugin-dependency' |
| | | import { supportFunctionCall } from '@/utils/tool-call' |
| | | |
| | | type PublishConfig = { |
| | | modelConfig: ModelConfig |
| | |
| | | }))) |
| | | const { data: fileUploadConfigResponse } = useSWR({ url: '/files/upload' }, fetchFileUploadConfig) |
| | | |
| | | const latestPublishedAt = useMemo(() => appDetail?.model_config?.updated_at, [appDetail]) |
| | | const latestPublishedAt = useMemo(() => appDetail?.model_config.updated_at, [appDetail]) |
| | | const [formattingChanged, setFormattingChanged] = useState(false) |
| | | const { setShowAccountSettingModal } = useModalContext() |
| | | const [hasFetchedDetail, setHasFetchedDetail] = useState(false) |
| | |
| | | const setCompletionParams = (value: FormValue) => { |
| | | const params = { ...value } |
| | | |
| | | // eslint-disable-next-line ts/no-use-before-define |
| | | // eslint-disable-next-line @typescript-eslint/no-use-before-define |
| | | if ((!params.stop || params.stop.length === 0) && (modeModeTypeRef.current === ModelModeType.completion)) { |
| | | params.stop = getTempStop() |
| | | setTempStop([]) |
| | |
| | | } |
| | | |
| | | const [modelConfig, doSetModelConfig] = useState<ModelConfig>({ |
| | | provider: 'langgenius/openai/openai', |
| | | provider: 'openai', |
| | | model_id: 'gpt-3.5-turbo', |
| | | mode: ModelModeType.unset, |
| | | configs: { |
| | |
| | | dataSets: [], |
| | | agentConfig: DEFAULT_AGENT_SETTING, |
| | | }) |
| | | |
| | | const isAgent = mode === 'agent-chat' |
| | | |
| | | const isOpenAI = modelConfig.provider === 'langgenius/openai/openai' |
| | | const isOpenAI = modelConfig.provider === 'openai' |
| | | |
| | | const [collectionList, setCollectionList] = useState<Collection[]>([]) |
| | | const [datasetConfigs, doSetDatasetConfigs] = useState<DatasetConfigs>({ |
| | | useEffect(() => { |
| | | |
| | | }, []) |
| | | const [datasetConfigs, setDatasetConfigs] = useState<DatasetConfigs>({ |
| | | retrieval_model: RETRIEVE_TYPE.multiWay, |
| | | reranking_model: { |
| | | reranking_provider_name: '', |
| | |
| | | datasets: [], |
| | | }, |
| | | }) |
| | | const datasetConfigsRef = useRef(datasetConfigs) |
| | | const setDatasetConfigs = useCallback((newDatasetConfigs: DatasetConfigs) => { |
| | | doSetDatasetConfigs(newDatasetConfigs) |
| | | datasetConfigsRef.current = newDatasetConfigs |
| | | }, []) |
| | | |
| | | const setModelConfig = (newModelConfig: ModelConfig) => { |
| | | doSetModelConfig(newModelConfig) |
| | |
| | | }, [modelModeType]) |
| | | |
| | | const [dataSets, setDataSets] = useState<DataSet[]>([]) |
| | | const contextVar = modelConfig.configs.prompt_variables.find(item => item.is_context_var)?.key |
| | | const contextVar = modelConfig.configs.prompt_variables.find((item: any) => item.is_context_var)?.key |
| | | const hasSetContextVar = !!contextVar |
| | | const [isShowSelectDataSet, { setTrue: showSelectDataSet, setFalse: hideSelectDataSet }] = useBoolean(false) |
| | | const selectedIds = dataSets.map(item => item.id) |
| | |
| | | formattingChangedDispatcher() |
| | | let newDatasets = data |
| | | if (data.find(item => !item.name)) { // has not loaded selected dataset |
| | | const newSelected = produce(data, (draft) => { |
| | | const newSelected = produce(data, (draft: any) => { |
| | | data.forEach((item, index) => { |
| | | if (!item.name) { // not fetched database |
| | | const newItem = dataSets.find(i => i.id === item.id) |
| | |
| | | }) |
| | | |
| | | setDatasetConfigs({ |
| | | ...datasetConfigsRef.current, |
| | | ...retrievalConfig, |
| | | reranking_model: { |
| | | reranking_provider_name: retrievalConfig?.reranking_model?.provider || '', |
| | |
| | | }, |
| | | ) |
| | | |
| | | const isFunctionCall = supportFunctionCall(currModel?.features) |
| | | const isFunctionCall = (() => { |
| | | const features = currModel?.features |
| | | if (!features) |
| | | return false |
| | | return features.includes(ModelFeatureEnum.toolCall) || features.includes(ModelFeatureEnum.multiToolCall) |
| | | })() |
| | | |
| | | // Fill old app data missing model mode. |
| | | useEffect(() => { |
| | |
| | | const [canReturnToSimpleMode, setCanReturnToSimpleMode] = useState(true) |
| | | const setPromptMode = async (mode: PromptMode) => { |
| | | if (mode === PromptMode.advanced) { |
| | | // eslint-disable-next-line ts/no-use-before-define |
| | | // eslint-disable-next-line @typescript-eslint/no-use-before-define |
| | | await migrateToDefaultPrompt() |
| | | setCanReturnToSimpleMode(true) |
| | | } |
| | |
| | | useEffect(() => { |
| | | (async () => { |
| | | const collectionList = await fetchCollectionList() |
| | | if (basePath) { |
| | | collectionList.forEach((item) => { |
| | | if (typeof item.icon == 'string' && !item.icon.includes(basePath)) |
| | | item.icon = `${basePath}${item.icon}` |
| | | }) |
| | | } |
| | | setCollectionList(collectionList) |
| | | fetchAppDetail({ url: '/apps', id: appId }).then(async (res: any) => { |
| | | setMode(res.mode) |
| | |
| | | if (modelConfig.chat_prompt_config && modelConfig.chat_prompt_config.prompt.length > 0) |
| | | setChatPromptConfig(modelConfig.chat_prompt_config) |
| | | else |
| | | setChatPromptConfig(clone(DEFAULT_CHAT_PROMPT_CONFIG)) |
| | | setChatPromptConfig(clone(DEFAULT_CHAT_PROMPT_CONFIG) as any) |
| | | setCompletionPromptConfig(modelConfig.completion_prompt_config || clone(DEFAULT_COMPLETION_PROMPT_CONFIG) as any) |
| | | setCanReturnToSimpleMode(false) |
| | | } |
| | |
| | | if (modelConfig.retriever_resource) |
| | | setCitationConfig(modelConfig.retriever_resource) |
| | | |
| | | if (modelConfig.annotation_reply) { |
| | | let annotationConfig = modelConfig.annotation_reply |
| | | if (modelConfig.annotation_reply.enabled) { |
| | | annotationConfig = { |
| | | ...modelConfig.annotation_reply, |
| | | embedding_model: { |
| | | ...modelConfig.annotation_reply.embedding_model, |
| | | embedding_provider_name: correctModelProvider(modelConfig.annotation_reply.embedding_model.embedding_provider_name), |
| | | }, |
| | | } |
| | | } |
| | | setAnnotationConfig(annotationConfig, true) |
| | | } |
| | | if (modelConfig.annotation_reply) |
| | | setAnnotationConfig(modelConfig.annotation_reply, true) |
| | | |
| | | if (modelConfig.sensitive_word_avoidance) |
| | | setModerationConfig(modelConfig.sensitive_word_avoidance) |
| | |
| | | |
| | | const config = { |
| | | modelConfig: { |
| | | provider: correctModelProvider(model.provider), |
| | | provider: model.provider, |
| | | model_id: model.name, |
| | | mode: model.mode, |
| | | configs: { |
| | |
| | | annotation_reply: modelConfig.annotation_reply, |
| | | external_data_tools: modelConfig.external_data_tools, |
| | | dataSets: datasets || [], |
| | | // eslint-disable-next-line multiline-ternary |
| | | agentConfig: res.mode === 'agent-chat' ? { |
| | | max_iteration: DEFAULT_AGENT_SETTING.max_iteration, |
| | | ...modelConfig.agent_mode, |
| | |
| | | tools: modelConfig.agent_mode?.tools.filter((tool: any) => { |
| | | return !tool.dataset |
| | | }).map((tool: any) => { |
| | | const toolInCollectionList = collectionList.find(c => tool.provider_id === c.id) |
| | | return { |
| | | ...tool, |
| | | isDeleted: res.deleted_tools?.some((deletedTool: any) => deletedTool.id === tool.id && deletedTool.tool_name === tool.tool_name), |
| | | notAuthor: toolInCollectionList?.is_team_authorization === false, |
| | | ...(tool.provider_type === 'builtin' ? { |
| | | provider_id: correctToolProvider(tool.provider_name, !!toolInCollectionList), |
| | | provider_name: correctToolProvider(tool.provider_name, !!toolInCollectionList), |
| | | } : {}), |
| | | isDeleted: res.deleted_tools?.includes(tool.tool_name), |
| | | notAuthor: collectionList.find(c => tool.provider_id === c.id)?.is_team_authorization === false, |
| | | } |
| | | }), |
| | | } : DEFAULT_AGENT_SETTING, |
| | |
| | | |
| | | syncToPublishedConfig(config) |
| | | setPublishedConfig(config) |
| | | const retrievalConfig = getMultipleRetrievalConfig({ |
| | | ...modelConfig.dataset_configs, |
| | | reranking_model: modelConfig.dataset_configs.reranking_model && { |
| | | provider: modelConfig.dataset_configs.reranking_model.reranking_provider_name, |
| | | model: modelConfig.dataset_configs.reranking_model.reranking_model_name, |
| | | }, |
| | | }, datasets, datasets, { |
| | | const retrievalConfig = getMultipleRetrievalConfig(modelConfig.dataset_configs, datasets, datasets, { |
| | | provider: currentRerankProvider?.provider, |
| | | model: currentRerankModel?.model, |
| | | }) |
| | |
| | | retrieval_model: RETRIEVE_TYPE.multiWay, |
| | | ...modelConfig.dataset_configs, |
| | | ...retrievalConfig, |
| | | ...(retrievalConfig.reranking_model ? { |
| | | reranking_model: { |
| | | reranking_model_name: retrievalConfig.reranking_model.model, |
| | | reranking_provider_name: correctModelProvider(retrievalConfig.reranking_model.provider), |
| | | }, |
| | | } : {}), |
| | | }) |
| | | setHasFetchedDetail(true) |
| | | }) |
| | |
| | | } |
| | | |
| | | if (isLoading) { |
| | | return <div className='flex h-full items-center justify-center'> |
| | | return <div className='flex items-center justify-center h-full'> |
| | | <Loading type='area' /> |
| | | </div> |
| | | } |
| | |
| | | dataSets, |
| | | setDataSets, |
| | | datasetConfigs, |
| | | datasetConfigsRef, |
| | | setDatasetConfigs, |
| | | hasSetContextVar, |
| | | isShowVisionConfig, |
| | |
| | | > |
| | | <FeaturesProvider features={featuresData}> |
| | | <> |
| | | <div className="flex h-full flex-col"> |
| | | <div className='relative flex h-[200px] grow pt-14'> |
| | | <div className="flex flex-col h-full"> |
| | | <div className='relative flex grow h-[200px] pt-14'> |
| | | {/* Header */} |
| | | <div className='bg-default-subtle absolute left-0 top-0 h-14 w-full'> |
| | | <div className='flex h-14 items-center justify-between px-6'> |
| | | <div className='absolute top-0 left-0 w-full bg-white h-14'> |
| | | <div className='flex items-center justify-between px-6 h-14'> |
| | | <div className='flex items-center'> |
| | | <div className='system-xl-semibold text-text-primary'>{t('appDebug.orchestrate')}</div> |
| | | <div className='flex h-[14px] items-center space-x-1 text-xs'> |
| | | <div className='text-base font-semibold leading-6 text-gray-900'>{t('appDebug.orchestrate')}</div> |
| | | <div className='flex items-center h-[14px] space-x-1 text-xs'> |
| | | {isAdvancedMode && ( |
| | | <div className='system-xs-medium-uppercase ml-1 flex h-5 items-center rounded-md border border-components-button-secondary-border px-1.5 uppercase text-text-tertiary'>{t('appDebug.promptMode.advanced')}</div> |
| | | <div className='ml-1 flex items-center h-5 px-1.5 border border-gray-100 rounded-md text-[11px] font-medium text-gray-500 uppercase'>{t('appDebug.promptMode.advanced')}</div> |
| | | )} |
| | | </div> |
| | | </div> |
| | |
| | | debugWithMultipleModel={debugWithMultipleModel} |
| | | onDebugWithMultipleModelChange={handleDebugWithMultipleModelChange} |
| | | /> |
| | | <Divider type='vertical' className='mx-2 h-[14px]' /> |
| | | <div className='mx-2 w-[1px] h-[14px] bg-gray-200'></div> |
| | | </> |
| | | )} |
| | | {isMobile && ( |
| | | <Button className='mr-2 !h-8 !text-[13px] font-medium' onClick={showDebugPanel}> |
| | | <Button className='!h-8 !text-[13px] font-medium' onClick={showDebugPanel}> |
| | | <span className='mr-1'>{t('appDebug.operation.debugConfig')}</span> |
| | | <CodeBracketIcon className="h-4 w-4 text-text-tertiary" /> |
| | | <CodeBracketIcon className="w-4 h-4 text-gray-500" /> |
| | | </Button> |
| | | )} |
| | | <AppPublisher {...{ |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div className={`flex h-full w-full shrink-0 flex-col sm:w-1/2 ${debugWithMultipleModel && 'max-w-[560px]'}`}> |
| | | <div className={`w-full sm:w-1/2 shrink-0 flex flex-col h-full ${debugWithMultipleModel && 'max-w-[560px]'}`}> |
| | | <Config /> |
| | | </div> |
| | | {!isMobile && <div className="relative flex h-full w-1/2 grow flex-col overflow-y-auto " style={{ borderColor: 'rgba(0, 0, 0, 0.02)' }}> |
| | | <div className='flex grow flex-col rounded-tl-2xl border-l-[0.5px] border-t-[0.5px] border-components-panel-border bg-chatbot-bg '> |
| | | {!isMobile && <div className="relative flex flex-col w-1/2 h-full overflow-y-auto grow " style={{ borderColor: 'rgba(0, 0, 0, 0.02)' }}> |
| | | <div className='grow flex flex-col border-t-[0.5px] border-l-[0.5px] rounded-tl-2xl border-components-panel-border bg-chatbot-bg '> |
| | | <Debug |
| | | isAPIKeySet={isAPIKeySet} |
| | | onSetting={() => setShowAccountSettingModal({ payload: 'provider' })} |
| | |
| | | /> |
| | | )} |
| | | {isMobile && ( |
| | | <Drawer showClose isOpen={isShowDebugPanel} onClose={hideDebugPanel} mask footer={null}> |
| | | <Drawer showClose isOpen={isShowDebugPanel} onClose={hideDebugPanel} mask footer={null} panelClassname='!bg-gray-50'> |
| | | <Debug |
| | | isAPIKeySet={isAPIKeySet} |
| | | onSetting={() => setShowAccountSettingModal({ payload: 'provider' })} |
| | |
| | | onAutoAddPromptVariable={handleAddPromptVariable} |
| | | /> |
| | | )} |
| | | <PluginDependency /> |
| | | </> |
| | | </FeaturesProvider> |
| | | </ConfigContext.Provider> |