Commit 5d4dd4a1 by archer

fix: ui bug

parent 5bf95bd8
......@@ -35,184 +35,9 @@ docker-compose -v
### 2. 创建 3 个初始化文件
手动创建或者直接把 fastgpt 文件夹复制过去。
**/root/fastgpt/pg/init.sql PG 数据库初始化**
```sql
set -e
psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
CREATE EXTENSION vector;
-- init table
CREATE TABLE modelData (
id BIGSERIAL PRIMARY KEY,
vector VECTOR(1536),
status VARCHAR(50) NOT NULL,
user_id VARCHAR(50) NOT NULL,
model_id VARCHAR(50) NOT NULL,
q TEXT NOT NULL,
a TEXT NOT NULL
);
-- create index
CREATE INDEX modelData_status_index ON modelData USING HASH (status);
CREATE INDEX modelData_userId_index ON modelData USING HASH (user_id);
CREATE INDEX modelData_modelId_index ON modelData USING HASH (model_id);
EOSQL
```
**/root/fastgpt/nginx/nginx.conf Nginx 配置**
```conf
user nginx;
worker_processes auto;
worker_rlimit_nofile 51200;
events {
worker_connections 1024;
}
http {
resolver 8.8.8.8;
proxy_ssl_server_name on;
access_log off;
server_names_hash_bucket_size 512;
client_header_buffer_size 64k;
large_client_header_buffers 4 64k;
client_max_body_size 50M;
fastgpt 文件夹。分别为:fastgpt/docker-compose.yaml, fastgpt/pg/init.sql, fastgpt/nginx/nginx.conf
proxy_connect_timeout 240s;
proxy_read_timeout 240s;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 8k;
gzip_http_version 1.1;
gzip_comp_level 6;
gzip_vary on;
gzip_types text/plain application/x-javascript text/css application/javascript application/json application/xml;
gzip_disable "MSIE [1-6]\.";
open_file_cache max=1000 inactive=1d;
open_file_cache_valid 30s;
open_file_cache_min_uses 8;
open_file_cache_errors off;
server {
listen 443 ssl;
# 改成自己的域名和证书
server_name docgpt.ahapocket.cn;
ssl_certificate /ssl/docgpt.pem;
ssl_certificate_key /ssl/docgpt.key;
ssl_session_timeout 5m;
location / {
proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
server {
listen 80;
server_name docgpt.ahapocket.cn;
rewrite ^(.*) https://$server_name$1 permanent;
}
}
```
**/root/fastgpt/docker-compose.yml 核心部署文件**
环境变量内容和开发时的环境变量基本相同,除了数据库的地址。
```yml
version: '3.3'
services:
pg:
image: ankane/pgvector:v0.4.1
container_name: pg
restart: always
ports:
- 8100:5432
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- POSTGRES_USER=fastgpt
- POSTGRES_PASSWORD=1234
- POSTGRES_DB=fastgpt
volumes:
# 刚创建的文件
- /root/fastgpt/pg/init.sql:/docker-entrypoint-initdb.d/init.sh
- /root/fastgpt/pg/data:/var/lib/postgresql/data
- /etc/localtime:/etc/localtime:ro
mongodb:
image: mongo:6.0.4
container_name: mongo
restart: always
ports:
- 27017:27017
environment:
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
- MONGO_INITDB_ROOT_USERNAME=username
- MONGO_INITDB_ROOT_PASSWORD=password
volumes:
- /root/fastgpt/mongo/data:/data/db
- /root/fastgpt/mongo/logs:/var/log/mongodb
- /etc/localtime:/etc/localtime:ro
fastgpt:
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest
network_mode: host
restart: always
container_name: fastgpt
environment:
# proxy(可选)
- AXIOS_PROXY_HOST=127.0.0.1
- AXIOS_PROXY_PORT=7890
# 是否开启队列任务。 1-开启,0-关闭(请求 parentUrl 去执行任务,单机时直接填1)
- queueTask=1
- parentUrl=https://hostname/api/openapi/startEvents
# 发送邮箱验证码配置。用的是QQ邮箱。参考 nodeMail 获取MAILE_CODE,自行百度。
- MY_MAIL=xxxx@qq.com
- MAILE_CODE=xxxx
# 阿里短信服务(邮箱和短信至少二选一)
- aliAccessKeyId=xxxx
- aliAccessKeySecret=xxxx
- aliSignName=xxxxx
- aliTemplateCode=SMS_xxxx
# token加密凭证(随便填,作为登录凭证)
- TOKEN_KEY=xxxx
# 和上方mongo镜像的username,password对应
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
- MONGODB_NAME=fastgpt
- PG_HOST=0.0.0.0
- PG_PORT=8100
# 和上方PG镜像对应.
- PG_USER=fastgpt # POSTGRES_USER
- PG_PASSWORD=1234 # POSTGRES_PASSWORD
- PG_DB_NAME=fastgpt # POSTGRES_DB
# openai
- OPENAIKEY=sk-xxxxx
- GPT4KEY=sk-xxx
- OPENAI_BASE_URL=https://api.openai.com/v1
- OPENAI_BASE_URL_AUTH=可选的安全凭证
# claude
- CLAUDE_BASE_URL=calude模型请求地址
- CLAUDE_KEY=CLAUDE_KEY
nginx:
image: nginx:alpine3.17
container_name: nginx
restart: always
network_mode: host
volumes:
# 刚创建的文件
- /root/fastgpt/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- /root/fastgpt/nginx/logs:/var/log/nginx
# https证书,没有的话不填,对应的nginx.conf也要修改
- /root/fastgpt/nginx/ssl/docgpt.key:/ssl/docgpt.key
- /root/fastgpt/nginx/ssl/docgpt.pem:/ssl/docgpt.pem
```
手动创建或者直接把 fastgpt 文件夹复制过去。
### 3. 运行 docker-compose
......
version: '3.3'
services:
pg:
image: ankane/pgvector:v0.4.1
image: ankane/pgvector:v0.4.2
container_name: pg
restart: always
ports:
......
......@@ -7,7 +7,7 @@ interface Props extends BoxProps {}
const SideBar = (e?: Props) => {
const {
w = [1, '0 0 250px', '0 0 280px', '0 0 310px', '0 0 340px'],
w = ['100%', '0 0 250px', '0 0 280px', '0 0 310px', '0 0 340px'],
children,
...props
} = e || {};
......
......@@ -146,7 +146,7 @@ const DataCard = ({ kbId }: { kbId: string }) => {
});
return (
<Box position={'relative'} w={'100%'}>
<Box position={'relative'}>
<Flex>
<Box fontWeight={'bold'} fontSize={'lg'} flex={1} mr={2}>
知识库数据: {total}组
......@@ -155,7 +155,7 @@ const DataCard = ({ kbId }: { kbId: string }) => {
icon={<RepeatIcon />}
aria-label={'refresh'}
variant={'outline'}
mr={4}
mr={[2, 4]}
size={'sm'}
onClick={() => refetchData(pageNum)}
/>
......@@ -218,73 +218,70 @@ const DataCard = ({ kbId }: { kbId: string }) => {
}}
/>
</Flex>
<Box mt={4}>
<TableContainer>
<Table variant={'simple'} w={'100%'}>
<Thead>
<Tr>
<Th>
匹配的知识点
<Tooltip
label={
'对话时,会将用户的问题和知识库的 "匹配知识点" 进行比较,找到最相似的前 n 条记录,将这些记录的 "匹配知识点"+"补充知识点" 作为 chatgpt 的系统提示词。'
<TableContainer mt={4} minH={'200px'}>
<Table>
<Thead>
<Tr>
<Th>
匹配的知识点
<Tooltip
label={
'对话时,会将用户的问题和知识库的 "匹配知识点" 进行比较,找到最相似的前 n 条记录,将这些记录的 "匹配知识点"+"补充知识点" 作为 chatgpt 的系统提示词。'
}
>
<QuestionOutlineIcon ml={1} />
</Tooltip>
</Th>
<Th>补充知识</Th>
<Th>状态</Th>
<Th>操作</Th>
</Tr>
</Thead>
<Tbody>
{modelDataList.map((item) => (
<Tr key={item.id}>
<Td>
<Box {...tdStyles.current}>{item.q}</Box>
</Td>
<Td>
<Box {...tdStyles.current}>{item.a || '-'}</Box>
</Td>
<Td>{ModelDataStatusMap[item.status]}</Td>
<Td>
<IconButton
mr={5}
icon={<EditIcon />}
variant={'outline'}
aria-label={'delete'}
size={'sm'}
onClick={() =>
setEditInputData({
dataId: item.id,
q: item.q,
a: item.a
})
}
>
<QuestionOutlineIcon ml={1} />
</Tooltip>
</Th>
<Th>补充知识</Th>
<Th>状态</Th>
<Th>操作</Th>
/>
<IconButton
icon={<DeleteIcon />}
variant={'outline'}
colorScheme={'gray'}
aria-label={'delete'}
size={'sm'}
onClick={async () => {
await delOneKbDataByDataId(item.id);
refetchData(pageNum);
}}
/>
</Td>
</Tr>
</Thead>
<Tbody>
{modelDataList.map((item) => (
<Tr key={item.id}>
<Td>
<Box {...tdStyles.current}>{item.q}</Box>
</Td>
<Td>
<Box {...tdStyles.current}>{item.a || '-'}</Box>
</Td>
<Td>{ModelDataStatusMap[item.status]}</Td>
<Td>
<IconButton
mr={5}
icon={<EditIcon />}
variant={'outline'}
aria-label={'delete'}
size={'sm'}
onClick={() =>
setEditInputData({
dataId: item.id,
q: item.q,
a: item.a
})
}
/>
<IconButton
icon={<DeleteIcon />}
variant={'outline'}
colorScheme={'gray'}
aria-label={'delete'}
size={'sm'}
onClick={async () => {
await delOneKbDataByDataId(item.id);
refetchData(pageNum);
}}
/>
</Td>
</Tr>
))}
</Tbody>
</Table>
</TableContainer>
<Flex mt={2} justifyContent={'flex-end'}>
<Pagination />
</Flex>
</Box>
))}
</Tbody>
</Table>
</TableContainer>
<Flex mt={2} justifyContent={'flex-end'}>
<Pagination />
</Flex>
<Loading loading={isLoading} fixed={false} />
{editInputData !== undefined && (
......
import React, { useCallback, useState } from 'react';
import React, { useCallback, useState, useMemo } from 'react';
import { Box, Flex, useTheme, Input, IconButton, Tooltip, Image, Tag } from '@chakra-ui/react';
import { AddIcon } from '@chakra-ui/icons';
import { useRouter } from 'next/router';
......@@ -17,6 +17,11 @@ const KbList = ({ kbId }: { kbId: string }) => {
const { myKbList, loadKbList } = useUserStore();
const [searchText, setSearchText] = useState('');
const kbs = useMemo(
() => myKbList.filter((item) => new RegExp(searchText, 'ig').test(item.name + item.tags)),
[myKbList, searchText]
);
/* 加载模型 */
const { isLoading } = useQuery(['loadModels'], () => loadKbList(false));
......@@ -82,7 +87,7 @@ const KbList = ({ kbId }: { kbId: string }) => {
</Tooltip>
</Flex>
<Box flex={'1 0 0'} h={0} overflow={'overlay'}>
{myKbList.map((item) => (
{kbs.map((item) => (
<Flex
key={item._id}
position={'relative'}
......
......@@ -23,11 +23,11 @@ const Kb = ({ kbId }: { kbId: string }) => {
<Flex h={'100%'} position={'relative'} overflow={'hidden'}>
{/* 模型列表 */}
{(isPc || !kbId) && (
<SideBar w={[1, '0 0 250px', '0 0 270px', '0 0 290px']}>
<SideBar w={['100%', '0 0 250px', '0 0 270px', '0 0 290px']}>
<KbList kbId={kbId} />
</SideBar>
)}
<Box flex={1} h={'100%'} position={'relative'}>
<Box flex={'1 0 0'} w={0} h={'100%'} position={'relative'}>
{kbId && <KbDetail kbId={kbId} />}
</Box>
</Flex>
......
......@@ -29,7 +29,7 @@ const Model = ({ modelId }: { modelId: string }) => {
<Flex h={'100%'} position={'relative'} overflow={'hidden'}>
{/* 模型列表 */}
{(isPc || !modelId) && (
<SideBar w={[1, '0 0 250px', '0 0 270px', '0 0 290px']}>
<SideBar w={['100%', '0 0 250px', '0 0 270px', '0 0 290px']}>
<ModelList modelId={modelId} />
</SideBar>
)}
......
......@@ -18,6 +18,7 @@ const ShareModelList = ({
<>
{models.map((model) => (
<Flex
w={'100%'}
flexDirection={'column'}
key={model._id}
p={4}
......
......@@ -6,6 +6,11 @@ import { useRouter } from 'next/router';
const list = [
{
icon: 'kb',
label: '我的知识库',
link: '/kb'
},
{
icon: 'shareMarket',
label: 'AI助手市场',
link: '/model/share'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment