@drax/ai-back 3.0.0 → 3.17.0

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.
Files changed (87) hide show
  1. package/dist/config/OpenAiConfig.js +1 -0
  2. package/dist/controllers/AIController.js +150 -0
  3. package/dist/controllers/AICrudController.js +150 -0
  4. package/dist/controllers/AIGenericController.js +83 -0
  5. package/dist/controllers/AILogController.js +18 -0
  6. package/dist/factory/AiProviderFactory.js +1 -1
  7. package/dist/factory/OpenAiProviderFactory.js +2 -1
  8. package/dist/factory/services/AILogServiceFactory.js +30 -0
  9. package/dist/index.js +14 -1
  10. package/dist/interfaces/IAILog.js +1 -0
  11. package/dist/interfaces/IAILogRepository.js +1 -0
  12. package/dist/models/AILogModel.js +50 -0
  13. package/dist/permissions/AILogPermissions.js +10 -0
  14. package/dist/permissions/AIPermissions.js +7 -0
  15. package/dist/providers/OpenAiProvider.js +176 -26
  16. package/dist/repository/mongo/AILogMongoRepository.js +13 -0
  17. package/dist/repository/sqlite/AILogSqliteRepository.js +45 -0
  18. package/dist/routes/AILogRoutes.js +21 -0
  19. package/dist/routes/AIRoutes.js +10 -0
  20. package/dist/schemas/AILogSchema.js +44 -0
  21. package/dist/services/AILogService.js +9 -0
  22. package/package.json +8 -2
  23. package/src/config/OpenAiConfig.ts +1 -0
  24. package/src/controllers/AICrudController.ts +168 -0
  25. package/src/controllers/AIGenericController.ts +97 -0
  26. package/src/controllers/AILogController.ts +29 -0
  27. package/src/factory/AiProviderFactory.ts +1 -1
  28. package/src/factory/OpenAiProviderFactory.ts +4 -2
  29. package/src/factory/services/AILogServiceFactory.ts +41 -0
  30. package/src/index.ts +47 -1
  31. package/src/interfaces/IAILogRepository.ts +11 -0
  32. package/src/interfaces/IAIProvider.ts +48 -2
  33. package/src/models/AILogModel.ts +65 -0
  34. package/src/permissions/AILogPermissions.ts +14 -0
  35. package/src/permissions/AIPermissions.ts +11 -0
  36. package/src/providers/OpenAiProvider.ts +231 -29
  37. package/src/repository/mongo/AILogMongoRepository.ts +22 -0
  38. package/src/repository/sqlite/AILogSqliteRepository.ts +53 -0
  39. package/src/routes/AILogRoutes.ts +38 -0
  40. package/src/routes/AIRoutes.ts +18 -0
  41. package/src/schemas/AILogSchema.ts +52 -0
  42. package/src/services/AILogService.ts +20 -0
  43. package/test/OpenAiProvider.test.ts +91 -0
  44. package/tsconfig.tsbuildinfo +1 -1
  45. package/types/config/OpenAiConfig.d.ts +2 -1
  46. package/types/config/OpenAiConfig.d.ts.map +1 -1
  47. package/types/controllers/AIController.d.ts +25 -0
  48. package/types/controllers/AIController.d.ts.map +1 -0
  49. package/types/controllers/AICrudController.d.ts +25 -0
  50. package/types/controllers/AICrudController.d.ts.map +1 -0
  51. package/types/controllers/AIGenericController.d.ts +7 -0
  52. package/types/controllers/AIGenericController.d.ts.map +1 -0
  53. package/types/controllers/AILogController.d.ts +8 -0
  54. package/types/controllers/AILogController.d.ts.map +1 -0
  55. package/types/factory/AiProviderFactory.d.ts +1 -1
  56. package/types/factory/AiProviderFactory.d.ts.map +1 -1
  57. package/types/factory/OpenAiProviderFactory.d.ts.map +1 -1
  58. package/types/factory/services/AILogServiceFactory.d.ts +8 -0
  59. package/types/factory/services/AILogServiceFactory.d.ts.map +1 -0
  60. package/types/index.d.ts +17 -3
  61. package/types/index.d.ts.map +1 -1
  62. package/types/interfaces/IAILog.d.ts +77 -0
  63. package/types/interfaces/IAILog.d.ts.map +1 -0
  64. package/types/interfaces/IAILogRepository.d.ts +6 -0
  65. package/types/interfaces/IAILogRepository.d.ts.map +1 -0
  66. package/types/interfaces/IAIProvider.d.ts +32 -2
  67. package/types/interfaces/IAIProvider.d.ts.map +1 -1
  68. package/types/models/AILogModel.d.ts +15 -0
  69. package/types/models/AILogModel.d.ts.map +1 -0
  70. package/types/permissions/AILogPermissions.d.ts +10 -0
  71. package/types/permissions/AILogPermissions.d.ts.map +1 -0
  72. package/types/permissions/AIPermissions.d.ts +7 -0
  73. package/types/permissions/AIPermissions.d.ts.map +1 -0
  74. package/types/providers/OpenAiProvider.d.ts +71 -2
  75. package/types/providers/OpenAiProvider.d.ts.map +1 -1
  76. package/types/repository/mongo/AILogMongoRepository.d.ts +9 -0
  77. package/types/repository/mongo/AILogMongoRepository.d.ts.map +1 -0
  78. package/types/repository/sqlite/AILogSqliteRepository.d.ts +23 -0
  79. package/types/repository/sqlite/AILogSqliteRepository.d.ts.map +1 -0
  80. package/types/routes/AILogRoutes.d.ts +4 -0
  81. package/types/routes/AILogRoutes.d.ts.map +1 -0
  82. package/types/routes/AIRoutes.d.ts +4 -0
  83. package/types/routes/AIRoutes.d.ts.map +1 -0
  84. package/types/schemas/AILogSchema.d.ts +81 -0
  85. package/types/schemas/AILogSchema.d.ts.map +1 -0
  86. package/types/services/AILogService.d.ts +10 -0
  87. package/types/services/AILogService.d.ts.map +1 -0
@@ -0,0 +1,97 @@
1
+ import {z} from "zod";
2
+ import {CommonController} from "@drax/common-back";
3
+ import AiProviderFactory from "../factory/AiProviderFactory.js";
4
+ import AIPermissions from "../permissions/AIPermissions.js";
5
+ import type {IPromptParams} from "../interfaces/IAIProvider.js";
6
+
7
+ const PromptImageSchema = z.object({
8
+ url: z.string().min(1),
9
+ detail: z.enum(["auto", "low", "high"]).optional(),
10
+ })
11
+
12
+ const PromptContentPartSchema = z.discriminatedUnion("type", [
13
+ z.object({
14
+ type: z.literal("text"),
15
+ text: z.string(),
16
+ }),
17
+ z.object({
18
+ type: z.literal("image"),
19
+ imageUrl: z.string().min(1),
20
+ detail: z.enum(["auto", "low", "high"]).optional(),
21
+ }),
22
+ ])
23
+
24
+ const PromptMessageSchema = z.object({
25
+ role: z.enum(["user", "assistant", "system"]),
26
+ content: z.union([
27
+ z.string(),
28
+ z.array(PromptContentPartSchema),
29
+ ]),
30
+ })
31
+
32
+ const PromptMemorySchema = z.object({
33
+ key: z.string().min(1),
34
+ value: z.string(),
35
+ })
36
+
37
+ const PromptInputFileSchema = z.object({
38
+ filename: z.string().optional(),
39
+ filepath: z.string().optional(),
40
+ size: z.number().nullable().optional(),
41
+ mimetype: z.string().optional(),
42
+ url: z.string().optional(),
43
+ })
44
+
45
+ const GenericPromptRequestSchema = z.object({
46
+ systemPrompt: z.string().min(1),
47
+ userInput: z.string().optional(),
48
+ userImages: z.array(PromptImageSchema).optional(),
49
+ inputFiles: z.array(PromptInputFileSchema).optional(),
50
+ userContent: z.array(PromptContentPartSchema).optional(),
51
+ history: z.array(PromptMessageSchema).optional(),
52
+ memory: z.array(PromptMemorySchema).optional(),
53
+ memoryHeader: z.string().optional(),
54
+ knowledgeBase: z.array(z.string()).optional(),
55
+ knowledgeBaseHeader: z.string().optional(),
56
+ jsonSchema: z.record(z.string(), z.any()).or(z.array(z.any())).optional(),
57
+ model: z.string().optional(),
58
+ operationTitle: z.string().optional(),
59
+ operationGroup: z.string().optional(),
60
+ })
61
+
62
+ class AIGenericController extends CommonController {
63
+
64
+ async prompt(request, reply) {
65
+ try {
66
+ request.rbac.assertPermission(AIPermissions.Prompt)
67
+
68
+ const input = GenericPromptRequestSchema.parse(request.body ?? {})
69
+ const aiProvider = AiProviderFactory.instance()
70
+ const promptInput: IPromptParams = {
71
+ ...(input as IPromptParams),
72
+ operationTitle: input.operationTitle ?? "generic-ai-prompt",
73
+ operationGroup: input.operationGroup ?? "generic-ai-prompt",
74
+ ip: request.ip,
75
+ userAgent: request.headers["user-agent"],
76
+ tenant: request.rbac?.tenantId ?? null,
77
+ user: request.rbac?.userId ?? null,
78
+ }
79
+
80
+ const response = await aiProvider.prompt(promptInput)
81
+
82
+ return reply.send(response)
83
+ } catch (e: any) {
84
+ if (e?.name === "ZodError") {
85
+ return reply.status(400).send({
86
+ message: e?.message || "AI prompt validation error",
87
+ })
88
+ }
89
+
90
+ this.handleError(e, reply)
91
+ }
92
+ }
93
+
94
+ }
95
+
96
+ export default AIGenericController;
97
+ export {AIGenericController};
@@ -0,0 +1,29 @@
1
+
2
+ import AILogServiceFactory from "../factory/services/AILogServiceFactory.js";
3
+ import {AbstractFastifyController} from "@drax/crud-back";
4
+ import AILogPermissions from "../permissions/AILogPermissions.js";
5
+ import type {IAILog, IAILogBase} from "@drax/ai-share";
6
+
7
+ class AILogController extends AbstractFastifyController<IAILog, IAILogBase, IAILogBase> {
8
+
9
+ constructor() {
10
+ super(AILogServiceFactory.instance, AILogPermissions)
11
+ this.tenantField = "tenant";
12
+ this.userField = "user";
13
+
14
+ this.tenantFilter = true;
15
+ this.tenantSetter = true;
16
+ this.tenantAssert = true;
17
+
18
+ this.userFilter = true;
19
+ this.userSetter = true;
20
+ this.userAssert = true;
21
+ }
22
+
23
+ }
24
+
25
+ export default AILogController;
26
+ export {
27
+ AILogController
28
+ }
29
+
@@ -4,7 +4,7 @@ import OpenAiProviderFactory from "./OpenAiProviderFactory.js";
4
4
  class AiProviderFactory {
5
5
  private static singleton: IAIProvider;
6
6
 
7
- public static instance(provider: string): IAIProvider {
7
+ public static instance(provider: string = 'OpenAi'): IAIProvider {
8
8
  if (!AiProviderFactory.singleton) {
9
9
  switch (provider) {
10
10
  case 'OpenAi':
@@ -2,6 +2,7 @@ import {DraxConfig} from "@drax/common-back";
2
2
  import OpenAiConfig from "../config/OpenAiConfig.js";
3
3
  import type {IAIProvider} from "../interfaces/IAIProvider"
4
4
  import OpenAiProvider from "../providers/OpenAiProvider.js";
5
+ import AILogServiceFactory from "./services/AILogServiceFactory.js";
5
6
 
6
7
  class OpenAiProviderFactory {
7
8
  private static singleton: IAIProvider;
@@ -10,7 +11,9 @@ class OpenAiProviderFactory {
10
11
  if (!OpenAiProviderFactory.singleton) {
11
12
  OpenAiProviderFactory.singleton = new OpenAiProvider(
12
13
  DraxConfig.getOrLoad(OpenAiConfig.OpenAiApiKey),
13
- DraxConfig.getOrLoad(OpenAiConfig.OpenAiModel)
14
+ DraxConfig.getOrLoad(OpenAiConfig.OpenAiModel),
15
+ DraxConfig.getOrLoad(OpenAiConfig.OpenAiVisionModel),
16
+ AILogServiceFactory.instance
14
17
  );
15
18
  }
16
19
  return OpenAiProviderFactory.singleton;
@@ -21,4 +24,3 @@ export default OpenAiProviderFactory
21
24
  export {
22
25
  OpenAiProviderFactory
23
26
  }
24
-
@@ -0,0 +1,41 @@
1
+
2
+ import AILogMongoRepository from '../../repository/mongo/AILogMongoRepository.js'
3
+ import AILogSqliteRepository from '../../repository/sqlite/AILogSqliteRepository.js'
4
+ import type {IAILogRepository} from "../../interfaces/IAILogRepository";
5
+ import {AILogService} from '../../services/AILogService.js'
6
+ import {AILogBaseSchema, AILogSchema} from "../../schemas/AILogSchema.js";
7
+ import {COMMON, CommonConfig, DraxConfig} from "@drax/common-back";
8
+
9
+ class AILogServiceFactory {
10
+ private static service: AILogService;
11
+
12
+ public static get instance(): AILogService {
13
+ if (!AILogServiceFactory.service) {
14
+
15
+ let repository: IAILogRepository
16
+ switch (DraxConfig.getOrLoad(CommonConfig.DbEngine)) {
17
+ case COMMON.DB_ENGINES.MONGODB:
18
+ repository = new AILogMongoRepository()
19
+ break;
20
+ case COMMON.DB_ENGINES.SQLITE:
21
+ const dbFile = DraxConfig.getOrLoad(CommonConfig.SqliteDbFile)
22
+ repository = new AILogSqliteRepository(dbFile, false)
23
+ repository.build()
24
+ break;
25
+ default:
26
+ throw new Error("DraxConfig.DB_ENGINE must be one of " + Object.values(COMMON.DB_ENGINES).join(", "));
27
+ }
28
+
29
+ const baseSchema = AILogBaseSchema;
30
+ const fullSchema = AILogSchema;
31
+ AILogServiceFactory.service = new AILogService(repository, baseSchema, fullSchema);
32
+ }
33
+ return AILogServiceFactory.service;
34
+ }
35
+ }
36
+
37
+ export default AILogServiceFactory
38
+ export {
39
+ AILogServiceFactory
40
+ }
41
+
package/src/index.ts CHANGED
@@ -1,20 +1,66 @@
1
1
  import {OpenAiConfig} from "./config/OpenAiConfig.js";
2
+ import {AILogSchema, AILogBaseSchema} from "./schemas/AILogSchema.js";
3
+ import AILogModel from "./models/AILogModel.js";
4
+ import AILogMongoRepository from "./repository/mongo/AILogMongoRepository.js";
5
+ import AILogSqliteRepository from "./repository/sqlite/AILogSqliteRepository.js";
2
6
  import {OpenAiProviderFactory} from "./factory/OpenAiProviderFactory.js";
7
+ import AILogServiceFactory from "./factory/services/AILogServiceFactory.js";
3
8
  import {OpenAiProvider} from "./providers/OpenAiProvider.js";
4
9
  import {KnowledgeService} from "./services/KnowledgeService.js";
5
- import type {IAIProvider, IPromptResponse, IPromptParams, IPromptMessage, IPromptMemory} from "./interfaces/IAIProvider.js";
10
+ import {AILogService} from "./services/AILogService.js";
11
+ import AILogPermissions from "./permissions/AILogPermissions.js";
12
+ import AIPermissions from "./permissions/AIPermissions.js";
13
+ import AILogController from "./controllers/AILogController.js";
14
+ import AICrudController from "./controllers/AICrudController.js";
15
+ import AIGenericController from "./controllers/AIGenericController.js";
16
+ import AILogRoutes from "./routes/AILogRoutes.js";
17
+ import AIRoutes from "./routes/AIRoutes.js";
18
+ import type {IAILogRepository} from "./interfaces/IAILogRepository.js";
19
+ import type {
20
+ IAIProvider,
21
+ IPromptContentPart,
22
+ IPromptContentPartImage,
23
+ IPromptContentPartText,
24
+ IPromptImage,
25
+ IPromptImageDetail,
26
+ IPromptMessage,
27
+ IPromptMemory,
28
+ IPromptParams,
29
+ IPromptResponse
30
+ } from "./interfaces/IAIProvider.js";
6
31
 
7
32
  export type {
33
+
34
+ IAILogRepository,
8
35
  IAIProvider,
9
36
  IPromptParams,
10
37
  IPromptMessage,
11
38
  IPromptMemory,
39
+ IPromptImage,
40
+ IPromptImageDetail,
41
+ IPromptContentPart,
42
+ IPromptContentPartImage,
43
+ IPromptContentPartText,
12
44
  IPromptResponse,
13
45
  }
14
46
 
15
47
  export {
16
48
  OpenAiConfig,
49
+ AILogSchema,
50
+ AILogBaseSchema,
51
+ AILogModel,
52
+ AILogMongoRepository,
53
+ AILogSqliteRepository,
17
54
  OpenAiProviderFactory,
55
+ AILogServiceFactory,
18
56
  OpenAiProvider,
19
57
  KnowledgeService,
58
+ AILogService,
59
+ AILogPermissions,
60
+ AIPermissions,
61
+ AILogController,
62
+ AICrudController,
63
+ AIGenericController,
64
+ AILogRoutes,
65
+ AIRoutes
20
66
  }
@@ -0,0 +1,11 @@
1
+
2
+ import type {IAILog, IAILogBase} from '@drax/ai-share'
3
+ import {IDraxCrudRepository} from "@drax/crud-share";
4
+
5
+ interface IAILogRepository extends IDraxCrudRepository<IAILog, IAILogBase, IAILogBase>{
6
+
7
+ }
8
+
9
+ export {IAILogRepository}
10
+
11
+
@@ -2,9 +2,29 @@ import { ZodSchema } from 'zod'
2
2
 
3
3
  type Role = 'user' | 'assistant' | 'system';
4
4
 
5
+ type IPromptImageDetail = 'auto' | 'low' | 'high';
6
+
7
+ interface IPromptImage {
8
+ url: string;
9
+ detail?: IPromptImageDetail;
10
+ }
11
+
12
+ interface IPromptContentPartText {
13
+ type: 'text';
14
+ text: string;
15
+ }
16
+
17
+ interface IPromptContentPartImage {
18
+ type: 'image';
19
+ imageUrl: string;
20
+ detail?: IPromptImageDetail;
21
+ }
22
+
23
+ type IPromptContentPart = IPromptContentPartText | IPromptContentPartImage;
24
+
5
25
  interface IPromptMessage {
6
26
  role: Role;
7
- content: string;
27
+ content: string | IPromptContentPart[];
8
28
  }
9
29
 
10
30
  interface IPromptMemory {
@@ -15,6 +35,15 @@ interface IPromptMemory {
15
35
  interface IPromptParams {
16
36
  systemPrompt: string,
17
37
  userInput?: string,
38
+ userImages?: IPromptImage[],
39
+ inputFiles?: Array<{
40
+ filename?: string,
41
+ filepath?: string,
42
+ size?: number | null,
43
+ mimetype?: string,
44
+ url?: string
45
+ }>,
46
+ userContent?: IPromptContentPart[],
18
47
  history?: IPromptMessage[],
19
48
  memory?: IPromptMemory[],
20
49
  memoryHeader?: string | '[MEMORY]' | '[MEMORIA]'
@@ -23,6 +52,12 @@ interface IPromptParams {
23
52
  zodSchema?: ZodSchema<any>,
24
53
  jsonSchema?: object,
25
54
  model?: string,
55
+ operationTitle?: string,
56
+ operationGroup?: string,
57
+ ip?: string,
58
+ userAgent?: string,
59
+ tenant?: string | null,
60
+ user?: string | null,
26
61
  }
27
62
 
28
63
  interface IPromptResponse {
@@ -37,4 +72,15 @@ interface IAIProvider {
37
72
  prompt(input: IPromptParams): Promise<IPromptResponse>
38
73
  }
39
74
 
40
- export type {IAIProvider, IPromptParams, IPromptResponse, IPromptMessage, IPromptMemory}
75
+ export type {
76
+ IAIProvider,
77
+ IPromptParams,
78
+ IPromptResponse,
79
+ IPromptMessage,
80
+ IPromptMemory,
81
+ IPromptImage,
82
+ IPromptImageDetail,
83
+ IPromptContentPart,
84
+ IPromptContentPartImage,
85
+ IPromptContentPartText,
86
+ }
@@ -0,0 +1,65 @@
1
+
2
+ import {mongoose} from '@drax/common-back';
3
+ import {PaginateModel} from "mongoose";
4
+ import uniqueValidator from 'mongoose-unique-validator';
5
+ import mongoosePaginate from 'mongoose-paginate-v2'
6
+ import type {IAILog} from '@drax/ai-share'
7
+
8
+ const AILogSchema = new mongoose.Schema<IAILog>({
9
+ provider: {type: String, required: false, index: true, unique: false },
10
+ model: {type: String, required: false, index: true, unique: false },
11
+ operationTitle: {type: String, required: false, index: false, unique: false },
12
+ operationGroup: {type: String, required: false, index: false, unique: false },
13
+ ip: {type: String, required: false, index: false, unique: false },
14
+ userAgent: {type: String, required: false, index: false, unique: false },
15
+ input: {type: String, required: false, index: false, unique: false },
16
+ inputImages: [{
17
+ filename: {type: String, required: false, index: false, unique: false },
18
+ filepath: {type: String, required: false, index: false, unique: false },
19
+ size: {type: Number, required: false, index: false, unique: false },
20
+ mimetype: {type: String, required: false, index: false, unique: false },
21
+ url: {type: String, required: false, index: false, unique: false }
22
+ }],
23
+ inputFiles: [{
24
+ filename: {type: String, required: false, index: false, unique: false },
25
+ filepath: {type: String, required: false, index: false, unique: false },
26
+ size: {type: Number, required: false, index: false, unique: false },
27
+ mimetype: {type: String, required: false, index: false, unique: false },
28
+ url: {type: String, required: false, index: false, unique: false }
29
+ }],
30
+ inputTokens: {type: Number, required: false, index: false, unique: false },
31
+ outputTokens: {type: Number, required: false, index: false, unique: false },
32
+ tokens: {type: Number, required: false, index: false, unique: false },
33
+ startedAt: {type: Date, required: false, index: false, unique: false },
34
+ endedAt: {type: Date, required: false, index: false, unique: false },
35
+ responseTime: {type: String, required: false, index: false, unique: false },
36
+ output: {type: String, required: false, index: false, unique: false },
37
+ success: {type: Boolean, required: false, index: false, unique: false },
38
+ statusCode: {type: Number, required: false, index: false, unique: false },
39
+ errorMessage: {type: String, required: false, index: false, unique: false },
40
+ tenant: {type: mongoose.Schema.Types.ObjectId, ref: 'Tenant', required: false, index: false, unique: false },
41
+ user: {type: mongoose.Schema.Types.ObjectId, ref: 'User', required: false, index: false, unique: false }
42
+ }, {timestamps: true});
43
+
44
+ AILogSchema.plugin(uniqueValidator, {message: 'validation.unique'});
45
+ AILogSchema.plugin(mongoosePaginate);
46
+
47
+ AILogSchema.virtual("id").get(function () {
48
+ return this._id.toString();
49
+ });
50
+
51
+
52
+ AILogSchema.set('toJSON', {getters: true, virtuals: true});
53
+
54
+ AILogSchema.set('toObject', {getters: true, virtuals: true});
55
+
56
+ const MODEL_NAME = 'AILog';
57
+ const COLLECTION_NAME = 'AILog';
58
+ const AILogModel = mongoose.model<IAILog, PaginateModel<IAILog>>(MODEL_NAME, AILogSchema,COLLECTION_NAME);
59
+
60
+ export {
61
+ AILogSchema,
62
+ AILogModel
63
+ }
64
+
65
+ export default AILogModel
@@ -0,0 +1,14 @@
1
+
2
+ enum AILogPermissions {
3
+
4
+ Create = "ailog:create",
5
+ Update = "ailog:update",
6
+ Delete = "ailog:delete",
7
+ View = "ailog:view",
8
+ Manage = "ailog:manage"
9
+
10
+ }
11
+
12
+ export { AILogPermissions };
13
+ export default AILogPermissions;
14
+
@@ -0,0 +1,11 @@
1
+
2
+ enum AIPermissions {
3
+
4
+ Prompt = "ai:prompt",
5
+ PromptCrud = "ai:promptCrud",
6
+
7
+ }
8
+
9
+ export { AIPermissions };
10
+ export default AIPermissions;
11
+