mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
fix: ui bug
This commit is contained in:
@@ -35,185 +35,10 @@ docker-compose -v
|
||||
|
||||
### 2. 创建 3 个初始化文件
|
||||
|
||||
fastgpt 文件夹。分别为:fastgpt/docker-compose.yaml, fastgpt/pg/init.sql, fastgpt/nginx/nginx.conf
|
||||
|
||||
手动创建或者直接把 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;
|
||||
|
||||
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
|
||||
```
|
||||
|
||||
### 3. 运行 docker-compose
|
||||
|
||||
下面是一个辅助脚本,也可以直接 docker-compose up -d
|
||||
|
@@ -1,7 +1,7 @@
|
||||
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 && (
|
||||
|
@@ -1,4 +1,4 @@
|
||||
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}
|
||||
|
@@ -5,6 +5,11 @@ import MyIcon from '@/components/Icon';
|
||||
import { useRouter } from 'next/router';
|
||||
|
||||
const list = [
|
||||
{
|
||||
icon: 'kb',
|
||||
label: '我的知识库',
|
||||
link: '/kb'
|
||||
},
|
||||
{
|
||||
icon: 'shareMarket',
|
||||
label: 'AI助手市场',
|
||||
|
Reference in New Issue
Block a user