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
0cde9a10
authored
May 30, 2023
by
archer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: use last quote
parent
59ddf09b
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
70 additions
and
65 deletions
+70
-65
src/api/chat.ts
+1
-1
src/pages/api/chat/chat.ts
+4
-2
src/pages/api/chat/shareChat/chat.ts
+3
-2
src/pages/api/openapi/chat/chat.ts
+5
-4
src/pages/api/openapi/kb/appKbSearch.ts
+30
-46
src/service/utils/auth.ts
+2
-1
src/service/utils/chat/index.ts
+25
-9
No files found.
src/api/chat.ts
View file @
0cde9a10
...
@@ -5,7 +5,7 @@ import { RequestPaging } from '../types/index';
...
@@ -5,7 +5,7 @@ import { RequestPaging } from '../types/index';
import
type
{
ShareChatSchema
}
from
'@/types/mongoSchema'
;
import
type
{
ShareChatSchema
}
from
'@/types/mongoSchema'
;
import
type
{
ShareChatEditType
}
from
'@/types/model'
;
import
type
{
ShareChatEditType
}
from
'@/types/model'
;
import
{
Obj2Query
}
from
'@/utils/tools'
;
import
{
Obj2Query
}
from
'@/utils/tools'
;
import
{
QuoteItemType
}
from
'@/pages/api/openapi/kb/appKbSearch'
;
import
type
{
QuoteItemType
}
from
'@/pages/api/openapi/kb/appKbSearch'
;
import
type
{
Props
as
UpdateHistoryProps
}
from
'@/pages/api/chat/history/updateChatHistory'
;
import
type
{
Props
as
UpdateHistoryProps
}
from
'@/pages/api/chat/history/updateChatHistory'
;
/**
/**
...
...
src/pages/api/chat/chat.ts
View file @
0cde9a10
...
@@ -50,6 +50,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -50,6 +50,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// 读取对话内容
// 读取对话内容
const
prompts
=
[...
content
,
prompt
[
0
]];
const
prompts
=
[...
content
,
prompt
[
0
]];
const
{
const
{
code
=
200
,
code
=
200
,
systemPrompts
=
[],
systemPrompts
=
[],
...
@@ -61,7 +62,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -61,7 +62,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
{
code
,
searchPrompts
,
rawSearch
,
guidePrompt
}
=
await
appKbSearch
({
const
{
code
,
searchPrompts
,
rawSearch
,
guidePrompt
}
=
await
appKbSearch
({
model
,
model
,
userId
,
userId
,
prompts
,
fixedQuote
:
content
[
content
.
length
-
1
]?.
quote
||
[],
prompt
:
prompt
[
0
],
similarity
:
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
similarity
:
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
});
});
...
@@ -114,7 +116,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -114,7 +116,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
return
res
.
end
(
response
);
return
res
.
end
(
response
);
}
}
prompts
.
splice
(
prompts
.
length
-
3
,
0
,
...
systemPrompts
);
prompts
.
unshift
(
...
systemPrompts
);
// content check
// content check
await
sensitiveCheck
({
await
sensitiveCheck
({
...
...
src/pages/api/chat/shareChat/chat.ts
View file @
0cde9a10
...
@@ -47,7 +47,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -47,7 +47,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const
{
code
,
searchPrompts
}
=
await
appKbSearch
({
const
{
code
,
searchPrompts
}
=
await
appKbSearch
({
model
,
model
,
userId
,
userId
,
prompts
,
fixedQuote
:
[],
prompt
:
prompts
[
prompts
.
length
-
1
],
similarity
:
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
similarity
:
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
});
});
...
@@ -74,7 +75,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
...
@@ -74,7 +75,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
return
res
.
send
(
systemPrompts
[
0
]?.
value
);
return
res
.
send
(
systemPrompts
[
0
]?.
value
);
}
}
prompts
.
splice
(
prompts
.
length
-
3
,
0
,
...
systemPrompts
);
prompts
.
unshift
(
...
systemPrompts
);
// content check
// content check
await
sensitiveCheck
({
await
sensitiveCheck
({
...
...
src/pages/api/openapi/chat/chat.ts
View file @
0cde9a10
...
@@ -75,10 +75,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -75,10 +75,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
// 使用了知识库搜索
// 使用了知识库搜索
if
(
model
.
chat
.
relatedKbs
.
length
>
0
)
{
if
(
model
.
chat
.
relatedKbs
.
length
>
0
)
{
const
{
code
,
searchPrompts
}
=
await
appKbSearch
({
const
{
code
,
searchPrompts
}
=
await
appKbSearch
({
prompts
,
similarity
:
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
,
model
,
model
,
userId
userId
,
fixedQuote
:
[],
prompt
:
prompts
[
prompts
.
length
-
1
],
similarity
:
ModelVectorSearchModeMap
[
model
.
chat
.
searchMode
]?.
similarity
});
});
// search result is empty
// search result is empty
...
@@ -101,7 +102,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -101,7 +102,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
];
];
}
}
prompts
.
splice
(
prompts
.
length
-
3
,
0
,
...
systemPrompts
);
prompts
.
unshift
(
...
systemPrompts
);
// content check
// content check
await
sensitiveCheck
({
await
sensitiveCheck
({
...
...
src/pages/api/openapi/kb/appKbSearch.ts
View file @
0cde9a10
...
@@ -49,10 +49,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -49,10 +49,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
});
});
const
result
=
await
appKbSearch
({
const
result
=
await
appKbSearch
({
model
,
userId
,
userId
,
prompts
,
fixedQuote
:
[]
,
similarity
,
prompt
:
prompts
[
prompts
.
length
-
1
]
,
model
similarity
});
});
jsonRes
<
Response
>
(
res
,
{
jsonRes
<
Response
>
(
res
,
{
...
@@ -70,67 +71,53 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
...
@@ -70,67 +71,53 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
export
async
function
appKbSearch
({
export
async
function
appKbSearch
({
model
,
model
,
userId
,
userId
,
prompts
,
fixedQuote
,
prompt
,
similarity
similarity
}:
{
}:
{
model
:
ModelSchema
;
userId
:
string
;
userId
:
string
;
prompts
:
ChatItemSimpleType
[];
fixedQuote
:
QuoteItemType
[];
prompt
:
ChatItemSimpleType
;
similarity
:
number
;
similarity
:
number
;
model
:
ModelSchema
;
}):
Promise
<
Response
>
{
}):
Promise
<
Response
>
{
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
const
modelConstantsData
=
ChatModelMap
[
model
.
chat
.
chatModel
];
// search two times.
const
userPrompts
=
prompts
.
filter
((
item
)
=>
item
.
obj
===
'Human'
);
const
input
:
string
[]
=
[
userPrompts
[
userPrompts
.
length
-
1
].
value
,
userPrompts
[
userPrompts
.
length
-
2
]?.
value
].
filter
((
item
)
=>
item
);
// get vector
// get vector
const
promptVector
s
=
await
openaiEmbedding
({
const
promptVector
=
await
openaiEmbedding
({
userId
,
userId
,
input
,
input
:
[
prompt
.
value
]
,
type
:
'chat'
type
:
'chat'
});
});
// search kb
// search kb
const
searchRes
=
await
Promise
.
all
(
const
{
rows
:
searchRes
}
=
await
PgClient
.
select
<
QuoteItemType
>
(
'modelData'
,
{
promptVectors
.
map
((
promptVector
)
=>
PgClient
.
select
<
QuoteItemType
>
(
'modelData'
,
{
fields
:
[
'id'
,
'q'
,
'a'
],
fields
:
[
'id'
,
'q'
,
'a'
],
where
:
[
where
:
[
`kb_id IN (
${
model
.
chat
.
relatedKbs
.
map
((
item
)
=>
`'
${
item
}
'`
).
join
(
','
)}
)`
,
`kb_id IN (
${
model
.
chat
.
relatedKbs
.
map
((
item
)
=>
`'
${
item
}
'`
).
join
(
','
)}
)`
,
'AND'
,
'AND'
,
`vector <=> '[
${
promptVector
}
]' <
${
similarity
}
`
`vector <=> '[
${
promptVector
[
0
]
}
]' <
${
similarity
}
`
],
],
order
:
[{
field
:
'vector'
,
mode
:
`<=> '[
${
promptVector
}
]'`
}],
order
:
[{
field
:
'vector'
,
mode
:
`<=> '[
${
promptVector
[
0
]}
]'`
}],
limit
:
promptVectors
.
length
===
1
?
15
:
10
limit
:
8
}).
then
((
res
)
=>
res
.
rows
)
});
)
);
// filter same search result
// filter same search result
const
idSet
=
new
Set
<
string
>
();
const
idSet
=
new
Set
<
string
>
();
const
filterSearch
=
searchRes
.
map
((
search
)
=>
const
filterSearch
=
[
search
.
filter
((
item
)
=>
{
...
searchRes
.
slice
(
0
,
3
),
...
fixedQuote
.
slice
(
0
,
2
),
...
searchRes
.
slice
(
3
),
...
fixedQuote
.
slice
(
2
,
5
)
].
filter
((
item
)
=>
{
if
(
idSet
.
has
(
item
.
id
))
{
if
(
idSet
.
has
(
item
.
id
))
{
return
false
;
return
false
;
}
}
idSet
.
add
(
item
.
id
);
idSet
.
add
(
item
.
id
);
return
true
;
return
true
;
})
});
);
// slice search result by rate.
const
sliceRateMap
:
Record
<
number
,
number
[]
>
=
{
1
:
[
1
],
2
:
[
0.7
,
0.3
]
};
const
sliceRate
=
sliceRateMap
[
searchRes
.
length
]
||
sliceRateMap
[
0
];
// 计算固定提示词的 token 数量
// 计算固定提示词的 token 数量
const
guidePrompt
=
model
.
chat
.
systemPrompt
// user system prompt
const
guidePrompt
=
model
.
chat
.
systemPrompt
// user system prompt
?
{
?
{
obj
:
ChatRoleEnum
.
System
,
obj
:
ChatRoleEnum
.
System
,
...
@@ -154,24 +141,21 @@ export async function appKbSearch({
...
@@ -154,24 +141,21 @@ export async function appKbSearch({
const
fixedSystemTokens
=
modelToolMap
[
model
.
chat
.
chatModel
].
countTokens
({
const
fixedSystemTokens
=
modelToolMap
[
model
.
chat
.
chatModel
].
countTokens
({
messages
:
[
guidePrompt
]
messages
:
[
guidePrompt
]
});
});
const
maxTokens
=
modelConstantsData
.
systemMaxToken
-
fixedSystemTokens
;
const
sliceResult
=
modelToolMap
[
model
.
chat
.
chatModel
]
const
sliceResult
=
sliceRate
.
map
((
rate
,
i
)
=>
modelToolMap
[
model
.
chat
.
chatModel
]
.
tokenSlice
({
.
tokenSlice
({
maxToken
:
Math
.
round
(
maxTokens
*
rate
)
,
maxToken
:
modelConstantsData
.
systemMaxToken
-
fixedSystemTokens
,
messages
:
filterSearch
[
i
]
.
map
((
item
)
=>
({
messages
:
filterSearch
.
map
((
item
)
=>
({
obj
:
ChatRoleEnum
.
System
,
obj
:
ChatRoleEnum
.
System
,
value
:
`
${
item
.
q
}
\n
${
item
.
a
}
`
value
:
`
${
item
.
q
}
\n
${
item
.
a
}
`
}))
}))
})
})
.
map
((
item
)
=>
item
.
value
)
.
map
((
item
)
=>
item
.
value
);
);
// slice filterSearch
// slice filterSearch
const
sliceSearch
=
filterSearch
.
map
((
item
,
i
)
=>
item
.
slice
(
0
,
sliceResult
[
i
].
length
)).
flat
(
);
const
rawSearch
=
filterSearch
.
slice
(
0
,
sliceResult
.
length
);
// system prompt
// system prompt
const
systemPrompt
=
sliceResult
.
flat
().
join
(
'\n'
).
trim
();
const
systemPrompt
=
sliceResult
.
join
(
'\n'
).
trim
();
/* 高相似度+不回复 */
/* 高相似度+不回复 */
if
(
!
systemPrompt
&&
model
.
chat
.
searchMode
===
appVectorSearchModeEnum
.
hightSimilarity
)
{
if
(
!
systemPrompt
&&
model
.
chat
.
searchMode
===
appVectorSearchModeEnum
.
hightSimilarity
)
{
...
@@ -206,7 +190,7 @@ export async function appKbSearch({
...
@@ -206,7 +190,7 @@ export async function appKbSearch({
return
{
return
{
code
:
200
,
code
:
200
,
rawSearch
:
sliceSearch
,
rawSearch
,
guidePrompt
:
guidePrompt
.
value
||
''
,
guidePrompt
:
guidePrompt
.
value
||
''
,
searchPrompts
:
[
searchPrompts
:
[
{
{
...
...
src/service/utils/auth.ts
View file @
0cde9a10
...
@@ -280,7 +280,8 @@ export const authChat = async ({
...
@@ -280,7 +280,8 @@ export const authChat = async ({
{
{
$project
:
{
$project
:
{
obj
:
'$content.obj'
,
obj
:
'$content.obj'
,
value
:
'$content.value'
value
:
'$content.value'
,
quote
:
'$content.quote'
}
}
}
}
]);
]);
...
...
src/service/utils/chat/index.ts
View file @
0cde9a10
...
@@ -89,39 +89,55 @@ export const ChatContextFilter = ({
...
@@ -89,39 +89,55 @@ export const ChatContextFilter = ({
prompts
:
ChatItemSimpleType
[];
prompts
:
ChatItemSimpleType
[];
maxTokens
:
number
;
maxTokens
:
number
;
})
=>
{
})
=>
{
const
systemPrompts
:
ChatItemSimpleType
[]
=
[];
const
chatPrompts
:
ChatItemSimpleType
[]
=
[];
let
rawTextLen
=
0
;
let
rawTextLen
=
0
;
const
formatPrompts
=
prompts
.
map
<
ChatItemSimpleType
>
((
item
)
=>
{
prompts
.
forEach
((
item
)
=>
{
const
val
=
simplifyStr
(
item
.
value
);
const
val
=
simplifyStr
(
item
.
value
);
rawTextLen
+=
val
.
length
;
rawTextLen
+=
val
.
length
;
return
{
const
data
=
{
obj
:
item
.
obj
,
obj
:
item
.
obj
,
value
:
val
value
:
val
};
};
if
(
item
.
obj
===
ChatRoleEnum
.
System
)
{
systemPrompts
.
push
(
data
);
}
else
{
chatPrompts
.
push
(
data
);
}
});
});
// 长度太小时,不需要进行 token 截断
// 长度太小时,不需要进行 token 截断
if
(
formatPrompts
.
length
<=
2
||
rawTextLen
<
maxTokens
*
0.5
)
{
if
(
rawTextLen
<
maxTokens
*
0.5
)
{
return
formatPrompts
;
return
[...
systemPrompts
,
...
chatPrompts
]
;
}
}
// 去掉 system 的 token
maxTokens
-=
modelToolMap
[
model
].
countTokens
({
messages
:
systemPrompts
});
// 根据 tokens 截断内容
// 根据 tokens 截断内容
const
chats
:
ChatItemSimpleType
[]
=
[];
const
chats
:
ChatItemSimpleType
[]
=
[];
// 从后往前截取对话内容
// 从后往前截取对话内容
for
(
let
i
=
form
atPrompts
.
length
-
1
;
i
>=
0
;
i
--
)
{
for
(
let
i
=
ch
atPrompts
.
length
-
1
;
i
>=
0
;
i
--
)
{
chats
.
unshift
(
form
atPrompts
[
i
]);
chats
.
unshift
(
ch
atPrompts
[
i
]);
const
tokens
=
modelToolMap
[
model
].
countTokens
({
const
tokens
=
modelToolMap
[
model
].
countTokens
({
messages
:
chats
messages
:
chats
});
});
/* 整体 tokens 超出范围, system必须保留 */
/* 整体 tokens 超出范围, system必须保留 */
if
(
tokens
>=
maxTokens
&&
formatPrompts
[
i
].
obj
!==
ChatRoleEnum
.
System
)
{
if
(
tokens
>=
maxTokens
)
{
return
chats
.
slice
(
1
);
chats
.
shift
();
break
;
}
}
}
}
return
chats
;
return
[...
systemPrompts
,
...
chats
]
;
};
};
/* stream response */
/* stream response */
...
...
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