Skip to content

Commit

Permalink
Wire up the reset of search term.
Browse files Browse the repository at this point in the history
  • Loading branch information
mathewjordan committed Dec 18, 2024
1 parent a71bbb0 commit f4760f7
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 51 deletions.
17 changes: 10 additions & 7 deletions components/Chat/Chat.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,18 +72,21 @@ describe("Chat component", () => {
</SearchProvider>,
);

const uuidRegex =
/^[0-9a-f]{8}-[0-9a-f]{4}-[4][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
const el = screen.getByTestId("mock-chat-response");
expect(el).toBeInTheDocument();

const dataProps = el.getAttribute("data-props");
expect(JSON.parse(dataProps!)).toEqual({
isStreamingComplete: false,
searchTerm: "tell me about boats",
message: {
answer: "fake-answer-1",
end: "stop",
},
const dataPropsObj = JSON.parse(dataProps!);
expect(dataPropsObj.question).toEqual("tell me about boats");
expect(dataPropsObj.isStreamingComplete).toEqual(false);
expect(dataPropsObj.message).toEqual({
answer: "fake-answer-1",
end: "stop",
});
expect(typeof dataPropsObj.conversationRef).toBe("string");
expect(uuidRegex.test(dataPropsObj.conversationRef)).toBe(true);
});

it("sends a websocket message when the search term changes", () => {
Expand Down
83 changes: 59 additions & 24 deletions components/Chat/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ import Container from "@/components/Shared/Container";
import { prepareQuestion } from "@/lib/chat-helpers";
import useChatSocket from "@/hooks/useChatSocket";
import useQueryParams from "@/hooks/useQueryParams";
import { v4 as uuidv4 } from "uuid";

const Chat = ({
totalResults,
viewResultsCallback,
}: {
totalResults?: number;
viewResultsCallback?: () => void;
}) => {
const { searchTerm = "" } = useQueryParams();
Expand All @@ -37,35 +36,42 @@ const Chat = ({
searchState: { chat },
searchDispatch,
} = useSearchState();
const { question } = chat;
const { question, answer } = chat;

const [isStreamingComplete, setIsStreamingComplete] = useState(false);

useEffect(() => {
if (!isStreamingComplete && isConnected && authToken && searchTerm) {
if (
!isStreamingComplete &&
isConnected &&
authToken &&
searchTerm &&
conversationRef
) {
resetChat();
const preparedQuestion = prepareQuestion(searchTerm, authToken);
setConversationRef(preparedQuestion.ref);
const preparedQuestion = prepareQuestion(
searchTerm,
authToken,
conversationRef,
);
sendMessage(preparedQuestion);
}
}, [authToken, isStreamingComplete, isConnected, searchTerm, sendMessage]);
}, [
authToken,
isStreamingComplete,
isConnected,
searchTerm,
conversationRef,
sendMessage,
]);

useEffect(() => {
if (!message) return;

// const updateChat = () => {
// searchDispatch({
// chat: {
// answer: message.answer || "",
// documents: sourceDocuments,
// question: searchTerm || "",
// ref: message.ref,
// },
// type: "updateChat",
// });
// };

if (message.type === "final_message") setIsStreamingComplete(true);
setIsStreamingComplete(false);
setConversationRef(uuidv4());
}, [searchTerm]);

useEffect(() => {
if (!message || !conversationRef) return;
}, [message]);

function handleNewQuestion() {
Expand All @@ -90,13 +96,42 @@ const Chat = ({
</Container>
);

const handleResponseCallback = (content: any) => {
if (!conversationRef) return;

setIsStreamingComplete(true);
searchDispatch({
chat: {
// content here is now a react element
// once continued conversations ar e in place
// see note below for question refactor
answer: content,

// documents should be eventually removed as
// they are now integrated into content
// doing so will require some careful refactoring
// as the documents are used in feedback form
documents: [],

// question should become an entry[] with
// entry[n].question and entry[n].content
question: searchTerm || "",

ref: conversationRef,
},
type: "updateChat",
});
};

return (
<>
<ChatResponse
conversationRef={conversationRef}
isStreamingComplete={isStreamingComplete}
searchTerm={question || searchTerm}
key={conversationRef}
message={message}
conversationRef={conversationRef}
question={searchTerm}
responseCallback={handleResponseCallback}
/>
{streamingError && (
<Container>
Expand Down
6 changes: 5 additions & 1 deletion components/Chat/Response/Interstitial.styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@ const StyledInterstitialIcon = styled("div", {
const StyledInterstitial = styled("div", {
color: "$black",
fontFamily: "$northwesternSansBold",
fontSize: "$gr3",
fontSize: "$gr4",
display: "flex",
alignItems: "center",
gap: "$gr2",

em: {
color: "$purple",
},
});

export { StyledInterstitial, StyledInterstitialIcon };
16 changes: 12 additions & 4 deletions components/Chat/Response/Interstitial.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,25 @@ const ResponseInterstitial: React.FC<ResponseInterstitialProps> = ({
message,
}) => {
const { tool, input } = message;
let text = "";
let text: React.ReactElement = <></>;

switch (tool) {
case "aggregate":
text = `Aggregating ${input.agg_field} by ${input.term_field} ${input.term}`;
text = (
<>
Aggregating {input.agg_field} by {input.term_field} {input.term}
</>
);
break;
case "discover_fields":
text = "Discovering fields";
text = <>Discovering fields</>;
break;
case "search":
text = `Searching for: ${input.query}`;
text = (
<>
Searching for <em>{input.query}</em>
</>
);
break;
default:
console.warn("Unknown tool_start message", message);
Expand Down
2 changes: 1 addition & 1 deletion components/Chat/Response/Response.styled.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const StyledQuestion = styled("h3", {
fontSize: "$gr6",
letterSpacing: "-0.012em",
lineHeight: "1.35em",
margin: "0",
margin: "0 0 $gr4",
padding: "0",
color: "$black",
});
Expand Down
34 changes: 27 additions & 7 deletions components/Chat/Response/Response.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useState } from "react";
import React, { use, useEffect, useState } from "react";
import {
StyledQuestion,
StyledResponse,
Expand All @@ -14,16 +14,18 @@ import { StreamingMessage } from "@/types/components/chat";

interface ChatResponseProps {
conversationRef?: string;
message?: StreamingMessage;
searchTerm: string;
isStreamingComplete: boolean;
message?: StreamingMessage;
question: string;
responseCallback?: (renderedMessage: any) => void;
}

const ChatResponse: React.FC<ChatResponseProps> = ({
conversationRef,
message,
searchTerm,
isStreamingComplete,
message,
question,
responseCallback,
}) => {
const [renderedMessage, setRenderedMessage] = useState<any>();
const [streamedMessage, setStreamedMessage] = useState<string>("");
Expand Down Expand Up @@ -83,17 +85,35 @@ const ChatResponse: React.FC<ChatResponseProps> = ({
</>
));
}

/**
* Final message is the last message in the response
* and is used to trigger the responseCallback
* to store this response.
*/
if (type === "final_message") {
if (responseCallback) responseCallback(renderedMessage);
}
}, [message]);

useEffect(() => {
resetRenderedMessage();
resetStreamedMessage();
}, [conversationRef]);

function resetStreamedMessage() {
setStreamedMessage("");
}

function resetRenderedMessage() {
setRenderedMessage(undefined);
}

return (
<StyledResponseWrapper>
<Container>
<StyledResponse>
<StyledQuestion>{searchTerm}</StyledQuestion>
<StyledQuestion>{question}</StyledQuestion>
{renderedMessage}
{streamedMessage && <ResponseMarkdown content={streamedMessage} />}
{!isStreamingComplete && <BouncingLoader />}
Expand All @@ -103,4 +123,4 @@ const ChatResponse: React.FC<ChatResponseProps> = ({
);
};

export default React.memo(ChatResponse);
export default ChatResponse;
9 changes: 6 additions & 3 deletions lib/chat-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import axios, { AxiosError } from "axios";

import { DCAPI_CHAT_FEEDBACK } from "./constants/endpoints";
import { v4 as uuidv4 } from "uuid";

const prepareQuestion = (questionString: string, authToken: string) => {
const prepareQuestion = (
questionString: string,
authToken: string,
conversationRef: string,
) => {
return {
auth: authToken,
message: "chat",
question: questionString,
ref: uuidv4(),
ref: conversationRef,
};
};

Expand Down
5 changes: 1 addition & 4 deletions pages/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -254,10 +254,7 @@ const SearchPage: NextPage = () => {
renderTabList={showStreamedResponse}
/>
<Tabs.Content value="stream">
<Chat
totalResults={totalResults}
viewResultsCallback={handleViewResultsCallback}
/>
<Chat viewResultsCallback={handleViewResultsCallback} />
</Tabs.Content>

<Tabs.Content value="results">
Expand Down

0 comments on commit f4760f7

Please sign in to comment.