Skip to content

Commit

Permalink
first try that works
Browse files Browse the repository at this point in the history
  • Loading branch information
lectrician1 committed Nov 26, 2023
1 parent 28c0b88 commit 313cfc8
Show file tree
Hide file tree
Showing 9 changed files with 277 additions and 61 deletions.
77 changes: 72 additions & 5 deletions src/api/api.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
import { ShareGPTSubmitBodyInterface } from '@type/api';
import { ConfigInterface, MessageInterface, ModelOptions } from '@type/chat';
import { ConfigInterface, ImageContentInterface, MessageInterface, ModelOptions } from '@type/chat';
import { isAzureEndpoint } from '@utils/api';


// convert message blob urls to base64
const blobToBase64 = async (blob: Blob) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onerror = reject;
reader.onload = () => {
resolve(reader.result);
};
reader.readAsDataURL(blob);
});
};

export const getChatCompletion = async (
endpoint: string,
messages: MessageInterface[],
Expand Down Expand Up @@ -41,11 +54,37 @@ export const getChatCompletion = async (
}
}

// do this for all the messages that have image content
const validMessages = await Promise.all(
messages.map(async (message) => {
return {
...message,
content: message.content.map(async (content) => {
if ('image_url' in content) {
let imageContent = content as ImageContentInterface
if (imageContent.image_url.url.startsWith('blob:')) {
const blob = await fetch(imageContent.image_url.url).then((r) => r.blob());
let base64 = await blobToBase64(blob)
let url = `data:image/jpeg;base64,${base64}`
console.log(url)
return {
...imageContent,
image_url: {
url: url
}
}
}
return message.content;
}
})
}
}))

const response = await fetch(endpoint, {
method: 'POST',
headers,
body: JSON.stringify({
messages,
validImages: validMessages,
...config,
max_tokens: undefined,
}),
Expand Down Expand Up @@ -94,13 +133,41 @@ export const getChatCompletionStream = async (
}
}

const validMessages = await Promise.all(
messages.map(async (message) => {
return {
...message,
content: await Promise.all(message.content.map(async (content) => {
if ('image_url' in content) {
let imageContent = content as ImageContentInterface
if (imageContent.image_url.url.startsWith('blob:')) {
const blob = await fetch(imageContent.image_url.url).then((r) => r.blob());
let base64 = await blobToBase64(blob)
let url = base64
console.log(url)
return {
type: 'image_url',
image_url: {
url: url
}
}
}
// if not a locally stored image (future we can allow for urls from internet)
return content;
}
// if text and not image_url
return content;
}))
}
}))

const response = await fetch(endpoint, {
method: 'POST',
headers,
body: JSON.stringify({
messages,
messages: validMessages,
...config,
max_tokens: undefined,
max_tokens: config.max_tokens,
stream: true,
}),
});
Expand All @@ -110,7 +177,7 @@ export const getChatCompletionStream = async (
if (text.includes('model_not_found')) {
throw new Error(
text +
'\nMessage from Better ChatGPT:\nPlease ensure that you have access to the GPT-4 API!'
'\nMessage from Better ChatGPT:\nPlease ensure that you have access to the GPT-4 API!'
);
} else {
throw new Error(
Expand Down
7 changes: 5 additions & 2 deletions src/components/Chat/ChatContent/ChatContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import useSubmit from '@hooks/useSubmit';
import DownloadChat from './DownloadChat';
import CloneChat from './CloneChat';
import ShareGPT from '@components/ShareGPT';
import { ImageContentInterface, TextContentInterface } from '@type/chat';

const ChatContent = () => {
const inputRole = useStore((state) => state.inputRole);
Expand Down Expand Up @@ -68,7 +69,8 @@ const ChatContent = () => {
<React.Fragment key={index}>
<Message
role={message.role}
content={message.content}
text={(message.content[0] as TextContentInterface).text}
image_urls={message.content[1] ? (message.content.slice(1) as ImageContentInterface[]).map((imageContent) => imageContent.image_url.url) : []}
messageIndex={index}
/>
{!generating && advancedMode && <NewMessageButton messageIndex={index} />}
Expand All @@ -79,7 +81,8 @@ const ChatContent = () => {

<Message
role={inputRole}
content=''
text=''
image_urls={[]}
messageIndex={stickyIndex}
sticky
/>
Expand Down
9 changes: 6 additions & 3 deletions src/components/Chat/ChatContent/Message/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ const backgroundStyle = ['dark:bg-gray-800', 'bg-gray-50 dark:bg-gray-650'];
const Message = React.memo(
({
role,
content,
text,
image_urls,
messageIndex,
sticky = false,
}: {
role: Role;
content: string;
text: string;
image_urls: string[];
messageIndex: number;
sticky?: boolean;
}) => {
Expand Down Expand Up @@ -52,7 +54,8 @@ const Message = React.memo(
/>}
<MessageContent
role={role}
content={content}
text={text}
image_urls={image_urls}
messageIndex={messageIndex}
sticky={sticky}
/>
Expand Down
12 changes: 8 additions & 4 deletions src/components/Chat/ChatContent/Message/MessageContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ import EditView from './View/EditView';

const MessageContent = ({
role,
content,
text,
image_urls,
messageIndex,
sticky = false,
}: {
role: string;
content: string;
text: string;
image_urls: string[];
messageIndex: number;
sticky?: boolean;
}) => {
Expand All @@ -23,15 +25,17 @@ const MessageContent = ({
{advancedMode && <div className='flex flex-grow flex-col gap-3'></div>}
{isEdit ? (
<EditView
content={content}
text={text}
image_urls={image_urls}
setIsEdit={setIsEdit}
messageIndex={messageIndex}
sticky={sticky}
/>
) : (
<ContentView
role={role}
content={content}
text={text}
image_urls={image_urls}
setIsEdit={setIsEdit}
messageIndex={messageIndex}
/>
Expand Down
19 changes: 14 additions & 5 deletions src/components/Chat/ChatContent/Message/View/ContentView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@ import CodeBlock from '../CodeBlock';
const ContentView = memo(
({
role,
content,
text,
image_urls,
setIsEdit,
messageIndex,
}: {
role: string;
content: string;
text: string;
image_urls: string[];
setIsEdit: React.Dispatch<React.SetStateAction<boolean>>;
messageIndex: number;
}) => {
Expand Down Expand Up @@ -100,7 +102,7 @@ const ContentView = memo(
};

const handleCopy = () => {
navigator.clipboard.writeText(content);
navigator.clipboard.writeText(text);
};

return (
Expand Down Expand Up @@ -129,12 +131,19 @@ const ContentView = memo(
p,
}}
>
{content}
{text}
</ReactMarkdown>
) : (
<span className='whitespace-pre-wrap'>{content}</span>
<span className='whitespace-pre-wrap'>{text}</span>
)}
</div>
<div className="flex">
{image_urls.map((image, index) => (
<div key={index} className="image-container">
<img src={image} alt={`uploaded-${index}`} className="mr-2 h-20" />
</div>
))}
</div>
<div className='flex justify-end gap-2 w-full mt-2'>
{isDelete || (
<>
Expand Down
Loading

0 comments on commit 313cfc8

Please sign in to comment.