diff --git a/README.md b/README.md index aa400ef70..448dd8815 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Fast GPT 允许你使用自己的 openai API KEY 来快速的调用 openai 接口,包括 GPT3 及其微调方法,以及最新的 gpt3.5 接口。 -## 初始化 +## 开发 复制 .env.template 成 .env.local ,填写核心参数 ``` @@ -15,7 +15,6 @@ TOKEN_KEY=随便填一个,用于生成和校验 token OPENAIKEY=openai的key REDIS_URL=redis的地址 ``` - ```bash pnpm dev ``` @@ -32,48 +31,6 @@ docker push imageName:tag # 或者直接拉镜像,见下方 ``` -#### 服务器拉取镜像和运行 -```yml -# docker-compose -version: "3.3" -services: - fast-gpt: - image: c121914yu/fast-gpt:latest - environment: - AXIOS_PROXY_HOST: 127.0.0.1 - AXIOS_PROXY_PORT: 7890 - MY_MAIL: - MAILE_CODE: - TOKEN_KEY: - MONGODB_URI: - OPENAIKEY: - REDIS_URL: - network_mode: host - restart: always - container_name: fast-gpt -``` -```bash -#!/bin/bash -# 拉取最新镜像 -docker-compose pull -docker-compose up -d - -echo "Docker Compose 重新拉取镜像完成!" - -# 删除本地旧镜像 -images=$(docker images --format "{{.ID}} {{.Repository}}" | grep fast-gpt) - -# 将镜像 ID 和名称放入数组中 -IFS=$'\n' read -rd '' -a image_array <<<"$images" - -# 遍历数组并删除所有旧的镜像 -for ((i=1; i<${#image_array[@]}; i++)) -do - image=${image_array[$i]} - image_id=${image%% *} - docker rmi $image_id -done -``` #### 软件教程:docker 安装 ```bash @@ -163,3 +120,45 @@ appendfsync everysec # 添加索引 FT.CREATE idx:model:data:hash ON HASH PREFIX 1 model:data: SCHEMA modelId TAG userId TAG status TAG q TEXT text TEXT vector VECTOR FLAT 6 DIM 1536 DISTANCE_METRIC COSINE TYPE FLOAT32 ``` +#### 服务器拉取镜像和运行 +```yml +# docker-compose +version: "3.3" +services: + fast-gpt: + image: c121914yu/fast-gpt:latest + environment: + AXIOS_PROXY_HOST: 127.0.0.1 + AXIOS_PROXY_PORT: 7890 + MY_MAIL: + MAILE_CODE: + TOKEN_KEY: + MONGODB_URI: + OPENAIKEY: + REDIS_URL: + network_mode: host + restart: always + container_name: fast-gpt +``` +```bash +#!/bin/bash +# 拉取最新镜像 +docker-compose pull +docker-compose up -d + +echo "Docker Compose 重新拉取镜像完成!" + +# 删除本地旧镜像 +images=$(docker images --format "{{.ID}} {{.Repository}}" | grep fast-gpt) + +# 将镜像 ID 和名称放入数组中 +IFS=$'\n' read -rd '' -a image_array <<<"$images" + +# 遍历数组并删除所有旧的镜像 +for ((i=1; i<${#image_array[@]}; i++)) +do + image=${image_array[$i]} + image_id=${image%% *} + docker rmi $image_id +done +``` diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 61416d7d0..bb7f299f1 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -47,7 +47,7 @@ export default function App({ Component, pageProps }: AppProps) { diff --git a/src/pages/chat/index.tsx b/src/pages/chat/index.tsx index 54311de35..ffa171aee 100644 --- a/src/pages/chat/index.tsx +++ b/src/pages/chat/index.tsx @@ -1,13 +1,7 @@ import React, { useCallback, useState, useRef, useMemo, useEffect } from 'react'; import { useRouter } from 'next/router'; import Image from 'next/image'; -import { - getInitChatSiteInfo, - getChatSiteId, - postGPT3SendPrompt, - delChatRecordByIndex, - postSaveChat -} from '@/api/chat'; +import { getInitChatSiteInfo, getChatSiteId, delChatRecordByIndex, postSaveChat } from '@/api/chat'; import type { InitChatResponse } from '@/api/response/chat'; import { ChatSiteItemType } from '@/types/chat'; import { @@ -33,12 +27,11 @@ import { useGlobalStore } from '@/store/global'; import { useChatStore } from '@/store/chat'; import { useCopyData } from '@/utils/tools'; import { streamFetch } from '@/api/fetch'; -import SlideBar from './components/SlideBar'; -import Empty from './components/Empty'; import Icon from '@/components/Icon'; -import { encode } from 'gpt-token-utils'; import { modelList } from '@/constants/model'; +const SlideBar = dynamic(() => import('./components/SlideBar')); +const Empty = dynamic(() => import('./components/Empty')); const Markdown = dynamic(() => import('@/components/Markdown')); const textareaMinH = '22px'; @@ -48,10 +41,12 @@ interface ChatType extends InitChatResponse { } const Chat = ({ chatId }: { chatId: string }) => { - const { toast } = useToast(); - const router = useRouter(); const ChatBox = useRef(null); const TextareaDom = useRef(null); + + const { toast } = useToast(); + const router = useRouter(); + // 中断请求 const controller = useRef(new AbortController()); const [chatData, setChatData] = useState({ @@ -70,11 +65,11 @@ const Chat = ({ chatId }: { chatId: string }) => { () => chatData.history[chatData.history.length - 1]?.status === 'loading', [chatData.history] ); + const { isOpen: isOpenSlider, onClose: onCloseSlider, onOpen: onOpenSlider } = useDisclosure(); + const { copyData } = useCopyData(); const { isPc, media } = useScreen(); const { setLoading } = useGlobalStore(); - - const { isOpen: isOpenSlider, onClose: onCloseSlider, onOpen: onOpenSlider } = useDisclosure(); const { pushChatHistory } = useChatStore(); // 滚动到底部 @@ -211,12 +206,11 @@ const Chat = ({ chatId }: { chatId: string }) => { } // 长度校验 - const tokens = encode(val).length; const model = modelList.find((item) => item.model === chatData.modelName); - if (model && tokens >= model.maxToken) { + if (model && val.length >= model.maxToken) { toast({ - title: '单次输入超出 4000 tokens', + title: '单次输入超出 4000 字符', status: 'warning' }); return; @@ -314,14 +308,6 @@ const Chat = ({ chatId }: { chatId: string }) => { [copyData] ); - useEffect(() => { - controller.current = new AbortController(); - return () => { - // eslint-disable-next-line react-hooks/exhaustive-deps - controller.current?.abort(); - }; - }, [chatId]); - // 初始化聊天框 useQuery( ['init', chatId], @@ -359,6 +345,14 @@ const Chat = ({ chatId }: { chatId: string }) => { } ); + // 更新流中断对象 + useEffect(() => { + controller.current = new AbortController(); + return () => { + // eslint-disable-next-line react-hooks/exhaustive-deps + controller.current?.abort(); + }; + }, [chatId]); return ( { export default Chat; export async function getServerSideProps(context: any) { - const chatId = context.query?.chatId || ''; + const chatId = context?.query?.chatId || 'noid'; return { props: { chatId } diff --git a/src/pages/model/detail/components/SelectFileModal.tsx b/src/pages/model/detail/components/SelectFileModal.tsx index 7a8188779..c21face6a 100644 --- a/src/pages/model/detail/components/SelectFileModal.tsx +++ b/src/pages/model/detail/components/SelectFileModal.tsx @@ -127,7 +127,7 @@ const SelectFileModal = ({ tokens,账号余额不足时,未拆分的数据会被删除。 - 一共 {encode(fileText).length} 个tokens,大约 {formatPrice(encode(fileText).length * 4)} + 一共 {encode(fileText).length} 个tokens,大约 {formatPrice(encode(fileText).length * 3)} 元 diff --git a/src/pages/model/detail/components/SelectUrlModal.tsx b/src/pages/model/detail/components/SelectUrlModal.tsx index 7912eb3b6..1d011c0f2 100644 --- a/src/pages/model/detail/components/SelectUrlModal.tsx +++ b/src/pages/model/detail/components/SelectUrlModal.tsx @@ -106,7 +106,7 @@ const SelectUrlModal = ({ QA 拆分,需要较长训练时间,拆分需要消耗 tokens,账号余额不足时,未拆分的数据会被删除。 - 一共 {encode(webText).length} 个tokens,大约 {formatPrice(encode(webText).length * 4)}元 + 一共 {encode(webText).length} 个tokens,大约 {formatPrice(encode(webText).length * 3)}元 网站地址