Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
741381ec
authored
May 27, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
perf: generate queue
parent
f05b1297
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
291 additions
and
268 deletions
+291
-268
src/api/plugins/kb.ts
+3
-6
src/constants/plugin.ts
+5
-1
src/pages/api/admin/countTraining.ts
+37
-0
src/pages/api/openapi/kb/pushData.ts
+31
-20
src/pages/api/openapi/kb/updateData.ts
+9
-1
src/pages/api/openapi/text/splitText.ts
+0
-69
src/pages/api/plugins/kb/data/getTrainingData.ts
+12
-13
src/pages/kb/components/InputDataModal.tsx
+3
-1
src/pages/kb/components/SelectCsvModal.tsx
+3
-1
src/pages/kb/components/SelectFileModal.tsx
+7
-7
src/service/events/generateQA.ts
+44
-34
src/service/events/generateVector.ts
+92
-84
src/service/models/trainingData.ts
+16
-7
src/service/mongo.ts
+6
-18
src/service/pg.ts
+2
-2
src/service/response.ts
+1
-1
src/service/utils/tools.ts
+15
-1
src/types/index.d.ts
+2
-0
src/types/mongoSchema.d.ts
+3
-2
No files found.
src/api/plugins/kb.ts
View file @
741381ec
...
@@ -2,7 +2,7 @@ import { GET, POST, PUT, DELETE } from '../request';
...
@@ -2,7 +2,7 @@ import { GET, POST, PUT, DELETE } from '../request';
import
type
{
KbItemType
}
from
'@/types/plugin'
;
import
type
{
KbItemType
}
from
'@/types/plugin'
;
import
{
RequestPaging
}
from
'@/types/index'
;
import
{
RequestPaging
}
from
'@/types/index'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
import
{
KbDataItemType
}
from
'@/types/plugin
'
;
import
{
Props
as
PushDataProps
}
from
'@/pages/api/openapi/kb/pushData
'
;
export
type
KbUpdateParams
=
{
id
:
string
;
name
:
string
;
tags
:
string
;
avatar
:
string
};
export
type
KbUpdateParams
=
{
id
:
string
;
name
:
string
;
tags
:
string
;
avatar
:
string
};
...
@@ -46,10 +46,7 @@ export const getKbDataItemById = (dataId: string) =>
...
@@ -46,10 +46,7 @@ export const getKbDataItemById = (dataId: string) =>
/**
/**
* 直接push数据
* 直接push数据
*/
*/
export
const
postKbDataFromList
=
(
data
:
{
export
const
postKbDataFromList
=
(
data
:
PushDataProps
)
=>
POST
(
`/openapi/kb/pushData`
,
data
);
kbId
:
string
;
data
:
{
a
:
KbDataItemType
[
'a'
];
q
:
KbDataItemType
[
'q'
]
}[];
})
=>
POST
(
`/openapi/kb/pushData`
,
data
);
/**
/**
* 更新一条数据
* 更新一条数据
...
@@ -70,4 +67,4 @@ export const postSplitData = (data: {
...
@@ -70,4 +67,4 @@ export const postSplitData = (data: {
chunks
:
string
[];
chunks
:
string
[];
prompt
:
string
;
prompt
:
string
;
mode
:
`
${
TrainingTypeEnum
}
`
;
mode
:
`
${
TrainingTypeEnum
}
`
;
})
=>
POST
(
`/openapi/text/
splitText
`
,
data
);
})
=>
POST
(
`/openapi/text/
pushData
`
,
data
);
src/constants/plugin.ts
View file @
741381ec
export
enum
TrainingTypeEnum
{
export
enum
TrainingTypeEnum
{
'qa'
=
'qa'
,
'qa'
=
'qa'
,
'
subsection'
=
'subsection
'
'
index'
=
'index
'
}
}
export
const
TrainingTypeMap
=
{
[
TrainingTypeEnum
.
qa
]:
'qa'
,
[
TrainingTypeEnum
.
index
]:
'index'
};
src/pages/api/admin/countTraining.ts
0 → 100644
View file @
741381ec
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
connectToDatabase
,
TrainingData
}
from
'@/service/mongo'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
await
authUser
({
req
,
authRoot
:
true
});
await
connectToDatabase
();
// split queue data
const
result
=
await
TrainingData
.
aggregate
([
{
$group
:
{
_id
:
'$mode'
,
count
:
{
$sum
:
1
}
}
}
]);
jsonRes
(
res
,
{
data
:
{
qaListLen
:
result
.
find
((
item
)
=>
item
.
_id
===
TrainingTypeEnum
.
qa
)?.
count
||
0
,
vectorListLen
:
result
.
find
((
item
)
=>
item
.
_id
===
TrainingTypeEnum
.
index
)?.
count
||
0
}
});
}
catch
(
error
)
{
console
.
log
(
error
);
jsonRes
(
res
,
{
code
:
500
,
error
});
}
}
src/pages/api/openapi/kb/pushData.ts
View file @
741381ec
...
@@ -3,19 +3,21 @@ import type { KbDataItemType } from '@/types/plugin';
...
@@ -3,19 +3,21 @@ import type { KbDataItemType } from '@/types/plugin';
import
{
jsonRes
}
from
'@/service/response'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
connectToDatabase
,
TrainingData
}
from
'@/service/mongo'
;
import
{
connectToDatabase
,
TrainingData
}
from
'@/service/mongo'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
generateVector
}
from
'@/service/events/generateVector'
;
import
{
PgClient
}
from
'@/service/pg'
;
import
{
authKb
}
from
'@/service/utils/auth'
;
import
{
authKb
}
from
'@/service/utils/auth'
;
import
{
withNextCors
}
from
'@/service/utils/tools'
;
import
{
withNextCors
}
from
'@/service/utils/tools'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
import
{
startQueue
}
from
'@/service/utils/tools'
;
interface
Props
{
export
type
Props
=
{
kbId
:
string
;
kbId
:
string
;
data
:
{
a
:
KbDataItemType
[
'a'
];
q
:
KbDataItemType
[
'q'
]
}[];
data
:
{
a
:
KbDataItemType
[
'a'
];
q
:
KbDataItemType
[
'q'
]
}[];
}
mode
:
`
${
TrainingTypeEnum
}
`
;
prompt
?:
string
;
};
export
default
withNextCors
(
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
export
default
withNextCors
(
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
<
any
>
)
{
try
{
try
{
const
{
kbId
,
data
}
=
req
.
body
as
Props
;
const
{
kbId
,
data
,
mode
,
prompt
}
=
req
.
body
as
Props
;
if
(
!
kbId
||
!
Array
.
isArray
(
data
))
{
if
(
!
kbId
||
!
Array
.
isArray
(
data
))
{
throw
new
Error
(
'缺少参数'
);
throw
new
Error
(
'缺少参数'
);
...
@@ -29,7 +31,9 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -29,7 +31,9 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
data
:
await
pushDataToKb
({
data
:
await
pushDataToKb
({
kbId
,
kbId
,
data
,
data
,
userId
userId
,
mode
,
prompt
})
})
});
});
}
catch
(
err
)
{
}
catch
(
err
)
{
...
@@ -40,36 +44,43 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -40,36 +44,43 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
}
}
});
});
export
async
function
pushDataToKb
({
userId
,
kbId
,
data
}:
{
userId
:
string
}
&
Props
)
{
export
async
function
pushDataToKb
({
userId
,
kbId
,
data
,
mode
,
prompt
}:
{
userId
:
string
}
&
Props
)
{
await
authKb
({
await
authKb
({
userId
,
userId
,
kbId
kbId
});
});
if
(
data
.
length
===
0
)
{
if
(
data
.
length
===
0
)
{
return
{
return
{};
trainingId
:
''
};
}
}
// 插入记录
// 插入记录
const
{
_id
}
=
await
TrainingData
.
create
({
await
TrainingData
.
insertMany
(
userId
,
data
.
map
((
item
)
=>
({
kbId
,
q
:
item
.
q
,
vectorList
:
data
a
:
item
.
a
,
});
userId
,
kbId
,
mode
,
prompt
}))
);
generateVector
(
_id
);
startQueue
(
);
return
{
return
{};
trainingId
:
_id
};
}
}
export
const
config
=
{
export
const
config
=
{
api
:
{
api
:
{
bodyParser
:
{
bodyParser
:
{
sizeLimit
:
'
10
0mb'
sizeLimit
:
'
2
0mb'
}
}
}
}
};
};
src/pages/api/openapi/kb/updateData.ts
View file @
741381ec
...
@@ -33,7 +33,15 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -33,7 +33,15 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
// 更新 pg 内容.仅修改a,不需要更新向量。
// 更新 pg 内容.仅修改a,不需要更新向量。
await
PgClient
.
update
(
'modelData'
,
{
await
PgClient
.
update
(
'modelData'
,
{
where
:
[[
'id'
,
dataId
],
'AND'
,
[
'user_id'
,
userId
]],
where
:
[[
'id'
,
dataId
],
'AND'
,
[
'user_id'
,
userId
]],
values
:
[{
key
:
'a'
,
value
:
a
},
...(
q
?
[{
key
:
'q'
,
value
:
`
${
vector
[
0
]}
`
}]
:
[])]
values
:
[
{
key
:
'a'
,
value
:
a
},
...(
q
?
[
{
key
:
'q'
,
value
:
q
},
{
key
:
'vector'
,
value
:
`[
${
vector
[
0
]}
]`
}
]
:
[])
]
});
});
jsonRes
(
res
);
jsonRes
(
res
);
...
...
src/pages/api/openapi/text/splitText.ts
deleted
100644 → 0
View file @
f05b1297
import
type
{
NextApiRequest
,
NextApiResponse
}
from
'next'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
connectToDatabase
,
TrainingData
}
from
'@/service/mongo'
;
import
{
authKb
,
authUser
}
from
'@/service/utils/auth'
;
import
{
generateQA
}
from
'@/service/events/generateQA'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
import
{
withNextCors
}
from
'@/service/utils/tools'
;
import
{
pushDataToKb
}
from
'../kb/pushData'
;
/* split text */
export
default
withNextCors
(
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
try
{
const
{
chunks
,
kbId
,
prompt
,
mode
}
=
req
.
body
as
{
kbId
:
string
;
chunks
:
string
[];
prompt
:
string
;
mode
:
`
${
TrainingTypeEnum
}
`
;
};
if
(
!
chunks
||
!
kbId
||
!
prompt
)
{
throw
new
Error
(
'参数错误'
);
}
await
connectToDatabase
();
const
{
userId
}
=
await
authUser
({
req
});
// 验证是否是该用户的 model
await
authKb
({
kbId
,
userId
});
if
(
mode
===
TrainingTypeEnum
.
qa
)
{
// 批量QA拆分插入数据
const
{
_id
}
=
await
TrainingData
.
create
({
userId
,
kbId
,
qaList
:
chunks
,
prompt
});
generateQA
(
_id
);
}
else
if
(
mode
===
TrainingTypeEnum
.
subsection
)
{
// 分段导入,直接插入向量队列
const
response
=
await
pushDataToKb
({
kbId
,
data
:
chunks
.
map
((
item
)
=>
({
q
:
item
,
a
:
''
})),
userId
});
return
jsonRes
(
res
,
{
data
:
response
});
}
jsonRes
(
res
);
}
catch
(
err
)
{
jsonRes
(
res
,
{
code
:
500
,
error
:
err
});
}
});
export
const
config
=
{
api
:
{
bodyParser
:
{
sizeLimit
:
'100mb'
}
}
};
src/pages/api/plugins/kb/data/getTrainingData.ts
View file @
741381ec
...
@@ -2,9 +2,10 @@ import type { NextApiRequest, NextApiResponse } from 'next';
...
@@ -2,9 +2,10 @@ import type { NextApiRequest, NextApiResponse } from 'next';
import
{
jsonRes
}
from
'@/service/response'
;
import
{
jsonRes
}
from
'@/service/response'
;
import
{
connectToDatabase
,
TrainingData
}
from
'@/service/mongo'
;
import
{
connectToDatabase
,
TrainingData
}
from
'@/service/mongo'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
authUser
}
from
'@/service/utils/auth'
;
import
{
Types
}
from
'mongoose'
;
import
{
generateQA
}
from
'@/service/events/generateQA'
;
import
{
generateQA
}
from
'@/service/events/generateQA'
;
import
{
generateVector
}
from
'@/service/events/generateVector'
;
import
{
generateVector
}
from
'@/service/events/generateVector'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
import
{
Types
}
from
'mongoose'
;
/* 拆分数据成QA */
/* 拆分数据成QA */
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
export
default
async
function
handler
(
req
:
NextApiRequest
,
res
:
NextApiResponse
)
{
...
@@ -19,26 +20,24 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -19,26 +20,24 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// split queue data
// split queue data
const
result
=
await
TrainingData
.
aggregate
([
const
result
=
await
TrainingData
.
aggregate
([
{
$match
:
{
userId
:
new
Types
.
ObjectId
(
userId
),
kbId
:
new
Types
.
ObjectId
(
kbId
)
}
},
{
{
$
project
:
{
$
match
:
{
qaListLength
:
{
$size
:
{
$ifNull
:
[
'$qaList'
,
[]]
}
}
,
userId
:
new
Types
.
ObjectId
(
userId
)
,
vectorListLength
:
{
$size
:
{
$ifNull
:
[
'$vectorList'
,
[]]
}
}
kbId
:
new
Types
.
ObjectId
(
kbId
)
}
}
},
},
{
{
$group
:
{
$group
:
{
_id
:
null
,
_id
:
'$mode'
,
totalQaListLength
:
{
$sum
:
'$qaListLength'
},
count
:
{
$sum
:
1
}
totalVectorListLength
:
{
$sum
:
'$vectorListLength'
}
}
}
}
}
]);
]);
jsonRes
(
res
,
{
jsonRes
(
res
,
{
data
:
{
data
:
{
qaListLen
:
result
[
0
]?.
totalQaListLength
||
0
,
qaListLen
:
result
.
find
((
item
)
=>
item
.
_id
===
TrainingTypeEnum
.
qa
)?.
count
||
0
,
vectorListLen
:
result
[
0
]?.
totalVectorListLength
||
0
vectorListLen
:
result
.
find
((
item
)
=>
item
.
_id
===
TrainingTypeEnum
.
index
)?.
count
||
0
}
}
});
});
...
@@ -49,10 +48,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -49,10 +48,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
kbId
kbId
},
},
'_id'
'_id'
);
)
.
limit
(
10
)
;
list
.
forEach
((
item
)
=>
{
list
.
forEach
((
item
)
=>
{
generateQA
(
item
.
_id
);
generateQA
();
generateVector
(
item
.
_id
);
generateVector
();
});
});
}
}
}
catch
(
err
)
{
}
catch
(
err
)
{
...
...
src/pages/kb/components/InputDataModal.tsx
View file @
741381ec
...
@@ -13,6 +13,7 @@ import {
...
@@ -13,6 +13,7 @@ import {
import
{
useForm
}
from
'react-hook-form'
;
import
{
useForm
}
from
'react-hook-form'
;
import
{
postKbDataFromList
,
putKbDataById
}
from
'@/api/plugins/kb'
;
import
{
postKbDataFromList
,
putKbDataById
}
from
'@/api/plugins/kb'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
useToast
}
from
'@/hooks/useToast'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
export
type
FormData
=
{
dataId
?:
string
;
a
:
string
;
q
:
string
};
export
type
FormData
=
{
dataId
?:
string
;
a
:
string
;
q
:
string
};
...
@@ -59,7 +60,8 @@ const InputDataModal = ({
...
@@ -59,7 +60,8 @@ const InputDataModal = ({
a
:
e
.
a
,
a
:
e
.
a
,
q
:
e
.
q
q
:
e
.
q
}
}
]
],
mode
:
TrainingTypeEnum
.
index
});
});
toast
({
toast
({
...
...
src/pages/kb/components/SelectCsvModal.tsx
View file @
741381ec
...
@@ -19,6 +19,7 @@ import { postKbDataFromList } from '@/api/plugins/kb';
...
@@ -19,6 +19,7 @@ import { postKbDataFromList } from '@/api/plugins/kb';
import
Markdown
from
'@/components/Markdown'
;
import
Markdown
from
'@/components/Markdown'
;
import
{
useMarkdown
}
from
'@/hooks/useMarkdown'
;
import
{
useMarkdown
}
from
'@/hooks/useMarkdown'
;
import
{
fileDownload
}
from
'@/utils/file'
;
import
{
fileDownload
}
from
'@/utils/file'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
const
csvTemplate
=
`question,answer\n"什么是 laf","laf 是一个云函数开发平台……"\n"什么是 sealos","Sealos 是以 kubernetes 为内核的云操作系统发行版,可以……"`
;
const
csvTemplate
=
`question,answer\n"什么是 laf","laf 是一个云函数开发平台……"\n"什么是 sealos","Sealos 是以 kubernetes 为内核的云操作系统发行版,可以……"`
;
...
@@ -72,7 +73,8 @@ const SelectJsonModal = ({
...
@@ -72,7 +73,8 @@ const SelectJsonModal = ({
const
res
=
await
postKbDataFromList
({
const
res
=
await
postKbDataFromList
({
kbId
,
kbId
,
data
:
fileData
data
:
fileData
,
mode
:
TrainingTypeEnum
.
index
});
});
toast
({
toast
({
...
...
src/pages/kb/components/SelectFileModal.tsx
View file @
741381ec
...
@@ -17,7 +17,7 @@ import { useSelectFile } from '@/hooks/useSelectFile';
...
@@ -17,7 +17,7 @@ import { useSelectFile } from '@/hooks/useSelectFile';
import
{
useConfirm
}
from
'@/hooks/useConfirm'
;
import
{
useConfirm
}
from
'@/hooks/useConfirm'
;
import
{
readTxtContent
,
readPdfContent
,
readDocContent
}
from
'@/utils/file'
;
import
{
readTxtContent
,
readPdfContent
,
readDocContent
}
from
'@/utils/file'
;
import
{
useMutation
}
from
'@tanstack/react-query'
;
import
{
useMutation
}
from
'@tanstack/react-query'
;
import
{
post
SplitData
}
from
'@/api/plugins/kb'
;
import
{
post
KbDataFromList
}
from
'@/api/plugins/kb'
;
import
Radio
from
'@/components/Radio'
;
import
Radio
from
'@/components/Radio'
;
import
{
splitText_token
}
from
'@/utils/file'
;
import
{
splitText_token
}
from
'@/utils/file'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
...
@@ -32,7 +32,7 @@ const modeMap = {
...
@@ -32,7 +32,7 @@ const modeMap = {
price
:
4
,
price
:
4
,
isPrompt
:
true
isPrompt
:
true
},
},
subsection
:
{
index
:
{
maxLen
:
800
,
maxLen
:
800
,
slideLen
:
300
,
slideLen
:
300
,
price
:
0.4
,
price
:
0.4
,
...
@@ -53,7 +53,7 @@ const SelectFileModal = ({
...
@@ -53,7 +53,7 @@ const SelectFileModal = ({
const
{
toast
}
=
useToast
();
const
{
toast
}
=
useToast
();
const
[
prompt
,
setPrompt
]
=
useState
(
''
);
const
[
prompt
,
setPrompt
]
=
useState
(
''
);
const
{
File
,
onOpen
}
=
useSelectFile
({
fileType
:
fileExtension
,
multiple
:
true
});
const
{
File
,
onOpen
}
=
useSelectFile
({
fileType
:
fileExtension
,
multiple
:
true
});
const
[
mode
,
setMode
]
=
useState
<
`
${
TrainingTypeEnum
}
`
>
(
TrainingTypeEnum
.
subsection
);
const
[
mode
,
setMode
]
=
useState
<
`
${
TrainingTypeEnum
}
`
>
(
TrainingTypeEnum
.
index
);
const
[
fileTextArr
,
setFileTextArr
]
=
useState
<
string
[]
>
([
''
]);
const
[
fileTextArr
,
setFileTextArr
]
=
useState
<
string
[]
>
([
''
]);
const
[
splitRes
,
setSplitRes
]
=
useState
<
{
tokens
:
number
;
chunks
:
string
[]
}
>
({
const
[
splitRes
,
setSplitRes
]
=
useState
<
{
tokens
:
number
;
chunks
:
string
[]
}
>
({
tokens
:
0
,
tokens
:
0
,
...
@@ -108,9 +108,9 @@ const SelectFileModal = ({
...
@@ -108,9 +108,9 @@ const SelectFileModal = ({
mutationFn
:
async
()
=>
{
mutationFn
:
async
()
=>
{
if
(
splitRes
.
chunks
.
length
===
0
)
return
;
if
(
splitRes
.
chunks
.
length
===
0
)
return
;
await
post
SplitData
({
await
post
KbDataFromList
({
kbId
,
kbId
,
chunks
:
splitRes
.
chunks
,
data
:
splitRes
.
chunks
.
map
((
text
)
=>
({
q
:
text
,
a
:
''
}))
,
prompt
:
`下面是"
${
prompt
||
'一段长文本'
}
"`
,
prompt
:
`下面是"
${
prompt
||
'一段长文本'
}
"`
,
mode
mode
});
});
...
@@ -195,11 +195,11 @@ const SelectFileModal = ({
...
@@ -195,11 +195,11 @@ const SelectFileModal = ({
<
Radio
<
Radio
ml=
{
3
}
ml=
{
3
}
list=
{
[
list=
{
[
{
label
:
'直接分段'
,
value
:
'
subsection
'
},
{
label
:
'直接分段'
,
value
:
'
index
'
},
{
label
:
'QA拆分'
,
value
:
'qa'
}
{
label
:
'QA拆分'
,
value
:
'qa'
}
]
}
]
}
value=
{
mode
}
value=
{
mode
}
onChange=
{
(
e
)
=>
setMode
(
e
as
'
subsection
'
|
'qa'
)
}
onChange=
{
(
e
)
=>
setMode
(
e
as
'
index
'
|
'qa'
)
}
/>
/>
</
Flex
>
</
Flex
>
{
/* 内容介绍 */
}
{
/* 内容介绍 */
}
...
...
src/service/events/generateQA.ts
View file @
741381ec
...
@@ -7,49 +7,61 @@ import { modelServiceToolMap } from '../utils/chat';
...
@@ -7,49 +7,61 @@ import { modelServiceToolMap } from '../utils/chat';
import
{
ChatRoleEnum
}
from
'@/constants/chat'
;
import
{
ChatRoleEnum
}
from
'@/constants/chat'
;
import
{
BillTypeEnum
}
from
'@/constants/user'
;
import
{
BillTypeEnum
}
from
'@/constants/user'
;
import
{
pushDataToKb
}
from
'@/pages/api/openapi/kb/pushData'
;
import
{
pushDataToKb
}
from
'@/pages/api/openapi/kb/pushData'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
import
{
ERROR_ENUM
}
from
'../errorCode'
;
import
{
ERROR_ENUM
}
from
'../errorCode'
;
// 每次最多选 1 组
export
async
function
generateQA
():
Promise
<
any
>
{
const
listLen
=
1
;
const
maxProcess
=
Number
(
process
.
env
.
QA_MAX_PROCESS
||
10
);
if
(
global
.
qaQueueLen
>=
maxProcess
)
return
;
global
.
qaQueueLen
++
;
let
trainingId
=
''
;
let
userId
=
''
;
export
async
function
generateQA
(
trainingId
:
string
):
Promise
<
any
>
{
try
{
try
{
// 找出一个需要生成的 dataItem (4分钟锁)
// 找出一个需要生成的 dataItem (4分钟锁)
const
data
=
await
TrainingData
.
findOneAndUpdate
(
const
data
=
await
TrainingData
.
findOneAndUpdate
(
{
{
_id
:
trainingId
,
mode
:
TrainingTypeEnum
.
qa
,
lockTime
:
{
$lte
:
Date
.
now
()
-
4
*
60
*
1000
}
lockTime
:
{
$lte
:
new
Date
(
Date
.
now
()
-
2
*
60
*
1000
)
}
},
},
{
{
lockTime
:
new
Date
()
lockTime
:
new
Date
()
}
}
);
).
select
({
_id
:
1
,
userId
:
1
,
kbId
:
1
,
prompt
:
1
,
q
:
1
});
if
(
!
data
||
data
.
qaList
.
length
===
0
)
{
/* 无待生成的任务 */
await
TrainingData
.
findOneAndDelete
({
if
(
!
data
)
{
_id
:
trainingId
,
global
.
qaQueueLen
--
;
qaList
:
[],
!
global
.
qaQueueLen
&&
console
.
log
(
`没有需要【QA】的数据`
);
vectorList
:
[]
});
return
;
return
;
}
}
const
qaList
:
string
[]
=
data
.
qaList
.
slice
(
-
listLen
);
trainingId
=
data
.
_id
;
userId
=
String
(
data
.
userId
);
const
kbId
=
String
(
data
.
kbId
);
// 余额校验并获取 openapi Key
// 余额校验并获取 openapi Key
const
{
userOpenAiKey
,
systemAuthKey
}
=
await
getApiKey
({
const
{
userOpenAiKey
,
systemAuthKey
}
=
await
getApiKey
({
model
:
OpenAiChatEnum
.
GPT35
,
model
:
OpenAiChatEnum
.
GPT35
,
userId
:
data
.
userId
,
userId
,
type
:
'training'
type
:
'training'
});
});
console
.
log
(
`正在生成一组QA
, 包含
${
qaList
.
length
}
组文本。ID:
${
data
.
_i
d
}
`
);
console
.
log
(
`正在生成一组QA
。ID:
${
trainingI
d
}
`
);
const
startTime
=
Date
.
now
();
const
startTime
=
Date
.
now
();
// 请求 chatgpt 获取回答
// 请求 chatgpt 获取回答
const
response
=
await
Promise
.
all
(
const
response
=
await
Promise
.
all
(
qaList
.
map
((
text
)
=>
[
data
.
q
]
.
map
((
text
)
=>
modelServiceToolMap
[
OpenAiChatEnum
.
GPT35
]
modelServiceToolMap
[
OpenAiChatEnum
.
GPT35
]
.
chatCompletion
({
.
chatCompletion
({
apiKey
:
userOpenAiKey
||
systemAuthKey
,
apiKey
:
userOpenAiKey
||
systemAuthKey
,
...
@@ -100,24 +112,19 @@ A2:
...
@@ -100,24 +112,19 @@ A2:
// 创建 向量生成 队列
// 创建 向量生成 队列
pushDataToKb
({
pushDataToKb
({
kbId
:
data
.
kbId
,
kbId
,
data
:
responseList
,
data
:
responseList
,
userId
:
data
.
userId
userId
,
mode
:
TrainingTypeEnum
.
index
});
});
// 删除 QA 队列。如果小于 n 条,整个数据删掉。 如果大于 n 条,仅删数组后 n 个
// delete data from training
if
(
data
.
vectorList
.
length
<=
listLen
)
{
await
TrainingData
.
findByIdAndDelete
(
data
.
_id
);
await
TrainingData
.
findByIdAndDelete
(
data
.
_id
);
}
else
{
await
TrainingData
.
findByIdAndUpdate
(
data
.
_id
,
{
qaList
:
data
.
qaList
.
slice
(
0
,
-
listLen
),
lockTime
:
new
Date
(
'2000/1/1'
)
});
}
console
.
log
(
'生成QA成功,time:'
,
`
${(
Date
.
now
()
-
startTime
)
/
1000
}
s`
);
console
.
log
(
'生成QA成功,time:'
,
`
${(
Date
.
now
()
-
startTime
)
/
1000
}
s`
);
generateQA
(
trainingId
);
global
.
qaQueueLen
--
;
generateQA
();
}
catch
(
err
:
any
)
{
}
catch
(
err
:
any
)
{
// log
// log
if
(
err
?.
response
)
{
if
(
err
?.
response
)
{
...
@@ -130,25 +137,28 @@ A2:
...
@@ -130,25 +137,28 @@ A2:
// openai 账号异常或者账号余额不足,删除任务
// openai 账号异常或者账号余额不足,删除任务
if
(
openaiError2
[
err
?.
response
?.
data
?.
error
?.
type
]
||
err
===
ERROR_ENUM
.
insufficientQuota
)
{
if
(
openaiError2
[
err
?.
response
?.
data
?.
error
?.
type
]
||
err
===
ERROR_ENUM
.
insufficientQuota
)
{
console
.
log
(
'余额不足,删除向量生成任务'
);
console
.
log
(
'余额不足,删除向量生成任务'
);
await
TrainingData
.
findByIdAndDelete
(
trainingId
);
await
TrainingData
.
deleteMany
({
return
;
userId
});
return
generateQA
();
}
}
// unlock
// unlock
global
.
qaQueueLen
--
;
await
TrainingData
.
findByIdAndUpdate
(
trainingId
,
{
await
TrainingData
.
findByIdAndUpdate
(
trainingId
,
{
lockTime
:
new
Date
(
'2000/1/1'
)
lockTime
:
new
Date
(
'2000/1/1'
)
});
});
// 频率限制
// 频率限制
if
(
err
?.
response
?.
statusText
===
'Too Many Requests'
)
{
if
(
err
?.
response
?.
statusText
===
'Too Many Requests'
)
{
console
.
log
(
'生成向量次数限制,
3
0s后尝试'
);
console
.
log
(
'生成向量次数限制,
2
0s后尝试'
);
return
setTimeout
(()
=>
{
return
setTimeout
(()
=>
{
generateQA
(
trainingId
);
generateQA
();
},
3
0000
);
},
2
0000
);
}
}
setTimeout
(()
=>
{
setTimeout
(()
=>
{
generateQA
(
trainingId
);
generateQA
();
},
1000
);
},
1000
);
}
}
}
}
...
...
src/service/events/generateVector.ts
View file @
741381ec
...
@@ -3,104 +3,109 @@ import { insertKbItem, PgClient } from '@/service/pg';
...
@@ -3,104 +3,109 @@ import { insertKbItem, PgClient } from '@/service/pg';
import
{
openaiEmbedding
}
from
'@/pages/api/openapi/plugin/openaiEmbedding'
;
import
{
openaiEmbedding
}
from
'@/pages/api/openapi/plugin/openaiEmbedding'
;
import
{
TrainingData
}
from
'../models/trainingData'
;
import
{
TrainingData
}
from
'../models/trainingData'
;
import
{
ERROR_ENUM
}
from
'../errorCode'
;
import
{
ERROR_ENUM
}
from
'../errorCode'
;
import
{
TrainingTypeEnum
}
from
'@/constants/plugin'
;
// 每次最多选 5 组
const
listLen
=
5
;
/* 索引生成队列。每导入一次,就是一个单独的线程 */
/* 索引生成队列。每导入一次,就是一个单独的线程 */
export
async
function
generateVector
(
trainingId
:
string
):
Promise
<
any
>
{
export
async
function
generateVector
():
Promise
<
any
>
{
const
maxProcess
=
Number
(
process
.
env
.
VECTOR_MAX_PROCESS
||
10
);
if
(
global
.
vectorQueueLen
>=
maxProcess
)
return
;
global
.
vectorQueueLen
++
;
let
trainingId
=
''
;
let
userId
=
''
;
try
{
try
{
// 找出一个需要生成的 dataItem (2分钟锁)
const
data
=
await
TrainingData
.
findOneAndUpdate
(
const
data
=
await
TrainingData
.
findOneAndUpdate
(
{
{
_id
:
trainingId
,
mode
:
TrainingTypeEnum
.
index
,
lockTime
:
{
$lte
:
Date
.
now
()
-
2
*
60
*
1000
}
lockTime
:
{
$lte
:
new
Date
(
Date
.
now
()
-
2
*
60
*
1000
)
}
},
},
{
{
lockTime
:
new
Date
()
lockTime
:
new
Date
()
}
}
);
).
select
({
_id
:
1
,
userId
:
1
,
kbId
:
1
,
q
:
1
,
a
:
1
});
/* 无待生成的任务 */
if
(
!
data
)
{
if
(
!
data
)
{
await
TrainingData
.
findOneAndDelete
({
global
.
vectorQueueLen
--
;
_id
:
trainingId
,
!
global
.
vectorQueueLen
&&
console
.
log
(
`没有需要【索引】的数据`
);
qaList
:
[],
vectorList
:
[]
});
return
;
return
;
}
}
const
userId
=
String
(
data
.
userId
);
trainingId
=
data
.
_id
;
userId
=
String
(
data
.
userId
);
const
kbId
=
String
(
data
.
kbId
);
const
kbId
=
String
(
data
.
kbId
);
const
dataItems
:
{
q
:
string
;
a
:
string
}[]
=
data
.
vectorList
.
slice
(
-
listLen
).
map
((
item
)
=>
({
const
dataItems
=
[
q
:
item
.
q
,
{
a
:
item
.
a
q
:
data
.
q
,
}));
a
:
data
.
a
}
];
// 过滤重复的 qa 内容
// 过滤重复的 qa 内容
const
searchRes
=
await
Promise
.
allSettled
(
// const searchRes = await Promise.allSettled(
dataItems
.
map
(
async
({
q
,
a
=
''
})
=>
{
// dataItems.map(async ({ q, a = '' }) => {
if
(
!
q
)
{
// if (!q) {
return
Promise
.
reject
(
'q为空'
);
// return Promise.reject('q为空');
}
// }
q
=
q
.
replace
(
/
\\
n/g
,
'\n'
);
a
=
a
.
replace
(
/
\\
n/g
,
'\n'
);
// Exactly the same data, not push
try
{
const
count
=
await
PgClient
.
count
(
'modelData'
,
{
where
:
[[
'user_id'
,
userId
],
'AND'
,
[
'kb_id'
,
kbId
],
'AND'
,
[
'q'
,
q
],
'AND'
,
[
'a'
,
a
]]
});
if
(
count
>
0
)
{
return
Promise
.
reject
(
'已经存在'
);
}
}
catch
(
error
)
{
error
;
}
return
Promise
.
resolve
({
q
,
a
});
})
);
const
filterData
=
searchRes
.
filter
((
item
)
=>
item
.
status
===
'fulfilled'
)
.
map
<
{
q
:
string
;
a
:
string
}
>
((
item
:
any
)
=>
item
.
value
);
if
(
filterData
.
length
>
0
)
{
// 生成词向量
const
vectors
=
await
openaiEmbedding
({
input
:
filterData
.
map
((
item
)
=>
item
.
q
),
userId
,
type
:
'training'
});
// 生成结果插入到 pg
// q = q.replace(/\\n/g, '\n');
await
insertKbItem
({
// a = a.replace(/\\n/g, '\n');
userId
,
kbId
,
data
:
vectors
.
map
((
vector
,
i
)
=>
({
q
:
filterData
[
i
].
q
,
a
:
filterData
[
i
].
a
,
vector
}))
});
}
// 删除 mongo 训练队列. 如果小于 n 条,整个数据删掉。 如果大于 n 条,仅删数组后 n 个
// // Exactly the same data, not push
if
(
data
.
vectorList
.
length
<=
listLen
)
{
// try {
await
TrainingData
.
findByIdAndDelete
(
trainingId
);
// const count = await PgClient.count('modelData', {
console
.
log
(
`全部向量生成完毕:
${
trainingId
}
`
);
// where: [['user_id', userId], 'AND', ['kb_id', kbId], 'AND', ['q', q], 'AND', ['a', a]]
}
else
{
// });
await
TrainingData
.
findByIdAndUpdate
(
trainingId
,
{
vectorList
:
data
.
vectorList
.
slice
(
0
,
-
listLen
),
// if (count > 0) {
lockTime
:
new
Date
(
'2000/1/1'
)
// return Promise.reject('已经存在');
});
// }
console
.
log
(
`生成向量成功:
${
trainingId
}
`
);
// } catch (error) {
generateVector
(
trainingId
);
// error;
}
// }
// return Promise.resolve({
// q,
// a
// });
// })
// );
// const filterData = searchRes
// .filter((item) => item.status === 'fulfilled')
// .map<{ q: string; a: string }>((item: any) => item.value);
// 生成词向量
const
vectors
=
await
openaiEmbedding
({
input
:
dataItems
.
map
((
item
)
=>
item
.
q
),
userId
,
type
:
'training'
});
// 生成结果插入到 pg
await
insertKbItem
({
userId
,
kbId
,
data
:
vectors
.
map
((
vector
,
i
)
=>
({
q
:
dataItems
[
i
].
q
,
a
:
dataItems
[
i
].
a
,
vector
}))
});
// delete data from training
await
TrainingData
.
findByIdAndDelete
(
data
.
_id
);
console
.
log
(
`生成向量成功:
${
data
.
_id
}
`
);
global
.
vectorQueueLen
--
;
generateVector
();
}
catch
(
err
:
any
)
{
}
catch
(
err
:
any
)
{
// log
// log
if
(
err
?.
response
)
{
if
(
err
?.
response
)
{
...
@@ -113,25 +118,28 @@ export async function generateVector(trainingId: string): Promise<any> {
...
@@ -113,25 +118,28 @@ export async function generateVector(trainingId: string): Promise<any> {
// openai 账号异常或者账号余额不足,删除任务
// openai 账号异常或者账号余额不足,删除任务
if
(
openaiError2
[
err
?.
response
?.
data
?.
error
?.
type
]
||
err
===
ERROR_ENUM
.
insufficientQuota
)
{
if
(
openaiError2
[
err
?.
response
?.
data
?.
error
?.
type
]
||
err
===
ERROR_ENUM
.
insufficientQuota
)
{
console
.
log
(
'余额不足,删除向量生成任务'
);
console
.
log
(
'余额不足,删除向量生成任务'
);
await
TrainingData
.
findByIdAndDelete
(
trainingId
);
await
TrainingData
.
deleteMany
({
return
;
userId
});
return
generateVector
();
}
}
// unlock
// unlock
global
.
vectorQueueLen
--
;
await
TrainingData
.
findByIdAndUpdate
(
trainingId
,
{
await
TrainingData
.
findByIdAndUpdate
(
trainingId
,
{
lockTime
:
new
Date
(
'2000/1/1'
)
lockTime
:
new
Date
(
'2000/1/1'
)
});
});
// 频率限制
// 频率限制
if
(
err
?.
response
?.
statusText
===
'Too Many Requests'
)
{
if
(
err
?.
response
?.
statusText
===
'Too Many Requests'
)
{
console
.
log
(
'生成向量次数限制,
3
0s后尝试'
);
console
.
log
(
'生成向量次数限制,
2
0s后尝试'
);
return
setTimeout
(()
=>
{
return
setTimeout
(()
=>
{
generateVector
(
trainingId
);
generateVector
();
},
3
0000
);
},
2
0000
);
}
}
setTimeout
(()
=>
{
setTimeout
(()
=>
{
generateVector
(
trainingId
);
generateVector
();
},
1000
);
},
1000
);
}
}
}
}
src/service/models/trainingData.ts
View file @
741381ec
/* 模型的知识库 */
/* 模型的知识库 */
import
{
Schema
,
model
,
models
,
Model
as
MongoModel
}
from
'mongoose'
;
import
{
Schema
,
model
,
models
,
Model
as
MongoModel
}
from
'mongoose'
;
import
{
TrainingDataSchema
as
TrainingDateType
}
from
'@/types/mongoSchema'
;
import
{
TrainingDataSchema
as
TrainingDateType
}
from
'@/types/mongoSchema'
;
import
{
TrainingTypeMap
}
from
'@/constants/plugin'
;
// pgList and vectorList, Only one of them will work
// pgList and vectorList, Only one of them will work
const
TrainingDataSchema
=
new
Schema
({
const
TrainingDataSchema
=
new
Schema
({
userId
:
{
userId
:
{
type
:
Schema
.
Types
.
ObjectId
,
type
:
Schema
.
Types
.
ObjectId
,
...
@@ -19,18 +19,27 @@ const TrainingDataSchema = new Schema({
...
@@ -19,18 +19,27 @@ const TrainingDataSchema = new Schema({
type
:
Date
,
type
:
Date
,
default
:
()
=>
new
Date
(
'2000/1/1'
)
default
:
()
=>
new
Date
(
'2000/1/1'
)
},
},
vectorList
:
{
mode
:
{
type
:
[{
q
:
String
,
a
:
String
}],
type
:
String
,
default
:
[]
enum
:
Object
.
keys
(
TrainingTypeMap
),
required
:
true
},
},
prompt
:
{
prompt
:
{
// 拆分时的提示词
// 拆分时的提示词
type
:
String
,
type
:
String
,
default
:
''
default
:
''
},
},
qaList
:
{
q
:
{
type
:
[
String
],
// 如果是
default
:
[]
type
:
String
,
default
:
''
},
a
:
{
type
:
String
,
default
:
''
},
vectorList
:
{
type
:
Object
}
}
});
});
...
...
src/service/mongo.ts
View file @
741381ec
import
mongoose
from
'mongoose'
;
import
mongoose
from
'mongoose'
;
import
{
generateQA
}
from
'./events/generateQA'
;
import
{
generateVector
}
from
'./events/generateVector'
;
import
tunnel
from
'tunnel'
;
import
tunnel
from
'tunnel'
;
import
{
TrainingData
}
from
'./mongo'
;
import
{
TrainingData
}
from
'./mongo'
;
import
{
startQueue
}
from
'./utils/tools'
;
/**
/**
* 连接 MongoDB 数据库
* 连接 MongoDB 数据库
...
@@ -38,7 +37,10 @@ export async function connectToDatabase(): Promise<void> {
...
@@ -38,7 +37,10 @@ export async function connectToDatabase(): Promise<void> {
});
});
}
}
startTrain
();
global
.
qaQueueLen
=
0
;
global
.
vectorQueueLen
=
0
;
startQueue
();
// 5 分钟后解锁不正常的数据,并触发开始训练
// 5 分钟后解锁不正常的数据,并触发开始训练
setTimeout
(
async
()
=>
{
setTimeout
(
async
()
=>
{
await
TrainingData
.
updateMany
(
await
TrainingData
.
updateMany
(
...
@@ -49,24 +51,10 @@ export async function connectToDatabase(): Promise<void> {
...
@@ -49,24 +51,10 @@ export async function connectToDatabase(): Promise<void> {
lockTime
:
new
Date
(
'2000/1/1'
)
lockTime
:
new
Date
(
'2000/1/1'
)
}
}
);
);
start
Train
();
start
Queue
();
},
5
*
60
*
1000
);
},
5
*
60
*
1000
);
}
}
async
function
startTrain
()
{
const
qa
=
await
TrainingData
.
find
({
qaList
:
{
$exists
:
true
,
$ne
:
[]
}
});
qa
.
map
((
item
)
=>
generateQA
(
String
(
item
.
_id
)));
const
vector
=
await
TrainingData
.
find
({
vectorList
:
{
$exists
:
true
,
$ne
:
[]
}
});
vector
.
map
((
item
)
=>
generateVector
(
String
(
item
.
_id
)));
}
export
*
from
'./models/authCode'
;
export
*
from
'./models/authCode'
;
export
*
from
'./models/chat'
;
export
*
from
'./models/chat'
;
export
*
from
'./models/model'
;
export
*
from
'./models/model'
;
...
...
src/service/pg.ts
View file @
741381ec
...
@@ -14,8 +14,8 @@ export const connectPg = async () => {
...
@@ -14,8 +14,8 @@ export const connectPg = async () => {
password
:
process
.
env
.
PG_PASSWORD
,
password
:
process
.
env
.
PG_PASSWORD
,
database
:
process
.
env
.
PG_DB_NAME
,
database
:
process
.
env
.
PG_DB_NAME
,
max
:
20
,
max
:
20
,
idleTimeoutMillis
:
3
0000
,
idleTimeoutMillis
:
6
0000
,
connectionTimeoutMillis
:
2000
connectionTimeoutMillis
:
2000
0
});
});
global
.
pgClient
.
on
(
'error'
,
(
err
)
=>
{
global
.
pgClient
.
on
(
'error'
,
(
err
)
=>
{
...
...
src/service/response.ts
View file @
741381ec
...
@@ -45,7 +45,7 @@ export const jsonRes = <T = any>(
...
@@ -45,7 +45,7 @@ export const jsonRes = <T = any>(
}
else
if
(
openaiError
[
error
?.
response
?.
statusText
])
{
}
else
if
(
openaiError
[
error
?.
response
?.
statusText
])
{
msg
=
openaiError
[
error
.
response
.
statusText
];
msg
=
openaiError
[
error
.
response
.
statusText
];
}
}
console
.
log
(
error
);
console
.
log
(
error
?.
message
||
error
);
}
}
res
.
json
({
res
.
json
({
...
...
src/service/utils/tools.ts
View file @
741381ec
...
@@ -2,6 +2,8 @@ import type { NextApiResponse, NextApiHandler, NextApiRequest } from 'next';
...
@@ -2,6 +2,8 @@ import type { NextApiResponse, NextApiHandler, NextApiRequest } from 'next';
import
NextCors
from
'nextjs-cors'
;
import
NextCors
from
'nextjs-cors'
;
import
crypto
from
'crypto'
;
import
crypto
from
'crypto'
;
import
jwt
from
'jsonwebtoken'
;
import
jwt
from
'jsonwebtoken'
;
import
{
generateQA
}
from
'../events/generateQA'
;
import
{
generateVector
}
from
'../events/generateVector'
;
/* 密码加密 */
/* 密码加密 */
export
const
hashPassword
=
(
psw
:
string
)
=>
{
export
const
hashPassword
=
(
psw
:
string
)
=>
{
...
@@ -45,7 +47,7 @@ export function withNextCors(handler: NextApiHandler): NextApiHandler {
...
@@ -45,7 +47,7 @@ export function withNextCors(handler: NextApiHandler): NextApiHandler {
req
:
NextApiRequest
,
req
:
NextApiRequest
,
res
:
NextApiResponse
res
:
NextApiResponse
)
{
)
{
const
methods
=
[
'GET'
,
'HEAD'
,
'PUT'
,
'PATCH'
,
'POST'
,
'DELETE'
];
const
methods
=
[
'GET'
,
'
e
HEAD'
,
'PUT'
,
'PATCH'
,
'POST'
,
'DELETE'
];
const
origin
=
req
.
headers
.
origin
;
const
origin
=
req
.
headers
.
origin
;
await
NextCors
(
req
,
res
,
{
await
NextCors
(
req
,
res
,
{
methods
,
methods
,
...
@@ -56,3 +58,15 @@ export function withNextCors(handler: NextApiHandler): NextApiHandler {
...
@@ -56,3 +58,15 @@ export function withNextCors(handler: NextApiHandler): NextApiHandler {
return
handler
(
req
,
res
);
return
handler
(
req
,
res
);
};
};
}
}
export
const
startQueue
=
()
=>
{
const
qaMax
=
Number
(
process
.
env
.
QA_MAX_PROCESS
||
10
);
const
vectorMax
=
Number
(
process
.
env
.
VECTOR_MAX_PROCESS
||
10
);
for
(
let
i
=
0
;
i
<
qaMax
;
i
++
)
{
generateQA
();
}
for
(
let
i
=
0
;
i
<
vectorMax
;
i
++
)
{
generateVector
();
}
};
src/types/index.d.ts
View file @
741381ec
...
@@ -9,6 +9,8 @@ declare global {
...
@@ -9,6 +9,8 @@ declare global {
var
particlesJS
:
any
;
var
particlesJS
:
any
;
var
grecaptcha
:
any
;
var
grecaptcha
:
any
;
var
QRCode
:
any
;
var
QRCode
:
any
;
var
qaQueueLen
:
number
;
var
vectorQueueLen
:
number
;
interface
Window
{
interface
Window
{
[
'pdfjs-dist/build/pdf'
]:
any
;
[
'pdfjs-dist/build/pdf'
]:
any
;
...
...
src/types/mongoSchema.d.ts
View file @
741381ec
...
@@ -74,9 +74,10 @@ export interface TrainingDataSchema {
...
@@ -74,9 +74,10 @@ export interface TrainingDataSchema {
userId
:
string
;
userId
:
string
;
kbId
:
string
;
kbId
:
string
;
lockTime
:
Date
;
lockTime
:
Date
;
vectorList
:
{
q
:
string
;
a
:
string
}[]
;
mode
:
`
${
TrainingTypeEnum
}
`
;
prompt
:
string
;
prompt
:
string
;
qaList
:
string
[];
q
:
string
;
a
:
string
;
}
}
export
interface
ChatSchema
{
export
interface
ChatSchema
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment