From bec998ab947919cd229d55f30308fe13d9b99bc1 Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 25 Jan 2024 11:47:35 +0800 Subject: [PATCH] chore: remove universal chat code (#2194) --- web/app/(commonLayout)/explore/chat/page.tsx | 13 - .../dataset-config/card-item/index.tsx | 1 - web/app/components/base/audio-btn/index.tsx | 2 +- web/app/components/base/voice-input/index.tsx | 2 +- .../config-view/detail/index.tsx | 38 - .../config-view/detail/style.module.css | 9 - .../config-view/summary/index.tsx | 107 --- .../config-view/summary/style.module.css | 21 - .../config/data-config/index.tsx | 94 -- .../explore/universal-chat/config/index.tsx | 55 -- .../config/model-config/index.tsx | 39 - .../config/plugins-config/index.tsx | 103 --- .../config/plugins-config/item.module.css | 3 - .../config/plugins-config/item.tsx | 43 - .../universal-chat/hooks/use-conversation.ts | 73 -- .../explore/universal-chat/index.tsx | 831 ------------------ .../explore/universal-chat/init/index.tsx | 43 - .../universal-chat/init/style.module.css | 9 - web/app/components/share/chat/index.tsx | 1 - .../components/share/chat/sidebar/index.tsx | 25 +- .../share/chat/sidebar/list/index.tsx | 15 +- web/config/index.ts | 2 - web/i18n/lang/explore.en.ts | 39 - web/i18n/lang/explore.pt.ts | 39 - web/i18n/lang/explore.zh.ts | 39 - web/service/universal-chat.ts | 84 -- 26 files changed, 10 insertions(+), 1720 deletions(-) delete mode 100644 web/app/(commonLayout)/explore/chat/page.tsx delete mode 100644 web/app/components/explore/universal-chat/config-view/detail/index.tsx delete mode 100644 web/app/components/explore/universal-chat/config-view/detail/style.module.css delete mode 100644 web/app/components/explore/universal-chat/config-view/summary/index.tsx delete mode 100644 web/app/components/explore/universal-chat/config-view/summary/style.module.css delete mode 100644 web/app/components/explore/universal-chat/config/data-config/index.tsx delete mode 100644 web/app/components/explore/universal-chat/config/index.tsx delete mode 100644 web/app/components/explore/universal-chat/config/model-config/index.tsx delete mode 100644 web/app/components/explore/universal-chat/config/plugins-config/index.tsx delete mode 100644 web/app/components/explore/universal-chat/config/plugins-config/item.module.css delete mode 100644 web/app/components/explore/universal-chat/config/plugins-config/item.tsx delete mode 100644 web/app/components/explore/universal-chat/hooks/use-conversation.ts delete mode 100644 web/app/components/explore/universal-chat/index.tsx delete mode 100644 web/app/components/explore/universal-chat/init/index.tsx delete mode 100644 web/app/components/explore/universal-chat/init/style.module.css delete mode 100644 web/service/universal-chat.ts diff --git a/web/app/(commonLayout)/explore/chat/page.tsx b/web/app/(commonLayout)/explore/chat/page.tsx deleted file mode 100644 index 9610d868ce..0000000000 --- a/web/app/(commonLayout)/explore/chat/page.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { FC } from 'react' -import React from 'react' -import UniversalChat from '@/app/components/explore/universal-chat' - -const Chat: FC = () => { - return ( -
- -
- ) -} - -export default React.memo(Chat) diff --git a/web/app/components/app/configuration/dataset-config/card-item/index.tsx b/web/app/components/app/configuration/dataset-config/card-item/index.tsx index 767943303a..a784a7fd88 100644 --- a/web/app/components/app/configuration/dataset-config/card-item/index.tsx +++ b/web/app/components/app/configuration/dataset-config/card-item/index.tsx @@ -16,7 +16,6 @@ export type ICardItemProps = { onRemove: (id: string) => void readonly?: boolean } -// used in universal-chat const CardItem: FC = ({ className, config, diff --git a/web/app/components/base/audio-btn/index.tsx b/web/app/components/base/audio-btn/index.tsx index f64993669a..eaaca72594 100644 --- a/web/app/components/base/audio-btn/index.tsx +++ b/web/app/components/base/audio-btn/index.tsx @@ -33,7 +33,7 @@ const AudioBtn = ({ if (value !== '') { formData.append('text', removeCodeBlocks(value)) - let url = '/universal-chat/text-to-audio' + let url = '' let isPublic = false if (params.token) { diff --git a/web/app/components/base/voice-input/index.tsx b/web/app/components/base/voice-input/index.tsx index 0acf5576a3..5dd0a1dbc3 100644 --- a/web/app/components/base/voice-input/index.tsx +++ b/web/app/components/base/voice-input/index.tsx @@ -86,7 +86,7 @@ const VoiceInput = ({ const formData = new FormData() formData.append('file', mp3File) - let url = '/universal-chat/audio-to-text' + let url = '' let isPublic = false if (params.token) { diff --git a/web/app/components/explore/universal-chat/config-view/detail/index.tsx b/web/app/components/explore/universal-chat/config-view/detail/index.tsx deleted file mode 100644 index 1ba48d992a..0000000000 --- a/web/app/components/explore/universal-chat/config-view/detail/index.tsx +++ /dev/null @@ -1,38 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import cn from 'classnames' -import { useTranslation } from 'react-i18next' -import s from './style.module.css' -import Config from '@/app/components/explore/universal-chat/config' -import type { DataSet } from '@/models/datasets' - -type Props = { - modelId: string - providerName: string - plugins: Record - dataSets: DataSet[] -} -const ConfigViewPanel: FC = ({ - modelId, - providerName, - plugins, - dataSets, -}) => { - const { t } = useTranslation() - return ( -
-
- -
{t('explore.universalChat.viewConfigDetailTip')}
-
-
- ) -} -export default React.memo(ConfigViewPanel) diff --git a/web/app/components/explore/universal-chat/config-view/detail/style.module.css b/web/app/components/explore/universal-chat/config-view/detail/style.module.css deleted file mode 100644 index 0858e4d431..0000000000 --- a/web/app/components/explore/universal-chat/config-view/detail/style.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.btn { - background: url(~@/assets/action.svg) center center no-repeat transparent; - background-size: 16px 16px; - /* mask-image: ; */ -} - -.panelBorder { - border: 0.5px solid rgba(0, 0, 0, .05); -} diff --git a/web/app/components/explore/universal-chat/config-view/summary/index.tsx b/web/app/components/explore/universal-chat/config-view/summary/index.tsx deleted file mode 100644 index ec9ccc825e..0000000000 --- a/web/app/components/explore/universal-chat/config-view/summary/index.tsx +++ /dev/null @@ -1,107 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import cn from 'classnames' -import { useBoolean, useClickAway } from 'ahooks' -import s from './style.module.css' -import ModelIcon from '@/app/components/header/account-setting/model-provider-page/model-icon' -import ModelName from '@/app/components/header/account-setting/model-provider-page/model-name' -import { Google, WebReader, Wikipedia } from '@/app/components/base/icons/src/public/plugins' -import ConfigDetail from '@/app/components/explore/universal-chat/config-view/detail' -import type { DataSet } from '@/models/datasets' -import { useAgentThoughtCurrentProviderAndModelAndModelList } from '@/app/components/header/account-setting/model-provider-page/hooks' - -export type ISummaryProps = { - modelId: string - providerName: string - plugins: Record - dataSets: DataSet[] -} - -const getColorInfo = (modelId: string) => { - if (modelId === 'gpt-4') - return s.gpt4 - - if (modelId === 'claude-2') - return s.claude - - return s.gpt3 -} - -const getPlugIcon = (pluginId: string) => { - const className = 'w-4 h-4' - switch (pluginId) { - case 'google_search': - return - case 'web_reader': - return - case 'wikipedia': - return - default: - return null - } -} - -const Summary: FC = ({ - modelId, - providerName, - plugins, - dataSets, -}) => { - const { - currentModel: currModel, - currentProvider, - } = useAgentThoughtCurrentProviderAndModelAndModelList( - { provider: providerName, model: modelId }, - ) - // current_datetime is not configable and do not have icon - const pluginIds = Object.keys(plugins).filter(key => plugins[key] && key !== 'current_datetime') - const [isShowConfig, { setFalse: hideConfig, toggle: toggleShowConfig }] = useBoolean(false) - const configContentRef = React.useRef(null) - - useClickAway(() => { - hideConfig() - }, configContentRef) - return ( -
-
- -
- -
- { - pluginIds.length > 0 && ( -
-
-
- {pluginIds.map(pluginId => ( -
- {getPlugIcon(pluginId)}
- ))} -
-
- ) - } -
- {isShowConfig && ( - - )} -
- - ) -} -export default React.memo(Summary) diff --git a/web/app/components/explore/universal-chat/config-view/summary/style.module.css b/web/app/components/explore/universal-chat/config-view/summary/style.module.css deleted file mode 100644 index 15b37d66c1..0000000000 --- a/web/app/components/explore/universal-chat/config-view/summary/style.module.css +++ /dev/null @@ -1,21 +0,0 @@ -.border { - border: 1px solid rgba(0, 0, 0, 0.05); -} - -.gpt3 { - background: linear-gradient(0deg, #D3F8DF, #D3F8DF), -linear-gradient(0deg, #EDFCF2, #EDFCF2); - border: 1px solid rgba(211, 248, 223, 1) -} - -.gpt4 { - background: linear-gradient(0deg, #EBE9FE, #EBE9FE), - linear-gradient(0deg, #F4F3FF, #F4F3FF); - border: 1px solid rgba(235, 233, 254, 1) -} - -.claude { - background: linear-gradient(0deg, #F9EBDF, #F9EBDF), -linear-gradient(0deg, #FCF3EB, #FCF3EB); - border: 1px solid rgba(249, 235, 223, 1) -} \ No newline at end of file diff --git a/web/app/components/explore/universal-chat/config/data-config/index.tsx b/web/app/components/explore/universal-chat/config/data-config/index.tsx deleted file mode 100644 index a84a5d02ec..0000000000 --- a/web/app/components/explore/universal-chat/config/data-config/index.tsx +++ /dev/null @@ -1,94 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import { useTranslation } from 'react-i18next' -import { useBoolean } from 'ahooks' -import { isEqual } from 'lodash-es' -import produce from 'immer' -import FeaturePanel from '@/app/components/app/configuration/base/feature-panel' -import OperationBtn from '@/app/components/app/configuration/base/operation-btn' -import CardItem from '@/app/components/app/configuration/dataset-config/card-item' -import SelectDataSet from '@/app/components/app/configuration/dataset-config/select-dataset' -import type { DataSet } from '@/models/datasets' - -type Props = { - readonly?: boolean - dataSets: DataSet[] - onChange?: (data: DataSet[]) => void -} - -const DatasetConfig: FC = ({ - readonly, - dataSets, - onChange, -}) => { - const { t } = useTranslation() - - const selectedIds = dataSets.map(item => item.id) - - const hasData = dataSets.length > 0 - const [isShowSelectDataSet, { setTrue: showSelectDataSet, setFalse: hideSelectDataSet }] = useBoolean(false) - const handleSelect = (data: DataSet[]) => { - if (isEqual(data.map(item => item.id), dataSets.map(item => item.id))) { - hideSelectDataSet() - return - } - - if (data.find(item => !item.name)) { // has not loaded selected dataset - const newSelected = produce(data, (draft) => { - data.forEach((item, index) => { - if (!item.name) { // not fetched database - const newItem = dataSets.find(i => i.id === item.id) - if (newItem) - draft[index] = newItem - } - }) - }) - onChange?.(newSelected) - } - else { - onChange?.(data) - } - hideSelectDataSet() - } - const onRemove = (id: string) => { - onChange?.(dataSets.filter(item => item.id !== id)) - } - - return ( - } - hasHeaderBottomBorder={!hasData} - > - {hasData - ? ( -
- {dataSets.map(item => ( - - ))} -
- ) - : ( -
{t('appDebug.feature.dataSet.noData')}
- )} - - {isShowSelectDataSet && ( - - )} -
- ) -} -export default React.memo(DatasetConfig) diff --git a/web/app/components/explore/universal-chat/config/index.tsx b/web/app/components/explore/universal-chat/config/index.tsx deleted file mode 100644 index 825677e069..0000000000 --- a/web/app/components/explore/universal-chat/config/index.tsx +++ /dev/null @@ -1,55 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import ModelConfig from './model-config' -import DataConfig from './data-config' -import PluginConfig from './plugins-config' -import type { DataSet } from '@/models/datasets' - -export type IConfigProps = { - className?: string - readonly?: boolean - modelId: string - providerName: string - onModelChange?: (modelId: string, providerName: string) => void - plugins: Record - onPluginChange?: (key: string, value: boolean) => void - dataSets: DataSet[] - onDataSetsChange?: (contexts: DataSet[]) => void -} - -const Config: FC = ({ - className, - readonly, - modelId, - providerName, - onModelChange, - plugins, - onPluginChange, - dataSets, - onDataSetsChange, -}) => { - return ( -
- - - {(!readonly || (readonly && dataSets.length > 0)) && ( - - )} -
- ) -} -export default React.memo(Config) diff --git a/web/app/components/explore/universal-chat/config/model-config/index.tsx b/web/app/components/explore/universal-chat/config/model-config/index.tsx deleted file mode 100644 index 96c5fb9e26..0000000000 --- a/web/app/components/explore/universal-chat/config/model-config/index.tsx +++ /dev/null @@ -1,39 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import { useTranslation } from 'react-i18next' -import ModelSelector from '@/app/components/header/account-setting/model-provider-page/model-selector' -import { useProviderContext } from '@/context/provider-context' - -export type IModelConfigProps = { - modelId: string - providerName: string - onChange?: (modelId: string, providerName: string) => void - readonly?: boolean -} - -const ModelConfig: FC = ({ - modelId, - providerName, - onChange, - readonly, -}) => { - const { t } = useTranslation() - const { agentThoughtModelList } = useProviderContext() - - return ( -
-
{t('explore.universalChat.model')}
- { - onChange?.(model.model, model.provider) - }} - readonly={readonly} - /> -
- ) -} -export default React.memo(ModelConfig) diff --git a/web/app/components/explore/universal-chat/config/plugins-config/index.tsx b/web/app/components/explore/universal-chat/config/plugins-config/index.tsx deleted file mode 100644 index 718b215d8e..0000000000 --- a/web/app/components/explore/universal-chat/config/plugins-config/index.tsx +++ /dev/null @@ -1,103 +0,0 @@ -'use client' -import type { FC } from 'react' -import React, { useEffect } from 'react' -import { useTranslation } from 'react-i18next' -import Item from './item' -import FeaturePanel from '@/app/components/app/configuration/base/feature-panel' -import { Google, WebReader, Wikipedia } from '@/app/components/base/icons/src/public/plugins' -import { getToolProviders } from '@/service/explore' -import Loading from '@/app/components/base/loading' -import { useModalContext } from '@/context/modal-context' - -export type IPluginsProps = { - readonly?: boolean - config: Record - onChange?: (key: string, value: boolean) => void -} - -const plugins = [ - { key: 'google_search', icon: }, - { key: 'web_reader', icon: }, - { key: 'wikipedia', icon: }, -] as const - -const Plugins: FC = ({ - readonly, - config, - onChange, -}) => { - const { t } = useTranslation() - const { setShowAccountSettingModal } = useModalContext() - const [isLoading, setIsLoading] = React.useState(!readonly) - const [isSerpApiValid, setIsSerpApiValid] = React.useState(false) - const checkSerpApiKey = async () => { - if (readonly) - return - - const provides: any = await getToolProviders() - const isSerpApiValid = !!provides.find((v: any) => v.tool_name === 'serpapi' && v.is_enabled) - setIsSerpApiValid(isSerpApiValid) - setIsLoading(false) - } - useEffect(() => { - checkSerpApiKey() - }, []) - - const itemConfigs = plugins.map((plugin) => { - const res: Record = { ...plugin } - const { key } = plugin - res.name = t(`explore.universalChat.plugins.${key}.name`) - if (key === 'web_reader') - res.description = t(`explore.universalChat.plugins.${key}.description`) - - if (key === 'google_search' && !isSerpApiValid && !readonly) { - res.readonly = true - res.more = ( -
- {t('explore.universalChat.plugins.google_search.more.left')} - setShowAccountSettingModal({ payload: 'plugin', onCancelCallback: async () => await checkSerpApiKey() })}>{t('explore.universalChat.plugins.google_search.more.link')} - {t('explore.universalChat.plugins.google_search.more.right')} -
- ) - } - return res - }) - - const enabledPluginNum = Object.values(config).filter(v => v).length - - return ( - <> - -
{t('explore.universalChat.plugins.name')}
-
({enabledPluginNum}/{plugins.length})
- } - hasHeaderBottomBorder={false} - > - {isLoading - ? ( -
- -
- ) - : (
- {itemConfigs.map(item => ( - onChange?.(item.key, enabled)} - readonly={readonly || item.readonly} - /> - ))} -
)} -
- - ) -} -export default React.memo(Plugins) diff --git a/web/app/components/explore/universal-chat/config/plugins-config/item.module.css b/web/app/components/explore/universal-chat/config/plugins-config/item.module.css deleted file mode 100644 index 6acd346352..0000000000 --- a/web/app/components/explore/universal-chat/config/plugins-config/item.module.css +++ /dev/null @@ -1,3 +0,0 @@ -.shadow { - box-shadow: 0px 1px 2px 0px rgba(16, 24, 40, 0.05); -} \ No newline at end of file diff --git a/web/app/components/explore/universal-chat/config/plugins-config/item.tsx b/web/app/components/explore/universal-chat/config/plugins-config/item.tsx deleted file mode 100644 index 27af02ea2b..0000000000 --- a/web/app/components/explore/universal-chat/config/plugins-config/item.tsx +++ /dev/null @@ -1,43 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import cn from 'classnames' -import s from './item.module.css' -import Switch from '@/app/components/base/switch' - -export type IItemProps = { - icon: React.ReactNode - name: string - description?: string - more?: React.ReactNode - enabled: boolean - onChange: (enabled: boolean) => void - readonly?: boolean -} - -const Item: FC = ({ - icon, - name, - description, - more, - enabled, - onChange, - readonly, -}) => { - return ( -
-
-
- {icon} -
-
{name}
- {description &&
{description}
} -
-
- -
- {more} -
- ) -} -export default React.memo(Item) diff --git a/web/app/components/explore/universal-chat/hooks/use-conversation.ts b/web/app/components/explore/universal-chat/hooks/use-conversation.ts deleted file mode 100644 index 9b797a2474..0000000000 --- a/web/app/components/explore/universal-chat/hooks/use-conversation.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { useState } from 'react' -import produce from 'immer' -import { useGetState } from 'ahooks' -import type { ConversationItem } from '@/models/share' - -const storageConversationIdKey = 'conversationIdInfo' - -type ConversationInfoType = Omit -function useConversation() { - const [conversationList, setConversationList] = useState([]) - const [pinnedConversationList, setPinnedConversationList] = useState([]) - const [currConversationId, doSetCurrConversationId, getCurrConversationId] = useGetState('-1') - // when set conversation id, we do not have set appId - const setCurrConversationId = (id: string, appId: string, isSetToLocalStroge = true, newConversationName = '') => { - doSetCurrConversationId(id) - if (isSetToLocalStroge && id !== '-1') { - // conversationIdInfo: {[appId1]: conversationId1, [appId2]: conversationId2} - const conversationIdInfo = globalThis.localStorage?.getItem(storageConversationIdKey) ? JSON.parse(globalThis.localStorage?.getItem(storageConversationIdKey) || '') : {} - conversationIdInfo[appId] = id - globalThis.localStorage?.setItem(storageConversationIdKey, JSON.stringify(conversationIdInfo)) - } - } - - const getConversationIdFromStorage = (appId: string) => { - const conversationIdInfo = globalThis.localStorage?.getItem(storageConversationIdKey) ? JSON.parse(globalThis.localStorage?.getItem(storageConversationIdKey) || '') : {} - const id = conversationIdInfo[appId] - return id - } - - const isNewConversation = currConversationId === '-1' - // input can be updated by user - const [newConversationInputs, setNewConversationInputs] = useState | null>(null) - const resetNewConversationInputs = () => { - if (!newConversationInputs) - return - setNewConversationInputs(produce(newConversationInputs, (draft) => { - Object.keys(draft).forEach((key) => { - draft[key] = '' - }) - })) - } - const [existConversationInputs, setExistConversationInputs] = useState | null>(null) - const currInputs = isNewConversation ? newConversationInputs : existConversationInputs - const setCurrInputs = isNewConversation ? setNewConversationInputs : setExistConversationInputs - - // info is muted - const [newConversationInfo, setNewConversationInfo] = useState(null) - const [existConversationInfo, setExistConversationInfo] = useState(null) - const currConversationInfo = isNewConversation ? newConversationInfo : existConversationInfo - - return { - conversationList, - setConversationList, - pinnedConversationList, - setPinnedConversationList, - currConversationId, - getCurrConversationId, - setCurrConversationId, - getConversationIdFromStorage, - isNewConversation, - currInputs, - newConversationInputs, - existConversationInputs, - resetNewConversationInputs, - setCurrInputs, - currConversationInfo, - setNewConversationInfo, - existConversationInfo, - setExistConversationInfo, - } -} - -export default useConversation diff --git a/web/app/components/explore/universal-chat/index.tsx b/web/app/components/explore/universal-chat/index.tsx deleted file mode 100644 index 8e3044c3a6..0000000000 --- a/web/app/components/explore/universal-chat/index.tsx +++ /dev/null @@ -1,831 +0,0 @@ -/* eslint-disable react-hooks/exhaustive-deps */ -/* eslint-disable @typescript-eslint/no-use-before-define */ -'use client' -import type { FC } from 'react' -import React, { useEffect, useRef, useState } from 'react' -import cn from 'classnames' -import { useTranslation } from 'react-i18next' -import { useContext } from 'use-context-selector' -import produce from 'immer' -import { useBoolean, useGetState } from 'ahooks' -import AppUnavailable from '../../base/app-unavailable' -import useConversation from './hooks/use-conversation' -import Init from './init' -import { ToastContext } from '@/app/components/base/toast' -import Sidebar from '@/app/components/share/chat/sidebar' -import { - delConversation, - fetchAppParams, - fetchChatList, - fetchConversations, - fetchSuggestedQuestions, - generationConversationName, - pinConversation, - sendChatMessage, - stopChatMessageResponding, - unpinConversation, - updateFeedback, -} from '@/service/universal-chat' -import type { ConversationItem, SiteInfo } from '@/models/share' -import type { PromptConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug' -import type { Feedbacktype, IChatItem } from '@/app/components/app/chat/type' -import Chat from '@/app/components/app/chat' -import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' -import Loading from '@/app/components/base/loading' -import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel' -import { userInputsFormToPromptVariables } from '@/utils/model-config' -import Confirm from '@/app/components/base/confirm' -import type { DataSet } from '@/models/datasets' -import ConfigSummary from '@/app/components/explore/universal-chat/config-view/summary' -import { fetchDatasets } from '@/service/datasets' -import ItemOperation from '@/app/components/explore/item-operation' -import { useCurrentProviderAndModel } from '@/app/components/header/account-setting/model-provider-page/hooks' -import { useProviderContext } from '@/context/provider-context' - -const APP_ID = 'universal-chat' -const DEFAULT_PLUGIN = { - google_search: false, - web_reader: true, - wikipedia: true, -} -// Old configuration structure is not compatible with the current configuration -localStorage.removeItem('universal-chat-config') -const CONFIG_KEY = 'universal-chat-config-2' -type CONFIG = { - providerName: string - modelId: string - plugin: { - google_search: boolean - web_reader: boolean - wikipedia: boolean - } -} -let prevConfig: null | CONFIG = localStorage.getItem(CONFIG_KEY) ? JSON.parse(localStorage.getItem(CONFIG_KEY) as string) as CONFIG : null -const setPrevConfig = (config: CONFIG) => { - prevConfig = config - localStorage.setItem(CONFIG_KEY, JSON.stringify(prevConfig)) -} - -export type IMainProps = {} - -const Main: FC = () => { - const { t } = useTranslation() - const media = useBreakpoints() - const isMobile = media === MediaType.mobile - const { agentThoughtModelList } = useProviderContext() - const getInitConfig = (type: 'model' | 'plugin') => { - if (type === 'model') { - return { - providerName: prevConfig?.providerName || agentThoughtModelList[0]?.provider, - modelId: prevConfig?.modelId || agentThoughtModelList[0]?.models[0]?.model, - } - } - - if (type === 'plugin') - return prevConfig?.plugin || DEFAULT_PLUGIN - } - - useEffect(() => { - document.title = `${t('explore.sidebar.chat')} - Dify` - }, []) - /* - * app info - */ - const [appUnavailable, setAppUnavailable] = useState(false) - const [isUnknwonReason, setIsUnknwonReason] = useState(false) - const siteInfo: SiteInfo = ( - { - title: 'universal Chatbot', - icon: '', - icon_background: '', - description: '', - default_language: 'en', // TODO - prompt_public: true, - } - ) - const [promptConfig, setPromptConfig] = useState(null) - const [inited, setInited] = useState(false) - // in mobile, show sidebar by click button - const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false) - /* - * conversation info - */ - const [allConversationList, setAllConversationList] = useState([]) - const [isClearConversationList, { setTrue: clearConversationListTrue, setFalse: clearConversationListFalse }] = useBoolean(false) - const [isClearPinnedConversationList, { setTrue: clearPinnedConversationListTrue, setFalse: clearPinnedConversationListFalse }] = useBoolean(false) - const { - conversationList, - setConversationList, - pinnedConversationList, - setPinnedConversationList, - currConversationId, - getCurrConversationId, - setCurrConversationId, - getConversationIdFromStorage, - isNewConversation, - currConversationInfo, - currInputs, - newConversationInputs, - // existConversationInputs, - resetNewConversationInputs, - setCurrInputs, - setNewConversationInfo, - existConversationInfo, - setExistConversationInfo, - } = useConversation() - const [hasMore, setHasMore] = useState(true) - const [hasPinnedMore, setHasPinnedMore] = useState(true) - const onMoreLoaded = ({ data: conversations, has_more }: any) => { - setHasMore(has_more) - if (isClearConversationList) { - setConversationList(conversations) - clearConversationListFalse() - } - else { - setConversationList([...conversationList, ...conversations]) - } - } - const onPinnedMoreLoaded = ({ data: conversations, has_more }: any) => { - setHasPinnedMore(has_more) - if (isClearPinnedConversationList) { - setPinnedConversationList(conversations) - clearPinnedConversationListFalse() - } - else { - setPinnedConversationList([...pinnedConversationList, ...conversations]) - } - } - const [controlUpdateConversationList, setControlUpdateConversationList] = useState(0) - const noticeUpdateList = () => { - setHasMore(true) - clearConversationListTrue() - - setHasPinnedMore(true) - clearPinnedConversationListTrue() - - setControlUpdateConversationList(Date.now()) - } - const handlePin = async (id: string) => { - await pinConversation(id) - setControlItemOpHide(Date.now()) - notify({ type: 'success', message: t('common.api.success') }) - noticeUpdateList() - } - - const handleUnpin = async (id: string) => { - await unpinConversation(id) - setControlItemOpHide(Date.now()) - notify({ type: 'success', message: t('common.api.success') }) - noticeUpdateList() - } - const [isShowConfirm, { setTrue: showConfirm, setFalse: hideConfirm }] = useBoolean(false) - const [toDeleteConversationId, setToDeleteConversationId] = useState('') - const handleDelete = (id: string) => { - setToDeleteConversationId(id) - hideSidebar() // mobile - showConfirm() - } - - const didDelete = async () => { - await delConversation(toDeleteConversationId) - setControlItemOpHide(Date.now()) - notify({ type: 'success', message: t('common.api.success') }) - hideConfirm() - if (currConversationId === toDeleteConversationId) - handleConversationIdChange('-1') - - noticeUpdateList() - } - - const [suggestedQuestionsAfterAnswerConfig, setSuggestedQuestionsAfterAnswerConfig] = useState(null) - const [speechToTextConfig, setSpeechToTextConfig] = useState(null) - const [citationConfig, setCitationConfig] = useState(null) - - const [conversationIdChangeBecauseOfNew, setConversationIdChangeBecauseOfNew, getConversationIdChangeBecauseOfNew] = useGetState(false) - - const conversationName = currConversationInfo?.name || t('share.chat.newChatDefaultName') as string - const conversationIntroduction = currConversationInfo?.introduction || '' - - const handleConversationSwitch = async () => { - if (!inited) - return - - // update inputs of current conversation - let notSyncToStateIntroduction = '' - let notSyncToStateInputs: Record | undefined | null = {} - // debugger - if (!isNewConversation) { - const item = allConversationList.find(item => item.id === currConversationId) as any - notSyncToStateInputs = item?.inputs || {} - // setCurrInputs(notSyncToStateInputs) - notSyncToStateIntroduction = item?.introduction || '' - setExistConversationInfo({ - name: item?.name || '', - introduction: notSyncToStateIntroduction, - }) - const modelConfig = item?.model_config - if (modelConfig) { - setModeId(modelConfig.model_id) - const pluginConfig: Record = {} - const datasetIds: string[] = [] - modelConfig.agent_mode.tools.forEach((item: any) => { - const pluginName = Object.keys(item)[0] - if (pluginName === 'dataset') - datasetIds.push(item.dataset.id) - else - pluginConfig[pluginName] = item[pluginName].enabled - }) - setPlugins(pluginConfig) - if (datasetIds.length > 0) { - const { data } = await fetchDatasets({ url: '/datasets', params: { page: 1, ids: datasetIds } }) - setDateSets(data) - } - else { - setDateSets([]) - } - } - else { - configSetDefaultValue() - } - } - else { - configSetDefaultValue() - notSyncToStateInputs = newConversationInputs - setCurrInputs(notSyncToStateInputs) - } - - // update chat list of current conversation - if (!isNewConversation && !conversationIdChangeBecauseOfNew) { - fetchChatList(currConversationId).then((res: any) => { - const { data } = res - const newChatList: IChatItem[] = generateNewChatListWithOpenstatement(notSyncToStateIntroduction, notSyncToStateInputs) - - data.forEach((item: any) => { - newChatList.push({ - id: `question-${item.id}`, - content: item.query, - isAnswer: false, - }) - newChatList.push({ - ...item, - id: item.id, - content: item.answer, - feedback: item.feedback, - isAnswer: true, - citation: item.retriever_resources, - }) - }) - setChatList(newChatList) - setErrorHappened(false) - }) - } - - if (isNewConversation) { - setChatList(generateNewChatListWithOpenstatement()) - setErrorHappened(false) - } - - setControlFocus(Date.now()) - } - - useEffect(() => { - handleConversationSwitch() - }, [currConversationId, inited]) - - const handleConversationIdChange = (id: string) => { - if (id === '-1') { - createNewChat() - setConversationIdChangeBecauseOfNew(true) - } - else { - setConversationIdChangeBecauseOfNew(false) - } - // trigger handleConversationSwitch - setCurrConversationId(id, APP_ID) - setIsShowSuggestion(false) - hideSidebar() - } - - /* - * chat info. chat is under conversation. - */ - const [chatList, setChatList, getChatList] = useGetState([]) - const chatListDomRef = useRef(null) - useEffect(() => { - // scroll to bottom - if (chatListDomRef.current) - chatListDomRef.current.scrollTop = chatListDomRef.current.scrollHeight - }, [chatList, currConversationId]) - - // user can not edit inputs if user had send message - const createNewChat = async () => { - // if new chat is already exist, do not create new chat - abortController?.abort() - setResponsingFalse() - if (conversationList.some(item => item.id === '-1')) - return - - setConversationList(produce(conversationList, (draft) => { - draft.unshift({ - id: '-1', - name: t('share.chat.newChatDefaultName'), - inputs: newConversationInputs, - introduction: conversationIntroduction, - }) - })) - configSetDefaultValue() - } - - // sometime introduction is not applied to state - const generateNewChatListWithOpenstatement = (introduction?: string, inputs?: Record | null) => { - let caculatedIntroduction = introduction || conversationIntroduction || '' - const caculatedPromptVariables = inputs || currInputs || null - if (caculatedIntroduction && caculatedPromptVariables) - caculatedIntroduction = replaceStringWithValues(caculatedIntroduction, promptConfig?.prompt_variables || [], caculatedPromptVariables) - - const openstatement = { - id: `${Date.now()}`, - content: caculatedIntroduction, - isAnswer: true, - feedbackDisabled: true, - isOpeningStatement: true, - } - if (caculatedIntroduction) - return [openstatement] - - return [] - } - - const fetchAllConversations = () => { - return fetchConversations(undefined, undefined, 100) - } - - const fetchInitData = async () => { - return Promise.all([fetchAllConversations(), fetchAppParams()]) - } - - // init - useEffect(() => { - (async () => { - try { - const [conversationData, appParams]: any = await fetchInitData() - const prompt_template = '' - // handle current conversation id - const { data: allConversations } = conversationData as { data: ConversationItem[]; has_more: boolean } - const _conversationId = getConversationIdFromStorage(APP_ID) - const isNotNewConversation = allConversations.some(item => item.id === _conversationId) - setAllConversationList(allConversations) - // fetch new conversation info - const { user_input_form, opening_statement: introduction, suggested_questions_after_answer, speech_to_text, retriever_resource }: any = appParams - const prompt_variables = userInputsFormToPromptVariables(user_input_form) - - setNewConversationInfo({ - name: t('share.chat.newChatDefaultName'), - introduction, - }) - setPromptConfig({ - prompt_template, - prompt_variables, - } as PromptConfig) - setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer) - setSpeechToTextConfig(speech_to_text) - setCitationConfig(retriever_resource) - - if (isNotNewConversation) - setCurrConversationId(_conversationId, APP_ID, false) - - setInited(true) - } - catch (e: any) { - if (e.status === 404) { - setAppUnavailable(true) - } - else { - setIsUnknwonReason(true) - setAppUnavailable(true) - } - } - })() - }, []) - - const [isResponsing, { setTrue: setResponsingTrue, setFalse: setResponsingFalse }] = useBoolean(false) - const [abortController, setAbortController] = useState(null) - const { notify } = useContext(ToastContext) - const logError = (message: string) => { - notify({ type: 'error', message }) - } - - const checkCanSend = () => { - if (currConversationId !== '-1') - return true - - const prompt_variables = promptConfig?.prompt_variables - const inputs = currInputs - if (!inputs || !prompt_variables || prompt_variables?.length === 0) - return true - - let hasEmptyInput = false - const requiredVars = prompt_variables?.filter(({ key, name, required }) => { - const res = (!key || !key.trim()) || (!name || !name.trim()) || (required || required === undefined || required === null) - return res - }) || [] // compatible with old version - requiredVars.forEach(({ key }) => { - if (hasEmptyInput) - return - - if (!inputs?.[key]) - hasEmptyInput = true - }) - - if (hasEmptyInput) { - logError(t('appDebug.errorMessage.valueOfVarRequired')) - return false - } - return !hasEmptyInput - } - - const [controlFocus, setControlFocus] = useState(0) - const [isShowSuggestion, setIsShowSuggestion] = useState(false) - const doShowSuggestion = isShowSuggestion && !isResponsing - const [suggestQuestions, setSuggestQuestions] = useState([]) - const [messageTaskId, setMessageTaskId] = useState('') - const [hasStopResponded, setHasStopResponded, getHasStopResponded] = useGetState(false) - const [errorHappened, setErrorHappened] = useState(false) - const [isResponsingConIsCurrCon, setIsResponsingConCurrCon, getIsResponsingConIsCurrCon] = useGetState(true) - const initConfig = getInitConfig('model') - const [modelId, setModeId] = useState((initConfig as any)?.modelId as string) - const [providerName, setProviderName] = useState((initConfig as any)?.providerName) - const { currentModel } = useCurrentProviderAndModel( - agentThoughtModelList, - { provider: providerName, model: modelId }, - ) - const handleSend = async (message: string) => { - if (isNewConversation) { - const isModelSelected = modelId && !!currentModel - if (!isModelSelected) { - notify({ type: 'error', message: t('appDebug.errorMessage.notSelectModel') }) - return - } - setPrevConfig({ - modelId, - providerName, - plugin: plugins as any, - }) - } - - if (isResponsing) { - notify({ type: 'info', message: t('appDebug.errorMessage.waitForResponse') }) - return - } - const formattedPlugins = Object.keys(plugins).map(key => ({ - [key]: { - enabled: plugins[key], - }, - })) - const formattedDataSets = dataSets.map(({ id }) => { - return { - dataset: { - enabled: true, - id, - }, - } - }) - const data = { - query: message, - conversation_id: isNewConversation ? null : currConversationId, - model: modelId, - provider: providerName, - tools: [...formattedPlugins, ...formattedDataSets], - } - - // qustion - const questionId = `question-${Date.now()}` - const questionItem = { - id: questionId, - content: message, - agent_thoughts: [], - isAnswer: false, - } - - const placeholderAnswerId = `answer-placeholder-${Date.now()}` - const placeholderAnswerItem = { - id: placeholderAnswerId, - content: '', - isAnswer: true, - } - - const newList = [...getChatList(), questionItem, placeholderAnswerItem] - setChatList(newList) - - // answer - const responseItem: IChatItem = { - id: `${Date.now()}`, - content: '', - agent_thoughts: [], - isAnswer: true, - } - - const prevTempNewConversationId = getCurrConversationId() || '-1' - let tempNewConversationId = prevTempNewConversationId - - setHasStopResponded(false) - setResponsingTrue() - setErrorHappened(false) - setIsShowSuggestion(false) - setIsResponsingConCurrCon(true) - - sendChatMessage(data, { - getAbortController: (abortController) => { - setAbortController(abortController) - }, - onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId, taskId }: any) => { - responseItem.content = responseItem.content + message - responseItem.id = messageId - if (isFirstMessage && newConversationId) - tempNewConversationId = newConversationId - - setMessageTaskId(taskId) - // has switched to other conversation - if (prevTempNewConversationId !== getCurrConversationId()) { - setIsResponsingConCurrCon(false) - return - } - - // closesure new list is outdated. - const newListWithAnswer = produce( - getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId), - (draft) => { - if (!draft.find(item => item.id === questionId)) - draft.push({ ...questionItem } as any) - - draft.push({ ...responseItem }) - }) - - setChatList(newListWithAnswer) - }, - async onCompleted(hasError?: boolean) { - if (hasError) { - setResponsingFalse() - return - } - - if (getConversationIdChangeBecauseOfNew()) { - const { data: allConversations }: any = await fetchAllConversations() - const newItem: any = await generationConversationName(allConversations[0].id) - const newAllConversations = produce(allConversations, (draft: any) => { - draft[0].name = newItem.name - }) - setAllConversationList(newAllConversations as any) - noticeUpdateList() - } - setConversationIdChangeBecauseOfNew(false) - resetNewConversationInputs() - setCurrConversationId(tempNewConversationId, APP_ID, true) - if (getIsResponsingConIsCurrCon() && suggestedQuestionsAfterAnswerConfig?.enabled && !getHasStopResponded()) { - const { data }: any = await fetchSuggestedQuestions(responseItem.id) - setSuggestQuestions(data) - setIsShowSuggestion(true) - } - setResponsingFalse() - }, - onThought(thought) { - // thought finished then start to return message. Warning: use push agent_thoughts.push would caused problem when the thought is more then 2 - responseItem.id = thought.message_id; - (responseItem as any).agent_thoughts = [...(responseItem as any).agent_thoughts, thought] // .push(thought) - // has switched to other conversation - - if (prevTempNewConversationId !== getCurrConversationId()) { - setIsResponsingConCurrCon(false) - return - } - const newListWithAnswer = produce( - getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId), - (draft) => { - if (!draft.find(item => item.id === questionId)) - draft.push({ ...questionItem }) - draft.push({ ...responseItem }) - }) - setChatList(newListWithAnswer) - }, - onMessageEnd: (messageEnd) => { - responseItem.citation = messageEnd.metadata?.retriever_resources - - const newListWithAnswer = produce( - getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId), - (draft) => { - if (!draft.find(item => item.id === questionId)) - draft.push({ ...questionItem }) - - draft.push({ ...responseItem }) - }) - setChatList(newListWithAnswer) - }, - onError() { - setErrorHappened(true) - // role back placeholder answer - setChatList(produce(getChatList(), (draft) => { - draft.splice(draft.findIndex(item => item.id === placeholderAnswerId), 1) - })) - setResponsingFalse() - }, - }) - } - - const handleFeedback = async (messageId: string, feedback: Feedbacktype) => { - await updateFeedback({ url: `/messages/${messageId}/feedbacks`, body: { rating: feedback.rating } }) - const newChatList = chatList.map((item) => { - if (item.id === messageId) { - return { - ...item, - feedback, - } - } - return item - }) - setChatList(newChatList) - notify({ type: 'success', message: t('common.api.success') }) - } - - const [controlChatUpdateAllConversation, setControlChatUpdateAllConversation] = useState(0) - useEffect(() => { - (async () => { - if (controlChatUpdateAllConversation && !isNewConversation) { - const { data: allConversations } = await fetchAllConversations() as { data: ConversationItem[]; has_more: boolean } - const item = allConversations.find(item => item.id === currConversationId) - setAllConversationList(allConversations) - if (item) { - setExistConversationInfo({ - ...existConversationInfo, - name: item?.name || '', - } as any) - } - } - })() - }, [controlChatUpdateAllConversation]) - const renderSidebar = () => { - if (!APP_ID || !promptConfig) - return null - return ( - { - setConversationList(list) - setControlChatUpdateAllConversation(Date.now()) - }} - isClearConversationList={isClearConversationList} - pinnedList={pinnedConversationList} - onPinnedListChanged={(list) => { - setPinnedConversationList(list) - setControlChatUpdateAllConversation(Date.now()) - }} - isClearPinnedConversationList={isClearPinnedConversationList} - onMoreLoaded={onMoreLoaded} - onPinnedMoreLoaded={onPinnedMoreLoaded} - isNoMore={!hasMore} - isPinnedNoMore={!hasPinnedMore} - onCurrentIdChange={handleConversationIdChange} - currentId={currConversationId} - copyRight={''} - isInstalledApp={false} - isUniversalChat - installedAppId={''} - siteInfo={siteInfo} - onPin={handlePin} - onUnpin={handleUnpin} - controlUpdateList={controlUpdateConversationList} - onDelete={handleDelete} - onStartChat={() => handleConversationIdChange('-1')} - /> - ) - } - // const currModel = MODEL_LIST.find(item => item.id === modelId) - - const [plugins, setPlugins] = useState>(getInitConfig('plugin') as Record) - const handlePluginsChange = (key: string, value: boolean) => { - setPlugins({ - ...plugins, - [key]: value, - }) - } - const [dataSets, setDateSets] = useState([]) - const configSetDefaultValue = () => { - const initConfig = getInitConfig('model') - setModeId((initConfig as any)?.modelId as string) - setProviderName((initConfig as any)?.providerName) - setPlugins(getInitConfig('plugin') as any) - setDateSets([]) - } - const isCurrConversationPinned = !!pinnedConversationList.find(item => item.id === currConversationId) - const [controlItemOpHide, setControlItemOpHide] = useState(0) - if (appUnavailable) - return - - if (!promptConfig) - return - - return ( -
-
- {/* sidebar */} - {!isMobile && renderSidebar()} - {isMobile && isShowSidebar && ( -
-
e.stopPropagation()}> - {renderSidebar()} -
-
- )} - {/* main */} -
- {(!isNewConversation || isResponsing || errorHappened) && ( -
-
-
{conversationName}
-
- -
e.stopPropagation()}> - isCurrConversationPinned ? handleUnpin(currConversationId) : handlePin(currConversationId)} - isShowDelete - onDelete={() => handleDelete(currConversationId)} - /> -
-
-
-
- )} -
-
- { - setModeId(modelId) - setProviderName(providerName) - }} - plugins={plugins} - onPluginChange={handlePluginsChange} - dataSets={dataSets} - onDataSetsChange={setDateSets} - />} - chatList={chatList} - onSend={handleSend} - isHideFeedbackEdit - onFeedback={handleFeedback} - isResponsing={isResponsing} - canStopResponsing={!!messageTaskId && isResponsingConIsCurrCon} - abortResponsing={async () => { - await stopChatMessageResponding(messageTaskId) - setHasStopResponded(true) - setResponsingFalse() - }} - checkCanSend={checkCanSend} - controlFocus={controlFocus} - isShowSuggestion={doShowSuggestion} - suggestionList={suggestQuestions} - isShowSpeechToText={speechToTextConfig?.enabled} - isShowCitation={citationConfig?.enabled} - dataSets={dataSets} - /> -
-
- - {isShowConfirm && ( - - )} -
-
-
- ) -} -export default React.memo(Main) diff --git a/web/app/components/explore/universal-chat/init/index.tsx b/web/app/components/explore/universal-chat/init/index.tsx deleted file mode 100644 index 231786b4f9..0000000000 --- a/web/app/components/explore/universal-chat/init/index.tsx +++ /dev/null @@ -1,43 +0,0 @@ -'use client' -import type { FC } from 'react' -import React from 'react' -import { useTranslation } from 'react-i18next' -import cn from 'classnames' -import type { IConfigProps } from '../config' -import Config from '../config' -import s from './style.module.css' - -const Line = ( - - - - - - - - - - -) - -const Init: FC = ({ - ...configProps -}) => { - const { t } = useTranslation() - - return ( -
-
-
-
{t('explore.universalChat.welcome')}
-
{t('explore.universalChat.welcomeDescribe')}
-
-
- {Line} -
- -
-
- ) -} -export default React.memo(Init) diff --git a/web/app/components/explore/universal-chat/init/style.module.css b/web/app/components/explore/universal-chat/init/style.module.css deleted file mode 100644 index 7cbce70868..0000000000 --- a/web/app/components/explore/universal-chat/init/style.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.textGradient { - background: linear-gradient(to right, rgba(16, 74, 225, 1) 0, rgba(0, 152, 238, 1) 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; - text-fill-color: transparent; -} - - diff --git a/web/app/components/share/chat/index.tsx b/web/app/components/share/chat/index.tsx index c521f045e6..3f7990c964 100644 --- a/web/app/components/share/chat/index.tsx +++ b/web/app/components/share/chat/index.tsx @@ -58,7 +58,6 @@ export type IMainProps = { isInstalledApp?: boolean installedAppInfo?: InstalledApp isSupportPlugin?: boolean - isUniversalChat?: boolean } const Main: FC = ({ diff --git a/web/app/components/share/chat/sidebar/index.tsx b/web/app/components/share/chat/sidebar/index.tsx index 8d3fffdfc6..7fd4afeb5d 100644 --- a/web/app/components/share/chat/sidebar/index.tsx +++ b/web/app/components/share/chat/sidebar/index.tsx @@ -11,7 +11,6 @@ import AppInfo from '@/app/components/share/chat/sidebar/app-info' // import Card from './card' import type { ConversationItem, SiteInfo } from '@/models/share' import { fetchConversations } from '@/service/share' -import { fetchConversations as fetchUniversalConversations } from '@/service/universal-chat' export type ISidebarProps = { copyRight: string @@ -25,7 +24,6 @@ export type ISidebarProps = { isClearPinnedConversationList: boolean isInstalledApp: boolean installedAppId?: string - isUniversalChat?: boolean siteInfo: SiteInfo onMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void onPinnedMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void @@ -50,7 +48,6 @@ const Sidebar: FC = ({ isClearPinnedConversationList, isInstalledApp, installedAppId, - isUniversalChat, siteInfo, onMoreLoaded, onPinnedMoreLoaded, @@ -66,13 +63,7 @@ const Sidebar: FC = ({ const [hasPinned, setHasPinned] = useState(false) const checkHasPinned = async () => { - let res: any - if (isUniversalChat) - res = await fetchUniversalConversations(undefined, true) - - else - res = await fetchConversations(isInstalledApp, installedAppId, undefined, true) - + const res = await fetchConversations(isInstalledApp, installedAppId, undefined, true) as any setHasPinned(res.data.length > 0) } @@ -85,13 +76,13 @@ const Sidebar: FC = ({ checkHasPinned() }, [controlUpdateList]) - const maxListHeight = (isInstalledApp || isUniversalChat) ? 'max-h-[30vh]' : 'max-h-[40vh]' + const maxListHeight = (isInstalledApp) ? 'max-h-[30vh]' : 'max-h-[40vh]' return (
= ({ isClearConversationList={isClearPinnedConversationList} isInstalledApp={isInstalledApp} installedAppId={installedAppId} - isUniversalChat={isUniversalChat} onMoreLoaded={onPinnedMoreLoaded} isNoMore={isPinnedNoMore} isPinned={true} @@ -149,7 +139,6 @@ const Sidebar: FC = ({ isClearConversationList={isClearConversationList} isInstalledApp={isInstalledApp} installedAppId={installedAppId} - isUniversalChat={isUniversalChat} onMoreLoaded={onMoreLoaded} isNoMore={isNoMore} isPinned={false} @@ -160,11 +149,9 @@ const Sidebar: FC = ({
- {!isUniversalChat && ( -
-
© {copyRight} {(new Date()).getFullYear()}
-
- )} +
+
© {copyRight} {(new Date()).getFullYear()}
+
) } diff --git a/web/app/components/share/chat/sidebar/list/index.tsx b/web/app/components/share/chat/sidebar/list/index.tsx index 53beebb56d..23b5c67e03 100644 --- a/web/app/components/share/chat/sidebar/list/index.tsx +++ b/web/app/components/share/chat/sidebar/list/index.tsx @@ -9,7 +9,6 @@ import RenameModal from '../rename-modal' import Item from './item' import type { ConversationItem } from '@/models/share' import { fetchConversations, renameConversation } from '@/service/share' -import { fetchConversations as fetchUniversalConversations, renameConversation as renameUniversalConversation } from '@/service/universal-chat' import Toast from '@/app/components/base/toast' export type IListProps = { @@ -20,7 +19,6 @@ export type IListProps = { onListChanged?: (newList: ConversationItem[]) => void isClearConversationList: boolean isInstalledApp: boolean - isUniversalChat?: boolean installedAppId?: string onMoreLoaded: (res: { data: ConversationItem[]; has_more: boolean }) => void isNoMore: boolean @@ -38,7 +36,6 @@ const List: FC = ({ onListChanged, isClearConversationList, isInstalledApp, - isUniversalChat, installedAppId, onMoreLoaded, isNoMore, @@ -56,11 +53,7 @@ const List: FC = ({ let lastId = !isClearConversationList ? list[list.length - 1]?.id : undefined if (lastId === '-1') lastId = undefined - let res: any - if (isUniversalChat) - res = await fetchUniversalConversations(lastId, isPinned) - else - res = await fetchConversations(isInstalledApp, installedAppId, lastId, isPinned) + const res = await fetchConversations(isInstalledApp, installedAppId, lastId, isPinned) as any const { data: conversations, has_more }: any = res onMoreLoaded({ data: conversations, has_more }) } @@ -93,11 +86,7 @@ const List: FC = ({ setIsSaving() const currId = currentConversation.id try { - if (isUniversalChat) - await renameUniversalConversation(currId, newName) - - else - await renameConversation(isInstalledApp, installedAppId, currId, newName) + await renameConversation(isInstalledApp, installedAppId, currId, newName) Toast.notify({ type: 'success', diff --git a/web/config/index.ts b/web/config/index.ts index f3dab8f91d..35cd3e5654 100644 --- a/web/config/index.ts +++ b/web/config/index.ts @@ -52,8 +52,6 @@ export const MODEL_LIST = [ { id: 'claude-instant-1', name: 'claude-instant-1', type: AppType.completion, provider: ProviderType.anthropic }, // set 30k { id: 'claude-2', name: 'claude-2', type: AppType.completion, provider: ProviderType.anthropic }, // set 30k ] -const UNIVERSAL_CHAT_MODEL_ID_LIST = ['gpt-3.5-turbo', 'gpt-3.5-turbo-16k', 'gpt-4', 'claude-2'] -export const UNIVERSAL_CHAT_MODEL_LIST = MODEL_LIST.filter(({ id, type }) => UNIVERSAL_CHAT_MODEL_ID_LIST.includes(id) && (type === AppType.chat)) export const TONE_LIST = [ { id: 1, diff --git a/web/i18n/lang/explore.en.ts b/web/i18n/lang/explore.en.ts index 8d2d25dfdc..5af34cb37e 100644 --- a/web/i18n/lang/explore.en.ts +++ b/web/i18n/lang/explore.en.ts @@ -36,45 +36,6 @@ const translation = { Programming: 'Programming', HR: 'HR', }, - universalChat: { - welcome: 'Start chat with Dify', - welcomeDescribe: 'Your AI conversation companion for personalized assistance', - model: 'Model', - plugins: { - name: 'Plugins', - google_search: { - name: 'Google Search', - more: { - left: 'Enable the plugin, ', - link: 'set up your SerpAPI key', - right: ' first.', - }, - }, - web_reader: { - name: 'Web Reader', - description: 'Get needed information from any web link', - }, - wikipedia: { - name: 'Wikipedia', - }, - }, - thought: { - show: 'Show', - hide: 'Hide', - processOfThought: ' the process of thinking', - res: { - webReader: { - normal: 'Reading {url}', - hasPageInfo: 'Reading next page of {url}', - }, - google: 'Searching Google {{query}}', - wikipedia: 'Searching Wikipedia {{query}}', - dataset: 'Retrieving Knowledge {datasetName}', - date: 'Searching date', - }, - }, - viewConfigDetailTip: 'In conversation, cannot change above settings', - }, } export default translation diff --git a/web/i18n/lang/explore.pt.ts b/web/i18n/lang/explore.pt.ts index 4a1bdcfcb4..8ccf09b4fe 100644 --- a/web/i18n/lang/explore.pt.ts +++ b/web/i18n/lang/explore.pt.ts @@ -36,45 +36,6 @@ const translation = { Programming: 'Programação', HR: 'RH', }, - universalChat: { - welcome: 'Iniciar chat com Dify', - welcomeDescribe: 'Seu companheiro de conversa de IA para assistência personalizada', - model: 'Modelo', - plugins: { - name: 'Plugins', - google_search: { - name: 'Pesquisa do Google', - more: { - left: 'Ative o plugin, ', - link: 'configure sua chave SerpAPI', - right: ' primeiro.', - }, - }, - web_reader: { - name: 'Leitor da Web', - description: 'Obtenha informações necessárias de qualquer link da web', - }, - wikipedia: { - name: 'Wikipedia', - }, - }, - thought: { - show: 'Mostrar', - hide: 'Ocultar', - processOfThought: ' o processo de pensamento', - res: { - webReader: { - normal: 'Lendo {url}', - hasPageInfo: 'Lendo próxima página de {url}', - }, - google: 'Pesquisando no Google {{query}}', - wikipedia: 'Pesquisando na Wikipedia {{query}}', - dataset: 'Recuperando Conhecimento {datasetName}', - date: 'Pesquisando data', - }, - }, - viewConfigDetailTip: 'Na conversa, não é possível alterar as configurações acima', - }, } export default translation diff --git a/web/i18n/lang/explore.zh.ts b/web/i18n/lang/explore.zh.ts index ba90e9e676..dbc14f6e06 100644 --- a/web/i18n/lang/explore.zh.ts +++ b/web/i18n/lang/explore.zh.ts @@ -36,45 +36,6 @@ const translation = { Programming: '编程', HR: '人力资源', }, - universalChat: { - welcome: '开始和 Dify 聊天吧', - welcomeDescribe: '您的 AI 对话伴侣,为您提供个性化的帮助', - model: '模型', - plugins: { - name: '插件', - google_search: { - name: '谷歌搜索', - more: { - left: '启用插件,首先', - link: '设置您的 SerpAPI 密钥', - right: '', - }, - }, - web_reader: { - name: '解析链接', - description: '从任何网页链接获取所需信息', - }, - wikipedia: { - name: '维基百科', - }, - }, - thought: { - show: '显示', - hide: '隐藏', - processOfThought: '思考过程', - res: { - webReader: { - normal: '解析链接 {url}', - hasPageInfo: '解析链接 {url} 的下一页', - }, - google: '搜索谷歌 {{query}}', - wikipedia: '搜索维基百科 {{query}}', - dataset: '检索知识库 {datasetName}', - date: '查询日期', - }, - }, - viewConfigDetailTip: '在对话中,无法更改上述设置', - }, } export default translation diff --git a/web/service/universal-chat.ts b/web/service/universal-chat.ts deleted file mode 100644 index 56e6b671a5..0000000000 --- a/web/service/universal-chat.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { IOnCompleted, IOnData, IOnError, IOnMessageEnd, IOnThought } from './base' -import { - del, get, patch, post, ssePost, -} from './base' -import type { Feedbacktype } from '@/app/components/app/chat/type' - -const baseUrl = 'universal-chat' - -function getUrl(url: string) { - return `${baseUrl}/${url.startsWith('/') ? url.slice(1) : url}` -} - -export const sendChatMessage = async (body: Record, { onData, onCompleted, onError, onThought, onMessageEnd, getAbortController }: { - onData: IOnData - onCompleted: IOnCompleted - onError: IOnError - onThought: IOnThought - onMessageEnd: IOnMessageEnd - getAbortController?: (abortController: AbortController) => void -}) => { - return ssePost(getUrl('messages'), { - body: { - ...body, - response_mode: 'streaming', - }, - }, { onData, onCompleted, onThought, onError, getAbortController, onMessageEnd }) -} - -export const stopChatMessageResponding = async (taskId: string) => { - return post(getUrl(`messages/${taskId}/stop`)) -} - -export const fetchConversations = async (last_id?: string, pinned?: boolean, limit?: number) => { - return get(getUrl('conversations'), { params: { ...{ limit: limit || 20 }, ...(last_id ? { last_id } : {}), ...(pinned !== undefined ? { pinned } : {}) } }) -} - -export const pinConversation = async (id: string) => { - return patch(getUrl(`conversations/${id}/pin`)) -} - -export const unpinConversation = async (id: string) => { - return patch(getUrl(`conversations/${id}/unpin`)) -} - -export const delConversation = async (id: string) => { - return del(getUrl(`conversations/${id}`)) -} - -export const renameConversation = async (id: string, name: string) => { - return post(getUrl(`conversations/${id}/name`), { body: { name } }) -} - -export const generationConversationName = async (id: string) => { - return post(getUrl(`conversations/${id}/name`), { body: { auto_generate: true } }) -} - -export const fetchChatList = async (conversationId: string) => { - return get(getUrl('messages'), { params: { conversation_id: conversationId, limit: 20, last_id: '' } }) -} - -// init value. wait for server update -export const fetchAppParams = async () => { - return get(getUrl('parameters')) -} - -export const updateFeedback = async ({ url, body }: { url: string; body: Feedbacktype }) => { - return post(getUrl(url), { body }) -} - -export const fetchMoreLikeThis = async (messageId: string) => { - return get(getUrl(`/messages/${messageId}/more-like-this`), { - params: { - response_mode: 'blocking', - }, - }) -} - -export const fetchSuggestedQuestions = (messageId: string) => { - return get(getUrl(`/messages/${messageId}/suggested-questions`)) -} - -export const audioToText = (url: string, body: FormData) => { - return post(url, { body }, { bodyStringify: false, deleteContentType: true }) as Promise<{ text: string }> -}