mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-05-28 12:39:54 +02:00
Just display docs if QA fails
This commit is contained in:
parent
0b8c69ceeb
commit
51e05e3948
@ -9,6 +9,7 @@ import {
|
||||
Notebook,
|
||||
Key,
|
||||
Trash,
|
||||
Info,
|
||||
} from "@phosphor-icons/react";
|
||||
|
||||
interface IconProps {
|
||||
@ -66,3 +67,10 @@ export const GoogleDriveIcon = ({
|
||||
}: IconProps) => {
|
||||
return <GoogleDriveLogo size={size} className={className} />;
|
||||
};
|
||||
|
||||
export const InfoIcon = ({
|
||||
size = "16",
|
||||
className = defaultTailwindCSS,
|
||||
}: IconProps) => {
|
||||
return <Info size={size} className={className} />;
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
import React from "react";
|
||||
import { Quote, Document } from "./types";
|
||||
import { Quote, Document, SearchResponse } from "./types";
|
||||
import { getSourceIcon } from "../source";
|
||||
import { LoadingAnimation } from "../Loading";
|
||||
import { InfoIcon } from "../icons/icons";
|
||||
|
||||
const removeDuplicateDocs = (documents: Document[]) => {
|
||||
const seen = new Set<string>();
|
||||
@ -19,33 +20,35 @@ const removeDuplicateDocs = (documents: Document[]) => {
|
||||
};
|
||||
|
||||
interface SearchResultsDisplayProps {
|
||||
answer: string | null;
|
||||
quotes: Record<string, Quote> | null;
|
||||
documents: Document[] | null;
|
||||
searchResponse: SearchResponse | null;
|
||||
isFetching: boolean;
|
||||
}
|
||||
|
||||
export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
|
||||
answer,
|
||||
quotes,
|
||||
documents,
|
||||
searchResponse,
|
||||
isFetching,
|
||||
}) => {
|
||||
if (!answer) {
|
||||
if (isFetching) {
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="mx-auto">
|
||||
<LoadingAnimation />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
if (!searchResponse) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (answer === null) {
|
||||
return <div>Unable to find an answer</div>;
|
||||
if (isFetching) {
|
||||
return (
|
||||
<div className="flex">
|
||||
<div className="mx-auto">
|
||||
<LoadingAnimation />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const { answer, quotes, documents } = searchResponse;
|
||||
if (answer === null && documents === null && quotes === null) {
|
||||
return (
|
||||
<div className="text-red-800">
|
||||
Something went wrong, please try again.
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const dedupedQuotes: Quote[] = [];
|
||||
@ -61,38 +64,53 @@ export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="p-4 border-2 rounded-md border-gray-700">
|
||||
<div className="flex mb-1">
|
||||
<h2 className="text font-bold my-auto">AI Answer</h2>
|
||||
</div>
|
||||
<p className="mb-4">{answer}</p>
|
||||
{answer && (
|
||||
<div className="p-4 border-2 rounded-md border-gray-700">
|
||||
<div className="flex mb-1">
|
||||
<h2 className="text font-bold my-auto">AI Answer</h2>
|
||||
</div>
|
||||
<p className="mb-4">{answer}</p>
|
||||
|
||||
{quotes !== null && (
|
||||
<>
|
||||
<h2 className="text-sm font-bold mb-2">Sources</h2>
|
||||
{isFetching && dedupedQuotes.length === 0 ? (
|
||||
<LoadingAnimation text="Finding quotes" size="text-sm" />
|
||||
) : (
|
||||
<div className="flex">
|
||||
{dedupedQuotes.map((quoteInfo) => (
|
||||
<a
|
||||
key={quoteInfo.document_id}
|
||||
className="p-2 ml-1 border border-gray-800 rounded-lg text-sm flex max-w-[230px] hover:bg-gray-800"
|
||||
href={quoteInfo.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{getSourceIcon(quoteInfo.source_type, "20")}
|
||||
<p className="truncate break-all ml-0.5">
|
||||
{quoteInfo.semantic_identifier || quoteInfo.document_id}
|
||||
</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!answer && !isFetching && (
|
||||
<div className="flex">
|
||||
<InfoIcon
|
||||
size="20"
|
||||
className="text-red-800 my-auto flex flex-shrink-0"
|
||||
/>
|
||||
<div className="text-red-800 text-xs my-auto ml-1">
|
||||
GPT hurt itself in its confusion :(
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{quotes !== null && (
|
||||
<>
|
||||
<h2 className="text-sm font-bold mb-2">Sources</h2>
|
||||
{isFetching && dedupedQuotes.length === 0 ? (
|
||||
<LoadingAnimation text="Finding quotes" size="text-sm" />
|
||||
) : (
|
||||
<div className="flex">
|
||||
{dedupedQuotes.map((quoteInfo) => (
|
||||
<a
|
||||
key={quoteInfo.document_id}
|
||||
className="p-2 ml-1 border border-gray-800 rounded-lg text-sm flex max-w-[230px] hover:bg-gray-800"
|
||||
href={quoteInfo.link}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{getSourceIcon(quoteInfo.source_type, "20")}
|
||||
<p className="truncate break-all ml-0.5">
|
||||
{quoteInfo.semantic_identifier || quoteInfo.document_id}
|
||||
</p>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{/* Only display docs once we're done fetching to avoid distracting from the AI answer*/}
|
||||
{!isFetching && documents && documents.length > 0 && (
|
||||
<div className="mt-4">
|
||||
@ -103,7 +121,7 @@ export const SearchResultsDisplay: React.FC<SearchResultsDisplayProps> = ({
|
||||
.slice(0, 7)
|
||||
.map((doc) => (
|
||||
<div
|
||||
key={doc.document_id}
|
||||
key={doc.semantic_identifier}
|
||||
className="text-sm border-b border-gray-800 mb-3"
|
||||
>
|
||||
<a
|
||||
|
@ -3,7 +3,13 @@
|
||||
import { useState } from "react";
|
||||
import { SearchBar } from "./SearchBar";
|
||||
import { SearchResultsDisplay } from "./SearchResultsDisplay";
|
||||
import { Quote, Document } from "./types";
|
||||
import { Quote, Document, SearchResponse } from "./types";
|
||||
|
||||
const initialSearchResponse: SearchResponse = {
|
||||
answer: null,
|
||||
quotes: null,
|
||||
documents: null,
|
||||
};
|
||||
|
||||
const processSingleChunk = (
|
||||
chunk: string,
|
||||
@ -99,9 +105,6 @@ const searchRequestStreamed = async (
|
||||
answer += answerChunk;
|
||||
updateCurrentAnswer(answer);
|
||||
} else if (chunk.answer_finished) {
|
||||
// set quotes as non-null to signify that the answer is finished and
|
||||
// we're now looking for quotes
|
||||
updateQuotes({});
|
||||
if (
|
||||
!answer.endsWith(".") &&
|
||||
!answer.endsWith("?") &&
|
||||
@ -129,9 +132,9 @@ const searchRequestStreamed = async (
|
||||
};
|
||||
|
||||
export const SearchSection: React.FC<{}> = () => {
|
||||
const [answer, setAnswer] = useState<string | null>("");
|
||||
const [quotes, setQuotes] = useState<Record<string, Quote> | null>(null);
|
||||
const [documents, setDocuments] = useState<Document[] | null>(null);
|
||||
const [searchResponse, setSearchResponse] = useState<SearchResponse | null>(
|
||||
null
|
||||
);
|
||||
const [isFetching, setIsFetching] = useState(false);
|
||||
|
||||
return (
|
||||
@ -139,26 +142,36 @@ export const SearchSection: React.FC<{}> = () => {
|
||||
<SearchBar
|
||||
onSearch={(query) => {
|
||||
setIsFetching(true);
|
||||
setAnswer(null);
|
||||
setQuotes(null);
|
||||
setDocuments(null);
|
||||
searchRequestStreamed(query, setAnswer, setQuotes, setDocuments).then(
|
||||
({ quotes }) => {
|
||||
setIsFetching(false);
|
||||
// if no quotes were given, set to empty object so that the SearchResultsDisplay
|
||||
// component knows that the search was successful but no quotes were found
|
||||
if (!quotes) {
|
||||
setQuotes({});
|
||||
}
|
||||
}
|
||||
);
|
||||
setSearchResponse({
|
||||
answer: null,
|
||||
quotes: null,
|
||||
documents: null,
|
||||
});
|
||||
searchRequestStreamed(
|
||||
query,
|
||||
(answer) =>
|
||||
setSearchResponse((prevState) => ({
|
||||
...(prevState || initialSearchResponse),
|
||||
answer,
|
||||
})),
|
||||
(quotes) =>
|
||||
setSearchResponse((prevState) => ({
|
||||
...(prevState || initialSearchResponse),
|
||||
quotes,
|
||||
})),
|
||||
(documents) =>
|
||||
setSearchResponse((prevState) => ({
|
||||
...(prevState || initialSearchResponse),
|
||||
documents,
|
||||
}))
|
||||
).then(() => {
|
||||
setIsFetching(false);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<div className="mt-2">
|
||||
<SearchResultsDisplay
|
||||
answer={answer}
|
||||
quotes={quotes}
|
||||
documents={documents}
|
||||
searchResponse={searchResponse}
|
||||
isFetching={isFetching}
|
||||
/>
|
||||
</div>
|
||||
|
@ -17,6 +17,7 @@ export interface Document {
|
||||
}
|
||||
|
||||
export interface SearchResponse {
|
||||
answer: string;
|
||||
quotes: Record<string, Quote>;
|
||||
answer: string | null;
|
||||
quotes: Record<string, Quote> | null;
|
||||
documents: Document[] | null;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user