From 00b90f071d45c2b06b861ae5b83b0416c2184cb7 Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Sat, 18 Mar 2023 12:32:55 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=A8=A1=E5=9E=8B=E4=BB=8B=E7=BB=8D?= =?UTF-8?q?=E5=92=8C=E6=B8=A9=E5=BA=A6=E8=B0=83=E6=95=B4=E3=80=82=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E8=81=8A=E5=A4=A9=E9=A1=B5=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/model.ts | 8 +- src/api/response/chat.d.ts | 1 + src/components/Markdown/index.module.scss | 2 +- src/components/Markdown/index.tsx | 2 +- src/components/Slider/index.tsx | 82 ++++++++ src/constants/common.ts | 22 ++ src/constants/model.ts | 72 +++++-- src/pages/api/chat/chatGpt.ts | 14 +- src/pages/api/chat/gpt3.ts | 14 +- src/pages/api/chat/init.ts | 1 + src/pages/api/model/create.ts | 23 +- src/pages/api/model/detail.tsx | 4 +- src/pages/api/model/getTrainings.ts | 2 +- src/pages/api/model/putTrainStatus.ts | 4 +- src/pages/api/model/train.ts | 4 +- src/pages/api/model/update.ts | 7 +- src/pages/chat/components/Empty.tsx | 53 +++-- src/pages/chat/components/SlideBar.tsx | 138 +++++++----- src/pages/chat/index.tsx | 9 +- src/pages/model/components/CreateModel.tsx | 10 +- src/pages/model/components/ModelEditForm.tsx | 196 +++++++++--------- src/pages/model/components/ModelPhoneList.tsx | 4 +- src/pages/model/components/ModelTable.tsx | 12 +- src/pages/model/components/Training.tsx | 4 +- src/pages/model/detail.tsx | 158 ++++++++++---- src/pages/model/list.tsx | 4 +- src/service/models/chat.ts | 27 +-- src/service/models/model.ts | 20 +- src/store/user.ts | 8 +- src/types/chat.d.ts | 2 - src/types/model.d.ts | 40 +--- src/types/mongoSchema.d.ts | 8 +- 32 files changed, 628 insertions(+), 327 deletions(-) create mode 100644 src/components/Slider/index.tsx diff --git a/src/api/model.ts b/src/api/model.ts index dd35707e9..8381667fe 100644 --- a/src/api/model.ts +++ b/src/api/model.ts @@ -1,16 +1,16 @@ import { GET, POST, DELETE, PUT } from './request'; -import type { ModelType } from '@/types/model'; +import type { ModelSchema } from '@/types/mongoSchema'; import { ModelUpdateParams } from '@/types/model'; import { TrainingItemType } from '../types/training'; -export const getMyModels = () => GET('/model/list'); +export const getMyModels = () => GET('/model/list'); export const postCreateModel = (data: { name: string; serviceModelName: string }) => - POST('/model/create', data); + POST('/model/create', data); export const delModelById = (id: string) => DELETE(`/model/del?modelId=${id}`); -export const getModelById = (id: string) => GET(`/model/detail?modelId=${id}`); +export const getModelById = (id: string) => GET(`/model/detail?modelId=${id}`); export const putModelById = (id: string, data: ModelUpdateParams) => PUT(`/model/update?modelId=${id}`, data); diff --git a/src/api/response/chat.d.ts b/src/api/response/chat.d.ts index 48700736c..fe802c5ee 100644 --- a/src/api/response/chat.d.ts +++ b/src/api/response/chat.d.ts @@ -6,6 +6,7 @@ export type InitChatResponse = { modelId: string; name: string; avatar: string; + intro: string; secret: ModelSchema.secret; chatModel: ModelSchema.service.ChatModel; // 模型名 history: ChatItemType[]; diff --git a/src/components/Markdown/index.module.scss b/src/components/Markdown/index.module.scss index 7420c553b..c51910efa 100644 --- a/src/components/Markdown/index.module.scss +++ b/src/components/Markdown/index.module.scss @@ -172,7 +172,7 @@ } .markdown ul, .markdown ol { - padding-left: 30px; + padding-left: 1em; } .markdown ul.no-list, .markdown ol.no-list { diff --git a/src/components/Markdown/index.tsx b/src/components/Markdown/index.tsx index 09ac71b34..6ffaa1f39 100644 --- a/src/components/Markdown/index.tsx +++ b/src/components/Markdown/index.tsx @@ -12,7 +12,7 @@ import 'katex/dist/katex.min.css'; import styles from './index.module.scss'; import { codeLight } from './codeLight'; -const Markdown = ({ source, isChatting }: { source: string; isChatting: boolean }) => { +const Markdown = ({ source, isChatting = false }: { source: string; isChatting?: boolean }) => { const formatSource = useMemo(() => source, [source]); const { copyData } = useCopyData(); diff --git a/src/components/Slider/index.tsx b/src/components/Slider/index.tsx new file mode 100644 index 000000000..f2c9f8a5e --- /dev/null +++ b/src/components/Slider/index.tsx @@ -0,0 +1,82 @@ +import React, { useMemo } from 'react'; +import { + Slider, + SliderTrack, + SliderFilledTrack, + SliderThumb, + SliderMark, + Box +} from '@chakra-ui/react'; + +const MySlider = ({ + markList, + setVal, + activeVal, + max = 100, + min = 0, + step = 1 +}: { + markList: { + label: string | number; + value: number; + }[]; + activeVal?: number; + setVal: (index: number) => void; + max?: number; + min?: number; + step?: number; +}) => { + const startEndPointStyle = { + content: '""', + borderRadius: '10px', + width: '10px', + height: '10px', + backgroundColor: '#ffffff', + border: '2px solid #D7DBE2', + position: 'absolute', + zIndex: 1, + top: 0, + transform: 'translateY(-3px)' + }; + const value = useMemo(() => { + const index = markList.findIndex((item) => item.value === activeVal); + return index > -1 ? index : 0; + }, [activeVal, markList]); + + return ( + + {markList.map((item, i) => ( + + + {item.label} + + + ))} + + + + + + ); +}; + +export default MySlider; diff --git a/src/constants/common.ts b/src/constants/common.ts index bf6961f76..420659d82 100644 --- a/src/constants/common.ts +++ b/src/constants/common.ts @@ -39,3 +39,25 @@ export const introPage = ` ### 其他问题 还有其他问题,可以加我 wx: YNyiqi,拉个交流群大家一起聊聊。 `; + +export const chatProblem = ` +**代理出错** +服务器代理不稳定,可以过一会儿再尝试。 + +**API key 问题** +请把 openai 的 API key 粘贴到账号里再创建对话。如果是使用分享的对话,不需要填写 API key。 +`; + +export const versionIntro = ` +* 分享对话:使用的是分享者的 Api Key 生成一个对话窗口进行分享。 + * 分享空白对话:为该模型创建一个空白的聊天分享出去。 + * 分享当前对话:会把当前聊天的内容也分享出去,但是要注意不要多个人同时用一个聊天内容。 +* 增加模型介绍:可以在模型编辑页添加对模型的介绍,方便提示模型的范围。 +* 温度调整:可以在模型编辑页调整模型温度,以便适应不同类型的对话。例如,翻译类的模型可以把温度拉低;创作类的模型可以把温度拉高。 +`; + +export const shareHint = ` +你正准备分享对话,请确保分享链接不会滥用,因为它是使用的是你的 API key。 +* 分享空白对话:为该模型创建一个空白的聊天分享出去。 +* 分享当前对话:会把当前聊天的内容也分享出去,但是要注意不要多个人同时用一个聊天内容。 +`; diff --git a/src/constants/model.ts b/src/constants/model.ts index e4fd92425..7b12ca631 100644 --- a/src/constants/model.ts +++ b/src/constants/model.ts @@ -1,23 +1,37 @@ +import type { ServiceName } from '@/types/mongoSchema'; +import { ModelSchema } from '../types/mongoSchema'; + export enum ChatModelNameEnum { GPT35 = 'gpt-3.5-turbo', GPT3 = 'text-davinci-003' } -export const OpenAiList = [ - { - name: 'chatGPT', - model: ChatModelNameEnum.GPT35, - trainName: 'turbo', - canTraining: false, - maxToken: 4060 - }, - { - name: 'GPT3', - model: ChatModelNameEnum.GPT3, - trainName: 'davinci', - canTraining: true, - maxToken: 4060 - } -]; + +export type ModelConstantsData = { + name: string; + model: `${ChatModelNameEnum}`; + trainName: string; // 空字符串代表不能训练 + maxToken: number; + maxTemperature: number; +}; + +export const ModelList: Record = { + openai: [ + { + name: 'chatGPT', + model: ChatModelNameEnum.GPT35, + trainName: 'turbo', + maxToken: 4000, + maxTemperature: 2 + }, + { + name: 'GPT3', + model: ChatModelNameEnum.GPT3, + trainName: 'davinci', + maxToken: 4000, + maxTemperature: 2 + } + ] +}; export enum TrainingStatusEnum { pending = 'pending', @@ -51,3 +65,29 @@ export const formatModelStatus = { text: '已关闭' } }; + +export const defaultModel: ModelSchema = { + _id: '', + userId: '', + name: '', + avatar: '', + status: ModelStatusEnum.pending, + updateTime: Date.now(), + trainingTimes: 0, + systemPrompt: '', + intro: '', + temperature: 5, + service: { + company: 'openai', + trainId: '', + chatModel: ChatModelNameEnum.GPT35, + modelName: ChatModelNameEnum.GPT35 + }, + security: { + domain: ['*'], + contextMaxLen: 1, + contentMaxLen: 1, + expiredTime: 9999, + maxLoadAmount: 1 + } +}; diff --git a/src/pages/api/chat/chatGpt.ts b/src/pages/api/chat/chatGpt.ts index 37617d61b..aac6240b1 100644 --- a/src/pages/api/chat/chatGpt.ts +++ b/src/pages/api/chat/chatGpt.ts @@ -8,6 +8,7 @@ import { ChatItemType } from '@/types/chat'; import { jsonRes } from '@/service/response'; import type { ModelSchema } from '@/types/mongoSchema'; import { PassThrough } from 'stream'; +import { ModelList } from '@/constants/model'; /* 发送提示词 */ export default async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -56,6 +57,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) }); } + // 计算温度 + const modelConstantsData = ModelList['openai'].find( + (item) => item.model === model.service.modelName + ); + if (!modelConstantsData) { + throw new Error('模型异常'); + } + const temperature = modelConstantsData.maxTemperature * (model.temperature / 10); + // 获取 chatAPI const chatAPI = getOpenAIApi(userApiKey); let startTime = Date.now(); @@ -63,8 +73,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const chatResponse = await chatAPI.createChatCompletion( { model: model.service.chatModel, - temperature: 1, - // max_tokens: model.security.contentMaxLen, + temperature: temperature, + max_tokens: modelConstantsData.maxToken, messages: formatPrompts, stream: true }, diff --git a/src/pages/api/chat/gpt3.ts b/src/pages/api/chat/gpt3.ts index 82326eb92..5f0baea96 100644 --- a/src/pages/api/chat/gpt3.ts +++ b/src/pages/api/chat/gpt3.ts @@ -5,6 +5,7 @@ import { connectToDatabase } from '@/service/mongo'; import { getOpenAIApi, authChat } from '@/service/utils/chat'; import { ChatItemType } from '@/types/chat'; import { httpsAgent } from '@/service/utils/tools'; +import { ModelList } from '@/constants/model'; /* 发送提示词 */ export default async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -27,13 +28,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) // prompt处理 const formatPrompt = prompt.map((item) => `${item.value}\n\n###\n\n`).join(''); + // 计算温度 + const modelConstantsData = ModelList['openai'].find( + (item) => item.model === model.service.modelName + ); + if (!modelConstantsData) { + throw new Error('模型异常'); + } + const temperature = modelConstantsData.maxTemperature * (model.temperature / 10); + // 发送请求 const response = await chatAPI.createCompletion( { model: model.service.modelName, prompt: formatPrompt, - temperature: 0.5, - max_tokens: model.security.contentMaxLen, + temperature: temperature, + max_tokens: modelConstantsData.maxToken, top_p: 1, frequency_penalty: 0, presence_penalty: 0.6, diff --git a/src/pages/api/chat/init.ts b/src/pages/api/chat/init.ts index 9adabbbee..c76b0dea3 100644 --- a/src/pages/api/chat/init.ts +++ b/src/pages/api/chat/init.ts @@ -47,6 +47,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) modelId: model._id, name: model.name, avatar: model.avatar, + intro: model.intro, secret: model.security, chatModel: model.service.chatModel, history: chat.content diff --git a/src/pages/api/model/create.ts b/src/pages/api/model/create.ts index bb8b60d31..793321fc1 100644 --- a/src/pages/api/model/create.ts +++ b/src/pages/api/model/create.ts @@ -3,12 +3,21 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { jsonRes } from '@/service/response'; import { connectToDatabase } from '@/service/mongo'; import { authToken } from '@/service/utils/tools'; -import { ModelStatusEnum, OpenAiList } from '@/constants/model'; +import { ModelStatusEnum, ModelList, ChatModelNameEnum } from '@/constants/model'; +import type { ServiceName } from '@/types/mongoSchema'; import { Model } from '@/service/models/model'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { - const { name, serviceModelName, serviceModelCompany = 'openai' } = req.body; + const { + name, + serviceModelName, + serviceModelCompany = 'openai' + } = req.body as { + name: string; + serviceModelName: `${ChatModelNameEnum}`; + serviceModelCompany: ServiceName; + }; const { authorization } = req.headers; if (!authorization) { @@ -22,10 +31,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< // 凭证校验 const userId = await authToken(authorization); - const modelItem = OpenAiList.find((item) => item.model === serviceModelName); + const modelItem = ModelList[serviceModelCompany].find( + (item) => item.model === serviceModelName + ); if (!modelItem) { - throw new Error('模型错误'); + throw new Error('模型不存在'); } await connectToDatabase(); @@ -43,8 +54,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< const authCount = await Model.countDocuments({ userId }); - if (authCount >= 10) { - throw new Error('上限 10 个模型'); + if (authCount >= 20) { + throw new Error('上限 20 个模型'); } // 创建模型 diff --git a/src/pages/api/model/detail.tsx b/src/pages/api/model/detail.tsx index 1280d065e..8e3e31d6c 100644 --- a/src/pages/api/model/detail.tsx +++ b/src/pages/api/model/detail.tsx @@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response'; import { connectToDatabase } from '@/service/mongo'; import { authToken } from '@/service/utils/tools'; import { Model } from '@/service/models/model'; -import { ModelType } from '@/types/model'; +import type { ModelSchema } from '@/types/mongoSchema'; /* 获取我的模型 */ export default async function handler(req: NextApiRequest, res: NextApiResponse) { @@ -26,7 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< await connectToDatabase(); // 根据 userId 获取模型信息 - const model: ModelType | null = await Model.findOne({ + const model = await Model.findOne({ userId, _id: modelId }); diff --git a/src/pages/api/model/getTrainings.ts b/src/pages/api/model/getTrainings.ts index 87d64d983..bc7c54c98 100644 --- a/src/pages/api/model/getTrainings.ts +++ b/src/pages/api/model/getTrainings.ts @@ -6,7 +6,7 @@ import formidable from 'formidable'; import { authToken, getUserOpenaiKey } from '@/service/utils/tools'; import { join } from 'path'; import fs from 'fs'; -import type { ModelType } from '@/types/model'; +import type { ModelSchema } from '@/types/mongoSchema'; import type { OpenAIApi } from 'openai'; import { ModelStatusEnum, TrainingStatusEnum } from '@/constants/model'; import { httpsAgent } from '@/service/utils/tools'; diff --git a/src/pages/api/model/putTrainStatus.ts b/src/pages/api/model/putTrainStatus.ts index 72ada84d8..3ce4ba2c8 100644 --- a/src/pages/api/model/putTrainStatus.ts +++ b/src/pages/api/model/putTrainStatus.ts @@ -3,7 +3,7 @@ import { jsonRes } from '@/service/response'; import { connectToDatabase, Model, Training } from '@/service/mongo'; import { getOpenAIApi } from '@/service/utils/chat'; import { authToken, getUserOpenaiKey } from '@/service/utils/tools'; -import type { ModelType } from '@/types/model'; +import type { ModelSchema } from '@/types/mongoSchema'; import { TrainingItemType } from '@/types/training'; import { ModelStatusEnum, TrainingStatusEnum } from '@/constants/model'; import { OpenAiTuneStatusEnum } from '@/service/constants/training'; @@ -26,7 +26,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) await connectToDatabase(); // 获取模型 - const model: ModelType | null = await Model.findById(modelId); + const model = await Model.findById(modelId); if (!model || model.status !== 'training') { throw new Error('模型不在训练中'); diff --git a/src/pages/api/model/train.ts b/src/pages/api/model/train.ts index 0f16ab240..95bc033ec 100644 --- a/src/pages/api/model/train.ts +++ b/src/pages/api/model/train.ts @@ -7,7 +7,7 @@ import formidable from 'formidable'; import { authToken, getUserOpenaiKey } from '@/service/utils/tools'; import { join } from 'path'; import fs from 'fs'; -import type { ModelType } from '@/types/model'; +import type { ModelSchema } from '@/types/mongoSchema'; import type { OpenAIApi } from 'openai'; import { ModelStatusEnum, TrainingStatusEnum } from '@/constants/model'; import { httpsAgent } from '@/service/utils/tools'; @@ -38,7 +38,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) await connectToDatabase(); // 获取模型的状态 - const model: ModelType | null = await Model.findById(modelId); + const model = await Model.findById(modelId); if (!model || model.status !== 'running') { throw new Error('模型正忙'); diff --git a/src/pages/api/model/update.ts b/src/pages/api/model/update.ts index 8017c0b82..1de24e856 100644 --- a/src/pages/api/model/update.ts +++ b/src/pages/api/model/update.ts @@ -8,7 +8,8 @@ import type { ModelUpdateParams } from '@/types/model'; /* 获取我的模型 */ export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { - const { name, service, security, systemPrompt } = req.body as ModelUpdateParams; + const { name, service, security, systemPrompt, intro, temperature } = + req.body as ModelUpdateParams; const { modelId } = req.query as { modelId: string }; const { authorization } = req.headers; @@ -33,8 +34,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< }, { name, - service, systemPrompt, + intro, + temperature, + service, security } ); diff --git a/src/pages/chat/components/Empty.tsx b/src/pages/chat/components/Empty.tsx index 2733e9235..7823abcca 100644 --- a/src/pages/chat/components/Empty.tsx +++ b/src/pages/chat/components/Empty.tsx @@ -1,23 +1,44 @@ import React from 'react'; -import { Card, Flex, Box } from '@chakra-ui/react'; +import { Card, Box, Mark } from '@chakra-ui/react'; +import { versionIntro, chatProblem } from '@/constants/common'; +import Markdown from '@/components/Markdown'; -const Empty = () => { +const Empty = ({ intro }: { intro: string }) => { + const Header = ({ children }: { children: string }) => ( + + {children} + + ); return ( - - - - Fast Gpt version1.3 - - - 更新了聊天的数据结构,如果出现问题,请手动删除左侧旧的历史记录,并重新从模型页生成对话框进入。 - - 分享聊天使用的是分享者的 Api Key 进行收费,请确认分享安全 -
- 分享空白聊天,会分享一个该模型的空白聊天页 -
- 分享当前聊天,会把当前聊天的内容分享出去,请注意不会多人同时使用一个对话框 + + {!!intro && ( + +
模型介绍
+ {intro} +
+ )} + +
常见问题
+
-
+ {/* version intro */} + +
Fast Gpt version1.4
+ + 聊天的数据结构发生了比较大的改动。如果出现问题,请手动删除左侧旧的历史记录,并重新从模型页生成对话框进入。 + +
+ +
+ ); }; diff --git a/src/pages/chat/components/SlideBar.tsx b/src/pages/chat/components/SlideBar.tsx index 6341e7815..a5b75d1fe 100644 --- a/src/pages/chat/components/SlideBar.tsx +++ b/src/pages/chat/components/SlideBar.tsx @@ -1,7 +1,8 @@ import React, { useState, useEffect } from 'react'; -import { Box, Button } from '@chakra-ui/react'; -import { AddIcon, ChatIcon, EditIcon, DeleteIcon } from '@chakra-ui/icons'; +import { AddIcon, ChatIcon, DeleteIcon } from '@chakra-ui/icons'; import { + Box, + Button, Accordion, AccordionItem, AccordionButton, @@ -9,16 +10,26 @@ import { AccordionIcon, Flex, Divider, - IconButton + IconButton, + Modal, + ModalOverlay, + ModalContent, + ModalHeader, + ModalFooter, + ModalBody, + ModalCloseButton, + useDisclosure } from '@chakra-ui/react'; import { useUserStore } from '@/store/user'; import { useChatStore } from '@/store/chat'; import { useQuery } from '@tanstack/react-query'; import { useRouter } from 'next/router'; -import { useScreen } from '@/hooks/useScreen'; import { getToken } from '@/utils/user'; import MyIcon from '@/components/Icon'; import { useCopyData } from '@/utils/tools'; +import Markdown from '@/components/Markdown'; +import { shareHint } from '@/constants/common'; +import { getChatSiteId } from '@/api/chat'; const SlideBar = ({ name, @@ -36,10 +47,13 @@ const SlideBar = ({ const router = useRouter(); const { copyData } = useCopyData(); const { myModels, getMyModels } = useUserStore(); - const { chatHistory, removeChatHistoryByWindowId, generateChatWindow, updateChatHistory } = - useChatStore(); - const { isSuccess } = useQuery(['init'], getMyModels); + const { chatHistory, removeChatHistoryByWindowId } = useChatStore(); const [hasReady, setHasReady] = useState(false); + const { isOpen: isOpenShare, onOpen: onOpenShare, onClose: onCloseShare } = useDisclosure(); + + const { isSuccess } = useQuery(['init'], getMyModels, { + cacheTime: 5 * 60 * 1000 + }); useEffect(() => { setHasReady(true); @@ -119,19 +133,8 @@ const SlideBar = ({ {/* 我的模型 & 历史记录 折叠框*/} - {isSuccess ? ( - - - - - 历史记录 - - - - - {hasReady && } - - + + {isSuccess && ( @@ -161,7 +164,7 @@ const SlideBar = ({ : {})} onClick={async () => { if (item.name === name) return; - router.push(`/chat?chatId=${await generateChatWindow(item._id)}`); + router.push(`/chat?chatId=${await getChatSiteId(item._id)}`); onClose(); }} > @@ -173,43 +176,25 @@ const SlideBar = ({ ))} - - ) : ( - <> - - 历史记录 - - - - )} + )} + + + + 历史记录 + + + + + {hasReady && } + + + - {/* 分享 */} - {getToken() && ( - { - copyData( - `${location.origin}/chat?chatId=${await generateChatWindow(modelId)}`, - '已复制分享链接' - ); - }} - > - - 分享空白对话 - - )} { - copyData(`${location.origin}/chat?chatId=${chatId}`, '已复制分享链接'); + onClick={() => { + onOpenShare(); + onClose(); }} > - 分享当前对话 + 分享对话 + + {/* 分享提示modal */} + + + + 分享对话 + + + + + + + + {getToken() && ( + + )} + + + + + ); }; diff --git a/src/pages/chat/index.tsx b/src/pages/chat/index.tsx index dbe86355b..e1ee67a6e 100644 --- a/src/pages/chat/index.tsx +++ b/src/pages/chat/index.tsx @@ -51,6 +51,7 @@ const Chat = ({ chatId }: { chatId: string }) => { modelId: '', name: '', avatar: '', + intro: '', secret: {}, chatModel: '', history: [], @@ -113,7 +114,11 @@ const Chat = ({ chatId }: { chatId: string }) => { status: 'finish' })) }); - scrollToBottom(); + if (res.history.length > 0) { + setTimeout(() => { + scrollToBottom(); + }, 500); + } }, onError(e: any) { toast({ @@ -433,7 +438,7 @@ const Chat = ({ chatId }: { chatId: string }) => { ))} - {chatData.history.length === 0 && } + {chatData.history.length === 0 && } {/* 发送区 */} ; - onSuccess: Dispatch; + onSuccess: Dispatch; }) => { const [requesting, setRequesting] = useState(false); const toast = useToast({ @@ -42,7 +42,7 @@ const CreateModel = ({ formState: { errors } } = useForm({ defaultValues: { - serviceModelName: OpenAiList[0].model + serviceModelName: ModelList['openai'][0].model } }); @@ -95,7 +95,7 @@ const CreateModel = ({ required: '底层模型不能为空' })} > - {OpenAiList.map((item) => ( + {ModelList['openai'].map((item) => ( diff --git a/src/pages/model/components/ModelEditForm.tsx b/src/pages/model/components/ModelEditForm.tsx index 8b1f2b9b3..ba690b638 100644 --- a/src/pages/model/components/ModelEditForm.tsx +++ b/src/pages/model/components/ModelEditForm.tsx @@ -1,86 +1,37 @@ -import React, { useCallback, useEffect, useRef } from 'react'; -import { Grid, Box, Card, Flex, Button, FormControl, Input, Textarea } from '@chakra-ui/react'; -import type { ModelType } from '@/types/model'; -import { useForm } from 'react-hook-form'; -import { useToast } from '@/hooks/useToast'; -import { putModelById } from '@/api/model'; -import { useScreen } from '@/hooks/useScreen'; -import { useGlobalStore } from '@/store/global'; +import React, { useState } from 'react'; +import { + Box, + Card, + Flex, + FormControl, + Input, + Textarea, + Slider, + SliderTrack, + SliderFilledTrack, + SliderThumb, + SliderMark, + Tooltip +} from '@chakra-ui/react'; +import { QuestionOutlineIcon } from '@chakra-ui/icons'; +import type { ModelSchema } from '@/types/mongoSchema'; +import { UseFormReturn } from 'react-hook-form'; -const ModelEditForm = ({ model }: { model?: ModelType }) => { - const isInit = useRef(false); - const { - register, - handleSubmit, - reset, - formState: { errors } - } = useForm(); - const { setLoading } = useGlobalStore(); - const { toast } = useToast(); - const { media } = useScreen(); - - const onclickSave = useCallback( - async (data: ModelType) => { - setLoading(true); - try { - await putModelById(data._id, { - name: data.name, - systemPrompt: data.systemPrompt, - service: data.service, - security: data.security - }); - toast({ - title: '更新成功', - status: 'success' - }); - } catch (err) { - console.log('error->', err); - toast({ - title: err as string, - status: 'success' - }); - } - setLoading(false); - }, - [setLoading, toast] - ); - const submitError = useCallback(() => { - // deep search message - const deepSearch = (obj: any): string => { - if (!obj) return '提交表单错误'; - if (!!obj.message) { - return obj.message; - } - return deepSearch(Object.values(obj)[0]); - }; - toast({ - title: deepSearch(errors), - status: 'error', - duration: 4000, - isClosable: true - }); - }, [errors, toast]); - - /* model 只会改变一次 */ - useEffect(() => { - if (model && !isInit.current) { - reset(model); - isInit.current = true; - } - }, [model, reset]); +const ModelEditForm = ({ formHooks }: { formHooks: UseFormReturn }) => { + const { register, setValue, getValues } = formHooks; + const [refresh, setRefresh] = useState(false); return ( - + <> - - 修改模型信息 - - + 基本信息 - + - 展示名称: + + 名称: + { > - - - 对话模型: - {model?.service.modelName} - - - + + 介绍: