diff --git a/datacenter/app/agents/[agentId]/page.tsx b/datacenter/app/agents/[agentId]/page.tsx index 7409f4c75..61a99ee10 100644 --- a/datacenter/app/agents/[agentId]/page.tsx +++ b/datacenter/app/agents/[agentId]/page.tsx @@ -1,36 +1,42 @@ "use client" import { useRequest } from 'ahooks'; -import { sendGetRequest } from '@/utils/request'; +import { sendGetRequest, sendPostRequest } from '@/utils/request'; import useAgentChat from '@/hooks/useAgentChat'; import ChatBoxComp from '@/components/chatBox'; +import { useDialogueContext } from '@/app/context/dialogue'; const AgentPage = (props) => { + const { refreshDialogList } = useDialogueContext(); + const { data: historyList } = useRequest(async () => await sendGetRequest('/v1/chat/dialogue/messages/history', { con_uid: props.params?.agentId }), { ready: !!props.params?.agentId }); + const { data: paramsList } = useRequest(async () => await sendPostRequest(`/v1/chat/mode/params/list?chat_mode=${props.searchParams?.scene}`), { + ready: !!props.searchParams?.scene + }); + const { history, handleChatSubmit } = useAgentChat({ queryAgentURL: `http://30.183.154.8:5000/v1/chat/completions`, queryBody: { conv_uid: props.params?.agentId, - chat_mode: 'chat_normal' + chat_mode: props.searchParams?.scene || 'chat_normal', }, initHistory: historyList?.data }); return ( -
+
{ - const searchParams = new URLSearchParams(window.location.search); - searchParams.delete('initMessage'); - window.history.replaceState(null, null, `?${searchParams.toString()}`); + clearIntialMessage={async () => { + await refreshDialogList(); }} messages={history || []} onSubmit={handleChatSubmit} + paramsList={paramsList?.data} />
) diff --git a/datacenter/app/agents/page.tsx b/datacenter/app/agents/page.tsx index 9e1d252be..d808b340d 100644 --- a/datacenter/app/agents/page.tsx +++ b/datacenter/app/agents/page.tsx @@ -16,7 +16,7 @@ const Item = styled(Sheet)(({ theme }) => ({ const Agents = () => { const { handleChatSubmit, history } = useAgentChat({ - queryAgentURL: `/api/agents/query`, + queryAgentURL: `http://30.183.154.8:5000/v1/chat/completions`, }); const data = [ @@ -203,7 +203,7 @@ const Agents = () => { - +
diff --git a/datacenter/app/context/dialogue.tsx b/datacenter/app/context/dialogue.tsx new file mode 100644 index 000000000..208409aff --- /dev/null +++ b/datacenter/app/context/dialogue.tsx @@ -0,0 +1,35 @@ +import { useRequest } from 'ahooks'; +import { sendGetRequest } from '@/utils/request'; +import { createCtx } from '@/utils/ctx-helper'; +import { AxiosResponse } from 'axios'; +import React from 'react'; + +export const [useDialogueContext, DialogueProvider] = createCtx<{ + dialogueList?: void | AxiosResponse | undefined; + queryDialogueList: () => void; + refreshDialogList: () => void; +}>(); + +export default ({ children }: { + children: React.ReactElement +}) => { + const { + run: queryDialogueList, + data: dialogueList, + refresh: refreshDialogList, + } = useRequest(async () => await sendGetRequest('/v1/chat/dialogue/list'), { + manual: true, + }); + + return ( + + {children} + + ) +} \ No newline at end of file diff --git a/datacenter/app/datastores/constants.tsx b/datacenter/app/datastores/constants.tsx new file mode 100644 index 000000000..c5d7f8260 --- /dev/null +++ b/datacenter/app/datastores/constants.tsx @@ -0,0 +1 @@ +export const fetchBaseURL = 'http://30.183.154.125:5000'; diff --git a/datacenter/app/datastores/documents/chunklist/page.tsx b/datacenter/app/datastores/documents/chunklist/page.tsx index eb68e9296..0a3db6383 100644 --- a/datacenter/app/datastores/documents/chunklist/page.tsx +++ b/datacenter/app/datastores/documents/chunklist/page.tsx @@ -2,11 +2,13 @@ import { useSearchParams } from 'next/navigation' import React, { useState, useEffect } from 'react' -import { Table, Stack } from '@/lib/mui' +import { useColorScheme, Table, Stack } from '@/lib/mui' import { Popover, Pagination } from 'antd' +import { fetchBaseURL } from '@/app/datastores/constants' const page_size = 20 const ChunkList = () => { + const { mode } = useColorScheme() const spaceName = useSearchParams().get('spacename') const documentId = useSearchParams().get('documentid') const [total, setTotal] = useState(0) @@ -15,7 +17,7 @@ const ChunkList = () => { useEffect(() => { async function fetchChunks() { const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/chunk/list`, + `${fetchBaseURL}/knowledge/${spaceName}/chunk/list`, { method: 'POST', headers: { @@ -41,7 +43,20 @@ const ChunkList = () => {
{chunkList.length ? ( <> - +
@@ -78,9 +93,13 @@ const ChunkList = () => { ))}
Name
- + { total={total} onChange={async (page) => { const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/chunk/list`, + `${fetchBaseURL}/knowledge/${spaceName}/chunk/list`, { method: 'POST', headers: { diff --git a/datacenter/app/datastores/documents/page.tsx b/datacenter/app/datastores/documents/page.tsx index 8cb482b34..8e14b5d2c 100644 --- a/datacenter/app/datastores/documents/page.tsx +++ b/datacenter/app/datastores/documents/page.tsx @@ -3,6 +3,7 @@ import { useRouter, useSearchParams } from 'next/navigation' import React, { useState, useEffect } from 'react' import { + useColorScheme, Button, Table, Sheet, @@ -18,6 +19,7 @@ import moment from 'moment' import { InboxOutlined } from '@ant-design/icons' import type { UploadProps } from 'antd' import { Upload, Pagination, message } from 'antd' +import { fetchBaseURL } from '@/app/datastores/constants' const { Dragger } = Upload const Item = styled(Sheet)(({ theme }) => ({ @@ -48,14 +50,16 @@ const documentTypeList = [ { type: 'file', title: 'Document', - subTitle: 'Upload a document, document type can be PDF, CSV, Text, PowerPoint, Word, Markdown' + subTitle: + 'Upload a document, document type can be PDF, CSV, Text, PowerPoint, Word, Markdown' } ] -const page_size = 20; +const page_size = 20 const Documents = () => { const router = useRouter() const spaceName = useSearchParams().get('name') + const { mode } = useColorScheme() const [isAddDocumentModalShow, setIsAddDocumentModalShow] = useState(false) const [activeStep, setActiveStep] = useState(0) @@ -85,7 +89,7 @@ const Documents = () => { useEffect(() => { async function fetchDocuments() { const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/list`, + `${fetchBaseURL}/knowledge/${spaceName}/document/list`, { method: 'POST', headers: { @@ -123,7 +127,20 @@ const Documents = () => { {documents.length ? ( <> - +
@@ -138,11 +155,21 @@ const Documents = () => { {documents.map((row: any) => ( - - + +
Name
{row.doc_name}{row.doc_type}{row.chunk_size} + + {row.doc_type} + + {row.chunk_size} chunks {moment(row.last_sync).format('YYYY-MM-DD HH:MM:SS')} { size="sm" onClick={async () => { const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/sync`, + `${fetchBaseURL}/knowledge/${spaceName}/document/sync`, { method: 'POST', headers: { @@ -206,9 +233,13 @@ const Documents = () => { ))}
- + { total={total} onChange={async (page) => { const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/list`, + `${fetchBaseURL}/knowledge/${spaceName}/document/list`, { method: 'POST', headers: { @@ -369,7 +400,7 @@ const Documents = () => { return } const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/add`, + `${fetchBaseURL}/knowledge/${spaceName}/document/add`, { method: 'POST', headers: { @@ -387,7 +418,7 @@ const Documents = () => { message.success('success') setIsAddDocumentModalShow(false) const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/list`, + `${fetchBaseURL}/knowledge/${spaceName}/document/list`, { method: 'POST', headers: { @@ -401,7 +432,7 @@ const Documents = () => { ) const data = await res.json() if (data.success) { - setDocuments(data.data) + setDocuments(data.data.data) setTotal(data.data.total) setCurrent(data.data.page) } @@ -418,7 +449,7 @@ const Documents = () => { formData.append('doc_file', originFileObj) formData.append('doc_type', 'DOCUMENT') const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/upload`, + `${fetchBaseURL}/knowledge/${spaceName}/document/upload`, { method: 'POST', body: formData @@ -429,7 +460,7 @@ const Documents = () => { message.success('success') setIsAddDocumentModalShow(false) const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/list`, + `${fetchBaseURL}/knowledge/${spaceName}/document/list`, { method: 'POST', headers: { @@ -443,7 +474,7 @@ const Documents = () => { ) const data = await res.json() if (data.success) { - setDocuments(data.data) + setDocuments(data.data.data) setTotal(data.data.total) setCurrent(data.data.page) } @@ -456,7 +487,7 @@ const Documents = () => { return } const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/add`, + `${fetchBaseURL}/knowledge/${spaceName}/document/add`, { method: 'POST', headers: { @@ -475,7 +506,7 @@ const Documents = () => { message.success('success') setIsAddDocumentModalShow(false) const res = await fetch( - `http://30.183.154.125:5000/knowledge/${spaceName}/document/list`, + `${fetchBaseURL}/knowledge/${spaceName}/document/list`, { method: 'POST', headers: { @@ -489,7 +520,7 @@ const Documents = () => { ) const data = await res.json() if (data.success) { - setDocuments(data.data) + setDocuments(data.data.data) setTotal(data.data.total) setCurrent(data.data.page) } diff --git a/datacenter/app/datastores/page.tsx b/datacenter/app/datastores/page.tsx index 17d655a97..e66c39a1f 100644 --- a/datacenter/app/datastores/page.tsx +++ b/datacenter/app/datastores/page.tsx @@ -6,6 +6,7 @@ import { InboxOutlined } from '@ant-design/icons' import type { UploadProps } from 'antd' import { message, Upload } from 'antd' import { + useColorScheme, Modal, Button, Table, @@ -14,8 +15,10 @@ import { Box, Input, Textarea, + Chip, styled } from '@/lib/mui' +import { fetchBaseURL } from '@/app/datastores/constants' const { Dragger } = Upload @@ -49,12 +52,14 @@ const documentTypeList = [ { type: 'file', title: 'Document', - subTitle: 'Upload a document, document type can be PDF, CSV, Text, PowerPoint, Word, Markdown' + subTitle: + 'Upload a document, document type can be PDF, CSV, Text, PowerPoint, Word, Markdown' } ] const Index = () => { const router = useRouter() + const { mode } = useColorScheme() const [activeStep, setActiveStep] = useState(0) const [documentType, setDocumentType] = useState('') const [knowledgeSpaceList, setKnowledgeSpaceList] = useState([]) @@ -82,16 +87,13 @@ const Index = () => { } useEffect(() => { async function fetchData() { - const res = await fetch( - 'http://30.183.154.125:5000/knowledge/space/list', - { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({}) - } - ) + const res = await fetch(`${fetchBaseURL}/knowledge/space/list`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({}) + }) const data = await res.json() if (data.success) { setKnowledgeSpaceList(data.data) @@ -125,11 +127,24 @@ const Index = () => {
{knowledgeSpaceList.length ? ( - +
- + @@ -139,6 +154,7 @@ const Index = () => { - - + + ))} @@ -205,27 +237,24 @@ const Index = () => { message.error('please input the name') return } - const res = await fetch( - 'http://30.183.154.125:5000/knowledge/space/add', - { - method: 'POST', - headers: { - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - name: knowledgeSpaceName, - vector_type: 'Chroma', - owner: 'keting', - desc: 'test1' - }) - } - ) + const res = await fetch(`${fetchBaseURL}/knowledge/space/add`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + name: knowledgeSpaceName, + vector_type: 'Chroma', + owner: 'keting', + desc: 'test1' + }) + }) const data = await res.json() if (data.success) { message.success('success') setActiveStep(1) const res = await fetch( - 'http://30.183.154.125:5000/knowledge/space/list', + `${fetchBaseURL}/knowledge/space/list`, { method: 'POST', headers: { @@ -342,7 +371,7 @@ const Index = () => { return } const res = await fetch( - `http://30.183.154.125:5000/knowledge/${knowledgeSpaceName}/document/add`, + `${fetchBaseURL}/knowledge/${knowledgeSpaceName}/document/add`, { method: 'POST', headers: { @@ -372,7 +401,7 @@ const Index = () => { formData.append('doc_file', originFileObj) formData.append('doc_type', 'DOCUMENT') const res = await fetch( - `http://30.183.154.125:5000/knowledge/${knowledgeSpaceName}/document/upload`, + `${fetchBaseURL}/knowledge/${knowledgeSpaceName}/document/upload`, { method: 'POST', body: formData @@ -391,7 +420,7 @@ const Index = () => { return } const res = await fetch( - `http://30.183.154.125:5000/knowledge/${knowledgeSpaceName}/document/add`, + `${fetchBaseURL}/knowledge/${knowledgeSpaceName}/document/add`, { method: 'POST', headers: { diff --git a/datacenter/app/globals.css b/datacenter/app/globals.css index ae7bc662f..38471b71d 100644 --- a/datacenter/app/globals.css +++ b/datacenter/app/globals.css @@ -12,6 +12,31 @@ body { background-color: var(--joy-palette-background-body); } +table { + border-collapse: collapse; + width: 100%; +} + +th, td { + border: 1px solid #ddd; + text-align: left; + padding: 8px; +} + +th { + background-color: #f2f2f2; +} + +tr:nth-child(even) { + background-color: #f2f2f2; +} + +tr:hover { + background-color: #ddd; +} + +html body .ant-btn-primary { + background-color: #1677ff; .ant-pagination .ant-pagination-prev * { color: rgb(145, 35, 167) !important; } diff --git a/datacenter/app/layout.tsx b/datacenter/app/layout.tsx index 38d9a8293..35e2ac81d 100644 --- a/datacenter/app/layout.tsx +++ b/datacenter/app/layout.tsx @@ -5,18 +5,21 @@ import LeftSider from '@/components/leftSider'; import { CssVarsProvider, ThemeProvider } from '@mui/joy/styles'; import { joyTheme } from './defaultTheme'; import TopProgressBar from '@/components/topProgressBar'; +import DialogueContext from './context/dialogue'; + function RootLayout({ children, }: { children: React.ReactNode }) { - + return ( +
@@ -25,6 +28,7 @@ function RootLayout({
+
diff --git a/datacenter/app/page.tsx b/datacenter/app/page.tsx index 599478426..6c43b4e03 100644 --- a/datacenter/app/page.tsx +++ b/datacenter/app/page.tsx @@ -1,4 +1,5 @@ "use client"; +import { useRequest } from 'ahooks'; import { useState } from 'react'; import { Button, Input, useColorScheme } from '@/lib/mui'; import IconButton from '@mui/joy/IconButton'; @@ -8,7 +9,6 @@ import { useForm } from 'react-hook-form'; import { z } from 'zod'; import { sendPostRequest } from '@/utils/request'; import { useRouter } from 'next/navigation'; -import { useQueryDialog } from '@/hooks/useQueryDialogue'; export default function Home() { const Schema = z.object({ query: z.string().min(1) }); @@ -19,7 +19,8 @@ export default function Home() { resolver: zodResolver(Schema), defaultValues: {}, }); - const { refreshDialogList } = useQueryDialog(); + const { data: scenesList } = useRequest(async () => await sendPostRequest('v1/chat/dialogue/scenes')); + const submit = async ({ query }: z.infer) => { try { setIsLoading(true); @@ -50,11 +51,24 @@ export default function Home() {

Scenes

-
- - - - +
+ {scenesList?.data?.map(scene => ( + + ))}
diff --git a/datacenter/components/chatBox.tsx b/datacenter/components/chatBox.tsx index 877ed7977..682ec9e09 100644 --- a/datacenter/components/chatBox.tsx +++ b/datacenter/components/chatBox.tsx @@ -1,24 +1,21 @@ import { zodResolver } from '@hookform/resolvers/zod'; import SendRoundedIcon from '@mui/icons-material/SendRounded'; -import Button from '@mui/joy/Button'; -import Card from '@mui/joy/Card'; -import CircularProgress from '@mui/joy/CircularProgress'; -import IconButton from '@mui/joy/IconButton'; -import Input from '@mui/joy/Input'; -import Stack from '@mui/joy/Stack'; +import { Card, CircularProgress, IconButton, Input, Stack, Select, Option, Tooltip } from '@/lib/mui'; import React, { useState } from 'react'; import { useForm } from 'react-hook-form'; -import ReactMarkdown from 'react-markdown'; -import remarkGfm from 'remark-gfm'; import { z } from 'zod'; import { Message } from '@/types'; +import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'; +import Markdown from 'markdown-to-jsx'; +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { okaidia } from 'react-syntax-highlighter/dist/esm/styles/prism'; type Props = { messages: Message[]; - onSubmit: (message: string) => Promise; - messageTemplates?: string[]; + onSubmit: (message: string, otherQueryBody?: any) => Promise; initialMessage?: string; readOnly?: boolean; + paramsList?: { [key: string]: string }; clearIntialMessage?: () => void; }; @@ -27,15 +24,15 @@ const Schema = z.object({ query: z.string().min(1) }); const ChatBoxComp = ({ messages, onSubmit, - messageTemplates, initialMessage, readOnly, + paramsList, clearIntialMessage }: Props) => { const scrollableRef = React.useRef(null); const [isLoading, setIsLoading] = useState(false); const [firstMsg, setFirstMsg] = useState(); - const [hideTemplateMessages, setHideTemplateMessages] = useState(false); + const [currentParam, setCurrentParam] = useState(); const methods = useForm>({ resolver: zodResolver(Schema), @@ -45,9 +42,10 @@ const ChatBoxComp = ({ const submit = async ({ query }: z.infer) => { try { setIsLoading(true); - setHideTemplateMessages(true); methods.reset(); - await onSubmit(query); + await onSubmit(query, { + select_param: paramsList?.[currentParam] + }); } catch (err) { } finally { setIsLoading(false); @@ -55,10 +53,28 @@ const ChatBoxComp = ({ }; const handleInitMessage = async () => { - await submit({ query: (initialMessage as string) }); - clearIntialMessage?.(); + try { + const searchParams = new URLSearchParams(window.location.search); + searchParams.delete('initMessage'); + window.history.replaceState(null, null, `?${searchParams.toString()}`); + await submit({ query: (initialMessage as string) }); + } catch (err) { + console.log(err); + } finally { + clearIntialMessage?.(); + } } + const options = { + overrides: { + code: ({ children }) => ( + + {children} + + ), + }, + }; + React.useEffect(() => { if (!scrollableRef.current) { return; @@ -73,6 +89,12 @@ const ChatBoxComp = ({ } }, [initialMessage]); + React.useEffect(() => { + if (paramsList && Object.keys(paramsList || {})?.length > 0) { + setCurrentParam(Object.keys(paramsList || {})?.[0]); + } + }, [paramsList]); + return ( )} - {messages.filter(item => ['ai', 'human'].includes(item.role)).map((each, index) => ( + {messages.filter(item => ['view', 'human'].includes(item.role)).map((each, index) => ( @@ -133,9 +155,9 @@ const ChatBoxComp = ({ size="sm" variant={'outlined'} className={ - each.role === 'ai' ? 'message-agent' : 'message-human' + each.role === 'view' ? 'message-agent' : 'message-human' } - color={each.role === 'ai' ? 'primary' : 'neutral'} + color={each.role === 'view' ? 'primary' : 'neutral'} sx={(theme) => ({ px: 2, 'ol, ul': { @@ -157,9 +179,9 @@ const ChatBoxComp = ({ }, })} > - - {each.context} - + + {each.context?.replaceAll('\\n', '\n')} + ))} @@ -186,37 +208,41 @@ const ChatBoxComp = ({ justifyContent: 'center', marginLeft: 'auto', marginRight: 'auto', + flexDirection: 'column', + gap: '12px' }} onSubmit={(e) => { e.stopPropagation(); - methods.handleSubmit(submit)(e); }} > - {!hideTemplateMessages && (messageTemplates?.length || 0) > 0 && ( - - {messageTemplates?.map((each, idx) => ( - - ))} - + {(Object.keys(paramsList || {}).length > 0) && ( +
+ + + + +
)} { const pathname = usePathname(); + const router = useRouter(); + const { dialogueList, queryDialogueList, refreshDialogList } = useDialogueContext(); const { mode, setMode } = useColorScheme(); - const { dialogueList } = useQueryDialog(); const menus = useMemo(() => { return [{ @@ -33,6 +36,12 @@ const LeftSider = () => { } }; + useEffect(() => { + (async () => { + await queryDialogueList(); + })(); + }, []); + return ( <>
NameProviderVector Owner
{ router.push(`/datastores/documents?name=${row.name}`) @@ -148,8 +164,24 @@ const Index = () => { } {row.vector_type}{row.owner} + + {row.vector_type} + + + + {row.owner} + +