diff --git a/datacenter/app/agents/[agentId]/page.tsx b/datacenter/app/agents/[agentId]/page.tsx index 113bbb6a7..7409f4c75 100644 --- a/datacenter/app/agents/[agentId]/page.tsx +++ b/datacenter/app/agents/[agentId]/page.tsx @@ -11,14 +11,27 @@ const AgentPage = (props) => { ready: !!props.params?.agentId }); - const { handleChatSubmit, history } = useAgentChat({ - queryAgentURL: `/v1/chat/completions`, - queryBody: {} + const { history, handleChatSubmit } = useAgentChat({ + queryAgentURL: `http://30.183.154.8:5000/v1/chat/completions`, + queryBody: { + conv_uid: props.params?.agentId, + chat_mode: 'chat_normal' + }, + initHistory: historyList?.data }); return (
- + { + const searchParams = new URLSearchParams(window.location.search); + searchParams.delete('initMessage'); + window.history.replaceState(null, null, `?${searchParams.toString()}`); + }} + messages={history || []} + onSubmit={handleChatSubmit} + />
) } diff --git a/datacenter/app/datastores/documents/chunklist/page.tsx b/datacenter/app/datastores/documents/chunklist/page.tsx index ca17030e9..f25a42edd 100644 --- a/datacenter/app/datastores/documents/chunklist/page.tsx +++ b/datacenter/app/datastores/documents/chunklist/page.tsx @@ -2,12 +2,15 @@ import { useSearchParams } from 'next/navigation' import React, { useState, useEffect } from 'react' -import { Table } from '@/lib/mui' -import { Popover } from 'antd' +import { Table, Stack } from '@/lib/mui' +import { Popover, Pagination } from 'antd' +const page_size = 20; const ChunkList = () => { const spaceName = useSearchParams().get('spacename') const documentId = useSearchParams().get('documentid') + const [total, setTotal] = useState(0); + const [current, setCurrent] = useState(0); const [chunkList, setChunkList] = useState([]) useEffect(() => { async function fetchChunks() { @@ -19,13 +22,17 @@ const ChunkList = () => { 'Content-Type': 'application/json' }, body: JSON.stringify({ - document_id: documentId + document_id: documentId, + page: 1, + page_size }) } ) const data = await res.json() if (data.success) { - setChunkList(data.data) + setChunkList(data.data.data) + setTotal(data.data.total); + setCurrent(data.data.page); } } fetchChunks() @@ -69,6 +76,30 @@ const ChunkList = () => { ))} + + { + const res = await fetch( + `http://localhost:8000/knowledge/${spaceName}/chunk/list`, + { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + document_id: documentId, + page, + page_size + }) + } + ) + const data = await res.json() + if (data.success) { + setChunkList(data.data.data) + setTotal(data.data.total); + setCurrent(data.data.page); + } + }} hideOnSinglePage /> + ) } diff --git a/datacenter/app/datastores/documents/page.tsx b/datacenter/app/datastores/documents/page.tsx index 9b9393350..e5c8575dd 100644 --- a/datacenter/app/datastores/documents/page.tsx +++ b/datacenter/app/datastores/documents/page.tsx @@ -267,7 +267,6 @@ const Documents = () => { onChange={(e: any) => setDocumentName(e.target.value)} sx={{ marginBottom: '20px' }} /> - Web Page URL: {documentType === 'webPage' ? ( <> Web Page URL: @@ -297,9 +296,9 @@ const Documents = () => { ) : ( <> - Source: + Text Source(Optional): setTextSource(e.target.value)} sx={{ marginBottom: '20px' }} /> @@ -396,10 +395,6 @@ const Documents = () => { message.error(data.err_msg || 'failed') } } else { - if (textSource === '') { - message.error('Please input the source') - return - } if (text === '') { message.error('Please input the text') return diff --git a/datacenter/app/datastores/page.tsx b/datacenter/app/datastores/page.tsx index ec13378d3..f99e138f8 100644 --- a/datacenter/app/datastores/page.tsx +++ b/datacenter/app/datastores/page.tsx @@ -308,9 +308,9 @@ const Index = () => { ) : ( <> - Source: + Text Source(Optional): setTextSource(e.target.value)} sx={{ marginBottom: '20px' }} /> @@ -379,10 +379,6 @@ const Index = () => { message.error(data.err_msg || 'failed') } } else { - if (textSource === '') { - message.error('Please input the source') - return - } if (text === '') { message.error('Please input the text') return diff --git a/datacenter/app/globals.css b/datacenter/app/globals.css index 04a5d0afa..ae7bc662f 100644 --- a/datacenter/app/globals.css +++ b/datacenter/app/globals.css @@ -10,4 +10,21 @@ body { font-size: var(--joy-fontSize-md, 1rem); line-height: var(--joy-lineHeight-md, 1.5); background-color: var(--joy-palette-background-body); +} + +.ant-pagination .ant-pagination-prev * { + color: rgb(145, 35, 167) !important; +} + +.ant-pagination .ant-pagination-next * { + color: rgb(145, 35, 167) !important; +} + +.ant-pagination .ant-pagination-item { + border-color: rgb(145, 35, 167) !important; + background-color: rgb(145, 35, 167) !important; +} + +.ant-pagination .ant-pagination-item.ant-pagination-item-active a { + color: white !important; } \ No newline at end of file diff --git a/datacenter/app/layout.tsx b/datacenter/app/layout.tsx index 6cfbbdf7c..38d9a8293 100644 --- a/datacenter/app/layout.tsx +++ b/datacenter/app/layout.tsx @@ -5,12 +5,12 @@ import LeftSider from '@/components/leftSider'; import { CssVarsProvider, ThemeProvider } from '@mui/joy/styles'; import { joyTheme } from './defaultTheme'; import TopProgressBar from '@/components/topProgressBar'; - -export default function RootLayout({ +function RootLayout({ children, }: { children: React.ReactNode }) { + return ( @@ -31,3 +31,5 @@ export default function RootLayout({ ) } + +export default RootLayout; \ No newline at end of file diff --git a/datacenter/app/page.tsx b/datacenter/app/page.tsx index 9883b43a2..599478426 100644 --- a/datacenter/app/page.tsx +++ b/datacenter/app/page.tsx @@ -28,8 +28,7 @@ export default function Home() { chat_mode: 'chat_normal' }); if (res?.success && res?.data?.conv_uid) { - // router.push(`/agents/${res?.data?.conv_uid}?newMessage=${query}`); - // await refreshDialogList(); + router.push(`/agents/${res?.data?.conv_uid}?initMessage=${query}`); } } catch (err) { } finally { diff --git a/datacenter/components/chatBox.tsx b/datacenter/components/chatBox.tsx index c7a6619cd..877ed7977 100644 --- a/datacenter/components/chatBox.tsx +++ b/datacenter/components/chatBox.tsx @@ -17,8 +17,9 @@ type Props = { messages: Message[]; onSubmit: (message: string) => Promise; messageTemplates?: string[]; - initialMessage?: Message; + initialMessage?: string; readOnly?: boolean; + clearIntialMessage?: () => void; }; const Schema = z.object({ query: z.string().min(1) }); @@ -29,6 +30,7 @@ const ChatBoxComp = ({ messageTemplates, initialMessage, readOnly, + clearIntialMessage }: Props) => { const scrollableRef = React.useRef(null); const [isLoading, setIsLoading] = useState(false); @@ -52,6 +54,11 @@ const ChatBoxComp = ({ } }; + const handleInitMessage = async () => { + await submit({ query: (initialMessage as string) }); + clearIntialMessage?.(); + } + React.useEffect(() => { if (!scrollableRef.current) { return; @@ -61,11 +68,9 @@ const ChatBoxComp = ({ }, [messages?.length]); React.useEffect(() => { - setTimeout(() => { - setFirstMsg( - initialMessage ? initialMessage : undefined - ); - }, 0); + if (initialMessage && messages.length <= 0) { + handleInitMessage(); + } }, [initialMessage]); return ( @@ -116,7 +121,7 @@ const ChatBoxComp = ({ )} - {messages.map((each, index) => ( + {messages.filter(item => ['ai', 'human'].includes(item.role)).map((each, index) => ( { const pathname = usePathname(); const { mode, setMode } = useColorScheme(); - const [chatSelect, setChatSelect] = useState(); const { dialogueList } = useQueryDialog(); const menus = useMemo(() => { return [{ - label: 'Home', - icon: , - route: '/', - active: pathname === '/', - }, { label: 'Agents', icon: , route: '/agents', @@ -53,7 +46,7 @@ const LeftSider = () => { New Chat - + @@ -99,7 +92,9 @@ const LeftSider = () => { px: 2 }} > - + + + { '& .JoyListItemButton-root': { p: '8px' }, }} > - {dialogueList?.data?.map((each) => ( - - { - setChatSelect(each.conv_uid); - }} - > - - - - {each?.user_name || each?.user_input || 'undefined'} - - - - - - - ))} + {dialogueList?.data?.map((each) => { + const isSelect = pathname === `/agents/${each.conv_uid}`; + return ( + + + + + + {each?.user_name || each?.user_input || 'undefined'} + + + + + + ) + })} @@ -178,7 +172,6 @@ const LeftSider = () => { color="neutral" selected={each.active} variant={each.active ? 'soft' : 'plain'} - onClick={() => { setChatSelect(undefined); }} > { const [state, setState] = useStateReducer({ - history: [{ - role: 'human', - context: 'hello', - }, { - role: 'agent', - context: 'Hello! How can I assist you today?', - }] as { role: 'human' | 'agent'; context: string; id?: string }[], + history: (initHistory || []) as { role: 'human' | 'ai'; context: string; id?: string }[], }); - - const { visitorId } = useVisitorId(); - + + useEffect(() => { + if (initHistory) setState({ history: initHistory }); + }, [initHistory]); + const handleChatSubmit = async (context: string) => { if (!context) { return; @@ -50,9 +46,6 @@ import { const ctrl = new AbortController(); let buffer = ''; - class RetriableError extends Error {} - class FatalError extends Error {} - await fetchEventSource(queryAgentURL, { method: 'POST', headers: { @@ -60,9 +53,7 @@ import { }, body: JSON.stringify({ ...queryBody, - streaming: true, - query: context, - visitorId: visitorId, + user_input: context, channel, }), signal: ctrl.signal, @@ -79,64 +70,59 @@ import { response.status !== 429 ) { if (response.status === 402) { - throw new ApiError(ApiErrorType.USAGE_LIMIT); + //throw new ApiError(ApiErrorType.USAGE_LIMIT); } - throw new FatalError(); + // client-side errors are usually non-retriable: + //throw new FatalError(); } else { - throw new RetriableError(); + //throw new RetriableError(); } }, onclose() { - throw new RetriableError(); + // if the server closes the connection unexpectedly, retry: + console.log('onclose'); + //throw new RetriableError(); }, onerror(err) { throw new Error(err); - // if (err instanceof FatalError) { - // ctrl.abort(); - // throw new Error(); // rethrow to stop the operation - // } else if (err instanceof ApiError) { - // console.log('ApiError', ApiError); - // throw new Error(); - // } else { - // throw new Error(err); - // } }, onmessage: (event) => { + event.data = event.data.replaceAll('\\n', '\n'); console.log(event, 'event'); if (event.data === '[DONE]') { ctrl.abort(); } else if (event.data?.startsWith('[ERROR]')) { ctrl.abort(); - setState({ history: [ ...history, { - role: 'agent', + role: 'ai', context: event.data.replace('[ERROR]', ''), } as any, ], }); } else { - buffer += decodeURIComponent(event.data) as string; const h = [...history]; - if (h?.[nextIndex]) { - h[nextIndex].context = `${buffer}`; - } else { - h.push({ role: 'agent', context: buffer }); + if (event.data) { + if (h?.[nextIndex]) { + h[nextIndex].context = `${event.data}`; + } else { + h.push({ role: 'ai', context: event.data }); + } + setState({ + history: h as any, + }); } - setState({ - history: h as any, - }); + } }, }); } catch (err) { - console.log('err', err); setState({ history: [ ...history, - { role: 'agent', context: answer || '请求出错' as string }, + { role: 'ai', context: answer || '请求出错' as string }, ] as any, }); // if (err instanceof ApiError) { @@ -156,13 +142,12 @@ import { // setState({ // history: [ // ...history, - // { from: 'agent', message: answer as string }, + // { from: 'ai', message: answer as string }, // ] as any, // }); // } } }; - return { handleChatSubmit, history: state.history, diff --git a/datacenter/hooks/useNewChat.ts b/datacenter/hooks/useNewChat.ts new file mode 100644 index 000000000..9e38c1a94 --- /dev/null +++ b/datacenter/hooks/useNewChat.ts @@ -0,0 +1,10 @@ +import { useState } from 'react'; + +export const useNewChat = () => { + const [message, setMessage] = useState("hello"); + + return { + message, + setMessage + }; +} \ No newline at end of file diff --git a/datacenter/utils/request.ts b/datacenter/utils/request.ts index 25e327ca6..008f58c57 100644 --- a/datacenter/utils/request.ts +++ b/datacenter/utils/request.ts @@ -1,7 +1,7 @@ import axios from 'axios'; import { isPlainObject } from 'lodash'; -axios.defaults.baseURL = 'http://30.183.153.244:5000'; +axios.defaults.baseURL = 'http://30.183.154.8:5000'; axios.defaults.timeout = 10000;