From 467893db6709c63fff7013118d83e72b65dd1d3a Mon Sep 17 00:00:00 2001 From: Heiko Joerg Schick Date: Thu, 14 Dec 2023 20:39:19 +0100 Subject: [PATCH] Added GPT-4-vision --- components/Chat/Chat.tsx | 7 +- components/Chat/ChatInput.tsx | 251 ++++++++++++++++++++------------ components/Chat/ChatMessage.tsx | 33 +++-- pages/api/chat.ts | 3 +- types/chat.ts | 12 +- types/openai.ts | 9 +- utils/server/index.ts | 4 +- 7 files changed, 205 insertions(+), 114 deletions(-) diff --git a/components/Chat/Chat.tsx b/components/Chat/Chat.tsx index b7d782e..af97ac7 100644 --- a/components/Chat/Chat.tsx +++ b/components/Chat/Chat.tsx @@ -150,8 +150,9 @@ export const Chat = memo(({ stopConversationRef }: Props) => { if (!plugin) { if (updatedConversation.messages.length === 1) { const { content } = message; + var textContent = content.filter(c => c.type == "text").map(c => c.text).join(); const customName = - content.length > 30 ? content.substring(0, 30) + '...' : content; + textContent.length > 30 ? textContent.substring(0, 30) + '...' : textContent; updatedConversation = { ...updatedConversation, name: customName, @@ -177,7 +178,7 @@ export const Chat = memo(({ stopConversationRef }: Props) => { isFirst = false; const updatedMessages: Message[] = [ ...updatedConversation.messages, - { role: 'assistant', content: chunkValue }, + { role: 'assistant', content: [{type: "text", text: chunkValue}] }, ]; updatedConversation = { ...updatedConversation, @@ -193,7 +194,7 @@ export const Chat = memo(({ stopConversationRef }: Props) => { if (index === updatedConversation.messages.length - 1) { return { ...message, - content: text, + content: [{type:"text", text}], }; } return message; diff --git a/components/Chat/ChatInput.tsx b/components/Chat/ChatInput.tsx index 64f8df6..758fa0b 100644 --- a/components/Chat/ChatInput.tsx +++ b/components/Chat/ChatInput.tsx @@ -2,6 +2,7 @@ import { IconArrowDown, IconBolt, IconBrandGoogle, + IconPhoto, IconPlayerStop, IconRepeat, IconSend, @@ -18,7 +19,7 @@ import { import { useTranslation } from 'next-i18next'; -import { Message } from '@/types/chat'; +import { Content, Message } from '@/types/chat'; import { Plugin } from '@/types/plugin'; import { Prompt } from '@/types/prompt'; @@ -62,6 +63,40 @@ export const ChatInput = ({ const [isModalVisible, setIsModalVisible] = useState(false); const [showPluginSelect, setShowPluginSelect] = useState(false); const [plugin, setPlugin] = useState(null); + const [images, setImages] = useState([]); + const imageInputRef = useRef(null); + + const handleImageInputChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + + if (file) { + const reader = new FileReader(); + reader.onloadend = () => { + const base64Image = reader.result; + setImages((prevImages) => [...prevImages, base64Image as string]); + }; + reader.readAsDataURL(file); + } + }; + + const ImagePreview = ({ images }: { images: string[] }) => { + return ( +
+ {images.map((image, index) => ( + {`uploaded-${index}`} + ))} +
+ ); + }; + + const handleImageInputClick = () => { + imageInputRef.current?.click(); + }; const promptListRef = useRef(null); @@ -97,7 +132,14 @@ export const ChatInput = ({ return; } - onSend({ role: 'user', content }, plugin); + var messageContent:Content[] = [{"type": "text", "text": content}]; + if(images && images.length >0){ + var imageMessages = images.map(image => { return {type: "image_url", image_url:{"url": image}}}); + messageContent = [...messageContent, ...imageMessages] + } + + onSend({ role: 'user', content:messageContent }, plugin); + setImages([]); setContent(''); setPlugin(null); @@ -233,9 +275,8 @@ export const ChatInput = ({ if (textareaRef && textareaRef.current) { textareaRef.current.style.height = 'inherit'; textareaRef.current.style.height = `${textareaRef.current?.scrollHeight}px`; - textareaRef.current.style.overflow = `${ - textareaRef?.current?.scrollHeight > 400 ? 'auto' : 'hidden' - }`; + textareaRef.current.style.overflow = `${textareaRef?.current?.scrollHeight > 400 ? 'auto' : 'hidden' + }`; } }, [content]); @@ -280,103 +321,119 @@ export const ChatInput = ({ )}
- + - {showPluginSelect && ( -
- { - if (e.key === 'Escape') { - e.preventDefault(); +
+ + + {showPluginSelect && ( +
+ { + if (e.key === 'Escape') { + e.preventDefault(); + setShowPluginSelect(false); + textareaRef.current?.focus(); + } + }} + onPluginChange={(plugin: Plugin) => { + setPlugin(plugin); setShowPluginSelect(false); - textareaRef.current?.focus(); - } - }} - onPluginChange={(plugin: Plugin) => { - setPlugin(plugin); - setShowPluginSelect(false); - if (textareaRef && textareaRef.current) { - textareaRef.current.focus(); - } - }} - /> -
- )} - -