Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update citations in shared chat display #3487

Merged
merged 4 commits into from
Dec 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions backend/onyx/server/query_and_chat/chat_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,15 @@ def get_chat_session(
description=chat_session.description,
persona_id=chat_session.persona_id,
persona_name=chat_session.persona.name if chat_session.persona else None,
persona_icon_color=chat_session.persona.icon_color
if chat_session.persona
else None,
persona_icon_shape=chat_session.persona.icon_shape
if chat_session.persona
else None,
current_alternate_model=chat_session.current_alternate_model,
messages=[
translate_db_message_to_chat_message_detail(
msg, remove_doc_content=is_shared # if shared, don't leak doc content
)
for msg in session_messages
translate_db_message_to_chat_message_detail(msg) for msg in session_messages
],
time_created=chat_session.time_created,
shared_status=chat_session.shared_status,
Expand Down
2 changes: 2 additions & 0 deletions backend/onyx/server/query_and_chat/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ class ChatSessionDetailResponse(BaseModel):
description: str | None
persona_id: int | None = None
persona_name: str | None
persona_icon_color: str | None
persona_icon_shape: int | None
messages: list[ChatMessageDetail]
time_created: datetime
shared_status: ChatSessionSharedStatus
Expand Down
1 change: 1 addition & 0 deletions web/src/app/chat/ChatPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2105,6 +2105,7 @@ export function ChatPage({
}
/>
)}

