Spaces:
Runtime error
Runtime error
| "use client"; | |
| import React from "react"; | |
| import { PaperPlaneIcon, StopIcon } from "@radix-ui/react-icons"; | |
| import { ChatRequestOptions } from "ai"; | |
| import mistralTokenizer from "mistral-tokenizer-js"; | |
| import TextareaAutosize from "react-textarea-autosize"; | |
| import { tokenLimit } from "@/lib/token-counter"; | |
| import { Button } from "../ui/button"; | |
| interface ChatBottombarProps { | |
| selectedModel: string | undefined; | |
| input: string; | |
| handleInputChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void; | |
| handleSubmit: ( | |
| e: React.FormEvent<HTMLFormElement>, | |
| chatRequestOptions?: ChatRequestOptions | |
| ) => void; | |
| isLoading: boolean; | |
| stop: () => void; | |
| } | |
| export default function ChatBottombar({ | |
| selectedModel, | |
| input, | |
| handleInputChange, | |
| handleSubmit, | |
| isLoading, | |
| stop, | |
| }: ChatBottombarProps) { | |
| const inputRef = React.useRef<HTMLTextAreaElement>(null); | |
| const hasSelectedModel = selectedModel && selectedModel !== ""; | |
| const handleKeyPress = (e: React.KeyboardEvent<HTMLTextAreaElement>) => { | |
| if (e.key === "Enter" && !e.shiftKey && hasSelectedModel && !isLoading) { | |
| e.preventDefault(); | |
| handleSubmit(e as unknown as React.FormEvent<HTMLFormElement>); | |
| } | |
| }; | |
| const tokenCount = input ? mistralTokenizer.encode(input).length - 1 : 0; | |
| return ( | |
| <div> | |
| <div className="stretch flex flex-row gap-3 last:mb-2 md:last:mb-6 mx-2 md:mx-4 md:mx-auto md:max-w-2xl xl:max-w-3xl"> | |
| {/* <div className="p-2 pb-1 flex justify-between w-full items-center "> */} | |
| <div key="input" className="w-full relative mb-1 items-center"> | |
| <form | |
| onSubmit={handleSubmit} | |
| className="w-full items-center flex relative gap-2" | |
| > | |
| <TextareaAutosize | |
| autoComplete="off" | |
| value={input} | |
| ref={inputRef} | |
| onKeyDown={handleKeyPress} | |
| onChange={handleInputChange} | |
| name="message" | |
| placeholder="Ask vLLM anything..." | |
| className="border-input max-h-48 px-4 py-4 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 dark:focus-visible:ring-slate-500 disabled:cursor-not-allowed disabled:opacity-50 w-full border rounded-md flex items-center h-14 resize-none overflow-hidden dark:bg-card/35 pr-32" | |
| /> | |
| <div className="text-xs text-muted-foreground absolute right-14 px-0 text-right"> | |
| {tokenCount > tokenLimit ? ( | |
| <span className="text-red-700"> | |
| {tokenCount} token{tokenCount == 1 ? "" : "s"} | |
| </span> | |
| ) : ( | |
| <span> | |
| {tokenCount} token{tokenCount == 1 ? "" : "s"} | |
| </span> | |
| )} | |
| </div> | |
| {!isLoading ? ( | |
| <Button | |
| size="icon" | |
| className="absolute bottom-1.5 md:bottom-2 md:right-2 right-2 z-100" | |
| type="submit" | |
| disabled={isLoading || !input.trim() || !hasSelectedModel} | |
| > | |
| <PaperPlaneIcon className="w-5 h-5 text-white dark:text-black" /> | |
| </Button> | |
| ) : ( | |
| <Button | |
| size="icon" | |
| className="absolute bottom-1.5 md:bottom-2 md:right-2 right-2 z-100" | |
| onClick={stop} | |
| > | |
| <StopIcon className="w-5 h-5 text-white dark:text-black" /> | |
| </Button> | |
| )} | |
| </form> | |
| </div> | |
| </div> | |
| <div className="relative px-2 py-2 text-center text-xs text-slate-500 md:px-[60px]"> | |
| <span>Enter to send, Shift + Enter for new line</span> | |
| </div> | |
| </div> | |
| ); | |
| } | |