@lobehub/chat 1.15.6 → 1.15.8
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/CHANGELOG.md +50 -0
- package/README.md +6 -6
- package/README.zh-CN.md +6 -6
- package/docs/self-hosting/server-database/docker-compose.mdx +2 -2
- package/docs/self-hosting/server-database/docker-compose.zh-CN.mdx +2 -2
- package/locales/ar/knowledgeBase.json +1 -0
- package/locales/ar/ragEval.json +91 -0
- package/locales/bg-BG/knowledgeBase.json +1 -0
- package/locales/bg-BG/ragEval.json +91 -0
- package/locales/de-DE/knowledgeBase.json +1 -0
- package/locales/de-DE/ragEval.json +91 -0
- package/locales/en-US/knowledgeBase.json +1 -0
- package/locales/en-US/ragEval.json +91 -0
- package/locales/es-ES/knowledgeBase.json +1 -0
- package/locales/es-ES/ragEval.json +91 -0
- package/locales/fr-FR/knowledgeBase.json +1 -0
- package/locales/fr-FR/ragEval.json +91 -0
- package/locales/it-IT/knowledgeBase.json +1 -0
- package/locales/it-IT/ragEval.json +91 -0
- package/locales/ja-JP/knowledgeBase.json +1 -0
- package/locales/ja-JP/ragEval.json +91 -0
- package/locales/ko-KR/knowledgeBase.json +1 -0
- package/locales/ko-KR/ragEval.json +91 -0
- package/locales/nl-NL/knowledgeBase.json +1 -0
- package/locales/nl-NL/ragEval.json +91 -0
- package/locales/pl-PL/knowledgeBase.json +1 -0
- package/locales/pl-PL/ragEval.json +91 -0
- package/locales/pt-BR/knowledgeBase.json +1 -0
- package/locales/pt-BR/ragEval.json +91 -0
- package/locales/ru-RU/knowledgeBase.json +1 -0
- package/locales/ru-RU/ragEval.json +91 -0
- package/locales/tr-TR/knowledgeBase.json +1 -0
- package/locales/tr-TR/ragEval.json +91 -0
- package/locales/vi-VN/knowledgeBase.json +1 -0
- package/locales/vi-VN/ragEval.json +91 -0
- package/locales/zh-CN/knowledgeBase.json +1 -0
- package/locales/zh-CN/ragEval.json +91 -0
- package/locales/zh-TW/knowledgeBase.json +1 -0
- package/locales/zh-TW/ragEval.json +91 -0
- package/package.json +2 -1
- package/src/app/(main)/repos/[id]/@menu/Head/index.tsx +4 -13
- package/src/app/(main)/repos/[id]/@menu/Menu/index.tsx +30 -21
- package/src/app/(main)/repos/[id]/@menu/default.tsx +8 -2
- package/src/app/(main)/repos/[id]/evals/components/Container.tsx +25 -0
- package/src/app/(main)/repos/[id]/evals/components/Tabs.tsx +35 -0
- package/src/app/(main)/repos/[id]/evals/dataset/CreateDataset/CreateForm.tsx +72 -0
- package/src/app/(main)/repos/[id]/evals/dataset/CreateDataset/index.tsx +37 -0
- package/src/app/(main)/repos/[id]/evals/dataset/DatasetDetail/index.tsx +126 -0
- package/src/app/(main)/repos/[id]/evals/dataset/DatasetList/Item.tsx +59 -0
- package/src/app/(main)/repos/[id]/evals/dataset/DatasetList/index.tsx +32 -0
- package/src/app/(main)/repos/[id]/evals/dataset/EmptyGuide/index.tsx +33 -0
- package/src/app/(main)/repos/[id]/evals/dataset/page.tsx +47 -0
- package/src/app/(main)/repos/[id]/evals/evaluation/CreateEvaluation/CreateForm.tsx +93 -0
- package/src/app/(main)/repos/[id]/evals/evaluation/CreateEvaluation/index.tsx +28 -0
- package/src/app/(main)/repos/[id]/evals/evaluation/CreateEvaluation/useModal.tsx +39 -0
- package/src/app/(main)/repos/[id]/evals/evaluation/EmptyGuide/index.tsx +25 -0
- package/src/app/(main)/repos/[id]/evals/evaluation/EvaluationList/index.tsx +209 -0
- package/src/app/(main)/repos/[id]/evals/evaluation/page.tsx +32 -0
- package/src/app/(main)/repos/[id]/evals/layout.tsx +22 -0
- package/src/app/(main)/repos/[id]/evals/page.tsx +9 -0
- package/src/app/(main)/repos/[id]/evals/type.ts +5 -0
- package/src/app/(main)/repos/[id]/not-found.tsx +3 -0
- package/src/app/(main)/settings/llm/components/ProviderConfig/index.tsx +2 -2
- package/src/components/FileIcon/index.tsx +2 -2
- package/src/config/featureFlags/schema.ts +3 -1
- package/src/database/server/migrations/0008_add_rag_evals.sql +120 -0
- package/src/database/server/migrations/meta/0008_snapshot.json +3463 -0
- package/src/database/server/migrations/meta/_journal.json +7 -0
- package/src/database/server/models/file.ts +11 -2
- package/src/database/server/models/ragEval/dataset.ts +59 -0
- package/src/database/server/models/ragEval/datasetRecord.ts +87 -0
- package/src/database/server/models/ragEval/evaluation.ts +96 -0
- package/src/database/server/models/ragEval/evaluationRecord.ts +64 -0
- package/src/database/server/models/ragEval/index.ts +4 -0
- package/src/database/server/schemas/lobechat/asyncTask.ts +24 -0
- package/src/database/server/schemas/lobechat/file.ts +2 -18
- package/src/database/server/schemas/lobechat/index.ts +2 -0
- package/src/database/server/schemas/lobechat/ragEvals.ts +105 -0
- package/src/database/server/schemas/lobechat/relations.ts +2 -1
- package/src/libs/agent-runtime/types/chat.ts +3 -0
- package/src/libs/agent-runtime/utils/openaiCompatibleFactory/index.ts +3 -1
- package/src/libs/langchain/loaders/index.ts +1 -1
- package/src/locales/default/index.ts +2 -0
- package/src/locales/default/knowledgeBase.ts +1 -0
- package/src/locales/default/ragEval.ts +93 -0
- package/src/server/modules/S3/index.ts +11 -0
- package/src/server/routers/async/index.ts +2 -0
- package/src/server/routers/async/ragEval.ts +138 -0
- package/src/server/routers/lambda/index.ts +2 -1
- package/src/server/routers/lambda/ragEval.ts +296 -0
- package/src/services/ragEval.ts +67 -0
- package/src/services/upload.ts +11 -4
- package/src/store/file/slices/upload/action.ts +8 -6
- package/src/store/knowledgeBase/initialState.ts +3 -1
- package/src/store/knowledgeBase/slices/ragEval/actions/dataset.ts +88 -0
- package/src/store/knowledgeBase/slices/ragEval/actions/evaluation.ts +62 -0
- package/src/store/knowledgeBase/slices/ragEval/actions/index.ts +20 -0
- package/src/store/knowledgeBase/slices/ragEval/index.ts +2 -0
- package/src/store/knowledgeBase/slices/ragEval/initialState.ts +7 -0
- package/src/store/knowledgeBase/store.ts +9 -3
- package/src/store/serverConfig/selectors.test.ts +1 -0
- package/src/types/eval/dataset.ts +47 -0
- package/src/types/eval/evaluation.ts +53 -0
- package/src/types/eval/index.ts +3 -0
- package/src/types/eval/ragas.ts +9 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { asc, count, eq, ilike, inArray, notExists, sum } from 'drizzle-orm';
|
|
2
|
-
import { and, desc } from 'drizzle-orm/expressions';
|
|
1
|
+
import { asc, count, eq, ilike, inArray, notExists, or, sum } from 'drizzle-orm';
|
|
2
|
+
import { and, desc, like } from 'drizzle-orm/expressions';
|
|
3
3
|
|
|
4
4
|
import { serverDBEnv } from '@/config/db';
|
|
5
5
|
import { serverDB } from '@/database/server/core/db';
|
|
@@ -280,4 +280,13 @@ export class FileModel {
|
|
|
280
280
|
}
|
|
281
281
|
}
|
|
282
282
|
};
|
|
283
|
+
|
|
284
|
+
async findByNames(fileNames: string[]) {
|
|
285
|
+
return serverDB.query.files.findMany({
|
|
286
|
+
where: and(
|
|
287
|
+
or(...fileNames.map((name) => like(files.name, `${name}%`))),
|
|
288
|
+
eq(files.userId, this.userId),
|
|
289
|
+
),
|
|
290
|
+
});
|
|
291
|
+
}
|
|
283
292
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { and, desc, eq } from 'drizzle-orm';
|
|
2
|
+
|
|
3
|
+
import { serverDB } from '@/database/server';
|
|
4
|
+
import { NewEvalDatasetsItem, evalDatasets } from '@/database/server/schemas/lobechat';
|
|
5
|
+
import { RAGEvalDataSetItem } from '@/types/eval';
|
|
6
|
+
|
|
7
|
+
export class EvalDatasetModel {
|
|
8
|
+
private userId: string;
|
|
9
|
+
|
|
10
|
+
constructor(userId: string) {
|
|
11
|
+
this.userId = userId;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
create = async (params: NewEvalDatasetsItem) => {
|
|
15
|
+
const [result] = await serverDB
|
|
16
|
+
.insert(evalDatasets)
|
|
17
|
+
.values({ ...params, userId: this.userId })
|
|
18
|
+
.returning();
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
delete = async (id: number) => {
|
|
23
|
+
return serverDB
|
|
24
|
+
.delete(evalDatasets)
|
|
25
|
+
.where(and(eq(evalDatasets.id, id), eq(evalDatasets.userId, this.userId)));
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
query = async (knowledgeBaseId: string): Promise<RAGEvalDataSetItem[]> => {
|
|
29
|
+
return serverDB
|
|
30
|
+
.select({
|
|
31
|
+
createdAt: evalDatasets.createdAt,
|
|
32
|
+
description: evalDatasets.description,
|
|
33
|
+
id: evalDatasets.id,
|
|
34
|
+
name: evalDatasets.name,
|
|
35
|
+
updatedAt: evalDatasets.updatedAt,
|
|
36
|
+
})
|
|
37
|
+
.from(evalDatasets)
|
|
38
|
+
.where(
|
|
39
|
+
and(
|
|
40
|
+
eq(evalDatasets.userId, this.userId),
|
|
41
|
+
eq(evalDatasets.knowledgeBaseId, knowledgeBaseId),
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
.orderBy(desc(evalDatasets.createdAt));
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
findById = async (id: number) => {
|
|
48
|
+
return serverDB.query.evalDatasets.findFirst({
|
|
49
|
+
where: and(eq(evalDatasets.id, id), eq(evalDatasets.userId, this.userId)),
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
update = async (id: number, value: Partial<NewEvalDatasetsItem>) => {
|
|
54
|
+
return serverDB
|
|
55
|
+
.update(evalDatasets)
|
|
56
|
+
.set({ ...value, updatedAt: new Date() })
|
|
57
|
+
.where(and(eq(evalDatasets.id, id), eq(evalDatasets.userId, this.userId)));
|
|
58
|
+
};
|
|
59
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { and, eq, inArray } from 'drizzle-orm';
|
|
2
|
+
|
|
3
|
+
import { serverDB } from '@/database/server';
|
|
4
|
+
import {
|
|
5
|
+
NewEvalDatasetRecordsItem,
|
|
6
|
+
evalDatasetRecords,
|
|
7
|
+
files,
|
|
8
|
+
} from '@/database/server/schemas/lobechat';
|
|
9
|
+
import { EvalDatasetRecordRefFile } from '@/types/eval';
|
|
10
|
+
|
|
11
|
+
export class EvalDatasetRecordModel {
|
|
12
|
+
private userId: string;
|
|
13
|
+
|
|
14
|
+
constructor(userId: string) {
|
|
15
|
+
this.userId = userId;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
create = async (params: NewEvalDatasetRecordsItem) => {
|
|
19
|
+
const [result] = await serverDB
|
|
20
|
+
.insert(evalDatasetRecords)
|
|
21
|
+
.values({ ...params, userId: this.userId })
|
|
22
|
+
.returning();
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
batchCreate = async (params: NewEvalDatasetRecordsItem[]) => {
|
|
27
|
+
const [result] = await serverDB
|
|
28
|
+
.insert(evalDatasetRecords)
|
|
29
|
+
.values(params.map((item) => ({ ...item, userId: this.userId })))
|
|
30
|
+
.returning();
|
|
31
|
+
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
delete = async (id: number) => {
|
|
36
|
+
return serverDB
|
|
37
|
+
.delete(evalDatasetRecords)
|
|
38
|
+
.where(and(eq(evalDatasetRecords.id, id), eq(evalDatasetRecords.userId, this.userId)));
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
query = async (datasetId: number) => {
|
|
42
|
+
const list = await serverDB.query.evalDatasetRecords.findMany({
|
|
43
|
+
where: and(
|
|
44
|
+
eq(evalDatasetRecords.datasetId, datasetId),
|
|
45
|
+
eq(evalDatasetRecords.userId, this.userId),
|
|
46
|
+
),
|
|
47
|
+
});
|
|
48
|
+
const fileList = list.flatMap((item) => item.referenceFiles).filter(Boolean) as string[];
|
|
49
|
+
|
|
50
|
+
const fileItems = await serverDB
|
|
51
|
+
.select({ fileType: files.fileType, id: files.id, name: files.name })
|
|
52
|
+
.from(files)
|
|
53
|
+
.where(and(inArray(files.id, fileList), eq(files.userId, this.userId)))
|
|
54
|
+
.execute();
|
|
55
|
+
|
|
56
|
+
return list.map((item) => {
|
|
57
|
+
return {
|
|
58
|
+
...item,
|
|
59
|
+
referenceFiles: (item.referenceFiles?.map((fileId) => {
|
|
60
|
+
return fileItems.find((file) => file.id === fileId);
|
|
61
|
+
}) || []) as EvalDatasetRecordRefFile[],
|
|
62
|
+
};
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
findByDatasetId = async (datasetId: number) => {
|
|
67
|
+
return serverDB.query.evalDatasetRecords.findMany({
|
|
68
|
+
where: and(
|
|
69
|
+
eq(evalDatasetRecords.datasetId, datasetId),
|
|
70
|
+
eq(evalDatasetRecords.userId, this.userId),
|
|
71
|
+
),
|
|
72
|
+
});
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
findById = async (id: number) => {
|
|
76
|
+
return serverDB.query.evalDatasetRecords.findFirst({
|
|
77
|
+
where: and(eq(evalDatasetRecords.id, id), eq(evalDatasetRecords.userId, this.userId)),
|
|
78
|
+
});
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
update = async (id: number, value: Partial<NewEvalDatasetRecordsItem>) => {
|
|
82
|
+
return serverDB
|
|
83
|
+
.update(evalDatasetRecords)
|
|
84
|
+
.set(value)
|
|
85
|
+
.where(and(eq(evalDatasetRecords.id, id), eq(evalDatasetRecords.userId, this.userId)));
|
|
86
|
+
};
|
|
87
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { SQL, and, count, desc, eq, inArray } from 'drizzle-orm';
|
|
2
|
+
|
|
3
|
+
import { serverDB } from '@/database/server';
|
|
4
|
+
import {
|
|
5
|
+
NewEvalEvaluationItem,
|
|
6
|
+
evalDatasets,
|
|
7
|
+
evalEvaluation,
|
|
8
|
+
evaluationRecords,
|
|
9
|
+
} from '@/database/server/schemas/lobechat';
|
|
10
|
+
import { EvalEvaluationStatus, RAGEvalEvaluationItem } from '@/types/eval';
|
|
11
|
+
|
|
12
|
+
export class EvalEvaluationModel {
|
|
13
|
+
private userId: string;
|
|
14
|
+
|
|
15
|
+
constructor(userId: string) {
|
|
16
|
+
this.userId = userId;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
create = async (params: NewEvalEvaluationItem) => {
|
|
20
|
+
const [result] = await serverDB
|
|
21
|
+
.insert(evalEvaluation)
|
|
22
|
+
.values({ ...params, userId: this.userId })
|
|
23
|
+
.returning();
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
delete = async (id: number) => {
|
|
28
|
+
return serverDB
|
|
29
|
+
.delete(evalEvaluation)
|
|
30
|
+
.where(and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)));
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
queryByKnowledgeBaseId = async (knowledgeBaseId: string) => {
|
|
34
|
+
const evaluations = await serverDB
|
|
35
|
+
.select({
|
|
36
|
+
createdAt: evalEvaluation.createdAt,
|
|
37
|
+
dataset: {
|
|
38
|
+
id: evalDatasets.id,
|
|
39
|
+
name: evalDatasets.name,
|
|
40
|
+
},
|
|
41
|
+
evalRecordsUrl: evalEvaluation.evalRecordsUrl,
|
|
42
|
+
id: evalEvaluation.id,
|
|
43
|
+
name: evalEvaluation.name,
|
|
44
|
+
status: evalEvaluation.status,
|
|
45
|
+
updatedAt: evalEvaluation.updatedAt,
|
|
46
|
+
})
|
|
47
|
+
.from(evalEvaluation)
|
|
48
|
+
.leftJoin(evalDatasets, eq(evalDatasets.id, evalEvaluation.datasetId))
|
|
49
|
+
.orderBy(desc(evalEvaluation.createdAt))
|
|
50
|
+
.where(
|
|
51
|
+
and(
|
|
52
|
+
eq(evalEvaluation.userId, this.userId),
|
|
53
|
+
eq(evalEvaluation.knowledgeBaseId, knowledgeBaseId),
|
|
54
|
+
),
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
// 然后查询每个评估的记录统计
|
|
58
|
+
const evaluationIds = evaluations.map((evals) => evals.id);
|
|
59
|
+
|
|
60
|
+
const recordStats = await serverDB
|
|
61
|
+
.select({
|
|
62
|
+
evaluationId: evaluationRecords.evaluationId,
|
|
63
|
+
success: count(evaluationRecords.status).if(
|
|
64
|
+
eq(evaluationRecords.status, EvalEvaluationStatus.Success),
|
|
65
|
+
) as SQL<number>,
|
|
66
|
+
total: count(),
|
|
67
|
+
})
|
|
68
|
+
.from(evaluationRecords)
|
|
69
|
+
.where(inArray(evaluationRecords.evaluationId, evaluationIds))
|
|
70
|
+
.groupBy(evaluationRecords.evaluationId);
|
|
71
|
+
|
|
72
|
+
return evaluations.map((evaluation) => {
|
|
73
|
+
const stats = recordStats.find((stat) => stat.evaluationId === evaluation.id);
|
|
74
|
+
|
|
75
|
+
return {
|
|
76
|
+
...evaluation,
|
|
77
|
+
recordsStats: stats
|
|
78
|
+
? { success: Number(stats.success), total: Number(stats.total) }
|
|
79
|
+
: { success: 0, total: 0 },
|
|
80
|
+
} as RAGEvalEvaluationItem;
|
|
81
|
+
});
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
findById = async (id: number) => {
|
|
85
|
+
return serverDB.query.evalEvaluation.findFirst({
|
|
86
|
+
where: and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)),
|
|
87
|
+
});
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
update = async (id: number, value: Partial<NewEvalEvaluationItem>) => {
|
|
91
|
+
return serverDB
|
|
92
|
+
.update(evalEvaluation)
|
|
93
|
+
.set(value)
|
|
94
|
+
.where(and(eq(evalEvaluation.id, id), eq(evalEvaluation.userId, this.userId)));
|
|
95
|
+
};
|
|
96
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { and, eq } from 'drizzle-orm';
|
|
2
|
+
|
|
3
|
+
import { serverDB } from '@/database/server';
|
|
4
|
+
import { NewEvaluationRecordsItem, evaluationRecords } from '@/database/server/schemas/lobechat';
|
|
5
|
+
|
|
6
|
+
export class EvaluationRecordModel {
|
|
7
|
+
private userId: string;
|
|
8
|
+
|
|
9
|
+
constructor(userId: string) {
|
|
10
|
+
this.userId = userId;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
create = async (params: NewEvaluationRecordsItem) => {
|
|
14
|
+
const [result] = await serverDB
|
|
15
|
+
.insert(evaluationRecords)
|
|
16
|
+
.values({ ...params, userId: this.userId })
|
|
17
|
+
.returning();
|
|
18
|
+
return result;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
batchCreate = async (params: NewEvaluationRecordsItem[]) => {
|
|
22
|
+
return serverDB
|
|
23
|
+
.insert(evaluationRecords)
|
|
24
|
+
.values(params.map((item) => ({ ...item, userId: this.userId })))
|
|
25
|
+
.returning();
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
delete = async (id: number) => {
|
|
29
|
+
return serverDB
|
|
30
|
+
.delete(evaluationRecords)
|
|
31
|
+
.where(and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)));
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
query = async (reportId: number) => {
|
|
35
|
+
return serverDB.query.evaluationRecords.findMany({
|
|
36
|
+
where: and(
|
|
37
|
+
eq(evaluationRecords.evaluationId, reportId),
|
|
38
|
+
eq(evaluationRecords.userId, this.userId),
|
|
39
|
+
),
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
findById = async (id: number) => {
|
|
44
|
+
return serverDB.query.evaluationRecords.findFirst({
|
|
45
|
+
where: and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)),
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
findByEvaluationId = async (evaluationId: number) => {
|
|
50
|
+
return serverDB.query.evaluationRecords.findMany({
|
|
51
|
+
where: and(
|
|
52
|
+
eq(evaluationRecords.evaluationId, evaluationId),
|
|
53
|
+
eq(evaluationRecords.userId, this.userId),
|
|
54
|
+
),
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
update = async (id: number, value: Partial<NewEvaluationRecordsItem>) => {
|
|
59
|
+
return serverDB
|
|
60
|
+
.update(evaluationRecords)
|
|
61
|
+
.set(value)
|
|
62
|
+
.where(and(eq(evaluationRecords.id, id), eq(evaluationRecords.userId, this.userId)));
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
2
|
+
import { integer, jsonb, pgTable, text, uuid } from 'drizzle-orm/pg-core';
|
|
3
|
+
|
|
4
|
+
import { createdAt, updatedAt } from './_helpers';
|
|
5
|
+
import { users } from './user';
|
|
6
|
+
|
|
7
|
+
export const asyncTasks = pgTable('async_tasks', {
|
|
8
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
9
|
+
type: text('type'),
|
|
10
|
+
|
|
11
|
+
status: text('status'),
|
|
12
|
+
error: jsonb('error'),
|
|
13
|
+
|
|
14
|
+
userId: text('user_id')
|
|
15
|
+
.references(() => users.id, { onDelete: 'cascade' })
|
|
16
|
+
.notNull(),
|
|
17
|
+
duration: integer('duration'),
|
|
18
|
+
|
|
19
|
+
createdAt: createdAt(),
|
|
20
|
+
updatedAt: updatedAt(),
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export type NewAsyncTaskItem = typeof asyncTasks.$inferInsert;
|
|
24
|
+
export type AsyncTaskSelectItem = typeof asyncTasks.$inferSelect;
|
|
@@ -11,28 +11,12 @@ import {
|
|
|
11
11
|
} from 'drizzle-orm/pg-core';
|
|
12
12
|
import { createInsertSchema } from 'drizzle-zod';
|
|
13
13
|
|
|
14
|
-
import { chunks } from '@/database/server/schemas/lobechat/rag';
|
|
15
|
-
|
|
16
14
|
import { idGenerator } from '../../utils/idGenerator';
|
|
17
15
|
import { createdAt, updatedAt } from './_helpers';
|
|
16
|
+
import { asyncTasks } from './asyncTask';
|
|
17
|
+
import { chunks } from './rag';
|
|
18
18
|
import { users } from './user';
|
|
19
19
|
|
|
20
|
-
export const asyncTasks = pgTable('async_tasks', {
|
|
21
|
-
id: uuid('id').defaultRandom().primaryKey(),
|
|
22
|
-
type: text('type'),
|
|
23
|
-
status: text('status'),
|
|
24
|
-
error: jsonb('error'),
|
|
25
|
-
userId: text('user_id')
|
|
26
|
-
.references(() => users.id, { onDelete: 'cascade' })
|
|
27
|
-
.notNull(),
|
|
28
|
-
duration: integer('duration'),
|
|
29
|
-
createdAt: createdAt(),
|
|
30
|
-
updatedAt: updatedAt(),
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
export type NewAsyncTaskItem = typeof asyncTasks.$inferInsert;
|
|
34
|
-
export type AsyncTaskSelectItem = typeof asyncTasks.$inferSelect;
|
|
35
|
-
|
|
36
20
|
export const globalFiles = pgTable('global_files', {
|
|
37
21
|
hashId: varchar('hash_id', { length: 64 }).primaryKey(),
|
|
38
22
|
fileType: varchar('file_type', { length: 255 }).notNull(),
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
export * from './agent';
|
|
2
|
+
export * from './asyncTask';
|
|
2
3
|
export * from './discover';
|
|
3
4
|
export * from './file';
|
|
4
5
|
export * from './message';
|
|
5
6
|
export * from './nextauth';
|
|
6
7
|
export * from './rag';
|
|
8
|
+
export * from './ragEvals';
|
|
7
9
|
export * from './relations';
|
|
8
10
|
export * from './session';
|
|
9
11
|
export * from './topic';
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/* eslint-disable sort-keys-fix/sort-keys-fix */
|
|
2
|
+
import { integer, jsonb, pgTable, text, uuid } from 'drizzle-orm/pg-core';
|
|
3
|
+
|
|
4
|
+
import { DEFAULT_EMBEDDING_MODEL, DEFAULT_MODEL } from '@/const/settings';
|
|
5
|
+
import { EvalEvaluationStatus } from '@/types/eval';
|
|
6
|
+
|
|
7
|
+
import { createdAt, updatedAt } from './_helpers';
|
|
8
|
+
import { knowledgeBases } from './file';
|
|
9
|
+
import { embeddings } from './rag';
|
|
10
|
+
import { users } from './user';
|
|
11
|
+
|
|
12
|
+
export const evalDatasets = pgTable('rag_eval_datasets', {
|
|
13
|
+
id: integer('id').generatedAlwaysAsIdentity({ startWith: 30_000 }).primaryKey(),
|
|
14
|
+
|
|
15
|
+
description: text('description'),
|
|
16
|
+
name: text('name').notNull(),
|
|
17
|
+
|
|
18
|
+
knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, {
|
|
19
|
+
onDelete: 'cascade',
|
|
20
|
+
}),
|
|
21
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
|
|
22
|
+
|
|
23
|
+
updatedAt: updatedAt(),
|
|
24
|
+
createdAt: createdAt(),
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export type NewEvalDatasetsItem = typeof evalDatasets.$inferInsert;
|
|
28
|
+
export type EvalDatasetsSelectItem = typeof evalDatasets.$inferSelect;
|
|
29
|
+
|
|
30
|
+
export const evalDatasetRecords = pgTable('rag_eval_dataset_records', {
|
|
31
|
+
id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
|
|
32
|
+
datasetId: integer('dataset_id')
|
|
33
|
+
.references(() => evalDatasets.id, { onDelete: 'cascade' })
|
|
34
|
+
.notNull(),
|
|
35
|
+
|
|
36
|
+
ideal: text('ideal'),
|
|
37
|
+
question: text('question'),
|
|
38
|
+
referenceFiles: text('reference_files').array(),
|
|
39
|
+
metadata: jsonb('metadata'),
|
|
40
|
+
|
|
41
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
|
|
42
|
+
createdAt: createdAt(),
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export type NewEvalDatasetRecordsItem = typeof evalDatasetRecords.$inferInsert;
|
|
46
|
+
export type EvalDatasetRecordsSelectItem = typeof evalDatasetRecords.$inferSelect;
|
|
47
|
+
|
|
48
|
+
export const evalEvaluation = pgTable('rag_eval_evaluations', {
|
|
49
|
+
id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
|
|
50
|
+
name: text('name').notNull(),
|
|
51
|
+
description: text('description'),
|
|
52
|
+
|
|
53
|
+
evalRecordsUrl: text('eval_records_url'),
|
|
54
|
+
status: text('status').$defaultFn(() => EvalEvaluationStatus.Pending),
|
|
55
|
+
error: jsonb('error'),
|
|
56
|
+
|
|
57
|
+
datasetId: integer('dataset_id')
|
|
58
|
+
.references(() => evalDatasets.id, { onDelete: 'cascade' })
|
|
59
|
+
.notNull(),
|
|
60
|
+
knowledgeBaseId: text('knowledge_base_id').references(() => knowledgeBases.id, {
|
|
61
|
+
onDelete: 'cascade',
|
|
62
|
+
}),
|
|
63
|
+
languageModel: text('language_model').$defaultFn(() => DEFAULT_MODEL),
|
|
64
|
+
embeddingModel: text('embedding_model').$defaultFn(() => DEFAULT_EMBEDDING_MODEL),
|
|
65
|
+
|
|
66
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
|
|
67
|
+
createdAt: createdAt(),
|
|
68
|
+
updatedAt: updatedAt(),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
export type NewEvalEvaluationItem = typeof evalEvaluation.$inferInsert;
|
|
72
|
+
export type EvalEvaluationSelectItem = typeof evalEvaluation.$inferSelect;
|
|
73
|
+
|
|
74
|
+
export const evaluationRecords = pgTable('rag_eval_evaluation_records', {
|
|
75
|
+
id: integer('id').generatedAlwaysAsIdentity().primaryKey(),
|
|
76
|
+
|
|
77
|
+
question: text('question').notNull(),
|
|
78
|
+
answer: text('answer'),
|
|
79
|
+
context: text('context').array(),
|
|
80
|
+
ideal: text('ideal'),
|
|
81
|
+
|
|
82
|
+
status: text('status').$defaultFn(() => EvalEvaluationStatus.Pending),
|
|
83
|
+
error: jsonb('error'),
|
|
84
|
+
|
|
85
|
+
languageModel: text('language_model'),
|
|
86
|
+
embeddingModel: text('embedding_model'),
|
|
87
|
+
|
|
88
|
+
questionEmbeddingId: uuid('question_embedding_id').references(() => embeddings.id, {
|
|
89
|
+
onDelete: 'set null',
|
|
90
|
+
}),
|
|
91
|
+
|
|
92
|
+
duration: integer('duration'),
|
|
93
|
+
datasetRecordId: integer('dataset_record_id')
|
|
94
|
+
.references(() => evalDatasetRecords.id, { onDelete: 'cascade' })
|
|
95
|
+
.notNull(),
|
|
96
|
+
evaluationId: integer('evaluation_id')
|
|
97
|
+
.references(() => evalEvaluation.id, { onDelete: 'cascade' })
|
|
98
|
+
.notNull(),
|
|
99
|
+
|
|
100
|
+
userId: text('user_id').references(() => users.id, { onDelete: 'cascade' }),
|
|
101
|
+
createdAt: createdAt(),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export type NewEvaluationRecordsItem = typeof evaluationRecords.$inferInsert;
|
|
105
|
+
export type EvaluationRecordsSelectItem = typeof evaluationRecords.$inferSelect;
|
|
@@ -3,8 +3,9 @@ import { relations } from 'drizzle-orm';
|
|
|
3
3
|
import { pgTable, primaryKey, text } from 'drizzle-orm/pg-core';
|
|
4
4
|
|
|
5
5
|
import { agents, agentsFiles, agentsKnowledgeBases } from './agent';
|
|
6
|
+
import { asyncTasks } from './asyncTask';
|
|
6
7
|
import { agentsTags, plugins, pluginsTags, tags } from './discover';
|
|
7
|
-
import {
|
|
8
|
+
import { files, knowledgeBases } from './file';
|
|
8
9
|
import { messages, messagesFiles } from './message';
|
|
9
10
|
import { unstructuredChunks } from './rag';
|
|
10
11
|
import { sessionGroups, sessions } from './session';
|
|
@@ -72,6 +72,8 @@ export interface ChatStreamPayload {
|
|
|
72
72
|
* @default openai
|
|
73
73
|
*/
|
|
74
74
|
provider?: string;
|
|
75
|
+
|
|
76
|
+
responseMode?: 'streamText' | 'json';
|
|
75
77
|
/**
|
|
76
78
|
* @title 是否开启流式请求
|
|
77
79
|
* @default true
|
|
@@ -84,6 +86,7 @@ export interface ChatStreamPayload {
|
|
|
84
86
|
temperature: number;
|
|
85
87
|
tool_choice?: string;
|
|
86
88
|
tools?: ChatCompletionTool[];
|
|
89
|
+
|
|
87
90
|
/**
|
|
88
91
|
* @title 控制生成文本中最高概率的单个令牌
|
|
89
92
|
* @default 1
|
|
@@ -149,7 +149,7 @@ export const LobeOpenAICompatibleFactory = <T extends Record<string, any> = any>
|
|
|
149
149
|
this.baseURL = this.client.baseURL;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
async chat(payload: ChatStreamPayload, options?: ChatCompetitionOptions) {
|
|
152
|
+
async chat({ responseMode, ...payload }: ChatStreamPayload, options?: ChatCompetitionOptions) {
|
|
153
153
|
try {
|
|
154
154
|
const postPayload = chatCompletion?.handlePayload
|
|
155
155
|
? chatCompletion.handlePayload(payload, this._options)
|
|
@@ -186,6 +186,8 @@ export const LobeOpenAICompatibleFactory = <T extends Record<string, any> = any>
|
|
|
186
186
|
debugResponse(response);
|
|
187
187
|
}
|
|
188
188
|
|
|
189
|
+
if (responseMode === 'json') return Response.json(response);
|
|
190
|
+
|
|
189
191
|
const stream = transformResponseToStream(response as unknown as OpenAI.ChatCompletion);
|
|
190
192
|
|
|
191
193
|
return StreamingResponse(OpenAIStream(stream, options?.callback), {
|
|
@@ -27,7 +27,7 @@ export class ChunkingLoader {
|
|
|
27
27
|
const fileBlob = new Blob([Buffer.from(content)]);
|
|
28
28
|
const txt = this.uint8ArrayToString(content);
|
|
29
29
|
|
|
30
|
-
const type = this.getType(filename);
|
|
30
|
+
const type = this.getType(filename?.toLowerCase());
|
|
31
31
|
|
|
32
32
|
switch (type) {
|
|
33
33
|
case 'code': {
|
|
@@ -13,6 +13,7 @@ import migration from './migration';
|
|
|
13
13
|
import modelProvider from './modelProvider';
|
|
14
14
|
import plugin from './plugin';
|
|
15
15
|
import portal from './portal';
|
|
16
|
+
import ragEval from './ragEval';
|
|
16
17
|
import setting from './setting';
|
|
17
18
|
import welcome from './welcome';
|
|
18
19
|
|
|
@@ -31,6 +32,7 @@ const resources = {
|
|
|
31
32
|
modelProvider,
|
|
32
33
|
plugin,
|
|
33
34
|
portal,
|
|
35
|
+
ragEval,
|
|
34
36
|
setting,
|
|
35
37
|
tool,
|
|
36
38
|
welcome,
|