{sharingModalVisible && chatSessionIdRef.current !== null && (
<ShareChatSessionModal
message={message}
Expand Down
8 changes: 6 additions & 2 deletions web/src/app/chat/documentSidebar/ChatDocumentDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface DocumentDisplayProps {
isSelected: boolean;
handleSelect: (documentId: string) => void;
tokenLimitReached: boolean;
hideSelection?: boolean;
setPresentingDocument: Dispatch<SetStateAction<OnyxDocument | null>>;
}

Expand Down Expand Up @@ -62,6 +63,7 @@ export function ChatDocumentDisplay({
closeSidebar,
document,
modal,
hideSelection,
isSelected,
handleSelect,
tokenLimitReached,
Expand All @@ -76,7 +78,9 @@ export function ChatDocumentDisplay({
const hasMetadata =
document.updated_at || Object.keys(document.metadata).length > 0;
return (
<div className={`opacity-100 ${modal ? "w-[90vw]" : "w-full"}`}>
<div
className={`max-w-[400px] opacity-100 ${modal ? "w-[90vw]" : "w-full"}`}
>
<div
className={`flex relative flex-col gap-0.5 rounded-xl mx-2 my-1 ${
isSelected ? "bg-gray-200" : "hover:bg-background-125"
Expand Down Expand Up @@ -115,7 +119,7 @@ export function ChatDocumentDisplay({
)}
</div>
<div className="absolute top-2 right-2">
{!isInternet && (
{!isInternet && !hideSelection && (
<DocumentSelector
isSelected={isSelected}
handleSelect={() => handleSelect(document.document_id)}
Expand Down
10 changes: 7 additions & 3 deletions web/src/app/chat/documentSidebar/ChatFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { SourceSelector } from "../shared_chat_search/SearchFilters";
import { XIcon } from "@/components/icons/icons";

interface ChatFiltersProps {
filterManager: FilterManager;
filterManager?: FilterManager;
closeSidebar: () => void;
selectedMessage: Message | null;
selectedDocuments: OnyxDocument[] | null;
Expand All @@ -27,6 +27,7 @@ interface ChatFiltersProps {
maxTokens: number;
initialWidth: number;
isOpen: boolean;
isSharedChat?: boolean;
modal: boolean;
ccPairs: CCPairBasicInfo[];
tags: Tag[];
Expand All @@ -48,6 +49,7 @@ export const ChatFilters = forwardRef<HTMLDivElement, ChatFiltersProps>(
selectedDocumentTokens,
maxTokens,
initialWidth,
isSharedChat,
isOpen,
ccPairs,
tags,
Expand Down Expand Up @@ -79,13 +81,14 @@ export const ChatFilters = forwardRef<HTMLDivElement, ChatFiltersProps>(
const dedupedDocuments = removeDuplicateDocs(currentDocuments || []);

const tokenLimitReached = selectedDocumentTokens > maxTokens - 75;
console.log("SELECTED MESSAGE is", selectedMessage);

const hasSelectedDocuments = selectedDocumentIds.length > 0;

return (
<div
id="onyx-chat-sidebar"
className={`relative max-w-full ${
className={`relative bg-background max-w-full ${
!modal ? "border-l h-full border-sidebar-border" : ""
}`}
onClick={(e) => {
Expand Down Expand Up @@ -122,10 +125,10 @@ export const ChatFilters = forwardRef<HTMLDivElement, ChatFiltersProps>(
<div className="overflow-y-auto -mx-1 sm:mx-0 flex-grow gap-y-0 default-scrollbar dark-scrollbar flex flex-col">
{showFilters ? (
<SourceSelector
{...filterManager!}
modal={modal}
tagsOnLeft={true}
filtersUntoggled={false}
{...filterManager}
availableDocumentSets={documentSets}
existingSources={ccPairs.map((ccPair) => ccPair.source)}
availableTags={tags}
Expand Down Expand Up @@ -157,6 +160,7 @@ export const ChatFilters = forwardRef<HTMLDivElement, ChatFiltersProps>(
)!
);
}}
hideSelection={isSharedChat}
tokenLimitReached={tokenLimitReached}
/>
</div>
Expand Down
2 changes: 2 additions & 0 deletions web/src/app/chat/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ export interface BackendChatSession {
description: string;
persona_id: number;
persona_name: string;
persona_icon_color: string | null;
persona_icon_shape: number | null;
messages: BackendMessage[];
time_created: string;
shared_status: ChatSessionSharedStatus;
Expand Down
20 changes: 15 additions & 5 deletions web/src/app/chat/message/MemoizedTextComponents.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Citation } from "@/components/search/results/Citation";
import { WebResultIcon } from "@/components/WebResultIcon";
import { LoadedOnyxDocument } from "@/lib/search/interfaces";
import { LoadedOnyxDocument, OnyxDocument } from "@/lib/search/interfaces";
import { getSourceMetadata, SOURCE_METADATA_MAP } from "@/lib/sources";
import { ValidSources } from "@/lib/types";
import React, { memo } from "react";
Expand All @@ -9,7 +9,15 @@ import { SlackIcon } from "@/components/icons/icons";
import { SourceIcon } from "@/components/SourceIcon";

export const MemoizedAnchor = memo(
({ docs, updatePresentingDocument, children }: any) => {
({
docs,
updatePresentingDocument,
children,
}: {
docs?: OnyxDocument[] | null;
updatePresentingDocument: (doc: OnyxDocument) => void;
children: React.ReactNode;
}) => {
const value = children?.toString();
if (value?.startsWith("[") && value?.endsWith("]")) {
const match = value.match(/\[(\d+)\]/);
Expand All @@ -21,9 +29,11 @@ export const MemoizedAnchor = memo(
? new URL(associatedDoc.link).origin + "/favicon.ico"
: "";

const icon = (
<SourceIcon sourceType={associatedDoc?.source_type} iconSize={18} />
);
const icon =
(associatedDoc && (
<SourceIcon sourceType={associatedDoc?.source_type} iconSize={18} />
)) ||
null;

return (
<MemoizedLink
Expand Down
28 changes: 12 additions & 16 deletions web/src/app/chat/message/Messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ export const AIMessage = ({
const anchorCallback = useCallback(
(props: any) => (
<MemoizedAnchor
updatePresentingDocument={setPresentingDocument}
updatePresentingDocument={setPresentingDocument!}
docs={docs}
>
{props.children}
Expand Down Expand Up @@ -369,6 +369,7 @@ export const AIMessage = ({
onMessageSelection &&
otherMessagesCanSwitchTo &&
otherMessagesCanSwitchTo.length > 1;

return (
<div
id="onyx-ai-message"
Expand All @@ -393,21 +394,16 @@ export const AIMessage = ({
<div className="max-w-message-max break-words">
{!toolCall || toolCall.tool_name === SEARCH_TOOL_NAME ? (
<>
{query !== undefined &&
handleShowRetrieved !== undefined &&
!retrievalDisabled && (
<div className="mb-1">
<SearchSummary
index={index || 0}
query={query}
finished={toolCall?.tool_result != undefined}
hasDocs={hasDocs || false}
messageId={messageId}
handleShowRetrieved={handleShowRetrieved}
handleSearchQueryEdit={handleSearchQueryEdit}
/>
</div>
)}
{query !== undefined && !retrievalDisabled && (
<div className="mb-1">
<SearchSummary
index={index || 0}
query={query}
finished={toolCall?.tool_result != undefined}
handleSearchQueryEdit={handleSearchQueryEdit}
/>
</div>
)}
{handleForceSearch &&
content &&
query === undefined &&
Expand Down
6 changes: 0 additions & 6 deletions web/src/app/chat/message/SearchSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,12 @@ export function ShowHideDocsButton({
export function SearchSummary({
index,
query,
hasDocs,
finished,
messageId,
handleShowRetrieved,
handleSearchQueryEdit,
}: {
index: number;
finished: boolean;
query: string;
hasDocs: boolean;
messageId: number | null;
handleShowRetrieved: (messageId: number | null) => void;
handleSearchQueryEdit?: (query: string) => void;
}) {
const [isEditing, setIsEditing] = useState(false);
Expand Down
27 changes: 12 additions & 15 deletions web/src/app/chat/modal/ShareChatSessionModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ async function generateShareLink(chatSessionId: string) {
return null;
}

async function generateCloneLink(
async function generateSeedLink(
message?: string,
assistantId?: number,
modelOverride?: LlmOverride
Expand Down Expand Up @@ -115,7 +115,7 @@ export function ShareChatSessionModal({
{shareLink ? (
<div>
<Text>
This chat session is currently shared. Anyone at your
This chat session is currently shared. Anyone in your
organization can view the message history using the following
link:
</Text>
Expand Down Expand Up @@ -157,10 +157,8 @@ export function ShareChatSessionModal({
) : (
<div>
<Callout type="warning" title="Warning" className="mb-4">
Ensure that all content in the chat is safe to share with the
whole organization. The content of the retrieved documents
will not be visible, but the names of cited documents as well
as the AI and human messages will be visible.
Please make sure that all content in this chat is safe to
share with the whole organization.
</Callout>
<div className="flex w-full justify-between">
<Button
Expand Down Expand Up @@ -194,10 +192,9 @@ export function ShareChatSessionModal({

<Separator className="my-4" />
<div className="mb-4">
<Callout type="notice" title="Clone Chat">
Generate a link to clone this chat session with the current query.
This allows others to start a new chat with the same initial
message and settings.
<Callout type="notice" title="Seed New Chat">
Generate a link to a new chat session with the same settings as
this chat (including the assistant and model).
</Callout>
</div>
<div className="flex w-full justify-between">
Expand All @@ -207,18 +204,18 @@ export function ShareChatSessionModal({
// NOTE: for "insecure" non-https setup, the `navigator.clipboard.writeText` may fail
// as the browser may not allow the clipboard to be accessed.
try {
const cloneLink = await generateCloneLink(
const seedLink = await generateSeedLink(
message,
assistantId,
modelOverride
);
if (!cloneLink) {
if (!seedLink) {
setPopup({
message: "Failed to generate clone link",
message: "Failed to generate seed link",
type: "error",
});
} else {
navigator.clipboard.writeText(cloneLink);
navigator.clipboard.writeText(seedLink);
setPopup({
message: "Link copied to clipboard!",
type: "success",
Expand All @@ -232,7 +229,7 @@ export function ShareChatSessionModal({
size="sm"
variant="secondary"
>
Generate and Copy Clone Link
Generate and Copy Seed Link
</Button>
</div>
</>
Expand Down
Loading
Loading