v4.6.9-alpha (#918)

Co-authored-by: Mufei <327958099@qq.com>
Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
Archer
2024-03-04 00:05:25 +08:00
committed by GitHub
parent f9f0b4bffd
commit 42a8184ea0
153 changed files with 4906 additions and 4307 deletions

View File

@@ -1,11 +1,16 @@
import { ChatSchema } from '@fastgpt/global/core/chat/type';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { AuthModeType } from '@fastgpt/service/support/permission/type';
import { authOutLink } from './outLink';
import { authOutLink, authOutLinkInit } from './outLink';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { authUserRole } from '@fastgpt/service/support/permission/auth/user';
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
import { authTeamSpaceToken } from './team';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { authOutLinkValid } from '@fastgpt/service/support/permission/auth/outLink';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
/*
outLink: Must be the owner
token: team owner and chat owner have all permissions
@@ -14,46 +19,51 @@ export async function autChatCrud({
appId,
chatId,
shareId,
shareTeamId,
outLinkUid,
teamId: spaceTeamId,
teamToken,
per = 'owner',
...props
}: AuthModeType & {
appId: string;
chatId?: string;
shareTeamId?: string;
shareId?: string;
outLinkUid?: string;
teamId?: string;
teamToken?: string;
}): Promise<{
chat?: ChatSchema;
isOutLink: boolean;
uid?: string;
}> {
const isOutLink = Boolean((shareId || shareTeamId) && outLinkUid);
const isOutLink = Boolean((shareId || spaceTeamId) && outLinkUid);
if (!chatId) return { isOutLink, uid: outLinkUid };
const chat = await MongoChat.findOne({ appId, chatId }).lean();
if (!chat) return { isOutLink, uid: outLinkUid };
const { uid } = await (async () => {
// outLink Auth
if (shareId && outLinkUid) {
const { uid } = await authOutLink({ shareId, outLinkUid });
// auth outLinkUid
if (chat.shareId === shareId && chat.outLinkUid === uid) {
if (!chat || (chat.shareId === shareId && chat.outLinkUid === uid)) {
return { uid };
}
return Promise.reject(ChatErrEnum.unAuthChat);
}
if (shareTeamId && outLinkUid) {
if (chat.teamId == shareTeamId && chat.outLinkUid === outLinkUid) {
return { uid: outLinkUid };
// auth team space chat
if (spaceTeamId && teamToken) {
const { uid } = await authTeamSpaceToken({ teamId: spaceTeamId, teamToken });
if (!chat || (String(chat.teamId) === String(spaceTeamId) && chat.outLinkUid === uid)) {
return { uid };
}
return Promise.reject(ChatErrEnum.unAuthChat);
}
// req auth
if (!chat) return { id: outLinkUid };
// auth req
const { teamId, tmbId, role } = await authUserRole(props);
if (String(teamId) !== String(chat.teamId)) return Promise.reject(ChatErrEnum.unAuthChat);
@@ -67,9 +77,61 @@ export async function autChatCrud({
return Promise.reject(ChatErrEnum.unAuthChat);
})();
if (!chat) return { isOutLink, uid };
return {
chat,
isOutLink,
uid
};
}
/*
Different chat source
1. token (header)
2. apikey (header)
3. share page (body: shareId outLinkUid)
4. team chat page (body: teamId teamToken)
*/
export async function authChatCert(props: AuthModeType) {
const { teamId, teamToken, shareId, outLinkUid } = props.req.body as OutLinkChatAuthProps;
if (shareId && outLinkUid) {
const { shareChat } = await authOutLinkValid({ shareId });
const { uid } = await authOutLinkInit({
outLinkUid,
tokenUrl: shareChat.limit?.hookUrl
});
return {
teamId: String(shareChat.teamId),
tmbId: String(shareChat.tmbId),
authType: AuthUserTypeEnum.outLink,
apikey: '',
isOwner: false,
canWrite: false,
outLinkUid: uid
};
}
if (teamId && teamToken) {
const { uid } = await authTeamSpaceToken({ teamId, teamToken });
const tmb = await MongoTeamMember.findOne(
{ teamId, role: TeamMemberRoleEnum.owner },
'tmbId'
).lean();
if (!tmb) return Promise.reject(ChatErrEnum.unAuthChat);
return {
teamId,
tmbId: String(tmb._id),
authType: AuthUserTypeEnum.teamDomain,
apikey: '',
isOwner: false,
canWrite: false,
outLinkUid: uid
};
}
return authCert(props);
}

View File

@@ -1,9 +1,12 @@
import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
import { TeamMemberWithUserSchema } from '@fastgpt/global/support/user/team/type';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { MongoTeam } from '@fastgpt/service/support/user/team/teamSchema';
import { checkTeamAIPoints } from '@fastgpt/service/support/permission/teamLimit';
import axios from 'axios';
import { GET } from '@fastgpt/service/common/api/plusRequest';
import {
AuthTeamTagTokenProps,
AuthTokenFromTeamDomainResponse
} from '@fastgpt/global/support/user/team/tag';
export async function getUserChatInfoAndAuthTeamPoints(tmbId: string) {
const tmb = (await MongoTeamMember.findById(tmbId, 'teamId userId').populate(
@@ -19,25 +22,21 @@ export async function getUserChatInfoAndAuthTeamPoints(tmbId: string) {
};
}
type UserInfoType = {
data: {
uid: string;
tags: string[];
};
};
export async function getShareTeamUid(shareTeamId: string, authToken: string) {
try {
const teamInfo = await MongoTeam.findById(shareTeamId);
const tagsUrl = teamInfo?.tagsUrl;
const { data: userInfo } = await axios.post(tagsUrl + `/getUserInfo`, { autoken: authToken });
const uid = userInfo?.data?.uid;
if (uid) {
throw new Error('uid null');
}
return uid;
} catch (err) {
return '';
}
export function authTeamTagToken(data: AuthTeamTagTokenProps) {
return GET<AuthTokenFromTeamDomainResponse['data']>('/support/user/team/tag/authTeamToken', data);
}
export async function authTeamSpaceToken({
teamId,
teamToken
}: {
teamId: string;
teamToken: string;
}) {
// get outLink and app
const data = await authTeamTagToken({ teamId, teamToken });
const uid = data.uid;
return {
uid
};
}

View File

@@ -1,36 +0,0 @@
import { POST } from '@fastgpt/service/common/api/plusRequest';
import type { AuthOutLinkChatProps } from '@fastgpt/global/support/outLink/api.d';
import type { chatAppListSchema } from '@fastgpt/global/core/chat/type.d';
import { getUserChatInfoAndAuthTeamPoints } from './team';
import { MongoTeam } from '@fastgpt/service/support/user/team/teamSchema';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
export function authChatTeamInfo(data: { shareTeamId: string; authToken: string }) {
return POST<chatAppListSchema>('/core/chat/init', data);
}
export async function authTeamShareChatStart({
teamId,
ip,
outLinkUid,
question
}: AuthOutLinkChatProps & {
teamId: string;
}) {
// get outLink and app
const { teamInfo, uid } = await authChatTeamInfo({ shareTeamId: teamId, authToken: outLinkUid });
// check balance and chat limit
const tmb = await MongoTeamMember.findOne({ teamId, userId: String(teamInfo.ownerId) });
if (!tmb) {
throw new Error('can not find it');
}
const { user } = await getUserChatInfoAndAuthTeamPoints(String(tmb._id));
return {
user,
tmbId: String(tmb._id),
uid: uid
};
}

View File

@@ -1,10 +1,9 @@
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
import { ModelTypeEnum } from '@fastgpt/service/core/ai/model';
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type.d';
import { addLog } from '@fastgpt/service/common/system/log';
import { createUsage, concatUsage } from './controller';
import { formatModelChars2Points } from '@/service/support/wallet/usage/utils';
import { ChatModuleBillType } from '@fastgpt/global/support/wallet/bill/type';
import { formatModelChars2Points } from '@fastgpt/service/support/wallet/usage/utils';
import { ChatModuleUsageType } from '@fastgpt/global/support/wallet/bill/type';
export const pushChatUsage = ({
appName,
@@ -19,7 +18,7 @@ export const pushChatUsage = ({
teamId: string;
tmbId: string;
source: `${UsageSourceEnum}`;
moduleDispatchBills: ChatModuleBillType[];
moduleDispatchBills: ChatModuleUsageType[];
}) => {
const totalPoints = moduleDispatchBills.reduce((sum, item) => sum + (item.totalPoints || 0), 0);
@@ -34,7 +33,7 @@ export const pushChatUsage = ({
moduleName: item.moduleName,
amount: item.totalPoints || 0,
model: item.model,
charsLength: item.charsLength
tokens: item.tokens
}))
});
addLog.info(`finish completions`, {
@@ -50,20 +49,20 @@ export const pushQAUsage = async ({
teamId,
tmbId,
model,
charsLength,
tokens,
billId
}: {
teamId: string;
tmbId: string;
model: string;
charsLength: number;
tokens: number;
billId: string;
}) => {
// 计算价格
const { totalPoints } = formatModelChars2Points({
model,
modelType: ModelTypeEnum.llm,
charsLength
tokens
});
concatUsage({
@@ -71,7 +70,7 @@ export const pushQAUsage = async ({
teamId,
tmbId,
totalPoints,
charsLength,
tokens,
listIndex: 1
});
@@ -82,30 +81,30 @@ export const pushGenerateVectorUsage = ({
billId,
teamId,
tmbId,
charsLength,
tokens,
model,
source = UsageSourceEnum.fastgpt,
extensionModel,
extensionCharsLength
extensionTokens
}: {
billId?: string;
teamId: string;
tmbId: string;
charsLength: number;
tokens: number;
model: string;
source?: `${UsageSourceEnum}`;
extensionModel?: string;
extensionCharsLength?: number;
extensionTokens?: number;
}) => {
const { totalPoints: totalVector, modelName: vectorModelName } = formatModelChars2Points({
modelType: ModelTypeEnum.vector,
model,
charsLength
tokens
});
const { extensionTotalPoints, extensionModelName } = (() => {
if (!extensionModel || !extensionCharsLength)
if (!extensionModel || !extensionTokens)
return {
extensionTotalPoints: 0,
extensionModelName: ''
@@ -113,7 +112,7 @@ export const pushGenerateVectorUsage = ({
const { totalPoints, modelName } = formatModelChars2Points({
modelType: ModelTypeEnum.llm,
model: extensionModel,
charsLength: extensionCharsLength
tokens: extensionTokens
});
return {
extensionTotalPoints: totalPoints,
@@ -130,7 +129,7 @@ export const pushGenerateVectorUsage = ({
tmbId,
totalPoints,
billId,
charsLength,
tokens,
listIndex: 0
});
} else {
@@ -145,7 +144,7 @@ export const pushGenerateVectorUsage = ({
moduleName: 'support.wallet.moduleName.index',
amount: totalVector,
model: vectorModelName,
charsLength
tokens
},
...(extensionModel !== undefined
? [
@@ -153,7 +152,7 @@ export const pushGenerateVectorUsage = ({
moduleName: 'core.module.template.Query extension',
amount: extensionTotalPoints,
model: extensionModelName,
charsLength: extensionCharsLength
tokens: extensionTokens
}
]
: [])
@@ -164,17 +163,17 @@ export const pushGenerateVectorUsage = ({
};
export const pushQuestionGuideUsage = ({
charsLength,
tokens,
teamId,
tmbId
}: {
charsLength: number;
tokens: number;
teamId: string;
tmbId: string;
}) => {
const qgModel = global.llmModels[0];
const { totalPoints, modelName } = formatModelChars2Points({
charsLength,
tokens,
model: qgModel.model,
modelType: ModelTypeEnum.llm
});
@@ -190,14 +189,14 @@ export const pushQuestionGuideUsage = ({
moduleName: 'core.app.Next Step Guide',
amount: totalPoints,
model: modelName,
charsLength
tokens
}
]
});
};
export function pushAudioSpeechUsage({
appName = 'support.wallet.bill.Audio Speech',
appName = 'support.wallet.usage.Audio Speech',
model,
charsLength,
teamId,
@@ -213,7 +212,7 @@ export function pushAudioSpeechUsage({
}) {
const { totalPoints, modelName } = formatModelChars2Points({
model,
charsLength,
tokens: charsLength,
modelType: ModelTypeEnum.audioSpeech
});
@@ -249,12 +248,12 @@ export function pushWhisperUsage({
const { totalPoints, modelName } = formatModelChars2Points({
model: whisperModel.model,
charsLength: duration,
tokens: duration,
modelType: ModelTypeEnum.whisper,
multiple: 60
});
const name = 'support.wallet.bill.Whisper';
const name = 'support.wallet.usage.Whisper';
createUsage({
teamId,

View File

@@ -1,4 +1,3 @@
import { ModelTypeEnum, getModelMap } from '@fastgpt/service/core/ai/model';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
@@ -16,29 +15,3 @@ export function authType2UsageSource({
if (authType === AuthUserTypeEnum.apikey) return UsageSourceEnum.api;
return UsageSourceEnum.fastgpt;
}
export const formatModelChars2Points = ({
model,
charsLength = 0,
modelType,
multiple = 1000
}: {
model: string;
charsLength: number;
modelType: `${ModelTypeEnum}`;
multiple?: number;
}) => {
const modelData = getModelMap?.[modelType]?.(model);
if (!modelData)
return {
totalPoints: 0,
modelName: ''
};
const totalPoints = (modelData.charsPointsPrice || 0) * (charsLength / multiple);
return {
modelName: modelData.name,
totalPoints
};
};