From 3942051604abc3258608b069895b8d704676049f Mon Sep 17 00:00:00 2001 From: JzoNg Date: Tue, 10 Dec 2024 16:42:39 +0800 Subject: [PATCH 1/2] feat: dark mode of app log --- .../app/(appDetailLayout)/[appId]/layout.tsx | 4 +- .../components/app/log-annotation/index.tsx | 2 +- web/app/components/app/log/list.tsx | 303 +++++++----------- web/app/components/app/log/model-info.tsx | 107 +++++++ web/app/components/app/log/var-panel.tsx | 24 +- .../app/text-generate/item/index.tsx | 2 +- .../base/chat/chat/answer/index.tsx | 8 +- web/app/components/base/copy-icon/index.tsx | 4 +- web/app/components/base/drawer/index.tsx | 2 +- .../base/tab-slider-plain/index.tsx | 12 +- web/app/components/base/tooltip/index.tsx | 2 +- .../model-provider-page/model-badge/index.tsx | 2 +- .../model-provider-page/model-name/index.tsx | 13 +- web/app/components/header/tools-nav/index.tsx | 7 +- .../nodes/_base/components/editor/base.tsx | 8 +- web/i18n/en-US/app-log.ts | 1 + web/i18n/zh-Hans/app-log.ts | 1 + 17 files changed, 268 insertions(+), 234 deletions(-) create mode 100644 web/app/components/app/log/model-info.tsx diff --git a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx index 96ee874d53caff..7a5347c7d54eed 100644 --- a/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx +++ b/web/app/(commonLayout)/app/(appDetailLayout)/[appId]/layout.tsx @@ -141,7 +141,7 @@ const AppDetailLayout: FC = (props) => { if (!appDetail) { return ( -
+
) @@ -152,7 +152,7 @@ const AppDetailLayout: FC = (props) => { {appDetail && ( )} -
+
{children}
diff --git a/web/app/components/app/log-annotation/index.tsx b/web/app/components/app/log-annotation/index.tsx index 3fa13019f944c2..696cc19ba4054f 100644 --- a/web/app/components/app/log-annotation/index.tsx +++ b/web/app/components/app/log-annotation/index.tsx @@ -34,7 +34,7 @@ const LogAnnotation: FC = ({ if (!appDetail) { return ( -
+
) diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index 978e83737b13e1..8f064c209efe10 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -5,9 +5,8 @@ import useSWR from 'swr' import { HandThumbDownIcon, HandThumbUpIcon, - XMarkIcon, } from '@heroicons/react/24/outline' -import { RiEditFill, RiQuestionLine } from '@remixicon/react' +import { RiCloseLine, RiEditFill } from '@remixicon/react' import { get } from 'lodash-es' import InfiniteScroll from 'react-infinite-scroll-component' import dayjs from 'dayjs' @@ -18,20 +17,16 @@ import { useShallow } from 'zustand/react/shallow' import { useTranslation } from 'react-i18next' import type { ChatItemInTree } from '../../base/chat/types' import VarPanel from './var-panel' -import cn from '@/utils/classnames' import type { FeedbackFunc, FeedbackType, IChatItem, SubmitAnnotationFunc } from '@/app/components/base/chat/chat/type' import type { Annotation, ChatConversationGeneralDetail, ChatConversationsResponse, ChatMessage, ChatMessagesRequest, CompletionConversationGeneralDetail, CompletionConversationsResponse, LogAnnotation } from '@/models/log' import type { App } from '@/types/app' +import ActionButton from '@/app/components/base/action-button' import Loading from '@/app/components/base/loading' import Drawer from '@/app/components/base/drawer' -import Popover from '@/app/components/base/popover' import Chat from '@/app/components/base/chat/chat' import { ToastContext } from '@/app/components/base/toast' import { fetchChatConversationDetail, fetchChatMessages, fetchCompletionConversationDetail, updateLogMessageAnnotations, updateLogMessageFeedbacks } from '@/service/log' -import { TONE_LIST } from '@/config' -import ModelIcon from '@/app/components/header/account-setting/model-provider-page/model-icon' -import { useTextGenerationCurrentProviderAndModelAndModelList } from '@/app/components/header/account-setting/model-provider-page/hooks' -import ModelName from '@/app/components/header/account-setting/model-provider-page/model-name' +import ModelInfo from '@/app/components/app/log/model-info' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import TextGeneration from '@/app/components/app/text-generate/item' import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils' @@ -44,6 +39,7 @@ import Tooltip from '@/app/components/base/tooltip' import { CopyIcon } from '@/app/components/base/copy-icon' import { buildChatItemTree, getThreadMessages } from '@/app/components/base/chat/utils' import { getProcessedFilesFromResponse } from '@/app/components/base/file-uploader/utils' +import cn from '@/utils/classnames' dayjs.extend(utc) dayjs.extend(timezone) @@ -75,15 +71,6 @@ const HandThumbIconWithCount: FC<{ count: number; iconType: 'up' | 'down' }> = (
} -const PARAM_MAP = { - temperature: 'Temperature', - top_p: 'Top P', - presence_penalty: 'Presence Penalty', - max_tokens: 'Max Token', - stop: 'Stop', - frequency_penalty: 'Frequency Penalty', -} - const getFormattedChatList = (messages: ChatMessage[], conversationId: string, timezone: string, format: string) => { const newChatList: IChatItem[] = [] messages.forEach((item: ChatMessage) => { @@ -156,9 +143,6 @@ const getFormattedChatList = (messages: ChatMessage[], conversationId: string, t return newChatList } -// const displayedParams = CompletionParams.slice(0, -2) -const validatedParams = ['temperature', 'top_p', 'presence_penalty', 'frequency_penalty'] - type IDetailPanel = { detail: any onFeedback: FeedbackFunc @@ -315,22 +299,6 @@ function DetailPanel({ detail, onFeedback }: IDetailPanel) { const isChatMode = appDetail?.mode !== 'completion' const isAdvanced = appDetail?.mode === 'advanced-chat' - const targetTone = TONE_LIST.find((item: any) => { - let res = true - validatedParams.forEach((param) => { - res = item.config?.[param] === detail?.model_config.model?.completion_params?.[param] - }) - return res - })?.name ?? 'custom' - - const modelName = (detail.model_config as any).model?.name - const provideName = (detail.model_config as any).model?.provider as any - const { - currentModel, - currentProvider, - } = useTextGenerationCurrentProviderAndModelAndModelList( - { provider: provideName, model: modelName }, - ) const varList = (detail.model_config as any).user_input_form?.map((item: any) => { const itemContent = item[Object.keys(item)[0]] return { @@ -342,18 +310,6 @@ function DetailPanel({ detail, onFeedback }: IDetailPanel) { ? detail.message.message_files.map((item: any) => item.url) : [] - const getParamValue = (param: string) => { - const value = detail?.model_config.model?.completion_params?.[param] || '-' - if (param === 'stop') { - if (Array.isArray(value)) - return value.join(',') - else - return '-' - } - - return value - } - const [width, setWidth] = useState(0) const ref = useRef(null) @@ -367,162 +323,71 @@ function DetailPanel({ detail, onFeedback }: IDetailPanel) { }, []) return ( -
+
{/* Panel Header */} -
-
-
{isChatMode ? t('appLog.detail.conversationId') : t('appLog.detail.time')}
+
+
+
{isChatMode ? t('appLog.detail.conversationId') : t('appLog.detail.time')}
{isChatMode && ( -
+
-
{detail.id}
+
{detail.id}
)} {!isChatMode && ( -
{formatTime(detail.created_at, t('appLog.dateTimeFormat') as string)}
+
{formatTime(detail.created_at, t('appLog.dateTimeFormat') as string)}
)}
-
- {!isAdvanced && ( - <> -
- - -
- - {targetTone} - - } - htmlContent={
-
- Tone of responses -
{targetTone}
-
- {['temperature', 'top_p', 'presence_penalty', 'max_tokens', 'stop'].map((param: string, index: number) => { - return
- {PARAM_MAP[param as keyof typeof PARAM_MAP]} - {getParamValue(param)} -
- })} -
} - /> - - )} -
- -
+
+ {!isAdvanced && }
- + + +
{/* Panel Body */} - {(varList.length > 0 || (!isChatMode && message_files.length > 0)) && ( -
- -
- )} - - {!isChatMode - ?
-
-
{t('appLog.table.header.output')}
-
-
- { }} - isInstalledApp={false} - supportFeedback - feedback={detail.message.feedbacks.find((item: any) => item.from_source === 'admin')} - onFeedback={feedback => onFeedback(detail.message.id, feedback)} - supportAnnotation - isShowTextToSpeech - appId={appDetail?.id} - varList={varList} - siteInfo={null} - /> +
+
+ {(varList.length > 0 || (!isChatMode && message_files.length > 0)) && ( + + )}
- : threadChatItems.length < 8 - ?
- +
+ {!isChatMode + ?
+
+
{t('appLog.table.header.output')}
+
+
+ { }} + isInstalledApp={false} + supportFeedback + feedback={detail.message.feedbacks.find((item: any) => item.from_source === 'admin')} + onFeedback={feedback => onFeedback(detail.message.id, feedback)} + supportAnnotation + isShowTextToSpeech + appId={appDetail?.id} + varList={varList} + siteInfo={null} />
- :
- {/* Put the scroll bar always on the bottom */} - {t('appLog.detail.loading')}...
} - // endMessage={
Nothing more to show
} - // below props only if you need pull down functionality - refreshFunction={fetchData} - pullDownToRefresh - pullDownToRefreshThreshold={50} - // pullDownToRefreshContent={ - //
Pull down to refresh
- // } - // releaseToRefreshContent={ - //
Release to refresh
- // } - // To put endMessage and loader to the top. - style={{ display: 'flex', flexDirection: 'column-reverse' }} - inverse={true} - > + : threadChatItems.length < 8 + ?
- -
- } +
+ :
+ {/* Put the scroll bar always on the bottom */} + {t('appLog.detail.loading')}...
} + // endMessage={
Nothing more to show
} + // below props only if you need pull down functionality + refreshFunction={fetchData} + pullDownToRefresh + pullDownToRefreshThreshold={50} + // pullDownToRefreshContent={ + //
Pull down to refresh
+ // } + // releaseToRefreshContent={ + //
Release to refresh
+ // } + // To put endMessage and loader to the top. + style={{ display: 'flex', flexDirection: 'column-reverse' }} + inverse={true} + > + + +
+ } +
{showMessageLogModal && ( = ({ logs, appDetail, onRefresh }) onClose={onCloseDrawer} mask={isMobile} footer={null} - panelClassname='mt-16 mx-2 sm:mr-2 mb-4 !p-0 !max-w-[640px] rounded-xl bg-background-gradient-bg-fill-chat-bg-1' + panelClassname='mt-16 mx-2 sm:mr-2 mb-4 !p-0 !max-w-[640px] rounded-xl bg-components-panel-bg' > = ({ + model, +}) => { + const { t } = useTranslation() + const modelName = model.name + const provideName = model.provider as any + const { + currentModel, + currentProvider, + } = useTextGenerationCurrentProviderAndModelAndModelList( + { provider: provideName, model: modelName }, + ) + + const [open, setOpen] = React.useState(false) + + const getParamValue = (param: string) => { + const value = model.completion_params?.[param] || '-' + if (param === 'stop') { + if (Array.isArray(value)) + return value.join(',') + else + return '-' + } + + return value + } + + return ( +
+
+ + +
+ +
+ setOpen(v => !v)} + className='block' + > +
+ +
+
+ +
+
{t('appLog.detail.modelParams')}
+
+ {['temperature', 'top_p', 'presence_penalty', 'max_tokens', 'stop'].map((param: string, index: number) => { + return
+ {PARAM_MAP[param as keyof typeof PARAM_MAP]} + {getParamValue(param)} +
+ })} +
+
+
+
+
+
+ ) +} +export default React.memo(ModelInfo) diff --git a/web/app/components/app/log/var-panel.tsx b/web/app/components/app/log/var-panel.tsx index a22856339e5d31..3ae4bfb5c63a58 100644 --- a/web/app/components/app/log/var-panel.tsx +++ b/web/app/components/app/log/var-panel.tsx @@ -7,7 +7,9 @@ import { RiArrowDownSLine, RiArrowRightSLine, } from '@remixicon/react' +import { Variable02 } from '@/app/components/base/icons/src/vender/solid/development' import ImagePreview from '@/app/components/base/image-uploader/image-preview' +import cn from '@/utils/classnames' type Props = { varList: { label: string; value: string }[] @@ -23,34 +25,35 @@ const VarPanel: FC = ({ const [imagePreviewUrl, setImagePreviewUrl] = useState('') return ( -
+
+ +
{t('appLog.detail.variables')}
{ isCollapse - ? - : + ? + : } -
{t('appLog.detail.variables')}
{!isCollapse && ( -
+
{varList.map(({ label, value }, index) => ( -
-
+
+
{'{{'} {label} {'}}'}
-
{value}
+
{value}
))} {message_files.length > 0 && (
-
{t('appLog.detail.uploadImages')}
+
{t('appLog.detail.uploadImages')}
{message_files.map((url, index) => (
= ({ imagePreviewUrl && ( setImagePreviewUrl('')} /> ) diff --git a/web/app/components/app/text-generate/item/index.tsx b/web/app/components/app/text-generate/item/index.tsx index 0c4f62282ef579..ac868e6ee3c745 100644 --- a/web/app/components/app/text-generate/item/index.tsx +++ b/web/app/components/app/text-generate/item/index.tsx @@ -282,7 +282,7 @@ const GenerationItem: FC = ({ const [currentTab, setCurrentTab] = useState('DETAIL') return ( -
= ({
{ !responding && ( @@ -212,15 +212,15 @@ const Answer: FC = ({ disabled={!item.prevSibling} onClick={() => item.prevSibling && switchSibling?.(item.prevSibling)} > - + - {item.siblingIndex + 1} / {item.siblingCount} + {item.siblingIndex + 1} / {item.siblingCount}
}
diff --git a/web/app/components/base/copy-icon/index.tsx b/web/app/components/base/copy-icon/index.tsx index 425a9ad293b284..9f886a1f320eaa 100644 --- a/web/app/components/base/copy-icon/index.tsx +++ b/web/app/components/base/copy-icon/index.tsx @@ -39,10 +39,10 @@ export const CopyIcon = ({ content }: Props) => {
{!isCopied ? ( - + ) : ( - + ) }
diff --git a/web/app/components/base/drawer/index.tsx b/web/app/components/base/drawer/index.tsx index c2285b5c53ff14..d9df7cc0537108 100644 --- a/web/app/components/base/drawer/index.tsx +++ b/web/app/components/base/drawer/index.tsx @@ -49,7 +49,7 @@ export default function Drawer({ -
+
<> {title && = ({ return (
!isActive && onClick(option.value)} > -
{option.text}
+
{option.text}
{isActive && ( -
+
)}
) @@ -52,7 +56,7 @@ const TabSlider: FC = ({ itemClassName, }) => { return ( -
+
{options.map(option => ( = ({ > {popupContent && (
triggerMethod === 'hover' && setHoverPopup()} diff --git a/web/app/components/header/account-setting/model-provider-page/model-badge/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-badge/index.tsx index 78502785dec3f1..d272e96779b504 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-badge/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-badge/index.tsx @@ -11,7 +11,7 @@ const ModelBadge: FC = ({ }) => { return (
{children} diff --git a/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx b/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx index c5b7e8395c6d30..379a9f41cae4f4 100644 --- a/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx +++ b/web/app/components/header/account-setting/model-provider-page/model-name/index.tsx @@ -7,7 +7,7 @@ import { useLanguage } from '../hooks' import type { ModelItem } from '../declarations' import ModelBadge from '../model-badge' import FeatureIcon from '../model-selector/feature-icon' -import classNames from '@/utils/classnames' +import cn from '@/utils/classnames' type ModelNameProps = PropsWithChildren<{ modelItem: ModelItem @@ -37,12 +37,7 @@ const ModelName: FC = ({ if (!modelItem) return null return ( -
+
= ({
{ showModelType && modelItem.model_type && ( - + {modelTypeFormat(modelItem.model_type)} ) } { modelItem.model_properties.mode && showMode && ( - + {(modelItem.model_properties.mode as string).toLocaleUpperCase()} ) diff --git a/web/app/components/header/tools-nav/index.tsx b/web/app/components/header/tools-nav/index.tsx index 096a5522290f9d..81e2f48fa4b05e 100644 --- a/web/app/components/header/tools-nav/index.tsx +++ b/web/app/components/header/tools-nav/index.tsx @@ -21,9 +21,10 @@ const ToolsNav = ({ return ( { activated diff --git a/web/app/components/workflow/nodes/_base/components/editor/base.tsx b/web/app/components/workflow/nodes/_base/components/editor/base.tsx index 18ec5ea4a354e3..f1ffe556d143d0 100644 --- a/web/app/components/workflow/nodes/_base/components/editor/base.tsx +++ b/web/app/components/workflow/nodes/_base/components/editor/base.tsx @@ -73,9 +73,9 @@ const Base: FC = ({ return ( -
+
-
{title}
+
{title}
{ e.nativeEvent.stopImmediatePropagation() e.stopPropagation() @@ -88,10 +88,10 @@ const Base: FC = ({ )} {!isCopied ? ( - + ) : ( - + ) } diff --git a/web/i18n/en-US/app-log.ts b/web/i18n/en-US/app-log.ts index 587c305e8da26b..0d12340507b09d 100644 --- a/web/i18n/en-US/app-log.ts +++ b/web/i18n/en-US/app-log.ts @@ -52,6 +52,7 @@ const translation = { }, variables: 'Variables', uploadImages: 'Uploaded Images', + modelParams: 'Model parameters', }, filter: { period: { diff --git a/web/i18n/zh-Hans/app-log.ts b/web/i18n/zh-Hans/app-log.ts index 52b93d378ce88d..8c7ad62b4ff4fb 100644 --- a/web/i18n/zh-Hans/app-log.ts +++ b/web/i18n/zh-Hans/app-log.ts @@ -52,6 +52,7 @@ const translation = { }, variables: '变量', uploadImages: '上传的图片', + modelParams: '模型参数', }, filter: { period: { From 6f4e900c5f179b4cb41d5c767402871106ffb859 Mon Sep 17 00:00:00 2001 From: JzoNg Date: Wed, 11 Dec 2024 18:21:21 +0800 Subject: [PATCH 2/2] feat: dark mode for annotaions --- .../add-annotation-modal/edit-item/index.tsx | 6 +-- .../annotation/add-annotation-modal/index.tsx | 5 +- .../csv-downloader.tsx | 16 +++---- .../csv-uploader.tsx | 18 +++---- .../batch-add-annotation-modal/index.tsx | 7 ++- .../edit-annotation-modal/edit-item/index.tsx | 26 +++++----- .../edit-annotation-modal/index.tsx | 2 +- .../app/annotation/header-opts/index.tsx | 45 ++++++++--------- .../annotation/header-opts/style.module.css | 38 --------------- web/app/components/app/annotation/index.tsx | 29 +++++------ web/app/components/app/annotation/list.tsx | 26 ++++------ .../hit-history-no-data.tsx | 8 ++-- .../view-annotation-modal/index.tsx | 48 ++++++++++--------- .../view-annotation-modal/style.module.css | 9 ---- .../components/base/checkbox/assets/check.svg | 3 -- .../components/base/checkbox/index.module.css | 14 ------ web/app/components/base/checkbox/index.tsx | 28 ++++++++--- web/app/components/base/drawer-plus/index.tsx | 10 ++-- .../annotation-reply/config-param-modal.tsx | 4 +- .../annotation-reply/config-param.tsx | 6 +-- .../score-slider/base-slider/index.tsx | 2 +- .../annotation-reply/score-slider/index.tsx | 6 +-- web/app/components/base/modal/index.css | 2 +- web/app/components/base/modal/index.tsx | 12 ++--- web/app/components/base/popover/index.tsx | 17 ++++--- .../components/base/popover/style.module.css | 9 ---- 26 files changed, 158 insertions(+), 238 deletions(-) delete mode 100644 web/app/components/app/annotation/header-opts/style.module.css delete mode 100644 web/app/components/app/annotation/view-annotation-modal/style.module.css delete mode 100644 web/app/components/base/checkbox/assets/check.svg delete mode 100644 web/app/components/base/checkbox/index.module.css delete mode 100644 web/app/components/base/popover/style.module.css diff --git a/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx b/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx index 4da6b7cac4d0b4..032e4b83576adf 100644 --- a/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx +++ b/web/app/components/app/annotation/add-annotation-modal/edit-item/index.tsx @@ -2,7 +2,7 @@ import type { FC } from 'react' import React from 'react' import { useTranslation } from 'react-i18next' -import Textarea from 'rc-textarea' +import Textarea from '@/app/components/base/textarea' import { Robot, User } from '@/app/components/base/icons/src/public/avatar' export enum EditItemType { @@ -31,12 +31,10 @@ const EditItem: FC = ({ {avatar}
-
{name}
+
{name}