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