This commit is contained in:
Archer
2023-11-09 09:46:57 +08:00
committed by GitHub
parent 661ee79943
commit 8bb5588305
402 changed files with 9899 additions and 5967 deletions

View File

@@ -0,0 +1,14 @@
import { POST } from '@fastgpt/service/common/api/plusRequest';
import type {
AuthLinkLimitProps,
AuthShareChatInitProps
} from '@fastgpt/global/support/outLink/api.d';
export function authOutLinkLimit(data: AuthLinkLimitProps) {
return POST('/support/outLink/authLimit', data);
}
export function authShareChatInit(data: AuthShareChatInitProps) {
if (!global.feConfigs?.isPlus) return;
return POST('/support/outLink/authShareChatInit', data);
}

View File

@@ -0,0 +1,8 @@
import { GET } from '@fastgpt/service/common/api/plusRequest';
export const authTeamBalance = async (teamId: string) => {
if (global.systemEnv.pluginBaseUrl) {
return GET('/support/permission/authBalance', { teamId });
}
return true;
};

View File

@@ -0,0 +1,36 @@
import { getDatasetPgData } from '@/service/core/dataset/data/controller';
import { PgDataItemType } from '@fastgpt/global/core/dataset/type';
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
import { authDatasetCollection } from '@fastgpt/service/support/permission/auth/dataset';
import { parseHeaderCert } from '@fastgpt/service/support/permission/controller';
import { AuthModeType } from '@fastgpt/service/support/permission/type';
export async function authDatasetData({
dataId,
...props
}: AuthModeType & {
dataId: string;
}): Promise<
AuthResponseType & {
datasetData: PgDataItemType;
}
> {
const result = await parseHeaderCert(props);
const { tmbId } = result;
// get pg data
const datasetData = await getDatasetPgData({ id: dataId });
const isOwner = String(datasetData.tmbId) === tmbId;
// data has the same permissions as collection
const { canWrite } = await authDatasetCollection({
...props,
collectionId: datasetData.collectionId
});
return {
...result,
datasetData,
isOwner,
canWrite
};
}

View File

@@ -0,0 +1,31 @@
import { authOutLinkLimit } from '@/service/support/outLink/auth';
import { AuthLinkChatProps } from '@fastgpt/global/support/outLink/api.d';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
import { getUserAndAuthBalance } from './user';
import { authOutLinkValid } from '@fastgpt/service/support/permission/auth/outLink';
export async function authOutLinkChat({
shareId,
ip,
authToken,
question
}: AuthLinkChatProps & {
shareId: string;
}) {
// get outLink
const { shareChat, app } = await authOutLinkValid({ shareId });
const [user] = await Promise.all([
getUserAndAuthBalance({ tmbId: shareChat.tmbId, minBalance: 0 }),
global.feConfigs?.isPlus
? authOutLinkLimit({ outLink: shareChat, ip, authToken, question })
: undefined
]);
return {
authType: AuthUserTypeEnum.token,
responseDetail: shareChat.responseDetail,
user,
app
};
}

View File

@@ -0,0 +1,48 @@
import { AuthResponseType } from '@fastgpt/global/support/permission/type';
import { parseHeaderCert } from '@fastgpt/service/support/permission/controller';
import { AuthModeType } from '@fastgpt/service/support/permission/type';
import { UserErrEnum } from '@fastgpt/global/common/error/code/user';
import { UserType } from '@fastgpt/global/support/user/type';
import { getUserDetail } from '@/service/support/user/controller';
export async function getUserAndAuthBalance({
tmbId,
minBalance
}: {
tmbId: string;
minBalance?: number;
}) {
const user = await getUserDetail({ tmbId });
if (!user) {
return Promise.reject(UserErrEnum.unAuthUser);
}
if (minBalance !== undefined && global.feConfigs.isPlus && user.team.balance < minBalance) {
return Promise.reject(UserErrEnum.balanceNotEnough);
}
return user;
}
/* get user */
export async function authUser({
minBalance,
...props
}: AuthModeType & {
minBalance?: number;
}): Promise<
AuthResponseType & {
user: UserType;
}
> {
const { userId, teamId, tmbId } = await parseHeaderCert(props);
return {
userId,
teamId,
tmbId,
user: await getUserAndAuthBalance({ tmbId, minBalance }),
isOwner: true,
canWrite: true
};
}

View File

@@ -0,0 +1,30 @@
import { ERROR_ENUM } from '@fastgpt/global/common/error/errorCode';
import { MongoUser } from '@fastgpt/service/support/user/schema';
import { UserType } from '@fastgpt/global/support/user/type';
import { getTeamInfoByTmbId } from '@fastgpt/service/support/user/team/controller';
export async function getUserDetail({
tmbId,
userId
}: {
tmbId?: string;
userId?: string;
}): Promise<UserType> {
const team = await getTeamInfoByTmbId({ tmbId, userId });
const user = await MongoUser.findById(team.userId);
if (!user) {
return Promise.reject(ERROR_ENUM.unAuthorization);
}
return {
_id: user._id,
username: user.username,
avatar: user.avatar,
balance: user.balance,
timezone: user.timezone,
promotionRate: user.promotionRate,
openaiAccount: user.openaiAccount,
team
};
}

View File

