@lobehub/chat 1.112.5 → 1.113.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +1 -1
- package/CHANGELOG.md +50 -0
- package/changelog/v1.json +10 -0
- package/package.json +3 -3
- package/packages/const/src/image.ts +9 -1
- package/packages/model-runtime/src/bfl/createImage.test.ts +846 -0
- package/packages/model-runtime/src/bfl/createImage.ts +279 -0
- package/packages/model-runtime/src/bfl/index.test.ts +269 -0
- package/packages/model-runtime/src/bfl/index.ts +49 -0
- package/packages/model-runtime/src/bfl/types.ts +113 -0
- package/packages/model-runtime/src/index.ts +1 -0
- package/packages/model-runtime/src/qwen/createImage.ts +37 -82
- package/packages/model-runtime/src/runtimeMap.ts +2 -0
- package/packages/model-runtime/src/utils/asyncifyPolling.test.ts +491 -0
- package/packages/model-runtime/src/utils/asyncifyPolling.ts +175 -0
- package/src/app/(backend)/api/webhooks/casdoor/route.ts +2 -1
- package/src/app/(backend)/api/webhooks/clerk/route.ts +2 -1
- package/src/app/(backend)/api/webhooks/logto/route.ts +2 -1
- package/src/app/(backend)/webapi/user/avatar/[id]/[image]/route.ts +2 -1
- package/src/app/[variants]/(main)/image/@menu/features/ConfigPanel/index.tsx +1 -1
- package/src/config/aiModels/bfl.ts +145 -0
- package/src/config/aiModels/index.ts +3 -0
- package/src/config/llm.ts +6 -1
- package/src/config/modelProviders/bfl.ts +21 -0
- package/src/config/modelProviders/index.ts +3 -0
- package/src/database/server/models/ragEval/dataset.ts +9 -7
- package/src/database/server/models/ragEval/datasetRecord.ts +12 -10
- package/src/database/server/models/ragEval/evaluation.ts +10 -8
- package/src/database/server/models/ragEval/evaluationRecord.ts +11 -9
- package/src/server/routers/async/file.ts +1 -1
- package/src/server/routers/async/ragEval.ts +4 -4
- package/src/server/routers/lambda/chunk.ts +1 -1
- package/src/server/routers/lambda/ragEval.ts +4 -4
- package/src/server/routers/lambda/user.ts +1 -1
- package/src/server/services/chunk/index.ts +2 -2
- package/src/server/services/nextAuthUser/index.test.ts +1 -1
- package/src/server/services/nextAuthUser/index.ts +6 -4
- package/src/server/services/user/index.test.ts +3 -1
- package/src/server/services/user/index.ts +14 -8
- package/src/store/image/slices/generationConfig/hooks.ts +6 -10
@@ -6,18 +6,20 @@ import {
|
|
6
6
|
evalEvaluation,
|
7
7
|
evaluationRecords,
|
8
8
|
} from '@/database/schemas';
|
9
|
-
import {
|
9
|
+
import { LobeChatDatabase } from '@/database/type';
|
10
10
|
import { EvalEvaluationStatus, RAGEvalEvaluationItem } from '@/types/eval';
|
11
11
|
|
12
12
|
export class EvalEvaluationModel {
|
13
13
|
private userId: string;
|
14
|
+
private db: LobeChatDatabase;
|
14
15
|
|
15
|
-
constructor(userId: string) {
|
16
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
17
|
+
this.db = db;
|
16
18
|
this.userId = userId;
|
17
19
|
}
|
18
20
|
|
19
21
|
create = async (params: NewEvalEvaluationItem) => {
|
20
|
-
const [result] = await
|
22
|
+
const [result] = await this.db
|
21
23
|
.insert(evalEvaluation)
|
22
24
|
.values({ ...params, userId: this.userId })
|
23
25
|
.returning();
|
@@ -25,13 +27,13 @@ export class EvalEvaluationModel {
|
|
25
27
|
};
|
26
28
|
|
27
29
|
delete = async (id: number) => {
|
28
|
-
return
|
30
|
+
return this.db
|
29
31
|
.delete(evalEvaluation)
|
30
32
|
.where(and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)));
|
31
33
|
};
|
32
34
|
|
33
35
|
queryByKnowledgeBaseId = async (knowledgeBaseId: string) => {
|
34
|
-
const evaluations = await
|
36
|
+
const evaluations = await this.db
|
35
37
|
.select({
|
36
38
|
createdAt: evalEvaluation.createdAt,
|
37
39
|
dataset: {
|
@@ -57,7 +59,7 @@ export class EvalEvaluationModel {
|
|
57
59
|
// 然后查询每个评估的记录统计
|
58
60
|
const evaluationIds = evaluations.map((evals) => evals.id);
|
59
61
|
|
60
|
-
const recordStats = await
|
62
|
+
const recordStats = await this.db
|
61
63
|
.select({
|
62
64
|
evaluationId: evaluationRecords.evaluationId,
|
63
65
|
success: count(evaluationRecords.status).if(
|
@@ -82,13 +84,13 @@ export class EvalEvaluationModel {
|
|
82
84
|
};
|
83
85
|
|
84
86
|
findById = async (id: number) => {
|
85
|
-
return
|
87
|
+
return this.db.query.evalEvaluation.findFirst({
|
86
88
|
where: and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)),
|
87
89
|
});
|
88
90
|
};
|
89
91
|
|
90
92
|
update = async (id: number, value: Partial<NewEvalEvaluationItem>) => {
|
91
|
-
return
|
93
|
+
return this.db
|
92
94
|
.update(evalEvaluation)
|
93
95
|
.set(value)
|
94
96
|
.where(and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)));
|
@@ -1,17 +1,19 @@
|
|
1
1
|
import { and, eq } from 'drizzle-orm';
|
2
2
|
|
3
3
|
import { NewEvaluationRecordsItem, evaluationRecords } from '@/database/schemas';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
|
6
6
|
export class EvaluationRecordModel {
|
7
7
|
private userId: string;
|
8
|
+
private db: LobeChatDatabase;
|
8
9
|
|
9
|
-
constructor(userId: string) {
|
10
|
+
constructor(db: LobeChatDatabase, userId: string) {
|
11
|
+
this.db = db;
|
10
12
|
this.userId = userId;
|
11
13
|
}
|
12
14
|
|
13
15
|
create = async (params: NewEvaluationRecordsItem) => {
|
14
|
-
const [result] = await
|
16
|
+
const [result] = await this.db
|
15
17
|
.insert(evaluationRecords)
|
16
18
|
.values({ ...params, userId: this.userId })
|
17
19
|
.returning();
|
@@ -19,20 +21,20 @@ export class EvaluationRecordModel {
|
|
19
21
|
};
|
20
22
|
|
21
23
|
batchCreate = async (params: NewEvaluationRecordsItem[]) => {
|
22
|
-
return
|
24
|
+
return this.db
|
23
25
|
.insert(evaluationRecords)
|
24
26
|
.values(params.map((item) => ({ ...item, userId: this.userId })))
|
25
27
|
.returning();
|
26
28
|
};
|
27
29
|
|
28
30
|
delete = async (id: number) => {
|
29
|
-
return
|
31
|
+
return this.db
|
30
32
|
.delete(evaluationRecords)
|
31
33
|
.where(and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)));
|
32
34
|
};
|
33
35
|
|
34
36
|
query = async (reportId: number) => {
|
35
|
-
return
|
37
|
+
return this.db.query.evaluationRecords.findMany({
|
36
38
|
where: and(
|
37
39
|
eq(evaluationRecords.evaluationId, reportId),
|
38
40
|
eq(evaluationRecords.userId, this.userId),
|
@@ -41,13 +43,13 @@ export class EvaluationRecordModel {
|
|
41
43
|
};
|
42
44
|
|
43
45
|
findById = async (id: number) => {
|
44
|
-
return
|
46
|
+
return this.db.query.evaluationRecords.findFirst({
|
45
47
|
where: and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)),
|
46
48
|
});
|
47
49
|
};
|
48
50
|
|
49
51
|
findByEvaluationId = async (evaluationId: number) => {
|
50
|
-
return
|
52
|
+
return this.db.query.evaluationRecords.findMany({
|
51
53
|
where: and(
|
52
54
|
eq(evaluationRecords.evaluationId, evaluationId),
|
53
55
|
eq(evaluationRecords.userId, this.userId),
|
@@ -56,7 +58,7 @@ export class EvaluationRecordModel {
|
|
56
58
|
};
|
57
59
|
|
58
60
|
update = async (id: number, value: Partial<NewEvaluationRecordsItem>) => {
|
59
|
-
return
|
61
|
+
return this.db
|
60
62
|
.update(evaluationRecords)
|
61
63
|
.set(value)
|
62
64
|
.where(and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)));
|
@@ -32,7 +32,7 @@ const fileProcedure = asyncAuthedProcedure.use(async (opts) => {
|
|
32
32
|
ctx: {
|
33
33
|
asyncTaskModel: new AsyncTaskModel(ctx.serverDB, ctx.userId),
|
34
34
|
chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
|
35
|
-
chunkService: new ChunkService(ctx.userId),
|
35
|
+
chunkService: new ChunkService(ctx.serverDB, ctx.userId),
|
36
36
|
embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
|
37
37
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
38
38
|
fileService: new FileService(ctx.serverDB, ctx.userId),
|
@@ -25,11 +25,11 @@ const ragEvalProcedure = asyncAuthedProcedure.use(async (opts) => {
|
|
25
25
|
return opts.next({
|
26
26
|
ctx: {
|
27
27
|
chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
|
28
|
-
chunkService: new ChunkService(ctx.userId),
|
29
|
-
datasetRecordModel: new EvalDatasetRecordModel(ctx.userId),
|
28
|
+
chunkService: new ChunkService(ctx.serverDB, ctx.userId),
|
29
|
+
datasetRecordModel: new EvalDatasetRecordModel(ctx.serverDB, ctx.userId),
|
30
30
|
embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
|
31
|
-
evalRecordModel: new EvaluationRecordModel(ctx.userId),
|
32
|
-
evaluationModel: new EvalEvaluationModel(ctx.userId),
|
31
|
+
evalRecordModel: new EvaluationRecordModel(ctx.serverDB, ctx.userId),
|
32
|
+
evaluationModel: new EvalEvaluationModel(ctx.serverDB, ctx.userId),
|
33
33
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
34
34
|
},
|
35
35
|
});
|
@@ -26,7 +26,7 @@ const chunkProcedure = authedProcedure
|
|
26
26
|
ctx: {
|
27
27
|
asyncTaskModel: new AsyncTaskModel(ctx.serverDB, ctx.userId),
|
28
28
|
chunkModel: new ChunkModel(ctx.serverDB, ctx.userId),
|
29
|
-
chunkService: new ChunkService(ctx.userId),
|
29
|
+
chunkService: new ChunkService(ctx.serverDB, ctx.userId),
|
30
30
|
embeddingModel: new EmbeddingModel(ctx.serverDB, ctx.userId),
|
31
31
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
32
32
|
messageModel: new MessageModel(ctx.serverDB, ctx.userId),
|
@@ -35,11 +35,11 @@ const ragEvalProcedure = authedProcedure
|
|
35
35
|
|
36
36
|
return opts.next({
|
37
37
|
ctx: {
|
38
|
-
datasetModel: new EvalDatasetModel(ctx.userId),
|
38
|
+
datasetModel: new EvalDatasetModel(ctx.serverDB, ctx.userId),
|
39
39
|
fileModel: new FileModel(ctx.serverDB, ctx.userId),
|
40
|
-
datasetRecordModel: new EvalDatasetRecordModel(ctx.userId),
|
41
|
-
evaluationModel: new EvalEvaluationModel(ctx.userId),
|
42
|
-
evaluationRecordModel: new EvaluationRecordModel(ctx.userId),
|
40
|
+
datasetRecordModel: new EvalDatasetRecordModel(ctx.serverDB, ctx.userId),
|
41
|
+
evaluationModel: new EvalEvaluationModel(ctx.serverDB, ctx.userId),
|
42
|
+
evaluationRecordModel: new EvaluationRecordModel(ctx.serverDB, ctx.userId),
|
43
43
|
fileService: new FileService(ctx.serverDB, ctx.userId),
|
44
44
|
},
|
45
45
|
});
|
@@ -58,7 +58,7 @@ export const userRouter = router({
|
|
58
58
|
if (enableClerk) {
|
59
59
|
const user = await ctx.clerkAuth.getCurrentUser();
|
60
60
|
if (user) {
|
61
|
-
const userService = new UserService();
|
61
|
+
const userService = new UserService(ctx.serverDB);
|
62
62
|
|
63
63
|
await userService.createUser(user.id, {
|
64
64
|
created_at: user.createdAt,
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { ClientSecretPayload } from '@/const/auth';
|
2
2
|
import { AsyncTaskModel } from '@/database/models/asyncTask';
|
3
3
|
import { FileModel } from '@/database/models/file';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
import { ChunkContentParams, ContentChunk } from '@/server/modules/ContentChunk';
|
6
6
|
import { createAsyncCaller } from '@/server/routers/async';
|
7
7
|
import {
|
@@ -17,7 +17,7 @@ export class ChunkService {
|
|
17
17
|
private fileModel: FileModel;
|
18
18
|
private asyncTaskModel: AsyncTaskModel;
|
19
19
|
|
20
|
-
constructor(userId: string) {
|
20
|
+
constructor(serverDB: LobeChatDatabase, userId: string) {
|
21
21
|
this.userId = userId;
|
22
22
|
|
23
23
|
this.chunkClient = new ContentChunk();
|
@@ -2,15 +2,17 @@ import { NextResponse } from 'next/server';
|
|
2
2
|
|
3
3
|
import { UserModel } from '@/database/models/user';
|
4
4
|
import { UserItem } from '@/database/schemas';
|
5
|
-
import {
|
5
|
+
import { LobeChatDatabase } from '@/database/type';
|
6
6
|
import { pino } from '@/libs/logger';
|
7
7
|
import { LobeNextAuthDbAdapter } from '@/libs/next-auth/adapter';
|
8
8
|
|
9
9
|
export class NextAuthUserService {
|
10
10
|
adapter;
|
11
|
+
private db: LobeChatDatabase;
|
11
12
|
|
12
|
-
constructor() {
|
13
|
-
this.
|
13
|
+
constructor(db: LobeChatDatabase) {
|
14
|
+
this.db = db;
|
15
|
+
this.adapter = LobeNextAuthDbAdapter(db);
|
14
16
|
}
|
15
17
|
|
16
18
|
safeUpdateUser = async (
|
@@ -27,7 +29,7 @@ export class NextAuthUserService {
|
|
27
29
|
|
28
30
|
// 2. If found, Update user data from provider
|
29
31
|
if (user?.id) {
|
30
|
-
const userModel = new UserModel(
|
32
|
+
const userModel = new UserModel(this.db, user.id);
|
31
33
|
|
32
34
|
// Perform update
|
33
35
|
await userModel.updateUser({
|
@@ -3,6 +3,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
|
|
3
3
|
|
4
4
|
import { UserModel } from '@/database/models/user';
|
5
5
|
import { UserItem } from '@/database/schemas';
|
6
|
+
import { LobeChatDatabase } from '@/database/type';
|
6
7
|
import { pino } from '@/libs/logger';
|
7
8
|
import { AgentService } from '@/server/services/agent';
|
8
9
|
|
@@ -46,6 +47,7 @@ vi.mock('@/server/services/agent', () => ({
|
|
46
47
|
|
47
48
|
let service: UserService;
|
48
49
|
const mockUserId = 'test-user-id';
|
50
|
+
const mockDB = {} as LobeChatDatabase;
|
49
51
|
|
50
52
|
// Mock user data
|
51
53
|
const mockUserJSON: UserJSON = {
|
@@ -62,7 +64,7 @@ const mockUserJSON: UserJSON = {
|
|
62
64
|
} as unknown as UserJSON;
|
63
65
|
|
64
66
|
beforeEach(() => {
|
65
|
-
service = new UserService();
|
67
|
+
service = new UserService(mockDB);
|
66
68
|
vi.clearAllMocks();
|
67
69
|
});
|
68
70
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { UserJSON } from '@clerk/backend';
|
2
2
|
|
3
3
|
import { UserModel } from '@/database/models/user';
|
4
|
-
import {
|
4
|
+
import { LobeChatDatabase } from '@/database/type';
|
5
5
|
import { initializeServerAnalytics } from '@/libs/analytics';
|
6
6
|
import { pino } from '@/libs/logger';
|
7
7
|
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
|
@@ -9,9 +9,15 @@ import { S3 } from '@/server/modules/S3';
|
|
9
9
|
import { AgentService } from '@/server/services/agent';
|
10
10
|
|
11
11
|
export class UserService {
|
12
|
+
private db: LobeChatDatabase;
|
13
|
+
|
14
|
+
constructor(db: LobeChatDatabase) {
|
15
|
+
this.db = db;
|
16
|
+
}
|
17
|
+
|
12
18
|
createUser = async (id: string, params: UserJSON) => {
|
13
19
|
// Check if user already exists
|
14
|
-
const res = await UserModel.findById(
|
20
|
+
const res = await UserModel.findById(this.db, id);
|
15
21
|
|
16
22
|
// If user already exists, skip creating a new user
|
17
23
|
if (res)
|
@@ -33,7 +39,7 @@ export class UserService {
|
|
33
39
|
/* ↑ cloud slot ↑ */
|
34
40
|
|
35
41
|
// 2. create user in database
|
36
|
-
await UserModel.createUser(
|
42
|
+
await UserModel.createUser(this.db, {
|
37
43
|
avatar: params.image_url,
|
38
44
|
clerkCreatedAt: new Date(params.created_at),
|
39
45
|
email: email?.email_address,
|
@@ -45,7 +51,7 @@ export class UserService {
|
|
45
51
|
});
|
46
52
|
|
47
53
|
// 3. Create an inbox session for the user
|
48
|
-
const agentService = new AgentService(
|
54
|
+
const agentService = new AgentService(this.db, id);
|
49
55
|
await agentService.createInbox();
|
50
56
|
|
51
57
|
/* ↓ cloud slot ↓ */
|
@@ -73,14 +79,14 @@ export class UserService {
|
|
73
79
|
};
|
74
80
|
|
75
81
|
deleteUser = async (id: string) => {
|
76
|
-
await UserModel.deleteUser(
|
82
|
+
await UserModel.deleteUser(this.db, id);
|
77
83
|
};
|
78
84
|
|
79
85
|
updateUser = async (id: string, params: UserJSON) => {
|
80
|
-
const userModel = new UserModel(
|
86
|
+
const userModel = new UserModel(this.db, id);
|
81
87
|
|
82
88
|
// Check if user already exists
|
83
|
-
const res = await UserModel.findById(
|
89
|
+
const res = await UserModel.findById(this.db, id);
|
84
90
|
|
85
91
|
// If user not exists, skip update the user
|
86
92
|
if (!res)
|
@@ -111,7 +117,7 @@ export class UserService {
|
|
111
117
|
};
|
112
118
|
|
113
119
|
getUserApiKeys = async (id: string) => {
|
114
|
-
return UserModel.getUserApiKeys(
|
120
|
+
return UserModel.getUserApiKeys(this.db, id, KeyVaultsGateKeeper.getUserKeyVaults);
|
115
121
|
};
|
116
122
|
|
117
123
|
getUserAvatar = async (id: string, image: string) => {
|
@@ -77,17 +77,13 @@ export function useDimensionControl() {
|
|
77
77
|
const aspectRatioOptions = useMemo(() => {
|
78
78
|
const modelOptions = paramsSchema?.aspectRatio?.enum || [];
|
79
79
|
|
80
|
-
//
|
81
|
-
|
80
|
+
// 如果 schema 里面有 aspectRatio 并且不为空,直接使用 schema 里面的选项
|
81
|
+
if (modelOptions.length > 0) {
|
82
|
+
return modelOptions;
|
83
|
+
}
|
82
84
|
|
83
|
-
//
|
84
|
-
|
85
|
-
if (!allOptions.includes(option)) {
|
86
|
-
allOptions.push(option);
|
87
|
-
}
|
88
|
-
});
|
89
|
-
|
90
|
-
return allOptions;
|
85
|
+
// 否则使用预设选项
|
86
|
+
return PRESET_ASPECT_RATIOS;
|
91
87
|
}, [paramsSchema]);
|
92
88
|
|
93
89
|
// 只要不是所有维度相关的控件都不显示,那么这个容器就应该显示
|