feat: annotation management frontend (#1764)

This commit is contained in:
Joel
2023-12-18 15:41:24 +08:00
committed by GitHub
parent 96d2de2258
commit 65fd4b39ce
122 changed files with 4718 additions and 214 deletions

View File

@@ -15,7 +15,7 @@ import s from './style.module.css'
import Loading from '@/app/components/base/loading'
import { fetchChatConversations, fetchCompletionConversations } from '@/service/log'
import { fetchAppDetail } from '@/service/apps'
import { APP_PAGE_LIMIT } from '@/config'
export type ILogsProps = {
appId: string
}
@@ -26,9 +26,6 @@ export type QueryParam = {
keyword?: string
}
// Custom page count is not currently supported.
const limit = 10
const ThreeDotsIcon = ({ className }: SVGProps<SVGElement>) => {
return <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg" className={className ?? ''}>
<path d="M5 6.5V5M8.93934 7.56066L10 6.5M10.0103 11.5H11.5103" stroke="#374151" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
@@ -60,7 +57,7 @@ const Logs: FC<ILogsProps> = ({ appId }) => {
const query = {
page: currPage + 1,
limit,
limit: APP_PAGE_LIMIT,
...(queryParams.period !== 'all'
? {
start: dayjs().subtract(queryParams.period as number, 'day').startOf('day').format('YYYY-MM-DD HH:mm'),
@@ -93,11 +90,8 @@ const Logs: FC<ILogsProps> = ({ appId }) => {
return (
<div className='flex flex-col h-full'>
<div className='flex flex-col justify-center px-6 pt-4'>
<h1 className='flex text-xl font-medium text-gray-900'>{t('appLog.title')}</h1>
<p className='flex text-sm font-normal text-gray-500'>{t('appLog.description')}</p>
</div>
<div className='flex flex-col px-6 py-4 flex-1'>
<p className='flex text-sm font-normal text-gray-500'>{t('appLog.description')}</p>
<div className='flex flex-col py-4 flex-1'>
<Filter appId={appId} queryParams={queryParams} setQueryParams={setQueryParams} />
{total === undefined
? <Loading type='app' />
@@ -106,14 +100,14 @@ const Logs: FC<ILogsProps> = ({ appId }) => {
: <EmptyElement appUrl={`${appDetail?.site.app_base_url}/${appDetail?.mode}/${appDetail?.site.access_token}`} />
}
{/* Show Pagination only if the total is more than the limit */}
{(total && total > limit)
{(total && total > APP_PAGE_LIMIT)
? <Pagination
className="flex items-center w-full h-10 text-sm select-none mt-8"
currentPage={currPage}
edgePageCount={2}
middlePagesSiblingCount={1}
setCurrentPage={setCurrPage}
totalPages={Math.ceil(total / limit)}
totalPages={Math.ceil(total / APP_PAGE_LIMIT)}
truncableClassName="w-8 px-0.5 text-center"
truncableText="..."
>
@@ -131,8 +125,8 @@ const Logs: FC<ILogsProps> = ({ appId }) => {
/>
</div>
<Pagination.NextButton
disabled={currPage === Math.ceil(total / limit) - 1}
className={`flex items-center mr-2 text-gray-500 focus:outline-none ${currPage === Math.ceil(total / limit) - 1 ? 'cursor-not-allowed opacity-50' : 'cursor-pointer hover:text-gray-600 dark:hover:text-gray-200'}`} >
disabled={currPage === Math.ceil(total / APP_PAGE_LIMIT) - 1}
className={`flex items-center mr-2 text-gray-500 focus:outline-none ${currPage === Math.ceil(total / APP_PAGE_LIMIT) - 1 ? 'cursor-not-allowed opacity-50' : 'cursor-pointer hover:text-gray-600 dark:hover:text-gray-200'}`} >
{t('appLog.table.pagination.next')}
<ArrowRightIcon className="ml-3 h-3 w-3" />
</Pagination.NextButton>

View File

@@ -34,6 +34,7 @@ import ModelIcon from '@/app/components/app/configuration/config-model/model-ico
import ModelName from '@/app/components/app/configuration/config-model/model-name'
import ModelModeTypeLabel from '@/app/components/app/configuration/config-model/model-mode-type-label'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import TextGeneration from '@/app/components/app/text-generate/item'
type IConversationList = {
logs?: ChatConversationsResponse | CompletionConversationsResponse
@@ -83,7 +84,6 @@ const getFormattedChatList = (messages: ChatMessage[]) => {
log: item.message as any,
message_files: item.message_files,
})
newChatList.push({
id: item.id,
content: item.answer,
@@ -96,7 +96,26 @@ const getFormattedChatList = (messages: ChatMessage[]) => {
tokens: item.answer_tokens + item.message_tokens,
latency: item.provider_response_latency.toFixed(2),
},
annotation: item.annotation,
annotation: (() => {
if (item.annotation_hit_history) {
return {
id: item.annotation_hit_history.annotation_id,
authorName: item.annotation_hit_history.annotation_create_account.name,
created_at: item.annotation_hit_history.created_at,
}
}
if (item.annotation) {
return {
id: '',
authorName: '',
logAnnotation: item.annotation,
created_at: 0,
}
}
return undefined
})(),
})
})
return newChatList
@@ -253,14 +272,26 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
)}
{!isChatMode
? <div className="px-2.5 py-4">
<Chat
chatList={getFormattedChatList([detail.message])}
isHideSendInput={true}
onFeedback={onFeedback}
onSubmitAnnotation={onSubmitAnnotation}
displayScene='console'
isShowPromptLog
? <div className="px-6 py-4">
<div className='flex h-[18px] items-center space-x-3'>
<div className='leading-[18px] text-xs font-semibold text-gray-500 uppercase'>{t('appLog.table.header.output')}</div>
<div className='grow h-[1px]' style={{
background: 'linear-gradient(270deg, rgba(243, 244, 246, 0) 0%, rgb(243, 244, 246) 100%)',
}}></div>
</div>
<TextGeneration
className='mt-2'
content={detail.message.answer}
messageId={detail.message.id}
isError={false}
onRetry={() => { }}
isInstalledApp={false}
supportFeedback
feedback={detail.message.feedbacks.find((item: any) => item.from_source === 'admin')}
onFeedback={feedback => onFeedback(detail.message.id, feedback)}
supportAnnotation
appId={appDetail?.id}
varList={varList}
/>
</div>
: items.length < 8
@@ -269,9 +300,11 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
chatList={items}
isHideSendInput={true}
onFeedback={onFeedback}
onSubmitAnnotation={onSubmitAnnotation}
displayScene='console'
isShowPromptLog
supportAnnotation
appId={appDetail?.id}
onChatListChange={setItems}
/>
</div>
: <div
@@ -309,7 +342,6 @@ function DetailPanel<T extends ChatConversationFullDetailResponse | CompletionCo
chatList={items}
isHideSendInput={true}
onFeedback={onFeedback}
onSubmitAnnotation={onSubmitAnnotation}
displayScene='console'
isShowPromptLog
/>
@@ -427,7 +459,7 @@ const ConversationList: FC<IConversationList> = ({ logs, appDetail, onRefresh })
<Tooltip
htmlContent={
<span className='text-xs text-gray-500 inline-flex items-center'>
<EditIconSolid className='mr-1' />{`${t('appLog.detail.annotationTip', { user: annotation?.account?.name })} ${dayjs.unix(annotation?.created_at || dayjs().unix()).format('MM-DD hh:mm A')}`}
<EditIconSolid className='mr-1' />{`${t('appLog.detail.annotationTip', { user: annotation?.logAnnotation?.account?.name })} ${dayjs.unix(annotation?.created_at || dayjs().unix()).format('MM-DD hh:mm A')}`}
</span>
}
className={(isHighlight && !isChatMode) ? '' : '!hidden'}