ai-chatbot icon indicating copy to clipboard operation
ai-chatbot copied to clipboard

Images are not persistent on page refresh

Open conacts opened this issue 11 months ago • 3 comments

I tracked this back to convertToUIMessages extracting and removing the images from our messages from database (const messagesFromDb = await getMessagesByChatId({ id });).

Is there anyway to retain these images, possibly using convertToCoreMessages rather than convertToUIMessages? It seems we store our messages in our DB as Core Messages, what is the advantage to UI Messages over core messages?

https://github.com/user-attachments/assets/b3bca6cf-6f6d-4719-a91e-8c6ffddc3ef6

conacts avatar Jan 14 '25 18:01 conacts

I can raise a PR

I can raise the PR for this, I have this running on my own for with this implementation:

I just didn't because I didn't want to set up a new neon & blob db.

export function convertToUIMessages(messages: Array<DBMessage>): Array<Message> {
	return messages.reduce((chatMessages: Array<Message>, message) => {
		if (message.role === 'tool') {
			return addToolMessageToChat({
				toolMessage: message as CoreToolMessage,
				messages: chatMessages,
			});
		}

		let textContent = '';
		const toolInvocations: Array<ToolInvocation> = [];
		const experimental_attachments: Attachment[] = [];

		if (typeof message.content === 'string') {
			textContent = message.content;
		} else if (Array.isArray(message.content)) {
			for (const content of message.content) {
				if (content.type === 'text') {
					textContent += content.text;
				} else if (content.type === 'tool-call') {
					toolInvocations.push({
						state: 'call',
						toolCallId: content.toolCallId,
						toolName: content.toolName,
						args: content.args,
					});
				} else if (content.type === 'image' && content.image) {
					experimental_attachments.push({
						name: content.name,
						url: content.image,
						contentType: 'image',
					});
				}
			}
		}

		chatMessages.push({
			id: message.id,
			role: message.role as Message['role'],
			content: textContent,
			toolInvocations,
			experimental_attachments: experimental_attachments.length > 0 ? experimental_attachments : undefined,
		});

		return chatMessages;
	}, []);
}

conacts avatar Jan 14 '25 18:01 conacts

@conacts Do you actually get the correct name for the image after reloading the chat? In my case it seems like the content.name is not persistent and I need to fetch it from the url with url.split('/').pop().

michaelwlt avatar Jan 14 '25 21:01 michaelwlt

I faced the same issue and noticed, that attachment info won't even be saved to database. So i changed message saving in chat route:

await saveMessages({
    messages: [
      {
        content: [
          {
            type: 'text',
            text: userMessage.content,
            experimental_attachments: userMessage.experimental_attachments,
          },
        ],
        createdAt: new Date(),
        chatId: id,
        role: 'user',
        id: userMessage.id,
      },
    ],
  });

And then in convertToUIMessages added new item to chatMessages.push:

chatMessages.push({
      id: message.id,
      role: message.role as Message['role'],
      content: textContent,
      reasoning,
      toolInvocations,
      experimental_attachments:
        Array.isArray(message.content) &&
        message.content[0]?.experimental_attachments
          ? message.content[0].experimental_attachments
          : undefined,
    });

And now previews work fine

rovnyart avatar Feb 10 '25 13:02 rovnyart