mirror of
https://github.com/danswer-ai/danswer.git
synced 2025-04-07 11:28:09 +02:00
Improve FE for no-retrieval personas
This commit is contained in:
parent
927e85319c
commit
61e2e68cf9
@ -5,7 +5,7 @@ personas:
|
||||
# this is for DanswerBot to use when tagged in a non-configured channel
|
||||
# Careful setting specific IDs, this won't autoincrement the next ID value for postgres
|
||||
- id: 0
|
||||
name: "Knowledge Assistant"
|
||||
name: "Danswer"
|
||||
description: >
|
||||
Assistant with access to documents from your Connected Sources.
|
||||
# Default Prompt objects attached to the persona, see prompts.yaml
|
||||
@ -40,7 +40,7 @@ personas:
|
||||
|
||||
|
||||
- id: 1
|
||||
name: "AI Assistant (No Sources)"
|
||||
name: "GPT"
|
||||
description: >
|
||||
Assistant with no access to documents. Chat with just the Language Model.
|
||||
prompts:
|
||||
@ -53,7 +53,7 @@ personas:
|
||||
|
||||
|
||||
- id: 2
|
||||
name: "Paraphrase Assistant"
|
||||
name: "Paraphrase"
|
||||
description: >
|
||||
Assistant that is heavily constrained and only provides exact quotes from Connected Sources.
|
||||
prompts:
|
||||
|
@ -214,9 +214,27 @@ function smallerNumberFirstComparator(a: number, b: number) {
|
||||
return a > b ? 1 : -1;
|
||||
}
|
||||
|
||||
function closerToZeroNegativesFirstComparator(a: number, b: number) {
|
||||
if (a < 0 && b > 0) {
|
||||
return -1;
|
||||
}
|
||||
if (a > 0 && b < 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
const absA = Math.abs(a);
|
||||
const absB = Math.abs(b);
|
||||
|
||||
if (absA === absB) {
|
||||
return a > b ? 1 : -1;
|
||||
}
|
||||
|
||||
return absA > absB ? 1 : -1;
|
||||
}
|
||||
|
||||
export function personaComparator(a: Persona, b: Persona) {
|
||||
if (a.display_priority === null && b.display_priority === null) {
|
||||
return smallerNumberFirstComparator(a.id, b.id);
|
||||
return closerToZeroNegativesFirstComparator(a.id, b.id);
|
||||
}
|
||||
|
||||
if (a.display_priority !== b.display_priority) {
|
||||
@ -230,5 +248,5 @@ export function personaComparator(a: Persona, b: Persona) {
|
||||
return smallerNumberFirstComparator(a.display_priority, b.display_priority);
|
||||
}
|
||||
|
||||
return smallerNumberFirstComparator(a.id, b.id);
|
||||
return closerToZeroNegativesFirstComparator(a.id, b.id);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import {
|
||||
handleAutoScroll,
|
||||
handleChatFeedback,
|
||||
nameChatSession,
|
||||
personaIncludesRetrieval,
|
||||
processRawChatHistory,
|
||||
sendMessage,
|
||||
} from "./lib";
|
||||
@ -172,7 +173,7 @@ export const Chat = ({
|
||||
const livePersona = selectedPersona || availablePersonas[0];
|
||||
|
||||
useEffect(() => {
|
||||
if (messageHistory.length === 0) {
|
||||
if (messageHistory.length === 0 && chatSessionId === null) {
|
||||
setSelectedPersona(
|
||||
availablePersonas.find(
|
||||
(persona) => persona.id === defaultSelectedPersonaId
|
||||
@ -480,6 +481,10 @@ export const Chat = ({
|
||||
}
|
||||
};
|
||||
|
||||
const retrievalDisabled = selectedPersona
|
||||
? !personaIncludesRetrieval(selectedPersona)
|
||||
: false;
|
||||
|
||||
return (
|
||||
<div className="flex w-full overflow-x-hidden" ref={masterFlexboxRef}>
|
||||
{popup}
|
||||
@ -510,6 +515,7 @@ export const Chat = ({
|
||||
onPersonaChange={(persona) => {
|
||||
if (persona) {
|
||||
setSelectedPersona(persona);
|
||||
textareaRef.current?.focus();
|
||||
router.push(`/chat?personaId=${persona.id}`);
|
||||
}
|
||||
}}
|
||||
@ -527,6 +533,7 @@ export const Chat = ({
|
||||
selectedPersona={selectedPersona}
|
||||
handlePersonaSelect={(persona) => {
|
||||
setSelectedPersona(persona);
|
||||
textareaRef.current?.focus();
|
||||
router.push(`/chat?personaId=${persona.id}`);
|
||||
}}
|
||||
/>
|
||||
@ -630,6 +637,7 @@ export const Chat = ({
|
||||
});
|
||||
}
|
||||
}}
|
||||
retrievalDisabled={retrievalDisabled}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -682,22 +690,24 @@ export const Chat = ({
|
||||
|
||||
<div className="absolute bottom-0 z-10 w-full bg-background border-t border-border">
|
||||
<div className="w-full pb-4 pt-2">
|
||||
<div className="flex">
|
||||
<div className="w-searchbar-xs 2xl:w-searchbar-sm 3xl:w-searchbar mx-auto px-4 pt-1 flex">
|
||||
{selectedDocuments.length > 0 ? (
|
||||
<SelectedDocuments
|
||||
selectedDocuments={selectedDocuments}
|
||||
/>
|
||||
) : (
|
||||
<ChatFilters
|
||||
{...filterManager}
|
||||
existingSources={finalAvailableSources}
|
||||
availableDocumentSets={finalAvailableDocumentSets}
|
||||
availableTags={availableTags}
|
||||
/>
|
||||
)}
|
||||
{!retrievalDisabled && (
|
||||
<div className="flex">
|
||||
<div className="w-searchbar-xs 2xl:w-searchbar-sm 3xl:w-searchbar mx-auto px-4 pt-1 flex">
|
||||
{selectedDocuments.length > 0 ? (
|
||||
<SelectedDocuments
|
||||
selectedDocuments={selectedDocuments}
|
||||
/>
|
||||
) : (
|
||||
<ChatFilters
|
||||
{...filterManager}
|
||||
existingSources={finalAvailableSources}
|
||||
availableDocumentSets={finalAvailableDocumentSets}
|
||||
availableTags={availableTags}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex justify-center py-2 max-w-screen-lg mx-auto mb-2">
|
||||
<div className="w-full shrink relative px-4 w-searchbar-xs 2xl:w-searchbar-sm 3xl:w-searchbar mx-auto">
|
||||
@ -785,21 +795,26 @@ export const Chat = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ResizableSection
|
||||
intialWidth={documentSidebarInitialWidth}
|
||||
minWidth={400}
|
||||
maxWidth={maxDocumentSidebarWidth || undefined}
|
||||
>
|
||||
<DocumentSidebar
|
||||
selectedMessage={aiMessage}
|
||||
selectedDocuments={selectedDocuments}
|
||||
toggleDocumentSelection={toggleDocumentSelection}
|
||||
clearSelectedDocuments={clearSelectedDocuments}
|
||||
selectedDocumentTokens={selectedDocumentTokens}
|
||||
maxTokens={maxTokens}
|
||||
isLoading={isFetchingChatMessages}
|
||||
/>
|
||||
</ResizableSection>
|
||||
{!retrievalDisabled ? (
|
||||
<ResizableSection
|
||||
intialWidth={documentSidebarInitialWidth}
|
||||
minWidth={400}
|
||||
maxWidth={maxDocumentSidebarWidth || undefined}
|
||||
>
|
||||
<DocumentSidebar
|
||||
selectedMessage={aiMessage}
|
||||
selectedDocuments={selectedDocuments}
|
||||
toggleDocumentSelection={toggleDocumentSelection}
|
||||
clearSelectedDocuments={clearSelectedDocuments}
|
||||
selectedDocumentTokens={selectedDocumentTokens}
|
||||
maxTokens={maxTokens}
|
||||
isLoading={isFetchingChatMessages}
|
||||
/>
|
||||
</ResizableSection>
|
||||
) : // Another option is to use a div with the width set to the initial width, so that the
|
||||
// chat section appears in the same place as before
|
||||
// <div style={documentSidebarInitialWidth ? {width: documentSidebarInitialWidth} : {}}></div>
|
||||
null}
|
||||
</>
|
||||
) : (
|
||||
<div className="mx-auto h-full flex flex-col">
|
||||
|
@ -124,63 +124,67 @@ export function ChatIntro({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Divider />
|
||||
<div>
|
||||
{selectedPersona && selectedPersona.document_sets.length > 0 && (
|
||||
<div className="mt-2">
|
||||
<p className="font-bold mb-1 mt-4 text-emphasis">
|
||||
Knowledge Sets:{" "}
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-x-2">
|
||||
{selectedPersona.document_sets.map((documentSet) => (
|
||||
<div key={documentSet.id} className="w-fit">
|
||||
<HoverPopup
|
||||
mainContent={
|
||||
<span className="flex w-fit p-1 rounded border border-border text-xs font-medium cursor-default">
|
||||
<div className="mr-1 my-auto">
|
||||
<FiBookmark />
|
||||
</div>
|
||||
{documentSet.name}
|
||||
</span>
|
||||
}
|
||||
popupContent={
|
||||
<div className="flex py-1 w-96">
|
||||
<FiInfo className="my-auto mr-2" />
|
||||
<div className="text-sm">
|
||||
{documentSet.description}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
direction="top"
|
||||
/>
|
||||
{selectedPersona && selectedPersona.num_chunks !== 0 && (
|
||||
<>
|
||||
<Divider />
|
||||
<div>
|
||||
{selectedPersona.document_sets.length > 0 && (
|
||||
<div className="mt-2">
|
||||
<p className="font-bold mb-1 mt-4 text-emphasis">
|
||||
Knowledge Sets:{" "}
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-x-2">
|
||||
{selectedPersona.document_sets.map((documentSet) => (
|
||||
<div key={documentSet.id} className="w-fit">
|
||||
<HoverPopup
|
||||
mainContent={
|
||||
<span className="flex w-fit p-1 rounded border border-border text-xs font-medium cursor-default">
|
||||
<div className="mr-1 my-auto">
|
||||
<FiBookmark />
|
||||
</div>
|
||||
{documentSet.name}
|
||||
</span>
|
||||
}
|
||||
popupContent={
|
||||
<div className="flex py-1 w-96">
|
||||
<FiInfo className="my-auto mr-2" />
|
||||
<div className="text-sm">
|
||||
{documentSet.description}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
direction="top"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{availableSources.length > 0 && (
|
||||
<div className="mt-2">
|
||||
<p className="font-bold mb-1 mt-4 text-emphasis">
|
||||
Connected Sources:{" "}
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-x-2">
|
||||
{availableSourceMetadata.map((sourceMetadata) => (
|
||||
<span
|
||||
key={sourceMetadata.internalName}
|
||||
className="flex w-fit p-1 rounded border border-border text-xs font-medium cursor-default"
|
||||
>
|
||||
<div className="mr-1 my-auto">
|
||||
{sourceMetadata.icon({})}
|
||||
</div>
|
||||
<div className="my-auto">
|
||||
{sourceMetadata.displayName}
|
||||
</div>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{availableSources.length > 0 && (
|
||||
<div className="mt-2">
|
||||
<p className="font-bold mb-1 mt-4 text-emphasis">
|
||||
Connected Sources:{" "}
|
||||
</p>
|
||||
<div className="flex flex-wrap gap-x-2">
|
||||
{availableSourceMetadata.map((sourceMetadata) => (
|
||||
<span
|
||||
key={sourceMetadata.internalName}
|
||||
className="flex w-fit p-1 rounded border border-border text-xs font-medium cursor-default"
|
||||
>
|
||||
<div className="mr-1 my-auto">
|
||||
{sourceMetadata.icon({})}
|
||||
</div>
|
||||
<div className="my-auto">
|
||||
{sourceMetadata.displayName}
|
||||
</div>
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="px-12 w-searchbar-xs 2xl:w-searchbar-sm 3xl:w-searchbar">
|
||||
|
@ -14,6 +14,7 @@ import {
|
||||
RetrievalType,
|
||||
StreamingError,
|
||||
} from "./interfaces";
|
||||
import { Persona } from "../admin/personas/interfaces";
|
||||
|
||||
export async function createChatSession(personaId: number): Promise<number> {
|
||||
const createChatSessionResponse = await fetch(
|
||||
@ -349,3 +350,7 @@ export function processRawChatHistory(rawMessages: BackendMessage[]) {
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
export function personaIncludesRetrieval(selectedPersona: Persona) {
|
||||
return selectedPersona.num_chunks !== 0;
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import { SearchSummary, ShowHideDocsButton } from "./SearchSummary";
|
||||
import { SourceIcon } from "@/components/SourceIcon";
|
||||
import { ThreeDots } from "react-loader-spinner";
|
||||
import { SkippedSearch } from "./SkippedSearch";
|
||||
import { SelectedDocuments } from "../modifiers/SelectedDocuments";
|
||||
|
||||
export const Hoverable: React.FC<{
|
||||
children: JSX.Element;
|
||||
@ -42,6 +41,7 @@ export const AIMessage = ({
|
||||
handleShowRetrieved,
|
||||
handleSearchQueryEdit,
|
||||
handleForceSearch,
|
||||
retrievalDisabled,
|
||||
}: {
|
||||
messageId: number | null;
|
||||
content: string | JSX.Element;
|
||||
@ -54,6 +54,7 @@ export const AIMessage = ({
|
||||
handleShowRetrieved?: (messageNumber: number | null) => void;
|
||||
handleSearchQueryEdit?: (query: string) => void;
|
||||
handleForceSearch?: () => void;
|
||||
retrievalDisabled?: boolean;
|
||||
}) => {
|
||||
const [copyClicked, setCopyClicked] = useState(false);
|
||||
return (
|
||||
@ -72,7 +73,8 @@ export const AIMessage = ({
|
||||
{query === undefined &&
|
||||
hasDocs &&
|
||||
handleShowRetrieved !== undefined &&
|
||||
isCurrentlyShowingRetrieved !== undefined && (
|
||||
isCurrentlyShowingRetrieved !== undefined &&
|
||||
!retrievalDisabled && (
|
||||
<div className="flex w-message-xs 2xl:w-message-sm 3xl:w-message-default absolute ml-8">
|
||||
<div className="ml-auto">
|
||||
<ShowHideDocsButton
|
||||
@ -88,7 +90,8 @@ export const AIMessage = ({
|
||||
<div className="w-message-xs 2xl:w-message-sm 3xl:w-message-default break-words mt-1 ml-8">
|
||||
{query !== undefined &&
|
||||
handleShowRetrieved !== undefined &&
|
||||
isCurrentlyShowingRetrieved !== undefined && (
|
||||
isCurrentlyShowingRetrieved !== undefined &&
|
||||
!retrievalDisabled && (
|
||||
<div className="my-1">
|
||||
<SearchSummary
|
||||
query={query}
|
||||
@ -103,7 +106,8 @@ export const AIMessage = ({
|
||||
{handleForceSearch &&
|
||||
content &&
|
||||
query === undefined &&
|
||||
!hasDocs && (
|
||||
!hasDocs &&
|
||||
!retrievalDisabled && (
|
||||
<div className="my-1">
|
||||
<SkippedSearch handleForceSearch={handleForceSearch} />
|
||||
</div>
|
||||
|
@ -95,6 +95,8 @@ export default async function Home() {
|
||||
}
|
||||
// remove those marked as hidden by an admin
|
||||
personas = personas.filter((persona) => persona.is_visible);
|
||||
// hide personas with no retrieval
|
||||
personas = personas.filter((persona) => persona.num_chunks !== 0);
|
||||
// sort them in priority order
|
||||
personas.sort(personaComparator);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user