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

AgentMessageFeedbacks API #8879

Merged
merged 14 commits into from
Nov 27, 2024
9 changes: 5 additions & 4 deletions front/components/assistant/conversation/AgentMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {
ConversationMessageEmojiSelectorProps,
ConversationMessageFeedbackSelectorProps,
ConversationMessageSizeType,
} from "@dust-tt/sparkle";
import {
Expand All @@ -13,6 +13,7 @@ import {
ConversationMessage,
DocumentDuplicateIcon,
EyeIcon,
FeedbackSelector,
Markdown,
Popover,
} from "@dust-tt/sparkle";
Expand Down Expand Up @@ -83,7 +84,7 @@ interface AgentMessageProps {
isInModal: boolean;
isLastMessage: boolean;
message: AgentMessageType;
messageEmoji?: ConversationMessageEmojiSelectorProps;
messageFeedback: ConversationMessageFeedbackSelectorProps;
owner: WorkspaceType;
user: UserType;
size: ConversationMessageSizeType;
Expand All @@ -100,7 +101,7 @@ export function AgentMessage({
isInModal,
isLastMessage,
message,
messageEmoji,
messageFeedback,
owner,
user,
size,
Expand Down Expand Up @@ -368,6 +369,7 @@ export function AgentMessage({
icon={ArrowPathIcon}
disabled={isRetryHandlerProcessing || shouldStream}
/>,
<FeedbackSelector key="feedback-selector" {...messageFeedback} />,
];

// References logic.
Expand Down Expand Up @@ -464,7 +466,6 @@ export function AgentMessage({
name={`@${agentConfiguration.name}`}
buttons={buttons}
avatarBusy={agentMessageToRender.status === "created"}
messageEmoji={messageEmoji}
renderName={() => {
return (
<div className="flex flex-row items-center gap-2">
Expand Down
17 changes: 7 additions & 10 deletions front/components/assistant/conversation/ConversationViewer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ import {
} from "@app/lib/client/conversation/event_handlers";
import {
useConversation,
useConversationFeedbacks,
useConversationMessages,
useConversationParticipants,
useConversationReactions,
useConversations,
} from "@app/lib/swr/conversations";
import { classNames } from "@app/lib/utils";
Expand All @@ -39,7 +39,6 @@ const DEFAULT_PAGE_LIMIT = 50;

interface ConversationViewerProps {
conversationId: string;
hideReactions?: boolean;
isFading?: boolean;
isInModal?: boolean;
onStickyMentionsChange?: (mentions: AgentMention[]) => void;
Expand All @@ -62,7 +61,6 @@ const ConversationViewer = React.forwardRef<
conversationId,
onStickyMentionsChange,
isInModal = false,
hideReactions = false,
isFading = false,
},
ref
Expand Down Expand Up @@ -95,11 +93,6 @@ const ConversationViewer = React.forwardRef<
limit: DEFAULT_PAGE_LIMIT,
});

const { reactions } = useConversationReactions({
workspaceId: owner.sId,
conversationId,
});

const { mutateConversationParticipants } = useConversationParticipants({
conversationId,
workspaceId: owner.sId,
Expand Down Expand Up @@ -192,6 +185,11 @@ const ConversationViewer = React.forwardRef<

const { ref: viewRef, inView: isTopOfListVisible } = useInView();

const { feedbacks } = useConversationFeedbacks({
conversationId: conversationId ?? "",
workspaceId: owner.sId,
});

// On page load or when new data is loaded, check if the top of the list
// is visible and there is more data to load. If so, set the current
// highest message ID and increment the page number to load more data.
Expand Down Expand Up @@ -346,10 +344,9 @@ const ConversationViewer = React.forwardRef<
messages={typedGroup}
isLastMessageGroup={isLastGroup}
conversationId={conversationId}
hideReactions={hideReactions}
feedbacks={feedbacks}
isInModal={isInModal}
owner={owner}
reactions={reactions}
prevFirstMessageId={prevFirstMessageId}
prevFirstMessageRef={prevFirstMessageRef}
user={user}
Expand Down
13 changes: 6 additions & 7 deletions front/components/assistant/conversation/MessageGroup.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {
ConversationMessageReactions,
FetchConversationMessagesResponse,
MessageWithContentFragmentsType,
UserType,
Expand All @@ -8,15 +7,15 @@ import type {
import React, { useEffect, useRef } from "react";

import MessageItem from "@app/components/assistant/conversation/MessageItem";
import type { AgentMessageFeedbackType } from "@app/lib/api/assistant/feedback";

interface MessageGroupProps {
messages: MessageWithContentFragmentsType[];
isLastMessageGroup: boolean;
conversationId: string;
hideReactions: boolean;
feedbacks: AgentMessageFeedbackType[];
isInModal: boolean;
owner: WorkspaceType;
reactions: ConversationMessageReactions;
prevFirstMessageId: string | null;
prevFirstMessageRef: React.RefObject<HTMLDivElement>;
user: UserType;
Expand All @@ -33,10 +32,9 @@ export default function MessageGroup({
messages,
isLastMessageGroup,
conversationId,
hideReactions,
feedbacks,
isInModal,
owner,
reactions,
prevFirstMessageId,
prevFirstMessageRef,
user,
Expand Down Expand Up @@ -66,11 +64,12 @@ export default function MessageGroup({
<MessageItem
key={`message-${message.sId}`}
conversationId={conversationId}
hideReactions={hideReactions}
messageFeedback={feedbacks.find(
(feedback) => feedback.messageId === message.sId
)}
isInModal={isInModal}
message={message}
owner={owner}
reactions={reactions}
ref={
message.sId === prevFirstMessageId ? prevFirstMessageRef : undefined
}
Expand Down
64 changes: 38 additions & 26 deletions front/components/assistant/conversation/MessageItem.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { CitationType } from "@dust-tt/sparkle";
import type {
CitationType,
ConversationMessageFeedbackSelectorProps,
} from "@dust-tt/sparkle";
import { Citation, ZoomableImageCitationWrapper } from "@dust-tt/sparkle";
import { useSendNotification } from "@dust-tt/sparkle";
import type {
ConversationMessageReactions,
MessageWithContentFragmentsType,
UserType,
WorkspaceType,
Expand All @@ -12,62 +15,71 @@ import { useSWRConfig } from "swr";

import { AgentMessage } from "@app/components/assistant/conversation/AgentMessage";
import { UserMessage } from "@app/components/assistant/conversation/UserMessage";
import type { AgentMessageFeedbackType } from "@app/lib/api/assistant/feedback";
import { useSubmitFunction } from "@app/lib/client/utils";

interface MessageItemProps {
conversationId: string;
hideReactions: boolean;
messageFeedback: AgentMessageFeedbackType | undefined;
isInModal: boolean;
isLastMessage: boolean;
message: MessageWithContentFragmentsType;
owner: WorkspaceType;
reactions: ConversationMessageReactions;
user: UserType;
}

const MessageItem = React.forwardRef<HTMLDivElement, MessageItemProps>(
function MessageItem(
{
conversationId,
hideReactions,
messageFeedback,
isInModal,
isLastMessage,
message,
owner,
reactions,
user,
}: MessageItemProps,
ref
) {
const { sId, type } = message;
const sendNotification = useSendNotification();

const convoReactions = reactions.find((r) => r.messageId === sId);
const messageReactions = convoReactions?.reactions || [];
const { mutate } = useSWRConfig();
const { submit: onSubmitEmoji, isSubmitting: isSubmittingEmoji } =
const { submit: onSubmitThumb, isSubmitting: isSubmittingThumb } =
useSubmitFunction(
async ({
emoji,
thumb,
isToRemove,
feedbackContent,
}: {
emoji: string;
thumb: string;
isToRemove: boolean;
feedbackContent?: string | null;
}) => {
const res = await fetch(
`/api/w/${owner.sId}/assistant/conversations/${conversationId}/messages/${message.sId}/reactions`,
`/api/w/${owner.sId}/assistant/conversations/${conversationId}/messages/${message.sId}/feedbacks`,
{
method: isToRemove ? "DELETE" : "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
reaction: emoji,
thumbDirection: thumb,
feedbackContent,
}),
}
);
if (res.ok) {
if (feedbackContent && !isToRemove) {
sendNotification({
title: "Feedback submitted",
description:
"Your comment has been submitted successfully to the Builder of this assistant. Thank you!",
type: "success",
});
}
await mutate(
`/api/w/${owner.sId}/assistant/conversations/${conversationId}/reactions`
`/api/w/${owner.sId}/assistant/conversations/${conversationId}/feedbacks`
);
}
}
Expand All @@ -77,17 +89,17 @@ const MessageItem = React.forwardRef<HTMLDivElement, MessageItemProps>(
return null;
}

const messageEmoji = hideReactions
? undefined
: {
reactions: messageReactions.map((reaction) => ({
emoji: reaction.emoji,
hasReacted: reaction.users.some((u) => u.userId === user.id),
count: reaction.users.length,
})),
onSubmitEmoji,
isSubmittingEmoji,
};
const messageFeedbackWithSubmit: ConversationMessageFeedbackSelectorProps =
{
feedback: messageFeedback
? {
thumb: messageFeedback.thumbDirection,
feedbackContent: messageFeedback.content,
}
: null,
onSubmitThumb,
isSubmittingThumb,
};

switch (type) {
case "user_message":
Expand Down Expand Up @@ -152,7 +164,7 @@ const MessageItem = React.forwardRef<HTMLDivElement, MessageItemProps>(
isInModal={isInModal}
isLastMessage={isLastMessage}
message={message}
messageEmoji={messageEmoji}
messageFeedback={messageFeedbackWithSubmit}
owner={owner}
user={user}
size={isInModal ? "compact" : "normal"}
Expand Down
8 changes: 1 addition & 7 deletions front/components/assistant/conversation/UserMessage.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import type {
ConversationMessageEmojiSelectorProps,
ConversationMessageSizeType,
} from "@dust-tt/sparkle";
import type { ConversationMessageSizeType } from "@dust-tt/sparkle";
import { ConversationMessage, Markdown } from "@dust-tt/sparkle";
import type { UserMessageType, WorkspaceType } from "@dust-tt/types";
import { useMemo } from "react";
Expand All @@ -23,7 +20,6 @@ interface UserMessageProps {
conversationId: string;
isLastMessage: boolean;
message: UserMessageType;
messageEmoji?: ConversationMessageEmojiSelectorProps;
owner: WorkspaceType;
size: ConversationMessageSizeType;
}
Expand All @@ -33,7 +29,6 @@ export function UserMessage({
conversationId,
isLastMessage,
message,
messageEmoji,
owner,
size,
}: UserMessageProps) {
Expand All @@ -54,7 +49,6 @@ export function UserMessage({
<ConversationMessage
pictureUrl={message.user?.image || message.context.profilePictureUrl}
name={message.context.fullName}
messageEmoji={messageEmoji}
renderName={(name) => <div className="text-base font-medium">{name}</div>}
type="user"
citations={citations}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ export default function AssistantBuilderRightPanel({
conversationId={conversation.sId}
onStickyMentionsChange={setStickyMentions}
isInModal
hideReactions
isFading={isFading}
key={conversation.sId}
/>
Expand Down
4 changes: 4 additions & 0 deletions front/lib/api/assistant/conversation/destroy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { AgentWebsearchAction } from "@app/lib/models/assistant/actions/websearc
import type { Conversation } from "@app/lib/models/assistant/conversation";
import {
AgentMessage,
AgentMessageFeedback,
ConversationParticipant,
Mention,
Message,
Expand Down Expand Up @@ -154,6 +155,9 @@ export async function destroyConversation(
await UserMessage.destroy({
where: { id: userMessageIds },
});
await AgentMessageFeedback.destroy({
where: { agentMessageId: agentMessageIds },
});
Comment on lines +158 to +160
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to do something similar in temporal/activities deleteConversationsActivity ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There you go: eab4ed6 :)

await AgentMessage.destroy({
where: { id: agentMessageIds },
});
Expand Down
Loading
Loading