feat: add support for thought processing in conversation flow and introduce ReActAgent

This commit is contained in:
Siddhant Rai
2025-03-27 23:19:08 +05:30
parent 1620b4f214
commit 82d377abf5
11 changed files with 643 additions and 334 deletions

View File

@@ -0,0 +1,11 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2 16C2.53043 16 3.03914 16.2107 3.41421 16.5858C3.78929 16.9609 4 17.4696 4 18C4 18.5304 3.78929 19.0391 3.41421 19.4142C3.03914 19.7893 2.53043 20 2 20C1.46957 20 0.960859 19.7893 0.585786 19.4142C0.210714 19.0391 0 18.5304 0 18C0 17.4696 0.210714 16.9609 0.585786 16.5858C0.960859 16.2107 1.46957 16 2 16ZM7.5 13C8.16304 13 8.79893 13.2634 9.26777 13.7322C9.73661 14.2011 10 14.837 10 15.5C10 16.163 9.73661 16.7989 9.26777 17.2678C8.79893 17.7366 8.16304 18 7.5 18C6.83696 18 6.20107 17.7366 5.73223 17.2678C5.26339 16.7989 5 16.163 5 15.5C5 14.837 5.26339 14.2011 5.73223 13.7322C6.20107 13.2634 6.83696 13 7.5 13ZM10 0C11.272 0.000250351 12.5033 0.448355 13.4779 1.26572C14.4525 2.08308 15.1082 3.2175 15.33 4.47H15.412C16.4105 4.47 17.3682 4.86667 18.0743 5.57274C18.7803 6.27882 19.177 7.23646 19.177 8.235C19.177 9.23354 18.7803 10.1912 18.0743 10.8973C17.3682 11.6033 16.4105 12 15.412 12H4.588C3.58946 12 2.63182 11.6033 1.92574 10.8973C1.21967 10.1912 0.823 9.23354 0.823 8.235C0.823 7.23646 1.21967 6.27882 1.92574 5.57274C2.63182 4.86667 3.58946 4.47 4.588 4.47H4.67C4.89179 3.2175 5.54749 2.08308 6.52211 1.26572C7.49673 0.448355 8.72801 0.000250351 10 0Z" fill="url(#paint0_linear_6161_11984)"/>
<defs>
<linearGradient id="paint0_linear_6161_11984" x1="0" y1="10" x2="19.177" y2="10" gradientUnits="userSpaceOnUse">
<stop stop-color="#70FDF7"/>
<stop offset="0.325" stop-color="#747696"/>
<stop offset="0.68" stop-color="#BD5372"/>
<stop offset="1" stop-color="#F5A06C"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -6,16 +6,16 @@ import ReactMarkdown from 'react-markdown';
import { useSelector } from 'react-redux';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import {
vscDarkPlus,
oneLight,
vscDarkPlus,
} from 'react-syntax-highlighter/dist/cjs/styles/prism';
import rehypeKatex from 'rehype-katex';
import remarkGfm from 'remark-gfm';
import remarkMath from 'remark-math';
import { useDarkTheme } from '../hooks';
import DocsGPT3 from '../assets/cute_docsgpt3.svg';
import ChevronDown from '../assets/chevron-down.svg';
import Cloud from '../assets/cloud.svg';
import DocsGPT3 from '../assets/cute_docsgpt3.svg';
import Dislike from '../assets/dislike.svg?react';
import Document from '../assets/document.svg';
import Edit from '../assets/edit.svg';
@@ -28,7 +28,7 @@ import Avatar from '../components/Avatar';
import CopyButton from '../components/CopyButton';
import Sidebar from '../components/Sidebar';
import SpeakButton from '../components/TextToSpeechButton';
import { useOutsideAlerter } from '../hooks';
import { useDarkTheme, useOutsideAlerter } from '../hooks';
import {
selectChunks,
selectSelectedDocs,
@@ -42,11 +42,12 @@ const DisableSourceFE = import.meta.env.VITE_DISABLE_SOURCE_FE || false;
const ConversationBubble = forwardRef<
HTMLDivElement,
{
message: string;
message?: string;
type: MESSAGE_TYPE;
className?: string;
feedback?: FEEDBACK;
handleFeedback?: (feedback: FEEDBACK) => void;
thought?: string;
sources?: { title: string; text: string; source: string }[];
toolCalls?: ToolCallsType[];
retryBtn?: React.ReactElement;
@@ -64,6 +65,7 @@ const ConversationBubble = forwardRef<
className,
feedback,
handleFeedback,
thought,
sources,
toolCalls,
retryBtn,
@@ -125,7 +127,7 @@ const ConversationBubble = forwardRef<
<button
onClick={() => {
setIsEditClicked(true);
setEditInputBox(message);
setEditInputBox(message ?? '');
}}
className={`flex-shrink-0 h-fit mt-3 p-2 cursor-pointer rounded-full hover:bg-light-silver dark:hover:bg-[#35363B] flex items-center ${isQuestionHovered || isEditClicked ? 'visible' : 'invisible'}`}
>
@@ -329,230 +331,237 @@ const ConversationBubble = forwardRef<
{toolCalls && toolCalls.length > 0 && (
<ToolCalls toolCalls={toolCalls} />
)}
<div className="flex flex-col flex-wrap items-start self-start lg:flex-nowrap">
<div className="my-2 flex flex-row items-center justify-center gap-3">
<Avatar
className="h-[34px] w-[34px] text-2xl"
avatar={
<img
src={DocsGPT3}
alt={t('conversation.answer')}
className="h-full w-full object-cover"
/>
}
/>
<p className="text-base font-semibold">
{t('conversation.answer')}
</p>
</div>
<div
className={`fade-in-bubble ml-2 mr-5 flex max-w-[90vw] rounded-[28px] bg-gray-1000 py-[18px] px-7 dark:bg-gun-metal md:max-w-[70vw] lg:max-w-[50vw] ${
type === 'ERROR'
? 'relative flex-row items-center rounded-full border border-transparent bg-[#FFE7E7] p-2 py-5 text-sm font-normal text-red-3000 dark:border-red-2000 dark:text-white'
: 'flex-col rounded-3xl'
}`}
>
<ReactMarkdown
className="fade-in whitespace-pre-wrap break-words leading-normal"
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeKatex]}
components={{
code(props) {
const { children, className, node, ref, ...rest } = props;
const match = /language-(\w+)/.exec(className || '');
const language = match ? match[1] : '';
return match ? (
<div className="group relative rounded-[14px] overflow-hidden border border-light-silver dark:border-raisin-black">
<div className="flex justify-between items-center px-2 py-1 bg-platinum dark:bg-eerie-black-2">
<span className="text-xs font-medium text-just-black dark:text-chinese-white">
{language}
</span>
<CopyButton
text={String(children).replace(/\n$/, '')}
/>
</div>
<SyntaxHighlighter
{...rest}
PreTag="div"
language={language}
style={isDarkTheme ? vscDarkPlus : oneLight}
className="!mt-0"
customStyle={{
margin: 0,
borderRadius: 0,
scrollbarWidth: 'thin',
}}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
</div>
) : (
<code className="whitespace-pre-line rounded-[6px] bg-gray-200 px-[8px] py-[4px] text-xs font-normal dark:bg-independence dark:text-bright-gray">
{children}
</code>
);
},
ul({ children }) {
return (
<ul
className={`list-inside list-disc whitespace-normal pl-4 ${classes.list}`}
>
{children}
</ul>
);
},
ol({ children }) {
return (
<ol
className={`list-inside list-decimal whitespace-normal pl-4 ${classes.list}`}
>
{children}
</ol>
);
},
table({ children }) {
return (
<div className="relative overflow-x-auto rounded-lg border border-silver/40 dark:border-silver/40">
<table className="w-full text-left text-gray-700 dark:text-bright-gray">
{children}
</table>
</div>
);
},
thead({ children }) {
return (
<thead className="text-xs uppercase text-gray-900 dark:text-bright-gray bg-gray-50 dark:bg-[#26272E]/50">
{children}
</thead>
);
},
tr({ children }) {
return (
<tr className="border-b border-gray-200 dark:border-silver/40 odd:bg-white dark:odd:bg-[#26272E] even:bg-gray-50 dark:even:bg-[#26272E]/50">
{children}
</tr>
);
},
th({ children }) {
return <th className="px-6 py-3">{children}</th>;
},
td({ children }) {
return <td className="px-6 py-3">{children}</td>;
},
}}
{thought && (
<Thought thought={thought} preprocessLaTeX={preprocessLaTeX} />
)}
{message && (
<div className="flex flex-col flex-wrap items-start self-start lg:flex-nowrap">
<div className="my-2 flex flex-row items-center justify-center gap-3">
<Avatar
className="h-[34px] w-[34px] text-2xl"
avatar={
<img
src={DocsGPT3}
alt={t('conversation.answer')}
className="h-full w-full object-cover"
/>
}
/>
<p className="text-base font-semibold">
{t('conversation.answer')}
</p>
</div>
<div
className={`fade-in-bubble ml-2 mr-5 flex max-w-[90vw] rounded-[28px] bg-gray-1000 py-[18px] px-7 dark:bg-gun-metal md:max-w-[70vw] lg:max-w-[50vw] ${
type === 'ERROR'
? 'relative flex-row items-center rounded-full border border-transparent bg-[#FFE7E7] p-2 py-5 text-sm font-normal text-red-3000 dark:border-red-2000 dark:text-white'
: 'flex-col rounded-3xl'
}`}
>
{preprocessLaTeX(message)}
</ReactMarkdown>
</div>
</div>
<div className="my-2 ml-2 flex justify-start">
<div
className={`relative mr-2 block items-center justify-center lg:invisible
${type !== 'ERROR' ? 'group-hover:lg:visible' : 'hidden'}`}
>
<div>
<CopyButton text={message} />
</div>
</div>
<div
className={`relative mr-2 block items-center justify-center lg:invisible
${type !== 'ERROR' ? 'group-hover:lg:visible' : 'hidden'}`}
>
<div>
<SpeakButton text={message} />
</div>
</div>
{type === 'ERROR' && (
<div className="relative mr-2 block items-center justify-center">
<div>{retryBtn}</div>
</div>
)}
{handleFeedback && (
<>
<div
className={`relative mr-2 flex items-center justify-center ${
feedback === 'LIKE' || isLikeClicked
? 'visible'
: 'lg:invisible'
} ${type !== 'ERROR' ? 'group-hover:lg:visible' : ''}
${feedback === 'DISLIKE' && type !== 'ERROR' ? 'hidden' : ''}`}
<ReactMarkdown
className="fade-in whitespace-pre-wrap break-words leading-normal"
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeKatex]}
components={{
code(props) {
const { children, className, node, ref, ...rest } = props;
const match = /language-(\w+)/.exec(className || '');
const language = match ? match[1] : '';
return match ? (
<div className="group relative rounded-[14px] overflow-hidden border border-light-silver dark:border-raisin-black">
<div className="flex justify-between items-center px-2 py-1 bg-platinum dark:bg-eerie-black-2">
<span className="text-xs font-medium text-just-black dark:text-chinese-white">
{language}
</span>
<CopyButton
text={String(children).replace(/\n$/, '')}
/>
</div>
<SyntaxHighlighter
{...rest}
PreTag="div"
language={language}
style={isDarkTheme ? vscDarkPlus : oneLight}
className="!mt-0"
customStyle={{
margin: 0,
borderRadius: 0,
scrollbarWidth: 'thin',
}}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
</div>
) : (
<code className="whitespace-pre-line rounded-[6px] bg-gray-200 px-[8px] py-[4px] text-xs font-normal dark:bg-independence dark:text-bright-gray">
{children}
</code>
);
},
ul({ children }) {
return (
<ul
className={`list-inside list-disc whitespace-normal pl-4 ${classes.list}`}
>
{children}
</ul>
);
},
ol({ children }) {
return (
<ol
className={`list-inside list-decimal whitespace-normal pl-4 ${classes.list}`}
>
{children}
</ol>
);
},
table({ children }) {
return (
<div className="relative overflow-x-auto rounded-lg border border-silver/40 dark:border-silver/40">
<table className="w-full text-left text-gray-700 dark:text-bright-gray">
{children}
</table>
</div>
);
},
thead({ children }) {
return (
<thead className="text-xs uppercase text-gray-900 dark:text-bright-gray bg-gray-50 dark:bg-[#26272E]/50">
{children}
</thead>
);
},
tr({ children }) {
return (
<tr className="border-b border-gray-200 dark:border-silver/40 odd:bg-white dark:odd:bg-[#26272E] even:bg-gray-50 dark:even:bg-[#26272E]/50">
{children}
</tr>
);
},
th({ children }) {
return <th className="px-6 py-3">{children}</th>;
},
td({ children }) {
return <td className="px-6 py-3">{children}</td>;
},
}}
>
<div>
<div
className={`flex items-center justify-center rounded-full p-2 ${
isLikeHovered
? 'bg-[#EEEEEE] dark:bg-purple-taupe'
: 'bg-[#ffffff] dark:bg-transparent'
}`}
>
<Like
className={`cursor-pointer
{preprocessLaTeX(message)}
</ReactMarkdown>
</div>
</div>
)}
{message && (
<div className="my-2 ml-2 flex justify-start">
<div
className={`relative mr-2 block items-center justify-center lg:invisible
${type !== 'ERROR' ? 'group-hover:lg:visible' : 'hidden'}`}
>
<div>
<CopyButton text={message} />
</div>
</div>
<div
className={`relative mr-2 block items-center justify-center lg:invisible
${type !== 'ERROR' ? 'group-hover:lg:visible' : 'hidden'}`}
>
<div>
<SpeakButton text={message} />
</div>
</div>
{type === 'ERROR' && (
<div className="relative mr-2 block items-center justify-center">
<div>{retryBtn}</div>
</div>
)}
{handleFeedback && (
<>
<div
className={`relative mr-2 flex items-center justify-center ${
feedback === 'LIKE' || isLikeClicked
? 'visible'
: 'lg:invisible'
} ${type !== 'ERROR' ? 'group-hover:lg:visible' : ''}
${feedback === 'DISLIKE' && type !== 'ERROR' ? 'hidden' : ''}`}
>
<div>
<div
className={`flex items-center justify-center rounded-full p-2 ${
isLikeHovered
? 'bg-[#EEEEEE] dark:bg-purple-taupe'
: 'bg-[#ffffff] dark:bg-transparent'
}`}
>
<Like
className={`cursor-pointer
${
isLikeClicked || feedback === 'LIKE'
? 'fill-white-3000 stroke-purple-30 dark:fill-transparent'
: 'fill-none stroke-gray-4000'
}`}
onClick={() => {
if (feedback === undefined || feedback === null) {
handleFeedback?.('LIKE');
setIsLikeClicked(true);
setIsDislikeClicked(false);
} else if (feedback === 'LIKE') {
handleFeedback?.(null);
setIsLikeClicked(false);
setIsDislikeClicked(false);
}
}}
onMouseEnter={() => setIsLikeHovered(true)}
onMouseLeave={() => setIsLikeHovered(false)}
></Like>
onClick={() => {
if (feedback === undefined || feedback === null) {
handleFeedback?.('LIKE');
setIsLikeClicked(true);
setIsDislikeClicked(false);
} else if (feedback === 'LIKE') {
handleFeedback?.(null);
setIsLikeClicked(false);
setIsDislikeClicked(false);
}
}}
onMouseEnter={() => setIsLikeHovered(true)}
onMouseLeave={() => setIsLikeHovered(false)}
></Like>
</div>
</div>
</div>
</div>
<div
className={`relative mr-2 flex items-center justify-center ${
feedback === 'DISLIKE' || isLikeClicked
? 'visible'
: 'lg:invisible'
} ${type !== 'ERROR' ? 'group-hover:lg:visible' : ''}
<div
className={`relative mr-2 flex items-center justify-center ${
feedback === 'DISLIKE' || isLikeClicked
? 'visible'
: 'lg:invisible'
} ${type !== 'ERROR' ? 'group-hover:lg:visible' : ''}
${feedback === 'LIKE' && type !== 'ERROR' ? 'hidden' : ''}`}
>
<div>
<div
className={`flex items-center justify-center rounded-full p-2 ${
isDislikeHovered
? 'bg-[#EEEEEE] dark:bg-purple-taupe'
: 'bg-[#ffffff] dark:bg-transparent'
}`}
>
<Dislike
className={`cursor-pointer ${
isDislikeClicked || feedback === 'DISLIKE'
? 'fill-white-3000 stroke-red-2000 dark:fill-transparent'
: 'fill-none stroke-gray-4000'
>
<div>
<div
className={`flex items-center justify-center rounded-full p-2 ${
isDislikeHovered
? 'bg-[#EEEEEE] dark:bg-purple-taupe'
: 'bg-[#ffffff] dark:bg-transparent'
}`}
onClick={() => {
if (feedback === undefined || feedback === null) {
handleFeedback?.('DISLIKE');
setIsDislikeClicked(true);
setIsLikeClicked(false);
} else if (feedback === 'DISLIKE') {
handleFeedback?.(null);
setIsLikeClicked(false);
setIsDislikeClicked(false);
}
}}
onMouseEnter={() => setIsDislikeHovered(true)}
onMouseLeave={() => setIsDislikeHovered(false)}
></Dislike>
>
<Dislike
className={`cursor-pointer ${
isDislikeClicked || feedback === 'DISLIKE'
? 'fill-white-3000 stroke-red-2000 dark:fill-transparent'
: 'fill-none stroke-gray-4000'
}`}
onClick={() => {
if (feedback === undefined || feedback === null) {
handleFeedback?.('DISLIKE');
setIsDislikeClicked(true);
setIsLikeClicked(false);
} else if (feedback === 'DISLIKE') {
handleFeedback?.(null);
setIsLikeClicked(false);
setIsDislikeClicked(false);
}
}}
onMouseEnter={() => setIsDislikeHovered(true)}
onMouseLeave={() => setIsDislikeHovered(false)}
></Dislike>
</div>
</div>
</div>
</div>
</>
)}
</div>
</>
)}
</div>
)}
{sources && (
<Sidebar
isOpen={isSidebarOpen}
@@ -699,3 +708,136 @@ function ToolCalls({ toolCalls }: { toolCalls: ToolCallsType[] }) {
</div>
);
}
function Thought({
thought,
preprocessLaTeX,
}: {
thought: string;
preprocessLaTeX: (content: string) => string;
}) {
const [isDarkTheme] = useDarkTheme();
const [isThoughtOpen, setIsThoughtOpen] = useState(true);
return (
<div className="mb-4 w-full flex flex-col flex-wrap items-start self-start lg:flex-nowrap">
<div className="my-2 flex flex-row items-center justify-center gap-3">
<Avatar
className="h-[26px] w-[30px] text-xl"
avatar={
<img
src={Cloud}
alt={'Thought'}
className="h-full w-full object-fill"
/>
}
/>
<button
className="flex flex-row items-center gap-2"
onClick={() => setIsThoughtOpen(!isThoughtOpen)}
>
<p className="text-base font-semibold">Reasoning</p>
<img
src={ChevronDown}
alt="ChevronDown"
className={`h-4 w-4 transform transition-transform duration-200 dark:invert ${isThoughtOpen ? 'rotate-180' : ''}`}
/>
</button>
</div>
{isThoughtOpen && (
<div className="fade-in ml-2 mr-5 max-w-[90vw] md:max-w-[70vw] lg:max-w-[50vw]">
<div className="rounded-[28px] bg-gray-1000 py-[18px] px-7 dark:bg-gun-metal">
<ReactMarkdown
className="fade-in whitespace-pre-wrap break-words leading-normal"
remarkPlugins={[remarkGfm, remarkMath]}
rehypePlugins={[rehypeKatex]}
components={{
code(props) {
const { children, className, node, ref, ...rest } = props;
const match = /language-(\w+)/.exec(className || '');
const language = match ? match[1] : '';
return match ? (
<div className="group relative rounded-[14px] overflow-hidden border border-light-silver dark:border-raisin-black">
<div className="flex justify-between items-center px-2 py-1 bg-platinum dark:bg-eerie-black-2">
<span className="text-xs font-medium text-just-black dark:text-chinese-white">
{language}
</span>
<CopyButton
text={String(children).replace(/\n$/, '')}
/>
</div>
<SyntaxHighlighter
{...rest}
PreTag="div"
language={language}
style={isDarkTheme ? vscDarkPlus : oneLight}
className="!mt-0"
customStyle={{
margin: 0,
borderRadius: 0,
scrollbarWidth: 'thin',
}}
>
{String(children).replace(/\n$/, '')}
</SyntaxHighlighter>
</div>
) : (
<code className="whitespace-pre-line rounded-[6px] bg-gray-200 px-[8px] py-[4px] text-xs font-normal dark:bg-independence dark:text-bright-gray">
{children}
</code>
);
},
ul({ children }) {
return (
<ul className="list-inside list-disc whitespace-normal pl-4">
{children}
</ul>
);
},
ol({ children }) {
return (
<ol className="list-inside list-decimal whitespace-normal pl-4">
{children}
</ol>
);
},
table({ children }) {
return (
<div className="relative overflow-x-auto rounded-lg border border-silver/40 dark:border-silver/40">
<table className="w-full text-left text-gray-700 dark:text-bright-gray">
{children}
</table>
</div>
);
},
thead({ children }) {
return (
<thead className="text-xs uppercase text-gray-900 dark:text-bright-gray bg-gray-50 dark:bg-[#26272E]/50">
{children}
</thead>
);
},
tr({ children }) {
return (
<tr className="border-b border-gray-200 dark:border-silver/40 odd:bg-white dark:odd:bg-[#26272E] even:bg-gray-50 dark:even:bg-[#26272E]/50">
{children}
</tr>
);
},
th({ children }) {
return <th className="px-6 py-3">{children}</th>;
},
td({ children }) {
return <td className="px-6 py-3">{children}</td>;
},
}}
>
{preprocessLaTeX(thought ?? '')}
</ReactMarkdown>
</div>
</div>
)}
</div>
);
}

View File

@@ -1,11 +1,12 @@
import { Fragment, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import ConversationBubble from './ConversationBubble';
import Hero from '../Hero';
import { FEEDBACK, Query, Status } from './conversationModels';
import ArrowDown from '../assets/arrow-down.svg';
import RetryIcon from '../components/RetryIcon';
import Hero from '../Hero';
import { useDarkTheme } from '../hooks';
import ConversationBubble from './ConversationBubble';
import { FEEDBACK, Query, Status } from './conversationModels';
interface ConversationMessagesProps {
handleQuestion: (params: {
@@ -83,13 +84,14 @@ export default function ConversationMessages({
const prepResponseView = (query: Query, index: number) => {
let responseView;
if (query.response) {
if (query.thought || query.response) {
responseView = (
<ConversationBubble
className={`${index === queries.length - 1 ? 'mb-32' : 'mb-7'}`}
key={`${index}ANSWER`}
message={query.response}
type={'ANSWER'}
thought={query.thought}
sources={query.sources}
toolCalls={query.tool_calls}
feedback={query.feedback}

View File

@@ -17,6 +17,7 @@ export function handleFetchAnswer(
| {
result: any;
answer: any;
thought: any;
sources: any;
toolCalls: ToolCallsType[];
conversationId: any;
@@ -25,6 +26,7 @@ export function handleFetchAnswer(
| {
result: any;
answer: any;
thought: any;
sources: any;
toolCalls: ToolCallsType[];
query: string;
@@ -67,9 +69,11 @@ export function handleFetchAnswer(
answer: result,
query: question,
result,
thought: data.thought,
sources: data.sources,
toolCalls: data.tool_calls,
conversationId: data.conversation_id,
title: data.title || null,
};
});
}
@@ -91,6 +95,7 @@ export function handleFetchAnswerSteaming(
return {
prompt: item.prompt,
response: item.response,
thought: item.thought,
tool_calls: item.tool_calls,
};
});

View File

@@ -21,6 +21,7 @@ export interface Answer {
result: string;
conversationId: string | null;
title: string | null;
thought: string;
sources: { title: string; text: string; source: string }[];
tool_calls: ToolCallsType[];
}
@@ -32,6 +33,7 @@ export interface Query {
error?: string;
conversationId?: string | null;
title?: string | null;
thought?: string;
sources?: { title: string; text: string; source: string }[];
tool_calls?: ToolCallsType[];
}

View File

@@ -75,6 +75,15 @@ export const fetchAnswer = createAsyncThunk<
query: { conversationId: data.id },
}),
);
} else if (data.type === 'thought') {
const result = data.thought;
console.log('thought', result);
dispatch(
updateThought({
index: indx ?? state.conversation.queries.length - 1,
query: { thought: result },
}),
);
} else if (data.type === 'source') {
isSourceUpdated = true;
dispatch(
@@ -141,6 +150,7 @@ export const fetchAnswer = createAsyncThunk<
index: indx ?? state.conversation.queries.length - 1,
query: {
response: answer.answer,
thought: answer.thought,
sources: sourcesPrepped,
tool_calls: answer.toolCalls,
},
@@ -168,6 +178,7 @@ export const fetchAnswer = createAsyncThunk<
answer: '',
query: question,
result: '',
thought: '',
sources: [],
tool_calls: [],
};
@@ -215,6 +226,21 @@ export const conversationSlice = createSlice({
state.conversationId = action.payload.query.conversationId ?? null;
state.status = 'idle';
},
updateThought(
state,
action: PayloadAction<{ index: number; query: Partial<Query> }>,
) {
const { index, query } = action.payload;
if (query.thought != undefined) {
state.queries[index].thought =
(state.queries[index].thought || '') + query.thought;
} else {
state.queries[index] = {
...state.queries[index],
...query,
};
}
},
updateStreamingSource(
state,
action: PayloadAction<{ index: number; query: Partial<Query> }>,
@@ -284,6 +310,7 @@ export const {
resendQuery,
updateStreamingQuery,
updateConversationId,
updateThought,
updateStreamingSource,
updateToolCalls,
setConversation,