Spaces:
Running
Running
MingruiZhang
commited on
Commit
·
cc43e3c
1
Parent(s):
a665cd2
lift 10 image restriction
Browse files- app/api/chat/route.ts +1 -0
- components/chat/ImageList.tsx +2 -2
- components/prompt-form.tsx +70 -70
- lib/hooks/useChatWithDataset.ts +8 -8
- lib/hooks/useImageUpload.ts +7 -7
app/api/chat/route.ts
CHANGED
@@ -33,6 +33,7 @@ export async function POST(req: Request) {
|
|
33 |
const formattedMessage: ChatCompletionMessageParam[] = messages.map(
|
34 |
message => {
|
35 |
const { dataset, ...rest } = message;
|
|
|
36 |
|
37 |
const contentWithImage: ChatCompletionContentPart[] = [
|
38 |
{
|
|
|
33 |
const formattedMessage: ChatCompletionMessageParam[] = messages.map(
|
34 |
message => {
|
35 |
const { dataset, ...rest } = message;
|
36 |
+
console.log('[Ming] ~ POST ~ dataset:', dataset?.length);
|
37 |
|
38 |
const contentWithImage: ChatCompletionContentPart[] = [
|
39 |
{
|
components/chat/ImageList.tsx
CHANGED
@@ -15,7 +15,7 @@ const ImageList: React.FC<ImageListProps> = () => {
|
|
15 |
const [dataset, setDataset] = useAtom(datasetAtom);
|
16 |
return (
|
17 |
<div className="relative size-full px-12 max-w-3xl mx-auto">
|
18 |
-
{dataset.length < 10 ? (
|
19 |
<div className="col-span-full px-8 py-4 rounded-xl bg-blue-100 text-blue-400 mb-8">
|
20 |
You can upload up to 10 images max by dragging image.
|
21 |
</div>
|
@@ -23,7 +23,7 @@ const ImageList: React.FC<ImageListProps> = () => {
|
|
23 |
<div className="col-span-full px-8 py-4 rounded-xl bg-red-100 text-red-400 mb-8">
|
24 |
You have reached the maximum limit of 10 images.
|
25 |
</div>
|
26 |
-
)}
|
27 |
<div
|
28 |
{...getRootProps()}
|
29 |
className="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 gap-4"
|
|
|
15 |
const [dataset, setDataset] = useAtom(datasetAtom);
|
16 |
return (
|
17 |
<div className="relative size-full px-12 max-w-3xl mx-auto">
|
18 |
+
{/* {dataset.length < 10 ? (
|
19 |
<div className="col-span-full px-8 py-4 rounded-xl bg-blue-100 text-blue-400 mb-8">
|
20 |
You can upload up to 10 images max by dragging image.
|
21 |
</div>
|
|
|
23 |
<div className="col-span-full px-8 py-4 rounded-xl bg-red-100 text-red-400 mb-8">
|
24 |
You have reached the maximum limit of 10 images.
|
25 |
</div>
|
26 |
+
)} */}
|
27 |
<div
|
28 |
{...getRootProps()}
|
29 |
className="grid grid-cols-1 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-3 gap-4"
|
components/prompt-form.tsx
CHANGED
@@ -1,52 +1,52 @@
|
|
1 |
-
import * as React from 'react'
|
2 |
-
import Textarea from 'react-textarea-autosize'
|
3 |
-
import { UseChatHelpers } from 'ai/react'
|
4 |
-
import { useEnterSubmit } from '@/lib/hooks/use-enter-submit'
|
5 |
-
import { cn } from '@/lib/utils'
|
6 |
-
import { Button, buttonVariants } from '@/components/ui/button'
|
7 |
import {
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
} from '@/components/ui/tooltip'
|
12 |
-
import { IconArrowElbow, IconPlus } from '@/components/ui/icons'
|
13 |
-
import { useRouter } from 'next/navigation'
|
14 |
|
15 |
export interface PromptProps
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
}
|
20 |
|
21 |
export function PromptForm({
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
}: PromptProps) {
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
<TooltipTrigger asChild>
|
51 |
<button
|
52 |
onClick={e => {
|
@@ -65,33 +65,33 @@ export function PromptForm({
|
|
65 |
</TooltipTrigger>
|
66 |
<TooltipContent>New Chat</TooltipContent>
|
67 |
</Tooltip> */}
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
}
|
|
|
1 |
+
import * as React from 'react';
|
2 |
+
import Textarea from 'react-textarea-autosize';
|
3 |
+
import { UseChatHelpers } from 'ai/react';
|
4 |
+
import { useEnterSubmit } from '@/lib/hooks/use-enter-submit';
|
5 |
+
import { cn } from '@/lib/utils';
|
6 |
+
import { Button, buttonVariants } from '@/components/ui/button';
|
7 |
import {
|
8 |
+
Tooltip,
|
9 |
+
TooltipContent,
|
10 |
+
TooltipTrigger,
|
11 |
+
} from '@/components/ui/tooltip';
|
12 |
+
import { IconArrowElbow, IconPlus } from '@/components/ui/icons';
|
13 |
+
import { useRouter } from 'next/navigation';
|
14 |
|
15 |
export interface PromptProps
|
16 |
+
extends Pick<UseChatHelpers, 'input' | 'setInput'> {
|
17 |
+
onSubmit: (value: string) => void;
|
18 |
+
isLoading: boolean;
|
19 |
}
|
20 |
|
21 |
export function PromptForm({
|
22 |
+
onSubmit,
|
23 |
+
input,
|
24 |
+
setInput,
|
25 |
+
isLoading,
|
26 |
}: PromptProps) {
|
27 |
+
const { formRef, onKeyDown } = useEnterSubmit();
|
28 |
+
const inputRef = React.useRef<HTMLTextAreaElement>(null);
|
29 |
+
const router = useRouter();
|
30 |
+
React.useEffect(() => {
|
31 |
+
if (inputRef.current) {
|
32 |
+
inputRef.current.focus();
|
33 |
+
}
|
34 |
+
}, []);
|
35 |
|
36 |
+
return (
|
37 |
+
<form
|
38 |
+
onSubmit={async e => {
|
39 |
+
e.preventDefault();
|
40 |
+
if (!input?.trim()) {
|
41 |
+
return;
|
42 |
+
}
|
43 |
+
setInput('');
|
44 |
+
await onSubmit(input);
|
45 |
+
}}
|
46 |
+
ref={formRef}
|
47 |
+
>
|
48 |
+
<div className="relative flex flex-col w-full px-8 pl-2 overflow-hidden max-h-60 grow bg-background sm:rounded-md sm:border sm:px-12 sm:pl-2">
|
49 |
+
{/* <Tooltip>
|
50 |
<TooltipTrigger asChild>
|
51 |
<button
|
52 |
onClick={e => {
|
|
|
65 |
</TooltipTrigger>
|
66 |
<TooltipContent>New Chat</TooltipContent>
|
67 |
</Tooltip> */}
|
68 |
+
<Textarea
|
69 |
+
ref={inputRef}
|
70 |
+
tabIndex={0}
|
71 |
+
onKeyDown={onKeyDown}
|
72 |
+
rows={1}
|
73 |
+
value={input}
|
74 |
+
onChange={e => setInput(e.target.value)}
|
75 |
+
placeholder="Ask questions about all or selected the images."
|
76 |
+
spellCheck={false}
|
77 |
+
className="min-h-[60px] w-full resize-none bg-transparent px-4 py-[1.3rem] focus-within:outline-none sm:text-sm"
|
78 |
+
/>
|
79 |
+
<div className="absolute right-0 top-4 sm:right-4">
|
80 |
+
<Tooltip>
|
81 |
+
<TooltipTrigger asChild>
|
82 |
+
<Button
|
83 |
+
type="submit"
|
84 |
+
size="icon"
|
85 |
+
disabled={isLoading || input === ''}
|
86 |
+
>
|
87 |
+
<IconArrowElbow />
|
88 |
+
<span className="sr-only">Send message</span>
|
89 |
+
</Button>
|
90 |
+
</TooltipTrigger>
|
91 |
+
<TooltipContent>Send message</TooltipContent>
|
92 |
+
</Tooltip>
|
93 |
+
</div>
|
94 |
+
</div>
|
95 |
+
</form>
|
96 |
+
);
|
97 |
}
|
lib/hooks/useChatWithDataset.ts
CHANGED
@@ -73,14 +73,14 @@ const useChatWithDataset = () => {
|
|
73 |
dataset;
|
74 |
|
75 |
const appendWithDataset: typeof append = message => {
|
76 |
-
const newSystemMessage: Message = {
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
};
|
83 |
-
setMessages([...messages, newSystemMessage]);
|
84 |
return append({
|
85 |
...message,
|
86 |
// @ts-ignore this is extra fields
|
|
|
73 |
dataset;
|
74 |
|
75 |
const appendWithDataset: typeof append = message => {
|
76 |
+
// const newSystemMessage: Message = {
|
77 |
+
// id: 'fake-id',
|
78 |
+
// content:
|
79 |
+
// 'For the next prompt, here are names of images provided by user, please use these name if you need reference: ' +
|
80 |
+
// selectedDataset.map(entity => entity.name).join(', '),
|
81 |
+
// role: 'system',
|
82 |
+
// };
|
83 |
+
// setMessages([...messages, newSystemMessage]);
|
84 |
return append({
|
85 |
...message,
|
86 |
// @ts-ignore this is extra fields
|
lib/hooks/useImageUpload.ts
CHANGED
@@ -12,12 +12,12 @@ const useImageUpload = (options?: Partial<DropzoneOptions>) => {
|
|
12 |
},
|
13 |
multiple: true,
|
14 |
onDrop: acceptedFiles => {
|
15 |
-
if (acceptedFiles.length > 10) {
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
}
|
20 |
-
acceptedFiles.
|
21 |
try {
|
22 |
const reader = new FileReader();
|
23 |
reader.onloadend = () => {
|
@@ -25,7 +25,7 @@ const useImageUpload = (options?: Partial<DropzoneOptions>) => {
|
|
25 |
setTarget(prev => {
|
26 |
// Check if the image already exists in the state
|
27 |
if (
|
28 |
-
prev.length >= 10 ||
|
29 |
prev.find(entity => entity.url === newImage)
|
30 |
) {
|
31 |
// If it does, return the state unchanged
|
|
|
12 |
},
|
13 |
multiple: true,
|
14 |
onDrop: acceptedFiles => {
|
15 |
+
// if (acceptedFiles.length > 10) {
|
16 |
+
// toast('You can only upload 10 images max.', {
|
17 |
+
// icon: '⚠️',
|
18 |
+
// });
|
19 |
+
// }
|
20 |
+
acceptedFiles.forEach(file => {
|
21 |
try {
|
22 |
const reader = new FileReader();
|
23 |
reader.onloadend = () => {
|
|
|
25 |
setTarget(prev => {
|
26 |
// Check if the image already exists in the state
|
27 |
if (
|
28 |
+
// prev.length >= 10 ||
|
29 |
prev.find(entity => entity.url === newImage)
|
30 |
) {
|
31 |
// If it does, return the state unchanged
|