@@ -0,0 +1,7 @@
import { POST } from '@fastgpt/service/common/api/plusRequest';
import { SendInformProps } from '@fastgpt/global/support/user/inform/type';
export function sendOneInform(data: SendInformProps) {
if (!global.systemEnv.pluginBaseUrl) return;
return POST('/support/user/inform/create', data);
}

View File

@@ -0,0 +1,201 @@
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
import { getAudioSpeechModel, getModelMap, ModelTypeEnum } from '@/service/core/ai/model';
import type { ChatHistoryItemResType } from '@fastgpt/global/core/chat/api.d';
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
import { addLog } from '@fastgpt/service/common/mongo/controller';
import type { ConcatBillProps, CreateBillProps } from '@fastgpt/global/support/wallet/bill/api.d';
import { defaultQGModels } from '@fastgpt/global/core/ai/model';
import { POST } from '@fastgpt/service/common/api/plusRequest';
export function createBill(data: CreateBillProps) {
if (!global.systemEnv.pluginBaseUrl) return;
POST('/support/wallet/bill/createBill', data);
}
export function concatBill(data: ConcatBillProps) {
if (!global.systemEnv.pluginBaseUrl) return;
POST('/support/wallet/bill/concatBill', data);
}
export const pushChatBill = ({
appName,
appId,
teamId,
tmbId,
source,
response
}: {
appName: string;
appId: string;
teamId: string;
tmbId: string;
source: `${BillSourceEnum}`;
response: ChatHistoryItemResType[];
}) => {
const total = response.reduce((sum, item) => sum + item.price, 0);
createBill({
teamId,
tmbId,
appName,
appId,
total,
source,
list: response.map((item) => ({
moduleName: item.moduleName,
amount: item.price || 0,
model: item.model,
tokenLen: item.tokens
}))
});
addLog.info(`finish completions`, {
source,
teamId,
tmbId,
price: formatPrice(total)
});
return { total };
};
export const pushQABill = async ({
teamId,
tmbId,
totalTokens,
billId
}: {
teamId: string;
tmbId: string;
totalTokens: number;
billId: string;
}) => {
addLog.info('splitData generate success', { totalTokens });
// 获取模型单价格
const unitPrice = global.qaModels?.[0]?.price || 3;
// 计算价格
const total = unitPrice * totalTokens;
concatBill({
billId,
teamId,
tmbId,
total,
tokens: totalTokens,
listIndex: 1
});
return { total };
};
export const pushGenerateVectorBill = async ({
billId,
teamId,
tmbId,
tokenLen,
model,
source = BillSourceEnum.fastgpt
}: {
billId?: string;
teamId: string;
tmbId: string;
tokenLen: number;
model: string;
source?: `${BillSourceEnum}`;
}) => {
// 计算价格. 至少为1
const vectorModel =
global.vectorModels.find((item) => item.model === model) || global.vectorModels[0];
const unitPrice = vectorModel.price || 0.2;
let total = unitPrice * tokenLen;
total = total > 1 ? total : 1;
// 插入 Bill 记录
if (billId) {
concatBill({
teamId,
tmbId,
total,
billId,
tokens: tokenLen,
listIndex: 0
});
} else {
createBill({
teamId,
tmbId,
appName: '索引生成',
total,
source,
list: [
{
moduleName: '索引生成',
amount: total,
model: vectorModel.name,
tokenLen
}
]
});
}
return { total };
};
export const pushQuestionGuideBill = ({
tokens,
teamId,
tmbId
}: {
tokens: number;
teamId: string;
tmbId: string;
}) => {
const qgModel = global.qgModels?.[0] || defaultQGModels[0];
const total = qgModel.price * tokens;
createBill({
teamId,
tmbId,
appName: '下一步指引',
total,
source: BillSourceEnum.fastgpt,
list: [
{
moduleName: '下一步指引',
amount: total,
model: qgModel.name,
tokenLen: tokens
}
]
});
};
export function pushAudioSpeechBill({
appName = 'wallet.bill.Audio Speech',
model,
textLength,
teamId,
tmbId,
source = BillSourceEnum.fastgpt
}: {
appName?: string;
model: string;
textLength: number;
teamId: string;
tmbId: string;
source: `${BillSourceEnum}`;
}) {
const modelData = getAudioSpeechModel(model);
const total = modelData.price * textLength;
createBill({
teamId,
tmbId,
appName,
total,
source,
list: [
{
moduleName: appName,
amount: total,
model: modelData.name,
tokenLen: textLength
}
]
});
}

View File

@@ -0,0 +1,32 @@
import { ModelTypeEnum, getModelMap } from '@/service/core/ai/model';
import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
export function authType2BillSource({
authType,
shareId,
source
}: {
authType?: `${AuthUserTypeEnum}`;
shareId?: string;
source?: `${BillSourceEnum}`;
}) {
if (source) return source;
if (shareId) return BillSourceEnum.shareLink;
if (authType === AuthUserTypeEnum.apikey) return BillSourceEnum.api;
return BillSourceEnum.fastgpt;
}
export const countModelPrice = ({
model,
tokens,
type
}: {
model: string;
tokens: number;
type: `${ModelTypeEnum}`;
}) => {
const modelData = getModelMap?.[type]?.(model);
if (!modelData) return 0;
return modelData.price * tokens;
};