From e08e8aa00b64427beac2a5007ad3956ca4c19b6c Mon Sep 17 00:00:00 2001 From: archer <545436317@qq.com> Date: Tue, 4 Apr 2023 13:15:34 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=AE=E6=94=B9=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=8F=AF=E4=BF=AE=E6=94=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/model.ts | 2 +- src/pages/api/chat/lafGpt.ts | 14 ++- src/pages/api/model/data/putModelData.ts | 19 +++-- .../detail/components/InputDataModal.tsx | 51 ++++++++--- .../model/detail/components/ModelDataCard.tsx | 85 +++++++++---------- 5 files changed, 100 insertions(+), 71 deletions(-) diff --git a/src/api/model.ts b/src/api/model.ts index 1c17d0c2f..1c84f9924 100644 --- a/src/api/model.ts +++ b/src/api/model.ts @@ -57,7 +57,7 @@ export const postModelDataJsonData = ( jsonData: { prompt: string; completion: string; vector?: number[] }[] ) => POST(`/model/data/pushModelDataJson`, { modelId, data: jsonData }); -export const putModelDataById = (data: { dataId: string; text: string }) => +export const putModelDataById = (data: { dataId: string; text: string; q?: string }) => PUT('/model/data/putModelData', data); export const delOneModelData = (dataId: string) => DELETE(`/model/data/delModelDataById?dataId=${dataId}`); diff --git a/src/pages/api/chat/lafGpt.ts b/src/pages/api/chat/lafGpt.ts index 3a37bde89..0edda1d18 100644 --- a/src/pages/api/chat/lafGpt.ts +++ b/src/pages/api/chat/lafGpt.ts @@ -65,27 +65,23 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) messages: [ { role: 'system', - content: `服务端逻辑生成器。根据用户输入的需求,拆解成代码实现的步骤,并按下面格式返回: - 1. - 2. - 3. - .... + content: `服务端逻辑生成器。根据用户输入的需求,拆解成代码实现的步骤,并按格式返回: 1.\n2.\n3.\n ...... 下面是一些例子: - 实现一个手机号注册账号的方法 - 发送手机验证码函数: + 实现一个手机号注册账号的方法,包含两个函数 + * 发送手机验证码函数: 1. 从 query 中获取 phone 2. 校验手机号格式是否正确,不正确返回{error: "手机号格式错误"} 3. 给 phone 发送一个短信验证码,验证码长度为6位字符串,内容为:你正在注册laf, 验证码为:code 4. 数据库添加数据,表为"codes",内容为 {phone, code} - 注册函数 + * 注册函数 1. 从 body 中获取 phone 和 code 2. 校验手机号格式是否正确,不正确返回{error: "手机号格式错误"} 2. 获取数据库数据,表为"codes",查找是否有符合 phone, code 等于body参数的记录,没有的话返回 {error:"验证码不正确"} 4. 添加数据库数据,表为"users" ,内容为{phone, code, createTime} 5. 删除数据库数据,删除 code 记录 --------------- - 更新播客记录。传入blogId,blogText,tags,还需要记录更新的时间 + 更新博客记录。传入blogId,blogText,tags,还需要记录更新的时间 1. 从 body 中获取 blogId,blogText 和 tags 2. 校验 blogId 是否为空,为空则返回 {error: "博客ID不能为空"} 3. 校验 blogText 是否为空,为空则返回 {error: "博客内容不能为空"} diff --git a/src/pages/api/model/data/putModelData.ts b/src/pages/api/model/data/putModelData.ts index f4d24997e..c146cd175 100644 --- a/src/pages/api/model/data/putModelData.ts +++ b/src/pages/api/model/data/putModelData.ts @@ -2,13 +2,12 @@ import type { NextApiRequest, NextApiResponse } from 'next'; import { jsonRes } from '@/service/response'; import { authToken } from '@/service/utils/tools'; import { connectRedis } from '@/service/redis'; +import { ModelDataStatusEnum } from '@/constants/redis'; +import { generateVector } from '@/service/events/generateVector'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { try { - let { dataId, text } = req.body as { - dataId: string; - text: string; - }; + const { dataId, text, q } = req.body as { dataId: string; text: string; q?: string }; const { authorization } = req.headers; if (!authorization) { @@ -31,7 +30,17 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse< } // 更新 - await redis.hSet(dataId, 'text', text); + await redis.sendCommand([ + 'HMSET', + dataId, + ...(q ? ['q', q, 'status', ModelDataStatusEnum.waiting] : []), + 'text', + text + ]); + + if (q) { + generateVector(); + } jsonRes(res); } catch (err) { diff --git a/src/pages/model/detail/components/InputDataModal.tsx b/src/pages/model/detail/components/InputDataModal.tsx index 97f4f746f..3859e8f46 100644 --- a/src/pages/model/detail/components/InputDataModal.tsx +++ b/src/pages/model/detail/components/InputDataModal.tsx @@ -1,7 +1,6 @@ import React, { useState, useCallback } from 'react'; import { Box, - IconButton, Flex, Button, Modal, @@ -9,37 +8,40 @@ import { ModalContent, ModalHeader, ModalCloseButton, - Input, Textarea } from '@chakra-ui/react'; -import { useForm, useFieldArray } from 'react-hook-form'; -import { postModelDataInput } from '@/api/model'; +import { useForm } from 'react-hook-form'; +import { postModelDataInput, putModelDataById } from '@/api/model'; import { useToast } from '@/hooks/useToast'; -import { DeleteIcon } from '@chakra-ui/icons'; import { customAlphabet } from 'nanoid'; const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12); -type FormData = { text: string; q: string }; +export type FormData = { dataId?: string; text: string; q: string }; const InputDataModal = ({ onClose, onSuccess, - modelId + modelId, + defaultValues = { + text: '', + q: '' + } }: { onClose: () => void; onSuccess: () => void; modelId: string; + defaultValues?: FormData; }) => { const [importing, setImporting] = useState(false); const { toast } = useToast(); - const { register, handleSubmit, control } = useForm({ - defaultValues: { - text: '', - q: '' - } + const { register, handleSubmit } = useForm({ + defaultValues }); + /** + * 确认导入新数据 + */ const sureImportData = useCallback( async (e: FormData) => { setImporting(true); @@ -72,6 +74,26 @@ const InputDataModal = ({ [modelId, onClose, onSuccess, toast] ); + const updateData = useCallback( + async (e: FormData) => { + if (!e.dataId) return; + if (e.text === defaultValues.text && e.q === defaultValues.q) return; + + await putModelDataById({ + dataId: e.dataId, + text: e.text, + q: e.q === defaultValues.q ? '' : e.q + }); + toast({ + title: '修改回答成功', + status: 'success' + }); + onClose(); + onSuccess(); + }, + [defaultValues.q, onClose, onSuccess, toast] + ); + return ( @@ -125,7 +147,10 @@ const InputDataModal = ({ - diff --git a/src/pages/model/detail/components/ModelDataCard.tsx b/src/pages/model/detail/components/ModelDataCard.tsx index 22ec44016..27f5df32e 100644 --- a/src/pages/model/detail/components/ModelDataCard.tsx +++ b/src/pages/model/detail/components/ModelDataCard.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from 'react'; +import React, { useCallback, useState } from 'react'; import { Box, TableContainer, @@ -12,7 +12,6 @@ import { Flex, Button, useDisclosure, - Textarea, Menu, MenuButton, MenuList, @@ -25,22 +24,21 @@ import { usePagination } from '@/hooks/usePagination'; import { getModelDataList, delOneModelData, - putModelDataById, getModelSplitDataList, getExportDataList } from '@/api/model'; -import { DeleteIcon, RepeatIcon } from '@chakra-ui/icons'; +import { DeleteIcon, RepeatIcon, EditIcon } from '@chakra-ui/icons'; import { useToast } from '@/hooks/useToast'; import { useLoading } from '@/hooks/useLoading'; import dynamic from 'next/dynamic'; import { useMutation, useQuery } from '@tanstack/react-query'; +import type { FormData as InputDataType } from './InputDataModal'; const InputModel = dynamic(() => import('./InputDataModal')); const SelectFileModel = dynamic(() => import('./SelectFileModal')); const SelectJsonModel = dynamic(() => import('./SelectJsonModal')); const ModelDataCard = ({ model }: { model: ModelSchema }) => { - const { toast } = useToast(); const { Loading } = useLoading(); const { @@ -58,25 +56,8 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { } }); - const updateAnswer = useCallback( - async (dataId: string, text: string) => { - await putModelDataById({ - dataId, - text - }); - toast({ - title: '修改回答成功', - status: 'success' - }); - }, - [toast] - ); + const [editInputData, setEditInputData] = useState(); - const { - isOpen: isOpenInputModal, - onOpen: onOpenInputModal, - onClose: onCloseInputModal - } = useDisclosure(); const { isOpen: isOpenSelectFileModal, onOpen: onOpenSelectFileModal, @@ -151,7 +132,16 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { 导入 - 手动输入 + + setEditInputData({ + text: '', + q: '' + }) + } + > + 手动输入 + 文件导入 JSON导入 @@ -170,34 +160,38 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { Question Text Status - + 操作 {modelDataList.map((item) => ( - - + + {item.q} - + + {item.text} + - {ModelDataStatusMap[item.status]} + {ModelDataStatusMap[item.status]} + } + variant={'outline'} + aria-label={'delete'} + size={'sm'} + onClick={() => + setEditInputData({ + dataId: item.id, + q: item.q, + text: item.text + }) + } + /> } variant={'outline'} @@ -221,8 +215,13 @@ const ModelDataCard = ({ model }: { model: ModelSchema }) => { - {isOpenInputModal && ( - + {editInputData !== undefined && ( + setEditInputData(undefined)} + onSuccess={refetchData} + /> )} {isOpenSelectFileModal && (