diff --git a/api/db/services/dialog_service.py b/api/db/services/dialog_service.py index 04e9c691b3..c1d90ebe4c 100644 --- a/api/db/services/dialog_service.py +++ b/api/db/services/dialog_service.py @@ -665,9 +665,9 @@ async def async_chat(dialog, messages, stream=True, **kwargs): while True: msg = await queue.get() if msg.find("") == 0: - yield {"answer": "", "reference": {}, "audio_binary": None, "final": False, "start_to_think": True} + yield {"answer": "", "reference": {}, "audio_binary": None, "final": False} elif msg.find("") == 0: - yield {"answer": "", "reference": {}, "audio_binary": None, "final": False, "end_to_think": True} + yield {"answer": "", "reference": {}, "audio_binary": None, "final": False} break else: yield {"answer": msg, "reference": {}, "audio_binary": None, "final": False} diff --git a/web/src/components/floating-chat-widget-markdown.tsx b/web/src/components/floating-chat-widget-markdown.tsx index bf828c4680..3a4e4942c6 100644 --- a/web/src/components/floating-chat-widget-markdown.tsx +++ b/web/src/components/floating-chat-widget-markdown.tsx @@ -10,6 +10,7 @@ import { currentReg, parseCitationIndex, preprocessLaTeX, + replaceRetrievingToSection, replaceTextByOldReg, replaceThinkToSection, showImage, @@ -66,7 +67,7 @@ const FloatingChatWidgetMarkdown = ({ const contentWithCursor = useMemo(() => { const text = content === '' ? t('chat.searching') : content; const nextText = replaceTextByOldReg(text); - return pipe(replaceThinkToSection, preprocessLaTeX)(nextText); + return pipe(replaceThinkToSection, replaceRetrievingToSection, preprocessLaTeX)(nextText); }, [content, t]); useEffect(() => { diff --git a/web/src/components/markdown-content/index.module.less b/web/src/components/markdown-content/index.module.less index 59a8b4771a..d07097b28d 100644 --- a/web/src/components/markdown-content/index.module.less +++ b/web/src/components/markdown-content/index.module.less @@ -1,10 +1,37 @@ .markdownContentWrapper { - :global(section.think) { + :global(details.think) { padding-inline-start: 10px; color: #8b8b8b; border-inline-start: 2px solid #d5d3d3; margin-bottom: 10px; font-size: 12px; + + summary { + cursor: pointer; + font-weight: 500; + color: #999; + user-select: none; + &:hover { + color: #666; + } + } + } + :global(details.retrieving) { + padding-inline-start: 10px; + color: #8b8b8b; + border-inline-start: 2px solid #a3d5c9; + margin-bottom: 10px; + font-size: 12px; + + summary { + cursor: pointer; + font-weight: 500; + color: #6ba89a; + user-select: none; + &:hover { + color: #4a8a7c; + } + } } :global(blockquote) { padding-inline-start: 10px; diff --git a/web/src/components/markdown-content/index.tsx b/web/src/components/markdown-content/index.tsx index 846d25d5a5..9dc1544404 100644 --- a/web/src/components/markdown-content/index.tsx +++ b/web/src/components/markdown-content/index.tsx @@ -23,6 +23,7 @@ import { currentReg, parseCitationIndex, preprocessLaTeX, + replaceRetrievingToSection, replaceTextByOldReg, replaceThinkToSection, } from '@/utils/chat'; @@ -63,7 +64,7 @@ const MarkdownContent = ({ useFetchDocumentThumbnailsByIds(); const contentWithCursor = useMemo(() => { let text = DOMPurify.sanitize(content, { - ADD_TAGS: ['think', 'section'], + ADD_TAGS: ['think', 'section', 'details', 'summary', 'retrieving'], ADD_ATTR: ['class'], }); @@ -72,7 +73,7 @@ const MarkdownContent = ({ text = t('chat.searching'); } const nextText = replaceTextByOldReg(text); - return pipe(replaceThinkToSection, preprocessLaTeX)(nextText); + return pipe(replaceThinkToSection, replaceRetrievingToSection, preprocessLaTeX)(nextText); }, [content, t]); useEffect(() => { diff --git a/web/src/components/message-item/index.module.less b/web/src/components/message-item/index.module.less index fbf35b8de0..e0f55c2a1b 100644 --- a/web/src/components/message-item/index.module.less +++ b/web/src/components/message-item/index.module.less @@ -34,9 +34,27 @@ .messageTextBase(); padding: 0; word-break: break-word; - :global(section.think) { + :global(details.think) { color: rgb(166, 166, 166); border-inline-start-color: rgb(78, 78, 86); + + summary { + color: rgb(140, 140, 140); + &:hover { + color: rgb(180, 180, 180); + } + } + } + :global(details.retrieving) { + color: rgb(166, 166, 166); + border-inline-start-color: rgb(60, 100, 90); + + summary { + color: rgb(120, 170, 155); + &:hover { + color: rgb(150, 200, 185); + } + } } } diff --git a/web/src/components/next-markdown-content/index.module.less b/web/src/components/next-markdown-content/index.module.less index 71de7f615c..aa20ab010c 100644 --- a/web/src/components/next-markdown-content/index.module.less +++ b/web/src/components/next-markdown-content/index.module.less @@ -1,10 +1,37 @@ .markdownContentWrapper { - :global(section.think) { + :global(details.think) { padding-inline-start: 10px; color: #8b8b8b; border-inline-start: 2px solid #d5d3d3; margin-bottom: 10px; font-size: 12px; + + summary { + cursor: pointer; + font-weight: 500; + color: #999; + user-select: none; + &:hover { + color: #666; + } + } + } + :global(details.retrieving) { + padding-inline-start: 10px; + color: #8b8b8b; + border-inline-start: 2px solid #a3d5c9; + margin-bottom: 10px; + font-size: 12px; + + summary { + cursor: pointer; + font-weight: 500; + color: #6ba89a; + user-select: none; + &:hover { + color: #4a8a7c; + } + } } :global(blockquote) { padding-inline-start: 10px; diff --git a/web/src/components/next-markdown-content/index.tsx b/web/src/components/next-markdown-content/index.tsx index 8fc966897d..ebedb0eed6 100644 --- a/web/src/components/next-markdown-content/index.tsx +++ b/web/src/components/next-markdown-content/index.tsx @@ -22,6 +22,7 @@ import { currentReg, parseCitationIndex, preprocessLaTeX, + replaceRetrievingToSection, replaceTextByOldReg, replaceThinkToSection, } from '@/utils/chat'; @@ -170,7 +171,7 @@ function MarkdownContent({ useFetchDocumentThumbnailsByIds(); const contentWithCursor = useMemo(() => { let text = DOMPurify.sanitize(content, { - ADD_TAGS: ['think', 'section'], + ADD_TAGS: ['think', 'section', 'details', 'summary', 'retrieving'], ADD_ATTR: ['class'], }); // let text = content; @@ -178,7 +179,7 @@ function MarkdownContent({ text = t('chat.searching'); } const nextText = replaceTextByOldReg(text); - return pipe(replaceThinkToSection, preprocessLaTeX)(nextText); + return pipe(replaceThinkToSection, replaceRetrievingToSection, preprocessLaTeX)(nextText); }, [content, t]); useEffect(() => { diff --git a/web/src/components/next-message-item/index.module.less b/web/src/components/next-message-item/index.module.less index 5b72726cf6..3589063717 100644 --- a/web/src/components/next-message-item/index.module.less +++ b/web/src/components/next-message-item/index.module.less @@ -37,16 +37,34 @@ .chunkText(); .messageTextBase(); word-break: break-word; - :global(section.think) { + :global(details.think) { color: rgb(166, 166, 166); border-inline-start-color: rgb(78, 78, 86); + + summary { + color: rgb(140, 140, 140); + &:hover { + color: rgb(180, 180, 180); + } + } + } + :global(details.retrieving) { + color: rgb(166, 166, 166); + border-inline-start-color: rgb(60, 100, 90); + + summary { + color: rgb(120, 170, 155); + &:hover { + color: rgb(150, 200, 185); + } + } } // RTL Support &[dir='rtl'] { text-align: right; - :global(section.think) { + :global(details.think) { border-inline-start-color: transparent; border-inline-end-color: rgb(78, 78, 86); border-inline-end-width: 2px; @@ -55,6 +73,15 @@ padding-inline-start: 0; padding-inline-end: 10px; } + :global(details.retrieving) { + border-inline-start-color: transparent; + border-inline-end-color: rgb(60, 100, 90); + border-inline-end-width: 2px; + border-inline-end-style: solid; + border-inline-start: none; + padding-inline-start: 0; + padding-inline-end: 10px; + } } } diff --git a/web/src/pages/next-search/markdown-content/index.tsx b/web/src/pages/next-search/markdown-content/index.tsx index a9eeec0375..a5522b7c7a 100644 --- a/web/src/pages/next-search/markdown-content/index.tsx +++ b/web/src/pages/next-search/markdown-content/index.tsx @@ -20,6 +20,7 @@ import { currentReg, parseCitationIndex, preprocessLaTeX, + replaceRetrievingToSection, replaceTextByOldReg, replaceThinkToSection, } from '@/utils/chat'; @@ -67,7 +68,7 @@ const MarkdownContent = ({ useFetchDocumentThumbnailsByIds(); const contentWithCursor = useMemo(() => { let text = DOMPurify.sanitize(content, { - ADD_TAGS: ['think', 'section'], + ADD_TAGS: ['think', 'section', 'details', 'summary', 'retrieving'], ADD_ATTR: ['class'], }); // let text = content; @@ -75,7 +76,7 @@ const MarkdownContent = ({ text = t('chat.searching'); } const nextText = replaceTextByOldReg(text); - return pipe(replaceThinkToSection, preprocessLaTeX)(nextText); + return pipe(replaceThinkToSection, replaceRetrievingToSection, preprocessLaTeX)(nextText); }, [content, t]); useEffect(() => { diff --git a/web/src/utils/chat.ts b/web/src/utils/chat.ts index 879289d3b1..923a4a9e3e 100644 --- a/web/src/utils/chat.ts +++ b/web/src/utils/chat.ts @@ -81,7 +81,15 @@ export const preprocessLaTeX = (content: string) => { export function replaceThinkToSection(text: string = '') { const pattern = /([\s\S]*?)<\/think>/g; - const result = text.replace(pattern, '
$1
'); + const result = text.replace(pattern, '
Thinking...$1
'); + + return result; +} + +export function replaceRetrievingToSection(text: string = '') { + const pattern = /([\s\S]*?)<\/retrieving>/g; + + const result = text.replace(pattern, '
Retrieving...$1
'); return result; }