Commit d55ccc9f by Archer Committed by GitHub

Doc (#2910)

* feat: add app chat openapi (#2908)

* add chat openapi

* create question guide openapi

* change auth method

* add chat openapi doc

* delete unused code

* feat: chat openapi doc

* rerank doc

* add chat detail openapi & doc

* update chat openapi doc

---------

Co-authored-by: heheer <heheer@sealos.io>
Co-authored-by: heheer <1239331448@qq.com>
parent 27ef4dc8
......@@ -77,7 +77,7 @@ https://github.com/labring/FastGPT/assets/15308462/7d3a38df-eb0e-4388-9250-2409b
`4` OpenAPI 接口
- [x] completions 接口 (chat 模式对齐 GPT 接口)
- [x] 知识库 CRUD
- [ ] 对话 CRUD
- [x] 对话 CRUD
`5` 运营能力
- [x] 免登录分享窗口
......
......@@ -227,6 +227,27 @@ weight: 708
}
```
### ReRank 接入(硅基流动)
有免费的 `bge-reranker-v2-m3` 模型可以使用。
1. 注册硅基流动账号: https://siliconflow.cn/
2. 进入控制台,获取 API key: https://cloud.siliconflow.cn/account/ak
3. 修改 FastGPT 配置文件
```json
{
"reRankModels": [
{
"model": "BAAI/bge-reranker-v2-m3", // 这里的model需要对应 siliconflow 的模型名
"name": "BAAI/bge-reranker-v2-m3",
"requestUrl": "https://api.siliconflow.cn/v1/rerank",
"requestAuth": "siliconflow 上申请的 key"
}
]
}
```
### ReRank 接入(Cohere)
这个重排模型对中文不是很好,不如 bge 的好用。
......@@ -239,7 +260,7 @@ weight: 708
"reRankModels": [
{
"model": "rerank-multilingual-v2.0", // 这里的model需要对应 cohere 的模型名
"name": "检索重排", // 随意
"name": "rerank-multilingual-v2.0",
"requestUrl": "https://api.cohere.ai/v1/rerank",
"requestAuth": "Coherer上申请的key"
}
......
......@@ -22,7 +22,7 @@ weight: 853
**新例子**
```bash
curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/usage/createTrainingUsage' \
curl --location --request POST 'http://localhost:3000/api/support/wallet/usage/createTrainingUsage' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
......@@ -34,7 +34,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/usage/
**x例子**
```bash
curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/bill/createTrainingBill' \
curl --location --request POST 'http://localhost:3000/api/support/wallet/bill/createTrainingBill' \
--header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \
--data-raw '{
......
export type UpdateChatFeedbackProps = {
appId: string;
chatId: string;
chatItemId: string;
dataId: string;
shareId?: string;
teamId?: string;
teamToken?: string;
......
......@@ -100,7 +100,7 @@ export type ChatItemSchema = (UserChatItemType | SystemChatItemType | AIChatItem
};
export type AdminFbkType = {
dataId: string;
feedbackDataId: string;
datasetId: string;
collectionId: string;
q: string;
......
......@@ -55,22 +55,22 @@ export const adaptStringValue = (value: any): ChatItemValueItemType[] => {
export const addCustomFeedbacks = async ({
appId,
chatId,
chatItemId,
dataId,
feedbacks
}: {
appId: string;
chatId?: string;
chatItemId?: string;
dataId?: string;
feedbacks: string[];
}) => {
if (!chatId || !chatItemId) return;
if (!chatId || !dataId) return;
try {
await MongoChatItem.findOneAndUpdate(
{
appId,
chatId,
dataId: chatItemId
dataId
},
{
$push: { customFeedbacks: { $each: feedbacks } }
......
......@@ -17,7 +17,7 @@ export const dispatchCustomFeedback = (props: Record<string, any>): Response =>
const {
runningAppInfo: { id: appId },
chatId,
responseChatItemId: chatItemId,
responseChatItemId: dataId,
stream,
workflowStreamResponse,
params: { system_textareaInput: feedbackText = '' }
......@@ -27,13 +27,13 @@ export const dispatchCustomFeedback = (props: Record<string, any>): Response =>
addCustomFeedbacks({
appId,
chatId,
chatItemId,
dataId,
feedbacks: [feedbackText]
});
}, 60000);
if (stream) {
if (!chatId || !chatItemId) {
if (!chatId || !dataId) {
workflowStreamResponse?.({
event: SseResponseEventEnum.fastAnswer,
data: textAdaptGptResponse({
......
......@@ -8,7 +8,7 @@ import { updateChatUserFeedback } from '@/web/core/chat/api';
const FeedbackModal = ({
appId,
chatId,
chatItemId,
dataId,
teamId,
teamToken,
shareId,
......@@ -18,7 +18,7 @@ const FeedbackModal = ({
}: {
appId: string;
chatId: string;
chatItemId: string;
dataId: string;
shareId?: string;
teamId?: string;
teamToken?: string;
......@@ -35,7 +35,7 @@ const FeedbackModal = ({
return updateChatUserFeedback({
appId,
chatId,
chatItemId,
dataId,
shareId,
teamId,
teamToken,
......
import React, { useState } from 'react';
import React from 'react';
import { ModalBody, useTheme, ModalFooter, Button, Box, Card, Flex, Grid } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import Avatar from '@fastgpt/web/components/common/Avatar';
......@@ -13,7 +13,7 @@ import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
const InputDataModal = dynamic(() => import('@/pages/dataset/detail/components/InputDataModal'));
export type AdminMarkType = {
dataId?: string;
feedbackDataId?: string;
datasetId?: string;
collectionId?: string;
q: string;
......@@ -137,7 +137,7 @@ const SelectMarkCollection = ({
});
}}
collectionId={adminMarkData.collectionId}
dataId={adminMarkData.dataId}
dataId={adminMarkData.feedbackDataId}
defaultValue={{
q: adminMarkData.q,
a: adminMarkData.a
......@@ -153,7 +153,7 @@ const SelectMarkCollection = ({
}
onSuccess({
dataId: data.dataId,
feedbackDataId: data.dataId,
datasetId: adminMarkData.datasetId,
collectionId: adminMarkData.collectionId,
q: data.q,
......
......@@ -142,10 +142,10 @@ const ChatBox = (
const [feedbackId, setFeedbackId] = useState<string>();
const [readFeedbackData, setReadFeedbackData] = useState<{
chatItemId: string;
dataId: string;
content: string;
}>();
const [adminMarkData, setAdminMarkData] = useState<AdminMarkType & { chatItemId: string }>();
const [adminMarkData, setAdminMarkData] = useState<AdminMarkType & { dataId: string }>();
const [questionGuides, setQuestionGuide] = useState<string[]>([]);
const {
......@@ -660,16 +660,16 @@ const ChatBox = (
if (chat.adminFeedback) {
setAdminMarkData({
chatItemId: chat.dataId,
dataId: chat.dataId,
datasetId: chat.adminFeedback.datasetId,
collectionId: chat.adminFeedback.collectionId,
dataId: chat.adminFeedback.dataId,
feedbackDataId: chat.adminFeedback.feedbackDataId,
q: chat.adminFeedback.q || q || '',
a: chat.adminFeedback.a
});
} else {
setAdminMarkData({
chatItemId: chat.dataId,
dataId: chat.dataId,
q,
a: formatChatValue2InputType(chat.value).text
});
......@@ -703,7 +703,7 @@ const ChatBox = (
chatId,
teamId,
teamToken,
chatItemId: chat.dataId,
dataId: chat.dataId,
shareId,
outLinkUid,
userGoodFeedback: isGoodFeedback ? undefined : 'yes'
......@@ -725,7 +725,7 @@ const ChatBox = (
teamId,
teamToken,
chatId,
chatItemId: chat.dataId,
dataId: chat.dataId,
userGoodFeedback: undefined
});
};
......@@ -750,7 +750,7 @@ const ChatBox = (
updateChatUserFeedback({
appId,
chatId,
chatItemId: chat.dataId,
dataId: chat.dataId,
shareId,
teamId,
teamToken,
......@@ -767,7 +767,7 @@ const ChatBox = (
return () => {
if (!chat.dataId) return;
setReadFeedbackData({
chatItemId: chat.dataId || '',
dataId: chat.dataId || '',
content: chat.userBadFeedback || ''
});
};
......@@ -778,7 +778,7 @@ const ChatBox = (
closeCustomFeedback({
appId,
chatId,
chatItemId: chat.dataId,
dataId: chat.dataId,
index: i
});
// update dom
......@@ -945,7 +945,7 @@ const ChatBox = (
text={t('common:core.app.feedback.Custom feedback')}
/>
{item.customFeedbacks.map((text, i) => (
<Box key={`${text}${i}`}>
<Box key={i}>
<MyTooltip
label={t('common:core.app.feedback.close custom feedback')}
>
......@@ -1035,7 +1035,7 @@ const ChatBox = (
teamId={teamId}
teamToken={teamToken}
chatId={chatId}
chatItemId={feedbackId}
dataId={feedbackId}
shareId={shareId}
outLinkUid={outLinkUid}
onClose={() => setFeedbackId(undefined)}
......@@ -1057,7 +1057,7 @@ const ChatBox = (
onCloseFeedback={() => {
setChatHistories((state) =>
state.map((chatItem) =>
chatItem.dataId === readFeedbackData.chatItemId
chatItem.dataId === readFeedbackData.dataId
? { ...chatItem, userBadFeedback: undefined }
: chatItem
)
......@@ -1067,7 +1067,7 @@ const ChatBox = (
updateChatUserFeedback({
appId,
chatId,
chatItemId: readFeedbackData.chatItemId
dataId: readFeedbackData.dataId
});
} catch (error) {}
setReadFeedbackData(undefined);
......@@ -1078,21 +1078,21 @@ const ChatBox = (
{!!adminMarkData && (
<SelectMarkCollection
adminMarkData={adminMarkData}
setAdminMarkData={(e) => setAdminMarkData({ ...e, chatItemId: adminMarkData.chatItemId })}
setAdminMarkData={(e) => setAdminMarkData({ ...e, dataId: adminMarkData.dataId })}
onClose={() => setAdminMarkData(undefined)}
onSuccess={(adminFeedback) => {
if (!appId || !chatId || !adminMarkData.chatItemId) return;
if (!appId || !chatId || !adminMarkData.dataId) return;
updateChatAdminFeedback({
appId,
chatId,
chatItemId: adminMarkData.chatItemId,
dataId: adminMarkData.dataId,
...adminFeedback
});
// update dom
setChatHistories((state) =>
state.map((chatItem) =>
chatItem.dataId === adminMarkData.chatItemId
chatItem.dataId === adminMarkData.dataId
? {
...chatItem,
adminFeedback
......@@ -1105,12 +1105,12 @@ const ChatBox = (
updateChatUserFeedback({
appId,
chatId,
chatItemId: readFeedbackData.chatItemId,
dataId: readFeedbackData.dataId,
userBadFeedback: undefined
});
setChatHistories((state) =>
state.map((chatItem) =>
chatItem.dataId === readFeedbackData.chatItemId
chatItem.dataId === readFeedbackData.dataId
? { ...chatItem, userBadFeedback: undefined }
: chatItem
)
......
......@@ -84,12 +84,12 @@ export type DeleteChatItemProps = OutLinkChatAuthProps & {
export type AdminUpdateFeedbackParams = AdminFbkType & {
appId: string;
chatId: string;
chatItemId: string;
dataId: string;
};
export type CloseCustomFeedbackParams = {
appId: string;
chatId: string;
chatItemId: string;
dataId: string;
index: number;
};
......@@ -13,7 +13,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const { tmbId, teamId } = await authChatCert({
req,
authToken: true
authToken: true,
authApiKey: true
});
const qgModel = global.llmModels[0];
......
......@@ -36,7 +36,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
};
}
if (appId) {
const { tmbId } = await authCert({ req, authToken: true });
const { tmbId } = await authCert({ req, authToken: true, authApiKey: true });
return {
tmbId,
......
......@@ -17,6 +17,7 @@ async function handler(req: ApiRequestProps<{}, DelHistoryProps>, res: NextApiRe
await authChatCrud({
req,
authToken: true,
authApiKey: true,
...req.query,
per: WritePermissionVal
});
......
......@@ -10,10 +10,10 @@ import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { appId, chatId, chatItemId, datasetId, dataId, q, a } =
const { appId, chatId, dataId, datasetId, feedbackDataId, q, a } =
req.body as AdminUpdateFeedbackParams;
if (!chatItemId || !datasetId || !dataId || !q) {
if (!dataId || !datasetId || !feedbackDataId || !q) {
throw new Error('missing parameter');
}
......@@ -29,12 +29,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
{
appId,
chatId,
dataId: chatItemId
dataId
},
{
adminFeedback: {
datasetId,
dataId,
dataId: feedbackDataId,
q,
a
}
......
......@@ -6,14 +6,15 @@ import type { CloseCustomFeedbackParams } from '@/global/core/chat/api.d';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { authChatCrud } from '@/service/support/permission/auth/chat';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
/* remove custom feedback */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { appId, chatId, chatItemId, index } = req.body as CloseCustomFeedbackParams;
const { appId, chatId, dataId, index } = req.body as CloseCustomFeedbackParams;
if (!chatItemId || !appId || !chatId || !chatItemId) {
if (!dataId || !appId || !chatId) {
throw new Error('missing parameter');
}
......@@ -26,10 +27,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
});
await authCert({ req, authToken: true });
await MongoChatItem.findOneAndUpdate(
{ appId, chatId, dataId: chatItemId },
{ $unset: { [`customFeedbacks.${index}`]: 1 } }
);
await mongoSessionRun(async (session) => {
await MongoChatItem.findOneAndUpdate(
{ appId, chatId, dataId },
{ $unset: { [`customFeedbacks.${index}`]: 1 } },
{
session
}
);
await MongoChatItem.findOneAndUpdate(
{ appId, chatId, dataId },
{ $pull: { customFeedbacks: null } },
{
session
}
);
});
jsonRes(res);
} catch (err) {
......
......@@ -11,7 +11,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
const {
appId,
chatId,
chatItemId,
dataId,
shareId,
teamId,
teamToken,
......@@ -36,15 +36,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
per: ReadPermissionVal
});
if (!chatItemId) {
throw new Error('chatItemId is required');
if (!dataId) {
throw new Error('dataId is required');
}
await MongoChatItem.findOneAndUpdate(
{
appId,
chatId,
dataId: chatItemId
dataId
},
{
$unset: {
......
......@@ -43,7 +43,7 @@ async function handler(
};
}
if (appId) {
const { tmbId } = await authCert({ req, authToken: true });
const { tmbId } = await authCert({ req, authToken: true, authApiKey: true });
return {
tmbId,
appId,
......
......@@ -26,7 +26,14 @@ async function handler(
req: ApiRequestProps<getPaginationRecordsBody, getPaginationRecordsQuery>,
res: ApiResponseType<any>
): Promise<getPaginationRecordsResponse> {
const { chatId, appId, offset, pageSize = 10, loadCustomFeedbacks, type } = req.body;
const {
appId,
chatId,
offset,
pageSize = 10,
loadCustomFeedbacks,
type = GetChatTypeEnum.normal
} = req.body;
if (!appId || !chatId) {
return {
......@@ -40,6 +47,7 @@ async function handler(
authChatCrud({
req,
authToken: true,
authApiKey: true,
...req.body,
per: ReadPermissionVal
})
......
......@@ -37,6 +37,7 @@ async function handler(
await authChatCrud({
req,
authToken: true,
authApiKey: true,
...req.query,
per: ReadPermissionVal
});
......@@ -44,6 +45,7 @@ async function handler(
await authApp({
req,
authToken: true,
authApiKey: true,
appId,
per: ManagePermissionVal
});
......
......@@ -29,6 +29,7 @@ async function handler(
authApp({
req,
authToken: true,
authApiKey: true,
appId,
per: ReadPermissionVal
}),
......
import type { NextApiRequest, NextApiResponse } from 'next';
import type { NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
import { authChatCrud } from '@/service/support/permission/auth/chat';
import type { DeleteChatItemProps } from '@/global/core/chat/api.d';
......@@ -9,7 +8,7 @@ import { ApiRequestProps } from '@fastgpt/service/type/next';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
async function handler(req: ApiRequestProps<{}, DeleteChatItemProps>, res: NextApiResponse) {
const { appId, chatId, contentId, shareId, outLinkUid } = req.query;
const { appId, chatId, contentId } = req.query;
if (!contentId || !chatId) {
return jsonRes(res);
......@@ -18,6 +17,7 @@ async function handler(req: ApiRequestProps<{}, DeleteChatItemProps>, res: NextA
await authChatCrud({
req,
authToken: true,
authApiKey: true,
...req.query,
per: WritePermissionVal
});
......
......@@ -24,7 +24,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
throw new Error('model or voice not found');
}
const { teamId, tmbId, authType } = await authChatCert({ req, authToken: true });
const { teamId, tmbId, authType } = await authChatCert({
req,
authToken: true,
authApiKey: true
});
const ttsModel = getAudioSpeechModel(ttsConfig.model);
const voiceData = ttsModel.voices?.find((item) => item.value === ttsConfig.voice);
......
import type { NextApiRequest, NextApiResponse } from 'next';
import type { NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { UpdateHistoryProps } from '@/global/core/chat/api.d';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
......@@ -13,6 +13,7 @@ async function handler(req: ApiRequestProps<UpdateHistoryProps>, res: NextApiRes
await authChatCrud({
req,
authToken: true,
authApiKey: true,
...req.body,
per: WritePermissionVal
});
......
......@@ -18,7 +18,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const {
appId,
chatId,
responseChatItemId: chatItemId,
responseChatItemId: dataId,
defaultFeedback,
customFeedback
} = req.body as Props;
......@@ -38,12 +38,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
addCustomFeedbacks({
appId,
chatId,
chatItemId,
dataId,
feedbacks: [feedback]
});
}, 60000);
if (!chatId || !chatItemId) {
if (!chatId || !dataId) {
return res.json({
response: `\\n\\n**自动反馈调试**: ${feedback}\\n\\n`
});
......
......@@ -20,7 +20,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
customFeedback,
appId,
chatId,
responseChatItemId: chatItemId,
responseChatItemId: dataId,
customInputs
} = req.body as Props;
......@@ -37,12 +37,12 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
addCustomFeedbacks({
appId,
chatId,
chatItemId,
dataId,
feedbacks: [feedbackText]
});
}, 60000);
if (!chatId || !chatItemId) {
if (!chatId || !dataId) {
return res.json({
[NodeOutputKeyEnum.answerText]: `\\n\\n**自动反馈调试**: "${feedbackText}"\\n\\n`,
text: feedbackText
......
import { create } from 'zustand';
import { devtools, persist } from 'zustand/middleware';
import { devtools } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';
export type MarkDataStore = {
chatItemId: string;
dataId: string;
datasetId?: string;
collectionId?: string;
q: string;
......
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