Fix feedback display

This commit is contained in:
Weves 2024-02-10 00:15:41 -08:00 committed by Chris Weaver
parent 37110df2de
commit d5168deac8
8 changed files with 65 additions and 52 deletions

View File

@ -106,13 +106,15 @@ export function ChatDocumentDisplay({
{buildDocumentSummaryDisplay(document.match_highlights, document.blurb)}
</p>
<div className="mb-2">
{/*
// TODO: find a way to include this
{queryEventId && (
<DocumentFeedbackBlock
documentId={document.document_id}
queryId={queryEventId}
setPopup={setPopup}
/>
)}
)} */}
</div>
</div>
);

View File

@ -133,14 +133,16 @@ export function DocumentMetadataBlock({
interface DocumentDisplayProps {
document: DanswerDocument;
queryEventId: number | null;
messageId: number | null;
documentRank: number;
isSelected: boolean;
setPopup: (popupSpec: PopupSpec | null) => void;
}
export const DocumentDisplay = ({
document,
queryEventId,
messageId,
documentRank,
isSelected,
setPopup,
}: DocumentDisplayProps) => {
@ -219,10 +221,11 @@ export const DocumentDisplay = ({
</p>
</a>
<div className="ml-auto">
{isHovered && queryEventId && (
{isHovered && messageId && (
<DocumentFeedbackBlock
documentId={document.document_id}
queryId={queryEventId}
messageId={messageId}
documentRank={documentRank}
setPopup={setPopup}
/>
)}

View File

@ -5,20 +5,21 @@ type DocumentFeedbackType = "endorse" | "reject" | "hide" | "unhide";
const giveDocumentFeedback = async (
documentId: string,
queryId: number,
messageId: number,
documentRank: number,
searchFeedback: DocumentFeedbackType
): Promise<string | null> => {
const response = await fetch("/api/doc-retrieval-feedback", {
const response = await fetch("/api/chat/document-search-feedback", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query_id: queryId,
search_feedback: searchFeedback,
click: false,
document_rank: 0,
message_id: messageId,
document_id: documentId,
document_rank: documentRank,
click: false,
search_feedback: searchFeedback,
}),
});
return response.ok
@ -28,14 +29,16 @@ const giveDocumentFeedback = async (
interface DocumentFeedbackIconProps {
documentId: string;
queryId: number;
messageId: number;
documentRank: number;
setPopup: (popupSpec: PopupSpec | null) => void;
feedbackType: DocumentFeedbackType;
}
const DocumentFeedback = ({
documentId,
queryId,
messageId,
documentRank,
setPopup,
feedbackType,
}: DocumentFeedbackIconProps) => {
@ -67,7 +70,8 @@ const DocumentFeedback = ({
onClick={async () => {
const errorMsg = await giveDocumentFeedback(
documentId,
queryId,
messageId,
documentRank,
feedbackType
);
if (!errorMsg) {
@ -91,27 +95,31 @@ const DocumentFeedback = ({
interface DocumentFeedbackBlockProps {
documentId: string;
queryId: number;
messageId: number;
documentRank: number;
setPopup: (popupSpec: PopupSpec | null) => void;
}
export const DocumentFeedbackBlock = ({
documentId,
queryId,
messageId,
documentRank,
setPopup,
}: DocumentFeedbackBlockProps) => {
return (
<div className="flex">
<DocumentFeedback
documentId={documentId}
queryId={queryId}
messageId={messageId}
documentRank={documentRank}
setPopup={setPopup}
feedbackType="endorse"
/>
<div className="ml-2">
<DocumentFeedback
documentId={documentId}
queryId={queryId}
messageId={messageId}
documentRank={documentRank}
setPopup={setPopup}
feedbackType="reject"
/>

View File

@ -5,30 +5,30 @@ import { ThumbsDownIcon, ThumbsUpIcon } from "../icons/icons";
type Feedback = "like" | "dislike";
const giveFeedback = async (
queryId: number,
messageId: number,
feedback: Feedback
): Promise<boolean> => {
const response = await fetch("/api/query-feedback", {
const response = await fetch("/api/chat/create-chat-message-feedback", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query_id: queryId,
feedback,
chat_message_id: messageId,
is_positive: feedback === "like",
}),
});
return response.ok;
};
interface QAFeedbackIconProps {
queryId: number;
messageId: number;
setPopup: (popupSpec: PopupSpec | null) => void;
feedbackType: Feedback;
}
const QAFeedback = ({
queryId,
messageId,
setPopup,
feedbackType,
}: QAFeedbackIconProps) => {
@ -40,7 +40,7 @@ const QAFeedback = ({
return (
<div
onClick={async () => {
const isSuccessful = await giveFeedback(queryId, feedbackType);
const isSuccessful = await giveFeedback(messageId, feedbackType);
if (isSuccessful) {
setPopup({
message: "Thanks for your feedback!",
@ -70,20 +70,24 @@ const QAFeedback = ({
};
interface QAFeedbackBlockProps {
queryId: number;
messageId: number;
setPopup: (popupSpec: PopupSpec | null) => void;
}
export const QAFeedbackBlock = ({
queryId,
messageId,
setPopup,
}: QAFeedbackBlockProps) => {
return (
<div className="flex">
<QAFeedback queryId={queryId} setPopup={setPopup} feedbackType="like" />
<QAFeedback
messageId={messageId}
setPopup={setPopup}
feedbackType="like"
/>
<div className="ml-2">
<QAFeedback
queryId={queryId}
messageId={messageId}
setPopup={setPopup}
feedbackType="dislike"
/>

View File

@ -11,7 +11,6 @@ import {
} from "@/lib/search/interfaces";
import { QAFeedbackBlock } from "./QAFeedback";
import { DocumentDisplay } from "./DocumentDisplay";
import { ResponseSection, StatusOptions } from "./results/ResponseSection";
import { QuotesSection } from "./results/QuotesSection";
import { AnswerSection } from "./results/AnswerSection";
import { ThreeDots } from "react-loader-spinner";
@ -50,7 +49,7 @@ export const SearchResultsDisplay = ({
}
const isPersona = personaName !== null;
const { answer, quotes, documents, error, queryEventId } = searchResponse;
const { answer, quotes, documents, error, messageId } = searchResponse;
if (isFetching && !answer && !documents) {
return (
@ -147,10 +146,10 @@ export const SearchResultsDisplay = ({
isAnswerable={validQuestionResponse.answerable}
/>
{searchResponse.queryEventId !== null && (
{searchResponse.messageId !== null && (
<div className="absolute right-3 bottom-3">
<QAFeedbackBlock
queryId={searchResponse.queryEventId}
messageId={searchResponse.messageId}
setPopup={setPopup}
/>
</div>
@ -166,11 +165,12 @@ export const SearchResultsDisplay = ({
<div className="font-bold text-emphasis border-b mb-3 pb-1 border-border text-lg">
Results
</div>
{removeDuplicateDocs(documents).map((document) => (
{removeDuplicateDocs(documents).map((document, ind) => (
<DocumentDisplay
key={document.document_id}
document={document}
queryEventId={queryEventId}
documentRank={ind + 1}
messageId={messageId}
isSelected={selectedDocumentIds.has(document.document_id)}
setPopup={setPopup}
/>

View File

@ -95,7 +95,7 @@ export const SearchSection = ({
suggestedFlowType: null,
selectedDocIndices: null,
error: null,
queryEventId: null,
messageId: null,
};
const updateCurrentAnswer = (answer: string) =>
setSearchResponse((prevState) => ({
@ -132,10 +132,10 @@ export const SearchSection = ({
...(prevState || initialSearchResponse),
error,
}));
const updateQueryEventId = (queryEventId: number) =>
const updateMessageId = (messageId: number) =>
setSearchResponse((prevState) => ({
...(prevState || initialSearchResponse),
queryEventId,
messageId,
}));
let lastSearchCancellationToken = useRef<CancellationToken | null>(null);
@ -190,9 +190,9 @@ export const SearchSection = ({
cancellationToken: lastSearchCancellationToken.current,
fn: updateError,
}),
updateQueryEventId: cancellable({
updateMessageId: cancellable({
cancellationToken: lastSearchCancellationToken.current,
fn: updateQueryEventId,
fn: updateMessageId,
}),
selectedSearchType: searchType ?? selectedSearchType,
offset: offset ?? defaultOverrides.offset,

View File

@ -62,10 +62,6 @@ export interface LLMRelevanceFilterPacket {
relevant_chunk_indices: number[];
}
export interface QueryEventIdPacket {
query_event_id: number;
}
export interface SearchResponse {
suggestedSearchType: SearchType | null;
suggestedFlowType: FlowType | null;
@ -74,7 +70,7 @@ export interface SearchResponse {
documents: DanswerDocument[] | null;
selectedDocIndices: number[] | null;
error: string | null;
queryEventId: number | null;
messageId: number | null;
}
export enum SourceCategory {
@ -116,7 +112,7 @@ export interface SearchRequestArgs {
updateSuggestedSearchType: (searchType: SearchType) => void;
updateSuggestedFlowType: (flowType: FlowType) => void;
updateError: (error: string) => void;
updateQueryEventId: (queryEventID: number) => void;
updateMessageId: (messageId: number) => void;
selectedSearchType: SearchType | null;
}

View File

@ -1,10 +1,10 @@
import { BackendMessage } from "@/app/chat/interfaces";
import {
AnswerPiecePacket,
DanswerDocument,
DocumentInfoPacket,
ErrorMessagePacket,
LLMRelevanceFilterPacket,
QueryEventIdPacket,
Quote,
QuotesInfoPacket,
SearchRequestArgs,
@ -26,7 +26,7 @@ export const searchRequestStreamed = async ({
updateSuggestedFlowType,
updateSelectedDocIndices,
updateError,
updateQueryEventId,
updateMessageId,
}: SearchRequestArgs) => {
let answer = "";
let quotes: Quote[] | null = null;
@ -78,7 +78,7 @@ export const searchRequestStreamed = async ({
| QuotesInfoPacket
| DocumentInfoPacket
| LLMRelevanceFilterPacket
| QueryEventIdPacket
| BackendMessage
>(decoder.decode(value, { stream: true }), previousPartialChunk);
if (!completedChunks.length && !partialChunk) {
break;
@ -150,9 +150,9 @@ export const searchRequestStreamed = async ({
return;
}
// check for query ID section
if (Object.hasOwn(chunk, "query_event_id")) {
updateQueryEventId((chunk as QueryEventIdPacket).query_event_id);
// check for message ID section
if (Object.hasOwn(chunk, "message_id")) {
updateMessageId((chunk as BackendMessage).message_id);
return;
}