Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f8ca11c85e | |||
| 467893db67 | |||
| 25df881a39 | |||
| 909ae9a233 |
@@ -150,8 +150,9 @@ export const Chat = memo(({ stopConversationRef }: Props) => {
|
|||||||
if (!plugin) {
|
if (!plugin) {
|
||||||
if (updatedConversation.messages.length === 1) {
|
if (updatedConversation.messages.length === 1) {
|
||||||
const { content } = message;
|
const { content } = message;
|
||||||
|
var textContent = content.filter(c => c.type == "text").map(c => c.text).join();
|
||||||
const customName =
|
const customName =
|
||||||
content.length > 30 ? content.substring(0, 30) + '...' : content;
|
textContent.length > 30 ? textContent.substring(0, 30) + '...' : textContent;
|
||||||
updatedConversation = {
|
updatedConversation = {
|
||||||
...updatedConversation,
|
...updatedConversation,
|
||||||
name: customName,
|
name: customName,
|
||||||
@@ -177,7 +178,7 @@ export const Chat = memo(({ stopConversationRef }: Props) => {
|
|||||||
isFirst = false;
|
isFirst = false;
|
||||||
const updatedMessages: Message[] = [
|
const updatedMessages: Message[] = [
|
||||||
...updatedConversation.messages,
|
...updatedConversation.messages,
|
||||||
{ role: 'assistant', content: chunkValue },
|
{ role: 'assistant', content: [{type: "text", text: chunkValue}] },
|
||||||
];
|
];
|
||||||
updatedConversation = {
|
updatedConversation = {
|
||||||
...updatedConversation,
|
...updatedConversation,
|
||||||
@@ -193,7 +194,7 @@ export const Chat = memo(({ stopConversationRef }: Props) => {
|
|||||||
if (index === updatedConversation.messages.length - 1) {
|
if (index === updatedConversation.messages.length - 1) {
|
||||||
return {
|
return {
|
||||||
...message,
|
...message,
|
||||||
content: text,
|
content: [{type:"text", text}],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import {
|
|||||||
IconArrowDown,
|
IconArrowDown,
|
||||||
IconBolt,
|
IconBolt,
|
||||||
IconBrandGoogle,
|
IconBrandGoogle,
|
||||||
|
IconPhoto,
|
||||||
IconPlayerStop,
|
IconPlayerStop,
|
||||||
IconRepeat,
|
IconRepeat,
|
||||||
IconSend,
|
IconSend,
|
||||||
@@ -18,7 +19,7 @@ import {
|
|||||||
|
|
||||||
import { useTranslation } from 'next-i18next';
|
import { useTranslation } from 'next-i18next';
|
||||||
|
|
||||||
import { Message } from '@/types/chat';
|
import { Content, Message } from '@/types/chat';
|
||||||
import { Plugin } from '@/types/plugin';
|
import { Plugin } from '@/types/plugin';
|
||||||
import { Prompt } from '@/types/prompt';
|
import { Prompt } from '@/types/prompt';
|
||||||
|
|
||||||
@@ -62,6 +63,40 @@ export const ChatInput = ({
|
|||||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
const [showPluginSelect, setShowPluginSelect] = useState(false);
|
const [showPluginSelect, setShowPluginSelect] = useState(false);
|
||||||
const [plugin, setPlugin] = useState<Plugin | null>(null);
|
const [plugin, setPlugin] = useState<Plugin | null>(null);
|
||||||
|
const [images, setImages] = useState<string[]>([]);
|
||||||
|
const imageInputRef = useRef<HTMLInputElement | null>(null);
|
||||||
|
|
||||||
|
const handleImageInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
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 (
|
||||||
|
<div className="flex flex-wrap gap-2 mb-2">
|
||||||
|
{images.map((image, index) => (
|
||||||
|
<img
|
||||||
|
key={index}
|
||||||
|
src={image}
|
||||||
|
alt={`uploaded-${index}`}
|
||||||
|
className="w-20 h-20 object-cover rounded-md border"
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImageInputClick = () => {
|
||||||
|
imageInputRef.current?.click();
|
||||||
|
};
|
||||||
|
|
||||||
const promptListRef = useRef<HTMLUListElement | null>(null);
|
const promptListRef = useRef<HTMLUListElement | null>(null);
|
||||||
|
|
||||||
@@ -97,7 +132,14 @@ export const ChatInput = ({
|
|||||||
return;
|
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('');
|
setContent('');
|
||||||
setPlugin(null);
|
setPlugin(null);
|
||||||
|
|
||||||
@@ -233,8 +275,7 @@ export const ChatInput = ({
|
|||||||
if (textareaRef && textareaRef.current) {
|
if (textareaRef && textareaRef.current) {
|
||||||
textareaRef.current.style.height = 'inherit';
|
textareaRef.current.style.height = 'inherit';
|
||||||
textareaRef.current.style.height = `${textareaRef.current?.scrollHeight}px`;
|
textareaRef.current.style.height = `${textareaRef.current?.scrollHeight}px`;
|
||||||
textareaRef.current.style.overflow = `${
|
textareaRef.current.style.overflow = `${textareaRef?.current?.scrollHeight > 400 ? 'auto' : 'hidden'
|
||||||
textareaRef?.current?.scrollHeight > 400 ? 'auto' : 'hidden'
|
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
}, [content]);
|
}, [content]);
|
||||||
@@ -280,10 +321,13 @@ export const ChatInput = ({
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<div className="relative mx-2 flex w-full flex-grow flex-col rounded-md border border-black/10 bg-white shadow-[0_0_10px_rgba(0,0,0,0.10)] dark:border-gray-900/50 dark:bg-[#40414F] dark:text-white dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] sm:mx-4">
|
<div className="relative mx-2 flex w-full flex-grow flex-col rounded-md border border-black/10 bg-white shadow-[0_0_10px_rgba(0,0,0,0.10)] dark:border-gray-900/50 dark:bg-[#40414F] dark:text-white dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] sm:mx-4">
|
||||||
|
<ImagePreview images={images} />
|
||||||
|
|
||||||
|
<div className="relative mx-0 flex w-full flex-grow flex-col rounded-md border border-black/10 bg-white shadow-[0_0_10px_rgba(0,0,0,0.10)] dark:border-gray-900/50 dark:bg-[#40414F] dark:text-white dark:shadow-[0_0_15px_rgba(0,0,0,0.10)] sm:mx-0">
|
||||||
<button
|
<button
|
||||||
className="absolute left-2 top-2 rounded-sm p-1 text-neutral-800 opacity-60 hover:bg-neutral-200 hover:text-neutral-900 dark:bg-opacity-50 dark:text-neutral-100 dark:hover:text-neutral-200"
|
className="absolute left-2 top-2 rounded-sm p-1 text-neutral-800 opacity-60 hover:bg-neutral-200 hover:text-neutral-900 dark:bg-opacity-50 dark:text-neutral-100 dark:hover:text-neutral-200"
|
||||||
onClick={() => setShowPluginSelect(!showPluginSelect)}
|
onClick={() => setShowPluginSelect(!showPluginSelect)}
|
||||||
onKeyDown={(e) => {}}
|
onKeyDown={(e) => { }}
|
||||||
>
|
>
|
||||||
{plugin ? <IconBrandGoogle size={20} /> : <IconBolt size={20} />}
|
{plugin ? <IconBrandGoogle size={20} /> : <IconBolt size={20} />}
|
||||||
</button>
|
</button>
|
||||||
@@ -310,16 +354,29 @@ export const ChatInput = ({
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<input
|
||||||
|
ref={imageInputRef}
|
||||||
|
type="file"
|
||||||
|
accept="image/*"
|
||||||
|
style={{ display: 'none' }}
|
||||||
|
onChange={handleImageInputChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button
|
||||||
|
className="absolute left-10 top-2 rounded-sm p-1 text-neutral-800 opacity-60 hover:bg-neutral-200 hover:text-neutral-900 dark:bg-opacity-50 dark:text-neutral-100 dark:hover:text-neutral-200"
|
||||||
|
onClick={handleImageInputClick}
|
||||||
|
>
|
||||||
|
<IconPhoto size={20} />
|
||||||
|
</button>
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
ref={textareaRef}
|
ref={textareaRef}
|
||||||
className="m-0 w-full resize-none border-0 bg-transparent p-0 py-2 pr-8 pl-10 text-black dark:bg-transparent dark:text-white md:py-3 md:pl-10"
|
className="m-0 w-full resize-none border-0 bg-transparent p-0 py-2 pr-8 pl-20 text-black dark:bg-transparent dark:text-white md:py-3 md:pl-20"
|
||||||
style={{
|
style={{
|
||||||
resize: 'none',
|
resize: 'none',
|
||||||
bottom: `${textareaRef?.current?.scrollHeight}px`,
|
bottom: `${textareaRef?.current?.scrollHeight}px`,
|
||||||
maxHeight: '400px',
|
maxHeight: '400px',
|
||||||
overflow: `${
|
overflow: `${textareaRef.current && textareaRef.current.scrollHeight > 400
|
||||||
textareaRef.current && textareaRef.current.scrollHeight > 400
|
|
||||||
? 'auto'
|
? 'auto'
|
||||||
: 'hidden'
|
: 'hidden'
|
||||||
}`,
|
}`,
|
||||||
@@ -334,7 +391,6 @@ export const ChatInput = ({
|
|||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
className="absolute right-2 top-2 rounded-sm p-1 text-neutral-800 opacity-60 hover:bg-neutral-200 hover:text-neutral-900 dark:bg-opacity-50 dark:text-neutral-100 dark:hover:text-neutral-200"
|
className="absolute right-2 top-2 rounded-sm p-1 text-neutral-800 opacity-60 hover:bg-neutral-200 hover:text-neutral-900 dark:bg-opacity-50 dark:text-neutral-100 dark:hover:text-neutral-200"
|
||||||
onClick={handleSend}
|
onClick={handleSend}
|
||||||
@@ -379,6 +435,7 @@ export const ChatInput = ({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div className="px-3 pt-2 pb-3 text-center text-[12px] text-black/50 dark:text-white/50 md:px-4 md:pt-3 md:pb-6">
|
<div className="px-3 pt-2 pb-3 text-center text-[12px] text-black/50 dark:text-white/50 md:px-4 md:pt-3 md:pb-6">
|
||||||
<a
|
<a
|
||||||
href="https://github.com/mckaywrigley/chatbot-ui"
|
href="https://github.com/mckaywrigley/chatbot-ui"
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
const [isEditing, setIsEditing] = useState<boolean>(false);
|
const [isEditing, setIsEditing] = useState<boolean>(false);
|
||||||
const [isTyping, setIsTyping] = useState<boolean>(false);
|
const [isTyping, setIsTyping] = useState<boolean>(false);
|
||||||
const [messageContent, setMessageContent] = useState(message.content);
|
const [messageContent, setMessageContent] = useState(message.content);
|
||||||
|
const [messageTextContent, setMessageTextContent] = useState(message.content[0].text ?? "");
|
||||||
const [messagedCopied, setMessageCopied] = useState(false);
|
const [messagedCopied, setMessageCopied] = useState(false);
|
||||||
|
|
||||||
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
const textareaRef = useRef<HTMLTextAreaElement>(null);
|
||||||
@@ -49,7 +50,9 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleInputChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
const handleInputChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||||
setMessageContent(event.target.value);
|
// messageContent[0].text = event.target.value;
|
||||||
|
// setMessageContent(messageContent);
|
||||||
|
setMessageTextContent(event.target.value);
|
||||||
if (textareaRef.current) {
|
if (textareaRef.current) {
|
||||||
textareaRef.current.style.height = 'inherit';
|
textareaRef.current.style.height = 'inherit';
|
||||||
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
|
textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
|
||||||
@@ -57,8 +60,9 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleEditMessage = () => {
|
const handleEditMessage = () => {
|
||||||
if (message.content != messageContent) {
|
if (message.content[0].text != messageTextContent) {
|
||||||
if (selectedConversation && onEdit) {
|
if (selectedConversation && onEdit) {
|
||||||
|
messageContent[0].text = messageTextContent;
|
||||||
onEdit({ ...message, content: messageContent });
|
onEdit({ ...message, content: messageContent });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -104,7 +108,9 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
const copyOnClick = () => {
|
const copyOnClick = () => {
|
||||||
if (!navigator.clipboard) return;
|
if (!navigator.clipboard) return;
|
||||||
|
|
||||||
navigator.clipboard.writeText(message.content).then(() => {
|
var content = message.content;
|
||||||
|
var textContent = content.filter(c => c.type == "text").map(c => c.text).join();
|
||||||
|
navigator.clipboard.writeText(textContent).then(() => {
|
||||||
setMessageCopied(true);
|
setMessageCopied(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setMessageCopied(false);
|
setMessageCopied(false);
|
||||||
@@ -113,7 +119,8 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMessageContent(message.content);
|
// setMessageContent(message.content);
|
||||||
|
setMessageTextContent(message.content[0].text ?? "");
|
||||||
}, [message.content]);
|
}, [message.content]);
|
||||||
|
|
||||||
|
|
||||||
@@ -150,7 +157,7 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
<textarea
|
<textarea
|
||||||
ref={textareaRef}
|
ref={textareaRef}
|
||||||
className="w-full resize-none whitespace-pre-wrap border-none dark:bg-[#343541]"
|
className="w-full resize-none whitespace-pre-wrap border-none dark:bg-[#343541]"
|
||||||
value={messageContent}
|
value={messageTextContent}
|
||||||
onChange={handleInputChange}
|
onChange={handleInputChange}
|
||||||
onKeyDown={handlePressEnter}
|
onKeyDown={handlePressEnter}
|
||||||
onCompositionStart={() => setIsTyping(true)}
|
onCompositionStart={() => setIsTyping(true)}
|
||||||
@@ -169,14 +176,15 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
<button
|
<button
|
||||||
className="h-[40px] rounded-md bg-blue-500 px-4 py-1 text-sm font-medium text-white enabled:hover:bg-blue-600 disabled:opacity-50"
|
className="h-[40px] rounded-md bg-blue-500 px-4 py-1 text-sm font-medium text-white enabled:hover:bg-blue-600 disabled:opacity-50"
|
||||||
onClick={handleEditMessage}
|
onClick={handleEditMessage}
|
||||||
disabled={messageContent.trim().length <= 0}
|
disabled={messageTextContent.length <= 0}
|
||||||
>
|
>
|
||||||
{t('Save & Submit')}
|
{t('Save & Submit')}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="h-[40px] rounded-md border border-neutral-300 px-4 py-1 text-sm font-medium text-neutral-700 hover:bg-neutral-100 dark:border-neutral-700 dark:text-neutral-300 dark:hover:bg-neutral-800"
|
className="h-[40px] rounded-md border border-neutral-300 px-4 py-1 text-sm font-medium text-neutral-700 hover:bg-neutral-100 dark:border-neutral-700 dark:text-neutral-300 dark:hover:bg-neutral-800"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMessageContent(message.content);
|
// setMessageContent(message.content);
|
||||||
|
setMessageTextContent(message.content[0].text ?? "");
|
||||||
setIsEditing(false);
|
setIsEditing(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -186,7 +194,14 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="prose whitespace-pre-wrap dark:prose-invert flex-1">
|
<div className="prose whitespace-pre-wrap dark:prose-invert flex-1">
|
||||||
{message.content}
|
<div>
|
||||||
|
{messageTextContent}
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-wrap justify-center">
|
||||||
|
{messageContent.filter(c => c.type === "image_url").map((c, index) => (
|
||||||
|
<img key={index} src={c.image_url?.url} alt="Message Content" className="max-w-full h-auto my-2" style={{objectFit: "contain"}} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -261,7 +276,7 @@ export const ChatMessage: FC<Props> = memo(({ message, messageIndex, onEdit }) =
|
|||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{`${message.content}${
|
{`${messageTextContent}${
|
||||||
messageIsStreaming && messageIndex == (selectedConversation?.messages.length ?? 0) - 1 ? '`▍`' : ''
|
messageIsStreaming && messageIndex == (selectedConversation?.messages.length ?? 0) - 1 ? '`▍`' : ''
|
||||||
}`}
|
}`}
|
||||||
</MemoizedReactMarkdown>
|
</MemoizedReactMarkdown>
|
||||||
|
|||||||
+2
-1
@@ -41,7 +41,7 @@ const handler = async (req: Request): Promise<Response> => {
|
|||||||
|
|
||||||
for (let i = messages.length - 1; i >= 0; i--) {
|
for (let i = messages.length - 1; i >= 0; i--) {
|
||||||
const message = messages[i];
|
const message = messages[i];
|
||||||
const tokens = encoding.encode(message.content);
|
const tokens = encoding.encode(message.content[0].text ?? "");
|
||||||
|
|
||||||
if (tokenCount + tokens.length + 1000 > model.tokenLimit) {
|
if (tokenCount + tokens.length + 1000 > model.tokenLimit) {
|
||||||
break;
|
break;
|
||||||
@@ -55,6 +55,7 @@ const handler = async (req: Request): Promise<Response> => {
|
|||||||
const stream = await OpenAIStream(model, promptToSend, temperatureToUse, key, messagesToSend);
|
const stream = await OpenAIStream(model, promptToSend, temperatureToUse, key, messagesToSend);
|
||||||
|
|
||||||
var resp = new Response(stream);
|
var resp = new Response(stream);
|
||||||
|
return resp;
|
||||||
|
|
||||||
// let proxy services like nginx or argo tunnel know about pass the chunk immediately
|
// let proxy services like nginx or argo tunnel know about pass the chunk immediately
|
||||||
// similar to nginx option `proxy_buffering off;`
|
// similar to nginx option `proxy_buffering off;`
|
||||||
|
|||||||
+11
-1
@@ -2,7 +2,17 @@ import { OpenAIModel } from './openai';
|
|||||||
|
|
||||||
export interface Message {
|
export interface Message {
|
||||||
role: Role;
|
role: Role;
|
||||||
content: string;
|
content: Content[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Content{
|
||||||
|
type: string;
|
||||||
|
text?: string;
|
||||||
|
image_url?: ImageUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ImageUrl{
|
||||||
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Role = 'assistant' | 'user';
|
export type Role = 'assistant' | 'user';
|
||||||
|
|||||||
+9
-2
@@ -13,7 +13,8 @@ export enum OpenAIModelID {
|
|||||||
GPT_3_5_16K = 'gpt-3.5-turbo-16k',
|
GPT_3_5_16K = 'gpt-3.5-turbo-16k',
|
||||||
GPT_4 = 'gpt-4',
|
GPT_4 = 'gpt-4',
|
||||||
GPT_4_32K = 'gpt-4-32k',
|
GPT_4_32K = 'gpt-4-32k',
|
||||||
GPT_4_TURBO = 'gpt-4-1106-preview'
|
GPT_4_TURBO = 'gpt-4-1106-preview',
|
||||||
|
GPT_4_TURBO_VISION = 'gpt-4-vision-preview'
|
||||||
}
|
}
|
||||||
|
|
||||||
// in case the `DEFAULT_MODEL` environment variable is not set or set to an unsupported model
|
// in case the `DEFAULT_MODEL` environment variable is not set or set to an unsupported model
|
||||||
@@ -53,7 +54,13 @@ export const OpenAIModels: Record<OpenAIModelID, OpenAIModel> = {
|
|||||||
[OpenAIModelID.GPT_4_TURBO]: {
|
[OpenAIModelID.GPT_4_TURBO]: {
|
||||||
id: OpenAIModelID.GPT_4_TURBO,
|
id: OpenAIModelID.GPT_4_TURBO,
|
||||||
name: 'GPT-4-TURBO',
|
name: 'GPT-4-TURBO',
|
||||||
maxLength: 380000,
|
maxLength: 384000,
|
||||||
|
tokenLimit: 128000,
|
||||||
|
},
|
||||||
|
[OpenAIModelID.GPT_4_TURBO_VISION]: {
|
||||||
|
id: OpenAIModelID.GPT_4_TURBO_VISION,
|
||||||
|
name: 'GPT-4-TURBO-VISION',
|
||||||
|
maxLength: 384000,
|
||||||
tokenLimit: 128000,
|
tokenLimit: 128000,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -53,11 +53,11 @@ export const OpenAIStream = async (
|
|||||||
messages: [
|
messages: [
|
||||||
{
|
{
|
||||||
role: 'system',
|
role: 'system',
|
||||||
content: systemPrompt,
|
content: [{type:"text", text: systemPrompt}],
|
||||||
},
|
},
|
||||||
...messages,
|
...messages,
|
||||||
],
|
],
|
||||||
max_tokens: 1000,
|
max_tokens: 4000,
|
||||||
temperature: temperature,
|
temperature: temperature,
|
||||||
stream: true,
|
stream: true,
|
||||||
}),
|
}),
|
||||||
@@ -89,10 +89,10 @@ export const OpenAIStream = async (
|
|||||||
const onParse = (event: ParsedEvent | ReconnectInterval) => {
|
const onParse = (event: ParsedEvent | ReconnectInterval) => {
|
||||||
if (event.type === 'event') {
|
if (event.type === 'event') {
|
||||||
const data = event.data;
|
const data = event.data;
|
||||||
|
if (data !== '[DONE]') {
|
||||||
try {
|
try {
|
||||||
const json = JSON.parse(data);
|
const json = JSON.parse(data);
|
||||||
if (json.choices[0].finish_reason != null) {
|
if (json.choices[0].finish_reason != null || json.choices[0].finish_details != null) {
|
||||||
controller.close();
|
controller.close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -103,6 +103,7 @@ export const OpenAIStream = async (
|
|||||||
controller.error(e);
|
controller.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const parser = createParser(onParse);
|
const parser = createParser(onParse);
|
||||||
|
|||||||
Reference in New Issue
Block a user