refactor: able to use ChatMessage independently (#23)

---------
Co-authored-by: Thuc Pham <51660321+thucpn@users.noreply.github.com>
This commit is contained in:
Marcus Schiesser
2024-11-12 11:09:44 +08:00
committed by GitHub
parent ace0c06547
commit fa3537b378
7 changed files with 58 additions and 38 deletions
+6
View File
@@ -0,0 +1,6 @@
---
'web': patch
'@llamaindex/chat-ui': patch
---
make chat message component stand alone without provider
+6 -2
View File
@@ -122,7 +122,7 @@ function Annotation({ annotations }: { annotations: any }) {
}
function CustomChatMessagesList() {
const { messages } = useChatUI()
const { messages, isLoading, append } = useChatUI()
return (
<ChatMessages.List>
{messages.map((message, index) => (
@@ -139,7 +139,11 @@ function CustomChatMessagesList() {
<img alt="LlamaIndex" src="/llama.png" />
)}
</ChatMessage.Avatar>
<ChatMessage.Content className="items-start">
<ChatMessage.Content
className="items-start"
isLoading={isLoading}
append={append}
>
<Markdown content={message.content} />
<Annotation annotations={message.annotations} />
</ChatMessage.Content>
+10 -17
View File
@@ -17,24 +17,22 @@ import {
MessageAnnotationType,
SuggestedQuestionsData,
} from './annotation'
import { useChatUI } from './chat.context'
import { Message } from './chat.interface'
import { ChatHandler, Message } from './chat.interface'
export function EventAnnotations({
message,
isLast,
showLoading,
}: {
message: Message
isLast: boolean
showLoading: boolean
}) {
const { isLoading } = useChatUI()
const annotations = message.annotations as MessageAnnotation[] | undefined
const eventData =
annotations && annotations.length > 0
? getAnnotationData<EventData>(annotations, MessageAnnotationType.EVENTS)
: null
if (!eventData?.length) return null
return <ChatEvents data={eventData} isLast={isLast} isLoading={isLoading} />
return <ChatEvents data={eventData} showLoading={showLoading} />
}
export function AgentEventAnnotations({ message }: { message: Message }) {
@@ -90,12 +88,11 @@ export function SourceAnnotations({ message }: { message: Message }) {
export function SuggestedQuestionsAnnotations({
message,
isLast,
append,
}: {
message: Message
isLast: boolean
append: ChatHandler['append']
}) {
const { append } = useChatUI()
const annotations = message.annotations as MessageAnnotation[] | undefined
const suggestedQuestionsData =
annotations && annotations.length > 0
@@ -104,12 +101,8 @@ export function SuggestedQuestionsAnnotations({
MessageAnnotationType.SUGGESTED_QUESTIONS
)
: null
if (!suggestedQuestionsData) return null
return suggestedQuestionsData[0] ? (
<SuggestedQuestions
questions={suggestedQuestionsData[0]}
append={append}
isLastMessage={isLast}
/>
) : null
if (!suggestedQuestionsData?.[0]) return null
return (
<SuggestedQuestions questions={suggestedQuestionsData[0]} append={append} />
)
}
+28 -7
View File
@@ -13,12 +13,14 @@ import {
SourceAnnotations,
SuggestedQuestionsAnnotations,
} from './chat-annotations'
import { Message } from './chat.interface'
import { ChatHandler, Message } from './chat.interface'
interface ChatMessageProps extends React.PropsWithChildren {
message: Message
isLast: boolean
className?: string
isLoading?: boolean
append?: ChatHandler['append']
}
interface ChatMessageAvatarProps extends React.PropsWithChildren {
@@ -53,6 +55,8 @@ type ContentDisplayConfig = {
interface ChatMessageContentProps extends React.PropsWithChildren {
className?: string
content?: ContentDisplayConfig[]
isLoading?: boolean
append?: ChatHandler['append']
}
interface ChatMessageActionsProps extends React.PropsWithChildren {
@@ -79,7 +83,7 @@ function ChatMessage(props: ChatMessageProps) {
const children = props.children ?? (
<>
<ChatMessageAvatar />
<ChatMessageContent />
<ChatMessageContent isLoading={props.isLoading} append={props.append} />
<ChatMessageActions />
</>
)
@@ -123,7 +127,10 @@ function ChatMessageContent(props: ChatMessageContentProps) {
[key in ContentPosition]?: React.ReactNode | null
} = {
[ContentPosition.CHAT_EVENTS]: (
<EventAnnotations message={message} isLast={isLast} />
<EventAnnotations
message={message}
showLoading={(isLast && props.isLoading) ?? false}
/>
),
[ContentPosition.CHAT_AGENT_EVENTS]: (
<AgentEventAnnotations message={message} />
@@ -141,9 +148,16 @@ function ChatMessageContent(props: ChatMessageContentProps) {
<DocumentFileAnnotations message={message} />
),
[ContentPosition.CHAT_SOURCES]: <SourceAnnotations message={message} />,
[ContentPosition.SUGGESTED_QUESTIONS]: (
<SuggestedQuestionsAnnotations message={message} isLast={isLast} />
),
...(isLast &&
props.append && {
// show suggested questions only on the last message
[ContentPosition.SUGGESTED_QUESTIONS]: (
<SuggestedQuestionsAnnotations
message={message}
append={props.append}
/>
),
}),
}
// Override the default display map with the custom content
@@ -155,7 +169,14 @@ function ChatMessageContent(props: ChatMessageContentProps) {
position: parseInt(position),
component,
}))
}, [annotations, isLast, message, props.content])
}, [
annotations,
isLast,
message,
props.append,
props.content,
props.isLoading,
])
const children = props.children ?? (
<>
+3 -1
View File
@@ -84,7 +84,7 @@ function ChatMessages(props: ChatMessagesProps) {
function ChatMessagesList(props: ChatMessagesListProps) {
const scrollableChatContainerRef = useRef<HTMLDivElement>(null)
const { messages } = useChatUI()
const { messages, isLoading, append } = useChatUI()
const { lastMessage, messageLength } = useChatMessages()
const scrollToBottom = () => {
@@ -106,6 +106,8 @@ function ChatMessagesList(props: ChatMessagesListProps) {
key={index}
message={message}
isLast={index === messageLength - 1}
isLoading={isLoading}
append={append}
/>
)
})}
+2 -5
View File
@@ -10,16 +10,13 @@ import { EventData } from '../chat/annotation'
export function ChatEvents({
data,
isLast,
isLoading,
showLoading,
}: {
data: EventData[]
isLast: boolean
isLoading: boolean
showLoading: boolean
}) {
const [isOpen, setIsOpen] = useState(false)
const showLoading = isLast && isLoading
const buttonLabel = isOpen ? 'Hide events' : 'Show events'
const EventIcon = isOpen ? (
@@ -4,16 +4,13 @@ import { ChatHandler } from '../chat/chat.interface'
export function SuggestedQuestions({
questions,
append,
isLastMessage,
}: {
questions: SuggestedQuestionsData
append?: Pick<ChatHandler, 'append'>['append']
isLastMessage: boolean
append: ChatHandler['append']
}) {
const showQuestions = isLastMessage && questions.length > 0
const showQuestions = questions.length > 0
return (
showQuestions &&
append !== undefined && (
showQuestions && (
<div className="flex flex-col space-y-2">
{questions.map((question, index) => (
<a