4.6.8-alpha (#804)

* perf: redirect request and err log replace

perf: dataset openapi

feat: session

fix: retry input error

feat: 468 doc

sub page

feat: standard sub

perf: rerank tip

perf: rerank tip

perf: api sdk

perf: openapi

sub plan

perf: sub ui

fix: ts

* perf: init log

* fix: variable select

* sub page

* icon

* perf: llm model config

* perf: menu ux

* perf: system store

* perf: publish app name

* fix: init data

* perf: flow edit ux

* fix: value type format and ux

* fix prompt editor default value (#13)

* fix prompt editor default value

* fix prompt editor update when not focus

* add key with variable

---------

Co-authored-by: Archer <545436317@qq.com>

* fix: value type

* doc

* i18n

* import path

* home page

* perf: mongo session running

* fix: ts

* perf: use toast

* perf: flow edit

* perf: sse response

* slider ui

* fetch error

* fix prompt editor rerender when not focus by key defaultvalue (#14)

* perf: prompt editor

* feat: dataset search concat

* perf: doc

* fix:ts

* perf: doc

* fix json editor onblur value (#15)

* faq

* vector model default config

* ipv6

---------

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
Archer
2024-02-01 21:57:41 +08:00
committed by GitHub
parent fc19c4cf09
commit 34602b25df
285 changed files with 10345 additions and 11223 deletions

View File

@@ -17,6 +17,7 @@ export async function authOpenApiKey({ apikey }: { apikey: string }) {
}
// auth limit
// @ts-ignore
if (global.feConfigs?.isPlus) {
await POST('/support/openapi/authLimit', { openApi } as AuthOpenApiLimitProps);
}

View File

@@ -68,6 +68,13 @@ const OpenApiSchema = new Schema(
}
);
try {
OpenApiSchema.index({ teamId: 1 });
OpenApiSchema.index({ apiKey: 1 });
} catch (error) {
console.log(error);
}
export const MongoOpenApi: Model<OpenApiSchema> =
models['openapi'] || model('openapi', OpenApiSchema);
MongoOpenApi.syncIndexes();

View File

@@ -2,7 +2,7 @@ import { AuthUserTypeEnum } from '@fastgpt/global/support/permission/constant';
import { parseHeaderCert } from '../controller';
import { AuthModeType } from '../type';
import { authOutLinkValid } from './outLink';
import { isIPv6 } from 'net';
import { SERVICE_LOCAL_HOST } from '../../../common/system/tools';
export const authCert = async (props: AuthModeType) => {
const result = await parseHeaderCert(props);
@@ -35,12 +35,7 @@ export async function authCertOrShareId({
/* auth the request from local service */
export const authRequestFromLocal = ({ req }: AuthModeType) => {
const host =
process.env.HOSTNAME && isIPv6(process.env.HOSTNAME)
? `[${process.env.HOSTNAME}]:${process.env.PORT || 3000}`
: `${process.env.HOSTNAME || 'localhost'}:${process.env.PORT || 3000}`;
if (host !== req.headers.host) {
if (req.headers.host !== SERVICE_LOCAL_HOST) {
return Promise.reject('Invalid request');
}
};

View File

@@ -111,8 +111,7 @@ export async function parseHeaderCert({
}
}
const { cookie, token, apikey, rootkey, authorization } = (req.headers ||
{}) as ReqHeaderAuthType;
const { cookie, token, rootkey, authorization } = (req.headers || {}) as ReqHeaderAuthType;
const { uid, teamId, tmbId, appId, openApiKey, authType } = await (async () => {
if (authApiKey && authorization) {
@@ -151,19 +150,6 @@ export async function parseHeaderCert({
authType: AuthUserTypeEnum.root
};
}
// apikey: abandon
if (authApiKey && apikey) {
// apikey
const parseResult = await authOpenApiKey({ apikey });
return {
uid: parseResult.userId,
teamId: parseResult.teamId,
tmbId: parseResult.tmbId,
appId: parseResult.appId,
openApiKey: parseResult.apikey,
authType: AuthUserTypeEnum.apikey
};
}
return Promise.reject(ERROR_ENUM.unAuthorization);
})();

View File

@@ -1,17 +1,18 @@
import { StandSubPlanLevelMapType } from '@fastgpt/global/support/wallet/sub/type';
import { getVectorCountByTeamId } from '../../../common/vectorStore/controller';
import { getTeamDatasetValidSub } from '../../wallet/sub/utils';
import { getTeamDatasetMaxSize } from '../../wallet/sub/utils';
export const checkDatasetLimit = async ({
teamId,
freeSize = Infinity,
insertLen = 0
insertLen = 0,
standardPlans
}: {
teamId: string;
freeSize?: number;
insertLen?: number;
standardPlans?: StandSubPlanLevelMapType;
}) => {
const [{ maxSize }, usedSize] = await Promise.all([
getTeamDatasetValidSub({ teamId, freeSize }),
getTeamDatasetMaxSize({ teamId, standardPlans }),
getVectorCountByTeamId(teamId)
]);

View File

@@ -1,5 +1,5 @@
import { TeamItemType, TeamMemberWithTeamSchema } from '@fastgpt/global/support/user/team/type';
import { Types } from '../../../common/mongo';
import { ClientSession, Types } from '../../../common/mongo';
import {
TeamMemberRoleEnum,
TeamMemberStatusEnum,
@@ -55,13 +55,15 @@ export async function createDefaultTeam({
teamName = 'My Team',
avatar = '/icon/logo.svg',
balance,
maxSize = 5
maxSize = 5,
session
}: {
userId: string;
teamName?: string;
avatar?: string;
balance?: number;
maxSize?: number;
session: ClientSession;
}) {
// auth default team
const tmb = await MongoTeamMember.findOne({
@@ -73,23 +75,33 @@ export async function createDefaultTeam({
console.log('create default team', userId);
// create
const { _id: insertedId } = await MongoTeam.create({
ownerId: userId,
name: teamName,
avatar,
balance,
maxSize,
createTime: new Date()
});
await MongoTeamMember.create({
teamId: insertedId,
userId,
name: 'Owner',
role: TeamMemberRoleEnum.owner,
status: TeamMemberStatusEnum.active,
createTime: new Date(),
defaultTeam: true
});
const [{ _id: insertedId }] = await MongoTeam.create(
[
{
ownerId: userId,
name: teamName,
avatar,
balance,
maxSize,
createTime: new Date()
}
],
{ session }
);
await MongoTeamMember.create(
[
{
teamId: insertedId,
userId,
name: 'Owner',
role: TeamMemberRoleEnum.owner,
status: TeamMemberStatusEnum.active,
createTime: new Date(),
defaultTeam: true
}
],
{ session }
);
} else {
console.log('default team exist', userId);
await MongoTeam.findByIdAndUpdate(tmb.teamId, {

View File

@@ -3,7 +3,6 @@ const { Schema, model, models } = connectionMongo;
import { TeamSchema as TeamType } from '@fastgpt/global/support/user/team/type.d';
import { userCollectionName } from '../../user/schema';
import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant';
import { PRICE_SCALE } from '@fastgpt/global/support/wallet/bill/constants';
const TeamSchema = new Schema({
name: {

View File

@@ -1,5 +1,6 @@
import { BillSourceEnum } from '@fastgpt/global/support/wallet/bill/constants';
import { MongoBill } from './schema';
import { ClientSession } from '../../../common/mongo';
export const createTrainingBill = async ({
teamId,
@@ -7,7 +8,8 @@ export const createTrainingBill = async ({
appName,
billSource,
vectorModel,
agentModel
agentModel,
session
}: {
teamId: string;
tmbId: string;
@@ -15,28 +17,34 @@ export const createTrainingBill = async ({
billSource: `${BillSourceEnum}`;
vectorModel: string;
agentModel: string;
session?: ClientSession;
}) => {
const { _id } = await MongoBill.create({
teamId,
tmbId,
appName,
source: billSource,
list: [
const [{ _id }] = await MongoBill.create(
[
{
moduleName: 'wallet.moduleName.index',
model: vectorModel,
charsLength: 0,
amount: 0
},
{
moduleName: 'wallet.moduleName.qa',
model: agentModel,
charsLength: 0,
amount: 0
teamId,
tmbId,
appName,
source: billSource,
list: [
{
moduleName: 'wallet.moduleName.index',
model: vectorModel,
charsLength: 0,
amount: 0
},
{
moduleName: 'wallet.moduleName.qa',
model: agentModel,
charsLength: 0,
amount: 0
}
],
total: 0
}
],
total: 0
});
{ session }
);
return { billId: String(_id) };
};

View File

@@ -29,6 +29,15 @@ const SubSchema = new Schema({
required: true
},
mode: {
type: String,
enum: Object.keys(subModeMap)
},
currentMode: {
type: String,
enum: Object.keys(subModeMap),
required: true
},
nextMode: {
type: String,
enum: Object.keys(subModeMap),
required: true
@@ -46,6 +55,10 @@ const SubSchema = new Schema({
type: Number,
required: true
},
pointPrice: {
// stand level point total price
type: Number
},
// sub content
currentSubLevel: {
@@ -56,6 +69,9 @@ const SubSchema = new Schema({
type: String,
enum: Object.keys(standardSubLevelMap)
},
totalPoints: {
type: Number
},
currentExtraDatasetSize: {
type: Number
@@ -72,48 +88,44 @@ const SubSchema = new Schema({
},
// standard sub limit
maxTeamMember: {
type: Number
},
maxAppAmount: {
type: Number
},
maxDatasetAmount: {
type: Number
},
chatHistoryStoreDuration: {
// n day
type: Number
},
maxDatasetSize: {
type: Number
},
trainingWeight: {
// 0 1 2 3
type: Number
},
customApiKey: {
type: Boolean
},
customCopyright: {
type: Boolean
},
exportDatasetInterval: {
// hours
type: Number
},
websiteSyncInterval: {
// hours
type: Number
},
reRankWeight: {
// 0 1 2 3
type: Number
},
totalPoints: {
// record standard sub points
type: Number
},
// maxTeamMember: {
// type: Number
// },
// maxAppAmount: {
// type: Number
// },
// maxDatasetAmount: {
// type: Number
// },
// chatHistoryStoreDuration: {
// // n day
// type: Number
// },
// maxDatasetSize: {
// type: Number
// },
// trainingWeight: {
// // 0 1 2 3
// type: Number
// },
// customApiKey: {
// type: Boolean
// },
// customCopyright: {
// type: Boolean
// },
// websiteSyncInterval: {
// // hours
// type: Number
// },
// reRankWeight: {
// // 0 1 2 3
// type: Number
// },
// totalPoints: {
// // record standard sub points
// type: Number
// },
surplusPoints: {
// standard sub / extra points sub

View File

@@ -1,28 +1,87 @@
import { SubTypeEnum } from '@fastgpt/global/support/wallet/sub/constants';
import { MongoTeamSub } from './schema';
import { addHours } from 'date-fns';
import { FeTeamSubType, StandSubPlanLevelMapType } from '@fastgpt/global/support/wallet/sub/type.d';
import { getVectorCountByTeamId } from '../../../common/vectorStore/controller';
/* get team dataset size */
export const getTeamDatasetValidSub = async ({
/* get team dataset max size */
export const getTeamDatasetMaxSize = async ({
teamId,
freeSize = Infinity
standardPlans
}: {
teamId: string;
freeSize?: number;
standardPlans?: StandSubPlanLevelMapType;
}) => {
const sub = await MongoTeamSub.findOne({
if (!standardPlans) {
return {
maxSize: Infinity,
sub: null
};
}
const plans = await MongoTeamSub.find({
teamId,
type: SubTypeEnum.extraDatasetSize,
expiredTime: { $gte: new Date() }
expiredTime: { $gte: addHours(new Date(), -3) }
}).lean();
const maxSize = (() => {
if (!sub || !sub.currentExtraDatasetSize) return freeSize;
const standard = plans.find((plan) => plan.type === SubTypeEnum.standard);
const extraDatasetSize = plans.find((plan) => plan.type === SubTypeEnum.extraDatasetSize);
return sub.currentExtraDatasetSize + freeSize;
})();
const standardMaxDatasetSize =
standard?.currentSubLevel && standardPlans
? standardPlans[standard.currentSubLevel]?.maxDatasetSize || Infinity
: Infinity;
const totalDatasetSize =
standardMaxDatasetSize + (extraDatasetSize?.currentExtraDatasetSize || 0);
return {
maxSize,
sub
maxSize: totalDatasetSize,
sub: extraDatasetSize
};
};
export const getTeamSubPlanStatus = async ({
teamId,
standardPlans
}: {
teamId: string;
standardPlans?: StandSubPlanLevelMapType;
}): Promise<FeTeamSubType> => {
const [plans, usedDatasetSize] = await Promise.all([
MongoTeamSub.find({ teamId }).lean(),
getVectorCountByTeamId(teamId)
]);
const standard = plans.find((plan) => plan.type === SubTypeEnum.standard);
const extraDatasetSize = plans.find((plan) => plan.type === SubTypeEnum.extraDatasetSize);
const extraPoints = plans.find((plan) => plan.type === SubTypeEnum.extraPoints);
const standardMaxDatasetSize =
standard?.currentSubLevel && standardPlans
? standardPlans[standard.currentSubLevel]?.maxDatasetSize || Infinity
: Infinity;
const totalDatasetSize =
standardMaxDatasetSize + (extraDatasetSize?.currentExtraDatasetSize || 0);
const standardMaxPoints =
standard?.currentSubLevel && standardPlans
? standardPlans[standard.currentSubLevel]?.totalPoints || Infinity
: Infinity;
const totalPoints = standardMaxPoints + (extraPoints?.currentExtraPoints || 0);
const surplusPoints = (standard?.surplusPoints || 0) + (extraPoints?.surplusPoints || 0);
return {
[SubTypeEnum.standard]: standard,
[SubTypeEnum.extraDatasetSize]: extraDatasetSize,
[SubTypeEnum.extraPoints]: extraPoints,
standardMaxDatasetSize,
datasetMaxSize: totalDatasetSize,
usedDatasetSize,
standardMaxPoints,
totalPoints,
usedPoints: totalPoints - surplusPoints
};
};