From d377c33c6e41270dbc3e42a011e09ae03a688b95 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 15:36:59 +0300 Subject: [PATCH 01/48] OV-52: - generatedText type --- .../src/bundles/open-ai/libs/types/generated-text.type.ts | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 backend/src/bundles/open-ai/libs/types/generated-text.type.ts diff --git a/backend/src/bundles/open-ai/libs/types/generated-text.type.ts b/backend/src/bundles/open-ai/libs/types/generated-text.type.ts deleted file mode 100644 index 895720bf7..000000000 --- a/backend/src/bundles/open-ai/libs/types/generated-text.type.ts +++ /dev/null @@ -1,5 +0,0 @@ -type GeneratedText = { - generatedText: string; -}; - -export { type GeneratedText }; From c369e9953541c18c8ec70d9591009b83df96db5d Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 15:38:09 +0300 Subject: [PATCH 02/48] OV-52: + enums --- shared/src/bundles/open-ai/enums/enums.ts | 3 +++ shared/src/bundles/open-ai/enums/open-ai-path.enum.ts | 5 +++++ .../src/bundles/open-ai/enums/text-generation-rule.enum.ts | 5 +++++ .../enums/text-generation-validation-message.enum.ts | 6 ++++++ 4 files changed, 19 insertions(+) create mode 100644 shared/src/bundles/open-ai/enums/enums.ts create mode 100644 shared/src/bundles/open-ai/enums/open-ai-path.enum.ts create mode 100644 shared/src/bundles/open-ai/enums/text-generation-rule.enum.ts create mode 100644 shared/src/bundles/open-ai/enums/text-generation-validation-message.enum.ts diff --git a/shared/src/bundles/open-ai/enums/enums.ts b/shared/src/bundles/open-ai/enums/enums.ts new file mode 100644 index 000000000..6d739d345 --- /dev/null +++ b/shared/src/bundles/open-ai/enums/enums.ts @@ -0,0 +1,3 @@ +export { OpenAIPath } from './open-ai-path.enum.js'; +export { TextGenerationValidationRule } from './text-generation-rule.enum.js'; +export { TextGenerationValidationMessage } from './text-generation-validation-message.enum.js'; diff --git a/shared/src/bundles/open-ai/enums/open-ai-path.enum.ts b/shared/src/bundles/open-ai/enums/open-ai-path.enum.ts new file mode 100644 index 000000000..b9e7146df --- /dev/null +++ b/shared/src/bundles/open-ai/enums/open-ai-path.enum.ts @@ -0,0 +1,5 @@ +const OpenAIPath = { + ROOT: '/', +} as const; + +export { OpenAIPath }; diff --git a/shared/src/bundles/open-ai/enums/text-generation-rule.enum.ts b/shared/src/bundles/open-ai/enums/text-generation-rule.enum.ts new file mode 100644 index 000000000..da7c7fd17 --- /dev/null +++ b/shared/src/bundles/open-ai/enums/text-generation-rule.enum.ts @@ -0,0 +1,5 @@ +const TextGenerationValidationRule = { + MESSAGE_MINIMUM_LENGTH: 6, +} as const; + +export { TextGenerationValidationRule }; diff --git a/shared/src/bundles/open-ai/enums/text-generation-validation-message.enum.ts b/shared/src/bundles/open-ai/enums/text-generation-validation-message.enum.ts new file mode 100644 index 000000000..9553c3e0f --- /dev/null +++ b/shared/src/bundles/open-ai/enums/text-generation-validation-message.enum.ts @@ -0,0 +1,6 @@ +const TextGenerationValidationMessage = { + MESSAGE_REQUIRED: 'User message is required', + MESSAGE_LENGTH: 'Message must have at least 6 characters', +} as const; + +export { TextGenerationValidationMessage }; From 0a9de7a25188e0fb0e5c8fce2a31b0320303f1cb Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 15:39:27 +0300 Subject: [PATCH 03/48] OV-52: + HTTPMethod enum --- shared/src/framework/http/enums/enum.ts | 1 + shared/src/framework/http/enums/http-method.enum.ts | 8 ++++++++ shared/src/framework/http/http.ts | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 shared/src/framework/http/enums/http-method.enum.ts diff --git a/shared/src/framework/http/enums/enum.ts b/shared/src/framework/http/enums/enum.ts index 2443406c8..0a49c8ff5 100644 --- a/shared/src/framework/http/enums/enum.ts +++ b/shared/src/framework/http/enums/enum.ts @@ -1,2 +1,3 @@ export { HttpCode } from './http-code.enum.js'; export { HttpHeader } from './http-header.enum.js'; +export { HTTPMethod } from './http-method.enum.js'; diff --git a/shared/src/framework/http/enums/http-method.enum.ts b/shared/src/framework/http/enums/http-method.enum.ts new file mode 100644 index 000000000..39decc34d --- /dev/null +++ b/shared/src/framework/http/enums/http-method.enum.ts @@ -0,0 +1,8 @@ +const HTTPMethod = { + DELETE: 'DELETE', + GET: 'GET', + POST: 'POST', + PUT: 'PUT', +} as const; + +export { HTTPMethod }; diff --git a/shared/src/framework/http/http.ts b/shared/src/framework/http/http.ts index 6bf40315c..dcfdc4cee 100644 --- a/shared/src/framework/http/http.ts +++ b/shared/src/framework/http/http.ts @@ -1,2 +1,2 @@ -export { HttpCode, HttpHeader } from './enums/enum.js'; +export { HttpCode, HttpHeader, HTTPMethod } from './enums/enum.js'; export { type Http, type HttpMethod, type HttpOptions } from './types/types.js'; From 23bbba913d5897045b666cc7d318d65ed6a8f5e0 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 15:40:41 +0300 Subject: [PATCH 04/48] OV-52: * ApiPath enum --- shared/src/enums/api-path.enum.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/shared/src/enums/api-path.enum.ts b/shared/src/enums/api-path.enum.ts index de8fc7b8d..43a92bb3a 100644 --- a/shared/src/enums/api-path.enum.ts +++ b/shared/src/enums/api-path.enum.ts @@ -1,6 +1,7 @@ const ApiPath = { USERS: '/users', AUTH: '/auth', + OPEN_AI: '/openai', } as const; export { ApiPath }; From 60bb05c713b525970f0dfd468ad4141749dbd690 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 15:43:00 +0300 Subject: [PATCH 05/48] OV-52: + HTTPMethod enum --- backend/src/common/http/enums/enums.ts | 2 +- backend/src/common/http/http.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/common/http/enums/enums.ts b/backend/src/common/http/enums/enums.ts index 2e94a326e..94e1c540d 100644 --- a/backend/src/common/http/enums/enums.ts +++ b/backend/src/common/http/enums/enums.ts @@ -1 +1 @@ -export { HttpCode } from 'shared'; +export { HttpCode, HTTPMethod } from 'shared'; diff --git a/backend/src/common/http/http.ts b/backend/src/common/http/http.ts index cc03c9476..90dd25ce9 100644 --- a/backend/src/common/http/http.ts +++ b/backend/src/common/http/http.ts @@ -1,3 +1,3 @@ -export { HttpCode } from './enums/enums.js'; +export { HttpCode, HTTPMethod } from './enums/enums.js'; export { HttpError } from './exceptions/exceptions.js'; export { type HttpMethod } from './types/types.js'; From 16b9285f0ecb946470e423d768bdf71634fbb0c5 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 15:44:26 +0300 Subject: [PATCH 06/48] OV-52: + GenerateTextRequestDto type --- .../src/bundles/open-ai/types/generate-text-request-dto.ts | 5 +++++ shared/src/bundles/open-ai/types/types.ts | 1 + 2 files changed, 6 insertions(+) create mode 100644 shared/src/bundles/open-ai/types/generate-text-request-dto.ts create mode 100644 shared/src/bundles/open-ai/types/types.ts diff --git a/shared/src/bundles/open-ai/types/generate-text-request-dto.ts b/shared/src/bundles/open-ai/types/generate-text-request-dto.ts new file mode 100644 index 000000000..fda54b53b --- /dev/null +++ b/shared/src/bundles/open-ai/types/generate-text-request-dto.ts @@ -0,0 +1,5 @@ +type GenerateTextRequestDto = { + message: string; +}; + +export { type GenerateTextRequestDto }; diff --git a/shared/src/bundles/open-ai/types/types.ts b/shared/src/bundles/open-ai/types/types.ts new file mode 100644 index 000000000..2fee7e222 --- /dev/null +++ b/shared/src/bundles/open-ai/types/types.ts @@ -0,0 +1 @@ +export { type GenerateTextRequestDto } from './generate-text-request-dto.js'; From fd75b00c518412af7fccaecd710c5dffdbe54c22 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 16:16:18 +0300 Subject: [PATCH 07/48] OV-52: + validation schema --- .../generate-text.validation-schema.ts | 26 +++++++++++++++++++ .../validation-schemas/validation-schemas.ts | 1 + 2 files changed, 27 insertions(+) create mode 100644 shared/src/bundles/open-ai/validation-schemas/generate-text.validation-schema.ts create mode 100644 shared/src/bundles/open-ai/validation-schemas/validation-schemas.ts diff --git a/shared/src/bundles/open-ai/validation-schemas/generate-text.validation-schema.ts b/shared/src/bundles/open-ai/validation-schemas/generate-text.validation-schema.ts new file mode 100644 index 000000000..c80148070 --- /dev/null +++ b/shared/src/bundles/open-ai/validation-schemas/generate-text.validation-schema.ts @@ -0,0 +1,26 @@ +import { z } from 'zod'; + +import { + TextGenerationValidationMessage, + TextGenerationValidationRule, +} from '../enums/enums.js'; + +type GenerateTextRequestValidationDto = { + message: z.ZodString; +}; + +const textGeneration = z + .object({ + message: z + .string({ + required_error: + TextGenerationValidationMessage.MESSAGE_REQUIRED, + }) + .trim() + .min(TextGenerationValidationRule.MESSAGE_MINIMUM_LENGTH, { + message: TextGenerationValidationMessage.MESSAGE_LENGTH, + }), + }) + .required(); + +export { textGeneration }; diff --git a/shared/src/bundles/open-ai/validation-schemas/validation-schemas.ts b/shared/src/bundles/open-ai/validation-schemas/validation-schemas.ts new file mode 100644 index 000000000..28665f967 --- /dev/null +++ b/shared/src/bundles/open-ai/validation-schemas/validation-schemas.ts @@ -0,0 +1 @@ +export { textGeneration } from './generate-text.validation-schema.js'; From a9b71987633324f62ee637aaa7e1dc9c517028ed Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 16:59:48 +0300 Subject: [PATCH 08/48] OV-52: * rename file --- shared/src/bundles/chat/chat.ts | 3 +++ shared/src/bundles/chat/enums/chat.enum.ts | 5 +++++ shared/src/bundles/{open-ai => chat}/enums/enums.ts | 2 +- .../{open-ai => chat}/enums/text-generation-rule.enum.ts | 0 .../enums/text-generation-validation-message.enum.ts | 0 .../{open-ai => chat}/types/generate-text-request-dto.ts | 0 shared/src/bundles/{open-ai => chat}/types/types.ts | 0 .../validation-schemas/generate-text.validation-schema.ts | 0 .../validation-schemas/validation-schemas.ts | 0 shared/src/bundles/open-ai/enums/open-ai-path.enum.ts | 5 ----- 10 files changed, 9 insertions(+), 6 deletions(-) create mode 100644 shared/src/bundles/chat/chat.ts create mode 100644 shared/src/bundles/chat/enums/chat.enum.ts rename shared/src/bundles/{open-ai => chat}/enums/enums.ts (76%) rename shared/src/bundles/{open-ai => chat}/enums/text-generation-rule.enum.ts (100%) rename shared/src/bundles/{open-ai => chat}/enums/text-generation-validation-message.enum.ts (100%) rename shared/src/bundles/{open-ai => chat}/types/generate-text-request-dto.ts (100%) rename shared/src/bundles/{open-ai => chat}/types/types.ts (100%) rename shared/src/bundles/{open-ai => chat}/validation-schemas/generate-text.validation-schema.ts (100%) rename shared/src/bundles/{open-ai => chat}/validation-schemas/validation-schemas.ts (100%) delete mode 100644 shared/src/bundles/open-ai/enums/open-ai-path.enum.ts diff --git a/shared/src/bundles/chat/chat.ts b/shared/src/bundles/chat/chat.ts new file mode 100644 index 000000000..8aaa42161 --- /dev/null +++ b/shared/src/bundles/chat/chat.ts @@ -0,0 +1,3 @@ +export { ChatPath } from './enums/enums.js'; +export { type GenerateTextRequestDto } from './types/types.js'; +export { textGeneration as textGenerationValidationSchema } from './validation-schemas/validation-schemas.js'; diff --git a/shared/src/bundles/chat/enums/chat.enum.ts b/shared/src/bundles/chat/enums/chat.enum.ts new file mode 100644 index 000000000..5580c6237 --- /dev/null +++ b/shared/src/bundles/chat/enums/chat.enum.ts @@ -0,0 +1,5 @@ +const ChatPath = { + ROOT: '/', +} as const; + +export { ChatPath }; diff --git a/shared/src/bundles/open-ai/enums/enums.ts b/shared/src/bundles/chat/enums/enums.ts similarity index 76% rename from shared/src/bundles/open-ai/enums/enums.ts rename to shared/src/bundles/chat/enums/enums.ts index 6d739d345..a70bbdbd4 100644 --- a/shared/src/bundles/open-ai/enums/enums.ts +++ b/shared/src/bundles/chat/enums/enums.ts @@ -1,3 +1,3 @@ -export { OpenAIPath } from './open-ai-path.enum.js'; +export { ChatPath } from './chat.enum.js'; export { TextGenerationValidationRule } from './text-generation-rule.enum.js'; export { TextGenerationValidationMessage } from './text-generation-validation-message.enum.js'; diff --git a/shared/src/bundles/open-ai/enums/text-generation-rule.enum.ts b/shared/src/bundles/chat/enums/text-generation-rule.enum.ts similarity index 100% rename from shared/src/bundles/open-ai/enums/text-generation-rule.enum.ts rename to shared/src/bundles/chat/enums/text-generation-rule.enum.ts diff --git a/shared/src/bundles/open-ai/enums/text-generation-validation-message.enum.ts b/shared/src/bundles/chat/enums/text-generation-validation-message.enum.ts similarity index 100% rename from shared/src/bundles/open-ai/enums/text-generation-validation-message.enum.ts rename to shared/src/bundles/chat/enums/text-generation-validation-message.enum.ts diff --git a/shared/src/bundles/open-ai/types/generate-text-request-dto.ts b/shared/src/bundles/chat/types/generate-text-request-dto.ts similarity index 100% rename from shared/src/bundles/open-ai/types/generate-text-request-dto.ts rename to shared/src/bundles/chat/types/generate-text-request-dto.ts diff --git a/shared/src/bundles/open-ai/types/types.ts b/shared/src/bundles/chat/types/types.ts similarity index 100% rename from shared/src/bundles/open-ai/types/types.ts rename to shared/src/bundles/chat/types/types.ts diff --git a/shared/src/bundles/open-ai/validation-schemas/generate-text.validation-schema.ts b/shared/src/bundles/chat/validation-schemas/generate-text.validation-schema.ts similarity index 100% rename from shared/src/bundles/open-ai/validation-schemas/generate-text.validation-schema.ts rename to shared/src/bundles/chat/validation-schemas/generate-text.validation-schema.ts diff --git a/shared/src/bundles/open-ai/validation-schemas/validation-schemas.ts b/shared/src/bundles/chat/validation-schemas/validation-schemas.ts similarity index 100% rename from shared/src/bundles/open-ai/validation-schemas/validation-schemas.ts rename to shared/src/bundles/chat/validation-schemas/validation-schemas.ts diff --git a/shared/src/bundles/open-ai/enums/open-ai-path.enum.ts b/shared/src/bundles/open-ai/enums/open-ai-path.enum.ts deleted file mode 100644 index b9e7146df..000000000 --- a/shared/src/bundles/open-ai/enums/open-ai-path.enum.ts +++ /dev/null @@ -1,5 +0,0 @@ -const OpenAIPath = { - ROOT: '/', -} as const; - -export { OpenAIPath }; From 9dc16e6338d641339a98bf14a0a26d7e73fe8a0d Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:00:54 +0300 Subject: [PATCH 09/48] OV-52: * rename endpoint --- shared/src/enums/api-path.enum.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/enums/api-path.enum.ts b/shared/src/enums/api-path.enum.ts index 43a92bb3a..63f0bbc02 100644 --- a/shared/src/enums/api-path.enum.ts +++ b/shared/src/enums/api-path.enum.ts @@ -1,7 +1,7 @@ const ApiPath = { USERS: '/users', AUTH: '/auth', - OPEN_AI: '/openai', + CHAT: '/chat', } as const; export { ApiPath }; From 23fd9b3357a7bd1ca90118aeec7ed71781ca9a47 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:01:51 +0300 Subject: [PATCH 10/48] OV-52: + shared exports --- shared/src/index.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/shared/src/index.ts b/shared/src/index.ts index d4b77ee0e..40647ed47 100644 --- a/shared/src/index.ts +++ b/shared/src/index.ts @@ -1,4 +1,9 @@ export { AuthApiPath } from './bundles/auth/auth.js'; +export { + type GenerateTextRequestDto, + ChatPath, + textGenerationValidationSchema, +} from './bundles/chat/chat.js'; export { type UserGetAllItemResponseDto, type UserGetAllResponseDto, @@ -29,6 +34,7 @@ export { type HttpOptions, HttpCode, HttpHeader, + HTTPMethod, } from './framework/http/http.js'; export { type Storage } from './framework/storage/storage.js'; export { configureString } from './helpers/helpers.js'; From 2cdc71840d7f5ba01a01d3a2727c3f54153f3e9f Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:03:37 +0300 Subject: [PATCH 11/48] OV-52: + session key --- backend/src/common/config/base-config.package.ts | 6 ++++++ backend/src/common/config/types/environment-schema.type.ts | 1 + 2 files changed, 7 insertions(+) diff --git a/backend/src/common/config/base-config.package.ts b/backend/src/common/config/base-config.package.ts index ef47737b3..bb1ba32fd 100644 --- a/backend/src/common/config/base-config.package.ts +++ b/backend/src/common/config/base-config.package.ts @@ -47,6 +47,12 @@ class BaseConfig implements Config { env: 'OPEN_AI_KEY', default: null, }, + SESSION_KEY: { + doc: 'Key for sessions', + format: String, + env: 'SESSION_KEY', + default: null, + }, }, DB: { CONNECTION_STRING: { diff --git a/backend/src/common/config/types/environment-schema.type.ts b/backend/src/common/config/types/environment-schema.type.ts index ce22834aa..60348afe5 100644 --- a/backend/src/common/config/types/environment-schema.type.ts +++ b/backend/src/common/config/types/environment-schema.type.ts @@ -6,6 +6,7 @@ type EnvironmentSchema = { PORT: number; ENVIRONMENT: ValueOf; OPEN_AI_KEY: string; + SESSION_KEY: string; }; DB: { CONNECTION_STRING: string; From da455ab7aaabb3560afcdae1504d93143c9e3a1a Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:04:56 +0300 Subject: [PATCH 12/48] OV-52: + fastify session library --- backend/package.json | 2 ++ package-lock.json | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/backend/package.json b/backend/package.json index 3e19ba323..6dcde8fac 100644 --- a/backend/package.json +++ b/backend/package.json @@ -27,6 +27,8 @@ "tsx": "4.17.0" }, "dependencies": { + "@fastify/cookie": "9.4.0", + "@fastify/session": "10.9.0", "@fastify/static": "7.0.4", "@fastify/swagger": "8.15.0", "@fastify/swagger-ui": "4.0.1", diff --git a/package-lock.json b/package-lock.json index 828e43422..1959c3d2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,6 +39,8 @@ }, "backend": { "dependencies": { + "@fastify/cookie": "9.4.0", + "@fastify/session": "10.9.0", "@fastify/static": "7.0.4", "@fastify/swagger": "8.15.0", "@fastify/swagger-ui": "4.0.1", @@ -2691,6 +2693,15 @@ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-2.4.0.tgz", "integrity": "sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==" }, + "node_modules/@fastify/cookie": { + "version": "9.4.0", + "resolved": "https://registry.npmjs.org/@fastify/cookie/-/cookie-9.4.0.tgz", + "integrity": "sha512-Th+pt3kEkh4MQD/Q2q1bMuJIB5NX/D5SwSpOKu3G/tjoGbwfpurIMJsWSPS0SJJ4eyjtmQ8OipDQspf8RbUOlg==", + "dependencies": { + "cookie-signature": "^1.1.0", + "fastify-plugin": "^4.0.0" + } + }, "node_modules/@fastify/error": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@fastify/error/-/error-3.4.1.tgz", @@ -2724,6 +2735,15 @@ "mime": "^3.0.0" } }, + "node_modules/@fastify/session": { + "version": "10.9.0", + "resolved": "https://registry.npmjs.org/@fastify/session/-/session-10.9.0.tgz", + "integrity": "sha512-u/c42RuAaxCeEuRCAwK2+/SfGqKOd0NSyRzEvDwFBWySQoKUZQyb9OmmJSWJBbOP1OfaU2OsDrjbPbghE1l/YQ==", + "dependencies": { + "fastify-plugin": "^4.0.0", + "safe-stable-stringify": "^2.3.1" + } + }, "node_modules/@fastify/static": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/@fastify/static/-/static-7.0.4.tgz", @@ -5259,6 +5279,14 @@ "node": ">= 0.6" } }, + "node_modules/cookie-signature": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.1.tgz", + "integrity": "sha512-78KWk9T26NhzXtuL26cIJ8/qNHANyJ/ZYrmEXFzUmhZdjpBv+DlWlOANRTGBt48YcyslsLrj0bMLFTmXvLRCOw==", + "engines": { + "node": ">=6.6.0" + } + }, "node_modules/copy-to-clipboard": { "version": "3.3.3", "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", From 0dcbe1cd3fc6de8b86687e2f164bc75c30ad19d7 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:06:28 +0300 Subject: [PATCH 13/48] OV-52: + types --- .../src/bundles/chat/libs/types/message.type.ts | 10 ++++++++++ .../chat/libs/types/open-ai-service.type.ts | 15 +++++++++++++++ backend/src/bundles/chat/libs/types/types.ts | 4 ++++ 3 files changed, 29 insertions(+) create mode 100644 backend/src/bundles/chat/libs/types/message.type.ts create mode 100644 backend/src/bundles/chat/libs/types/open-ai-service.type.ts create mode 100644 backend/src/bundles/chat/libs/types/types.ts diff --git a/backend/src/bundles/chat/libs/types/message.type.ts b/backend/src/bundles/chat/libs/types/message.type.ts new file mode 100644 index 000000000..1bd4ee658 --- /dev/null +++ b/backend/src/bundles/chat/libs/types/message.type.ts @@ -0,0 +1,10 @@ +import { type ValueOf } from 'shared'; + +import { type OpenAIRole } from '../enums/enums.js'; + +type Message = { + role: ValueOf; + content: string; +}; + +export { type Message }; diff --git a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts new file mode 100644 index 000000000..e988d31bf --- /dev/null +++ b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts @@ -0,0 +1,15 @@ +import { type ValueOf } from 'shared'; + +import { type OpenAIRole } from '../enums/enums.js'; +import { type Message } from './message.type.js'; + +type OpenAIService = { + generateText(messages: Message[]): Promise; + addMessageToHistory( + chatHistory: Message[], + userMessage: string, + role: ValueOf, + ): void; +}; + +export { type OpenAIService }; diff --git a/backend/src/bundles/chat/libs/types/types.ts b/backend/src/bundles/chat/libs/types/types.ts new file mode 100644 index 000000000..92b6f0cbc --- /dev/null +++ b/backend/src/bundles/chat/libs/types/types.ts @@ -0,0 +1,4 @@ +export { type Message } from './message.type.js'; +export { type OpenAIService } from './open-ai-service.type.js'; +export { type SessionChatHistory } from './session-chat-history.js'; +export { type GenerateTextRequestDto } from 'shared'; From 31e7bdca876fe1e3a49c865ac6a09ec229b0591c Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:08:42 +0300 Subject: [PATCH 14/48] OV-52: + libs --- .../{open-ai => chat}/libs/constants/chat-model.constant.ts | 0 .../src/bundles/{open-ai => chat}/libs/constants/constants.ts | 0 .../{open-ai => chat}/libs/constants/max-token.constant.ts | 0 backend/src/bundles/{open-ai => chat}/libs/enums/enums.ts | 1 + .../bundles/{open-ai => chat}/libs/enums/open-ai-role.enum.ts | 0 5 files changed, 1 insertion(+) rename backend/src/bundles/{open-ai => chat}/libs/constants/chat-model.constant.ts (100%) rename backend/src/bundles/{open-ai => chat}/libs/constants/constants.ts (100%) rename backend/src/bundles/{open-ai => chat}/libs/constants/max-token.constant.ts (100%) rename backend/src/bundles/{open-ai => chat}/libs/enums/enums.ts (60%) rename backend/src/bundles/{open-ai => chat}/libs/enums/open-ai-role.enum.ts (100%) diff --git a/backend/src/bundles/open-ai/libs/constants/chat-model.constant.ts b/backend/src/bundles/chat/libs/constants/chat-model.constant.ts similarity index 100% rename from backend/src/bundles/open-ai/libs/constants/chat-model.constant.ts rename to backend/src/bundles/chat/libs/constants/chat-model.constant.ts diff --git a/backend/src/bundles/open-ai/libs/constants/constants.ts b/backend/src/bundles/chat/libs/constants/constants.ts similarity index 100% rename from backend/src/bundles/open-ai/libs/constants/constants.ts rename to backend/src/bundles/chat/libs/constants/constants.ts diff --git a/backend/src/bundles/open-ai/libs/constants/max-token.constant.ts b/backend/src/bundles/chat/libs/constants/max-token.constant.ts similarity index 100% rename from backend/src/bundles/open-ai/libs/constants/max-token.constant.ts rename to backend/src/bundles/chat/libs/constants/max-token.constant.ts diff --git a/backend/src/bundles/open-ai/libs/enums/enums.ts b/backend/src/bundles/chat/libs/enums/enums.ts similarity index 60% rename from backend/src/bundles/open-ai/libs/enums/enums.ts rename to backend/src/bundles/chat/libs/enums/enums.ts index 58dc0594a..b111ba763 100644 --- a/backend/src/bundles/open-ai/libs/enums/enums.ts +++ b/backend/src/bundles/chat/libs/enums/enums.ts @@ -1 +1,2 @@ export { OpenAIRole } from './open-ai-role.enum.js'; +export { ChatPath } from 'shared'; diff --git a/backend/src/bundles/open-ai/libs/enums/open-ai-role.enum.ts b/backend/src/bundles/chat/libs/enums/open-ai-role.enum.ts similarity index 100% rename from backend/src/bundles/open-ai/libs/enums/open-ai-role.enum.ts rename to backend/src/bundles/chat/libs/enums/open-ai-role.enum.ts From fbd2dffa69de9b1b66a3dcf527235f2e4f2b7bff Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:11:52 +0300 Subject: [PATCH 15/48] OV-52: + libs --- .../src/bundles/chat/libs/types/session-chat-history.ts | 7 +++++++ .../chat/libs/validation-schemas/validation-schemas.ts | 1 + .../common/controller/types/api-handler-options.type.ts | 2 ++ .../src/common/plugins/libs/enums/controller-hook.enum.ts | 5 +++++ backend/src/common/plugins/libs/enums/enums.ts | 1 + 5 files changed, 16 insertions(+) create mode 100644 backend/src/bundles/chat/libs/types/session-chat-history.ts create mode 100644 backend/src/bundles/chat/libs/validation-schemas/validation-schemas.ts create mode 100644 backend/src/common/plugins/libs/enums/controller-hook.enum.ts create mode 100644 backend/src/common/plugins/libs/enums/enums.ts diff --git a/backend/src/bundles/chat/libs/types/session-chat-history.ts b/backend/src/bundles/chat/libs/types/session-chat-history.ts new file mode 100644 index 000000000..02ce4a1a0 --- /dev/null +++ b/backend/src/bundles/chat/libs/types/session-chat-history.ts @@ -0,0 +1,7 @@ +import { type Message } from './message.type.js'; + +type SessionChatHistory = { + chatHistory: Message[]; +}; + +export { type SessionChatHistory }; diff --git a/backend/src/bundles/chat/libs/validation-schemas/validation-schemas.ts b/backend/src/bundles/chat/libs/validation-schemas/validation-schemas.ts new file mode 100644 index 000000000..b7a3ade52 --- /dev/null +++ b/backend/src/bundles/chat/libs/validation-schemas/validation-schemas.ts @@ -0,0 +1 @@ +export { textGenerationValidationSchema } from 'shared'; diff --git a/backend/src/common/controller/types/api-handler-options.type.ts b/backend/src/common/controller/types/api-handler-options.type.ts index fd38e4503..8514b84a0 100644 --- a/backend/src/common/controller/types/api-handler-options.type.ts +++ b/backend/src/common/controller/types/api-handler-options.type.ts @@ -2,6 +2,7 @@ type DefaultApiHandlerOptions = { body?: unknown; query?: unknown; params?: unknown; + session?: unknown; }; type ApiHandlerOptions< @@ -10,6 +11,7 @@ type ApiHandlerOptions< body: T['body']; query: T['query']; params: T['params']; + session: T['session']; }; export { type ApiHandlerOptions }; diff --git a/backend/src/common/plugins/libs/enums/controller-hook.enum.ts b/backend/src/common/plugins/libs/enums/controller-hook.enum.ts new file mode 100644 index 000000000..d3541a9a8 --- /dev/null +++ b/backend/src/common/plugins/libs/enums/controller-hook.enum.ts @@ -0,0 +1,5 @@ +const ControllerHook = { + ON_REQUEST: 'onRequest', +} as const; + +export { ControllerHook }; diff --git a/backend/src/common/plugins/libs/enums/enums.ts b/backend/src/common/plugins/libs/enums/enums.ts new file mode 100644 index 000000000..24e279ff4 --- /dev/null +++ b/backend/src/common/plugins/libs/enums/enums.ts @@ -0,0 +1 @@ +export { ControllerHook } from './controller-hook.enum.js'; From dbe2dfbf5d054641f2bbde6b2f54179f3f4d0eb1 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:13:49 +0300 Subject: [PATCH 16/48] OV-52: + plugin --- .../controller/base-controller.package.ts | 3 +- backend/src/common/plugins/plugins.ts | 1 + .../common/plugins/session/session.plugin.ts | 31 +++++++++++++++++++ .../server-application/base-server-app.ts | 11 +++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 backend/src/common/plugins/plugins.ts create mode 100644 backend/src/common/plugins/session/session.plugin.ts diff --git a/backend/src/common/controller/base-controller.package.ts b/backend/src/common/controller/base-controller.package.ts index aa2f0fc8e..a481b972a 100644 --- a/backend/src/common/controller/base-controller.package.ts +++ b/backend/src/common/controller/base-controller.package.ts @@ -49,12 +49,13 @@ class BaseController implements Controller { private mapRequest( request: Parameters[0], ): ApiHandlerOptions { - const { body, query, params } = request; + const { body, query, params, session } = request; return { body, query, params, + session, }; } } diff --git a/backend/src/common/plugins/plugins.ts b/backend/src/common/plugins/plugins.ts new file mode 100644 index 000000000..262690612 --- /dev/null +++ b/backend/src/common/plugins/plugins.ts @@ -0,0 +1 @@ +export { session } from './session/session.plugin.js'; diff --git a/backend/src/common/plugins/session/session.plugin.ts b/backend/src/common/plugins/session/session.plugin.ts new file mode 100644 index 000000000..047a7376e --- /dev/null +++ b/backend/src/common/plugins/session/session.plugin.ts @@ -0,0 +1,31 @@ +import fastifyCookie from '@fastify/cookie'; +import fastifySession from '@fastify/session'; +import fp from 'fastify-plugin'; + +import { type BaseConfig } from '~/common/config/base-config.package.js'; + +import { ControllerHook } from '../libs/enums/enums.js'; + +type Options = { + services: { + config: BaseConfig; + }; +}; + +const session = fp(async (fastify, { services }) => { + await fastify.register(fastifyCookie); + await fastify.register(fastifySession, { + secret: services.config.ENV.APP.SESSION_KEY, + cookie: { secure: false }, + }); + + fastify.addHook(ControllerHook.ON_REQUEST, (request, _replay, done) => { + if (!request.session.chatHistory) { + request.session.chatHistory = []; + } + + done(); + }); +}); + +export { session }; diff --git a/backend/src/common/server-application/base-server-app.ts b/backend/src/common/server-application/base-server-app.ts index 25cef068b..a2bbca2bb 100644 --- a/backend/src/common/server-application/base-server-app.ts +++ b/backend/src/common/server-application/base-server-app.ts @@ -22,6 +22,7 @@ import { type ValidationSchema, } from '~/common/types/types.js'; +import { session } from '../plugins/plugins.js'; import { type ServerApp, type ServerAppApi, @@ -122,6 +123,14 @@ class BaseServerApp implements ServerApp { ); } + private registerPlugins(): void { + this.app.register(session, { + services: { + config: this.config, + }, + }); + } + private initValidationCompiler(): void { this.app.setValidatorCompiler( ({ schema }: { schema: ValidationSchema }) => { @@ -200,6 +209,8 @@ class BaseServerApp implements ServerApp { await this.initMiddlewares(); + this.registerPlugins(); + this.initValidationCompiler(); this.initErrorHandler(); From e69ce2a463df7a35bf4cc9f17eab72c9abb8980a Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:14:58 +0300 Subject: [PATCH 17/48] OV-52: + open ai service --- .../{open-ai => chat}/open-ai.service.ts | 27 ++++++++++++------- .../open-ai/libs/types/message.type.ts | 10 ------- .../libs/types/open-ai-service.type.ts | 8 ------ .../src/bundles/open-ai/libs/types/types.ts | 3 --- 4 files changed, 18 insertions(+), 30 deletions(-) rename backend/src/bundles/{open-ai => chat}/open-ai.service.ts (59%) delete mode 100644 backend/src/bundles/open-ai/libs/types/message.type.ts delete mode 100644 backend/src/bundles/open-ai/libs/types/open-ai-service.type.ts delete mode 100644 backend/src/bundles/open-ai/libs/types/types.ts diff --git a/backend/src/bundles/open-ai/open-ai.service.ts b/backend/src/bundles/chat/open-ai.service.ts similarity index 59% rename from backend/src/bundles/open-ai/open-ai.service.ts rename to backend/src/bundles/chat/open-ai.service.ts index b89b0e179..d04d927d4 100644 --- a/backend/src/bundles/open-ai/open-ai.service.ts +++ b/backend/src/bundles/chat/open-ai.service.ts @@ -1,23 +1,20 @@ import OpenAI, { type OpenAI as OpenAIType } from 'openai'; +import { type ValueOf } from 'shared'; import { type BaseConfig } from '~/common/config/base-config.package.js'; import { CHAT_MODEL, MAX_TOKEN } from './libs/constants/constants.js'; +import { type OpenAIRole } from './libs/enums/open-ai-role.enum.js'; import { - type GeneratedText, type Message, type OpenAIService as OpenAIServiceModule, } from './libs/types/types.js'; -type Constructor = { - config: BaseConfig; -}; - class OpenAIService implements OpenAIServiceModule { private config: BaseConfig; private openAi: OpenAIType; - public constructor({ config }: Constructor) { + public constructor(config: BaseConfig) { this.config = config; this.openAi = this.initOpenAi(); } @@ -28,15 +25,27 @@ class OpenAIService implements OpenAIServiceModule { }); }; - public async generateText(messages: Message[]): Promise { + public addMessageToHistory( + chatHistory: Message[], + userMessage: string, + role: ValueOf, + ): void { + const newUserMessage = { + content: userMessage, + role, + }; + + chatHistory.push(newUserMessage); + } + + public async generateText(messages: Message[]): Promise { const completion = await this.openAi.chat.completions.create({ messages, model: CHAT_MODEL, max_tokens: MAX_TOKEN, }); - const generatedText = completion.choices[0]?.message.content || ''; - return { generatedText }; + return completion.choices[0]?.message.content || ''; } } diff --git a/backend/src/bundles/open-ai/libs/types/message.type.ts b/backend/src/bundles/open-ai/libs/types/message.type.ts deleted file mode 100644 index 1bd4ee658..000000000 --- a/backend/src/bundles/open-ai/libs/types/message.type.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { type ValueOf } from 'shared'; - -import { type OpenAIRole } from '../enums/enums.js'; - -type Message = { - role: ValueOf; - content: string; -}; - -export { type Message }; diff --git a/backend/src/bundles/open-ai/libs/types/open-ai-service.type.ts b/backend/src/bundles/open-ai/libs/types/open-ai-service.type.ts deleted file mode 100644 index 313148017..000000000 --- a/backend/src/bundles/open-ai/libs/types/open-ai-service.type.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { type GeneratedText } from './generated-text.type.js'; -import { type Message } from './message.type.js'; - -type OpenAIService = { - generateText(messages: Message[]): Promise; -}; - -export { type OpenAIService }; diff --git a/backend/src/bundles/open-ai/libs/types/types.ts b/backend/src/bundles/open-ai/libs/types/types.ts deleted file mode 100644 index d3de0182b..000000000 --- a/backend/src/bundles/open-ai/libs/types/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export { type GeneratedText } from './generated-text.type.js'; -export { type Message } from './message.type.js'; -export { type OpenAIService } from './open-ai-service.type.js'; From 61e42d4e210b2536ed16685770364d6397048528 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:15:54 +0300 Subject: [PATCH 18/48] OV-52: + chat controller --- backend/src/bundles/chat/chat.controller.ts | 73 +++++++++++++++++++ backend/src/bundles/chat/chat.ts | 10 +++ .../server-application/server-application.ts | 2 + 3 files changed, 85 insertions(+) create mode 100644 backend/src/bundles/chat/chat.controller.ts create mode 100644 backend/src/bundles/chat/chat.ts diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts new file mode 100644 index 000000000..a774afb8c --- /dev/null +++ b/backend/src/bundles/chat/chat.controller.ts @@ -0,0 +1,73 @@ +import { + type ApiHandlerOptions, + type ApiHandlerResponse, + BaseController, +} from '~/common/controller/controller.js'; +import { ApiPath } from '~/common/enums/enums.js'; +import { HttpCode, HTTPMethod } from '~/common/http/http.js'; +import { type Logger } from '~/common/logger/logger.js'; + +import { ChatPath, OpenAIRole } from './libs/enums/enums.js'; +import { + type GenerateTextRequestDto, + type SessionChatHistory, +} from './libs/types/types.js'; +import { textGenerationValidationSchema } from './libs/validation-schemas/validation-schemas.js'; +import { type OpenAIService } from './open-ai.service.js'; + +class ChatController extends BaseController { + private openAIService: OpenAIService; + + public constructor(logger: Logger, openAIService: OpenAIService) { + super(logger, ApiPath.CHAT); + + this.openAIService = openAIService; + + this.addRoute({ + path: ChatPath.ROOT, + method: HTTPMethod.POST, + validation: { + body: textGenerationValidationSchema, + }, + handler: (options) => + this.generateChatAnswer( + options as ApiHandlerOptions<{ + body: GenerateTextRequestDto; + session: SessionChatHistory; + }>, + ), + }); + } + + private async generateChatAnswer( + options: ApiHandlerOptions<{ + body: GenerateTextRequestDto; + session: SessionChatHistory; + }>, + ): Promise { + const { body, session } = options; + + this.openAIService.addMessageToHistory( + session.chatHistory, + body.message, + OpenAIRole.USER, + ); + + const generatedText = await this.openAIService.generateText( + session.chatHistory, + ); + + this.openAIService.addMessageToHistory( + session.chatHistory, + generatedText, + OpenAIRole.ASSISTANT, + ); + + return { + payload: generatedText, + status: HttpCode.OK, + }; + } +} + +export { ChatController }; diff --git a/backend/src/bundles/chat/chat.ts b/backend/src/bundles/chat/chat.ts new file mode 100644 index 000000000..a77b520d5 --- /dev/null +++ b/backend/src/bundles/chat/chat.ts @@ -0,0 +1,10 @@ +import { config } from '~/common/config/config.js'; +import { logger } from '~/common/logger/logger.js'; + +import { ChatController } from './chat.controller.js'; +import { OpenAIService } from './open-ai.service.js'; + +const openAIService = new OpenAIService(config); +const chatController = new ChatController(logger, openAIService); + +export { chatController }; diff --git a/backend/src/common/server-application/server-application.ts b/backend/src/common/server-application/server-application.ts index c8c4a88f9..ea5ee7bdf 100644 --- a/backend/src/common/server-application/server-application.ts +++ b/backend/src/common/server-application/server-application.ts @@ -1,4 +1,5 @@ import { authController } from '~/bundles/auth/auth.js'; +import { chatController } from '~/bundles/chat/chat.js'; import { userController } from '~/bundles/users/users.js'; import { config } from '~/common/config/config.js'; import { database } from '~/common/database/database.js'; @@ -12,6 +13,7 @@ const apiV1 = new BaseServerAppApi( config, ...authController.routes, ...userController.routes, + ...chatController.routes, ); const serverApp = new BaseServerApp({ config, From f4a1e587bd7b6487b842ebc526253ddf7fe54ec0 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Fri, 23 Aug 2024 17:16:39 +0300 Subject: [PATCH 19/48] OV-52: + fastify module --- backend/src/packages.d.ts | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 backend/src/packages.d.ts diff --git a/backend/src/packages.d.ts b/backend/src/packages.d.ts new file mode 100644 index 000000000..335271c16 --- /dev/null +++ b/backend/src/packages.d.ts @@ -0,0 +1,7 @@ +import { type Message } from './bundles/chat/libs/types/types.ts'; + +declare module 'fastify' { + interface Session { + chatHistory: Message[]; + } +} From 7b3c9623987d13b6d31a3fe22287fe363c6a3fbc Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 00:38:41 +0300 Subject: [PATCH 20/48] OV-52: * HttpMethod type --- shared/src/framework/http/types/http-method.type.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/framework/http/types/http-method.type.ts b/shared/src/framework/http/types/http-method.type.ts index 884797ac9..3d15ae0aa 100644 --- a/shared/src/framework/http/types/http-method.type.ts +++ b/shared/src/framework/http/types/http-method.type.ts @@ -1,3 +1,3 @@ -type HttpMethod = 'GET' | 'POST'; +type HttpMethod = 'GET' | 'POST' | 'DELETE'; export { type HttpMethod }; From 3a1ebc3c8651b442239e1c37d768bcee9527e020 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 00:41:18 +0300 Subject: [PATCH 21/48] OV-52: * OpenAISerrvice type --- backend/src/bundles/chat/libs/types/open-ai-service.type.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts index e988d31bf..f40d25104 100644 --- a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts +++ b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts @@ -2,6 +2,7 @@ import { type ValueOf } from 'shared'; import { type OpenAIRole } from '../enums/enums.js'; import { type Message } from './message.type.js'; +import { type SessionChatHistory } from './session-chat-history.js'; type OpenAIService = { generateText(messages: Message[]): Promise; @@ -10,6 +11,7 @@ type OpenAIService = { userMessage: string, role: ValueOf, ): void; + clearChatHistory(session: SessionChatHistory): void; }; export { type OpenAIService }; From 4e9549291d34fa7c77e7da1618af226501850137 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 00:42:22 +0300 Subject: [PATCH 22/48] OV-52: + clear chat logic --- backend/src/bundles/chat/chat.controller.ts | 23 +++++++++++++++++++++ backend/src/bundles/chat/open-ai.service.ts | 5 +++++ 2 files changed, 28 insertions(+) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index a774afb8c..25b3c46c8 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -37,6 +37,17 @@ class ChatController extends BaseController { }>, ), }); + + this.addRoute({ + path: ChatPath.ROOT, + method: HTTPMethod.DELETE, + handler: (options) => + this.clearChat( + options as ApiHandlerOptions<{ + session: SessionChatHistory; + }>, + ), + }); } private async generateChatAnswer( @@ -68,6 +79,18 @@ class ChatController extends BaseController { status: HttpCode.OK, }; } + + private clearChat( + options: ApiHandlerOptions<{ + session: SessionChatHistory; + }>, + ): ApiHandlerResponse { + this.openAIService.clearChatHistory(options.session); + return { + payload: true, + status: HttpCode.OK, + }; + } } export { ChatController }; diff --git a/backend/src/bundles/chat/open-ai.service.ts b/backend/src/bundles/chat/open-ai.service.ts index d04d927d4..265fe1d4b 100644 --- a/backend/src/bundles/chat/open-ai.service.ts +++ b/backend/src/bundles/chat/open-ai.service.ts @@ -8,6 +8,7 @@ import { type OpenAIRole } from './libs/enums/open-ai-role.enum.js'; import { type Message, type OpenAIService as OpenAIServiceModule, + type SessionChatHistory, } from './libs/types/types.js'; class OpenAIService implements OpenAIServiceModule { @@ -38,6 +39,10 @@ class OpenAIService implements OpenAIServiceModule { chatHistory.push(newUserMessage); } + public clearChatHistory(session: SessionChatHistory): void { + session.chatHistory = []; + } + public async generateText(messages: Message[]): Promise { const completion = await this.openAi.chat.completions.create({ messages, From 6d3f7e000e5646255938f740bcf02ed5348ccb62 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:17:13 +0300 Subject: [PATCH 23/48] OV-52: - sessionChatHistory type --- .../src/bundles/chat/libs/types/session-chat-history.ts | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 backend/src/bundles/chat/libs/types/session-chat-history.ts diff --git a/backend/src/bundles/chat/libs/types/session-chat-history.ts b/backend/src/bundles/chat/libs/types/session-chat-history.ts deleted file mode 100644 index 02ce4a1a0..000000000 --- a/backend/src/bundles/chat/libs/types/session-chat-history.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { type Message } from './message.type.js'; - -type SessionChatHistory = { - chatHistory: Message[]; -}; - -export { type SessionChatHistory }; From 331a987588b4ae0d7f71b8f50ea192c3983f226f Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:17:45 +0300 Subject: [PATCH 24/48] OV-52: + tiktoken package --- backend/package.json | 3 ++- package-lock.json | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/backend/package.json b/backend/package.json index e1e718217..823fa5f0d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -45,6 +45,7 @@ "pino": "9.3.2", "pino-pretty": "10.3.1", "shared": "*", - "swagger-jsdoc": "6.2.8" + "swagger-jsdoc": "6.2.8", + "tiktoken": "1.0.16" } } diff --git a/package-lock.json b/package-lock.json index b1734afd5..3ff325381 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,7 +55,8 @@ "pino": "9.3.2", "pino-pretty": "10.3.1", "shared": "*", - "swagger-jsdoc": "6.2.8" + "swagger-jsdoc": "6.2.8", + "tiktoken": "1.0.16" }, "devDependencies": { "@types/bcrypt": "5.0.2", @@ -12486,6 +12487,11 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "node_modules/tiktoken": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/tiktoken/-/tiktoken-1.0.16.tgz", + "integrity": "sha512-hRcORIGF2YlAgWx3nzrGJOrKSJwLoc81HpXmMQk89632XAgURc7IeV2FgQ2iXo9z/J96fCvpsHg2kWoHcbj9fg==" + }, "node_modules/tildify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", From d5438bf675cde8f69c07d659867a5f95da82e57c Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:18:27 +0300 Subject: [PATCH 25/48] OV-52: * HttpMethod type --- shared/src/framework/http/types/http-method.type.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shared/src/framework/http/types/http-method.type.ts b/shared/src/framework/http/types/http-method.type.ts index 3d15ae0aa..6ef53eadb 100644 --- a/shared/src/framework/http/types/http-method.type.ts +++ b/shared/src/framework/http/types/http-method.type.ts @@ -1,3 +1,3 @@ -type HttpMethod = 'GET' | 'POST' | 'DELETE'; +type HttpMethod = 'GET' | 'POST' | 'DELETE' | 'PUT'; export { type HttpMethod }; From 37c3dd9a5ab9f720de2127990f3f10bae3af04df Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:19:05 +0300 Subject: [PATCH 26/48] OV-52: - sessionChatHistory type --- backend/src/bundles/chat/libs/types/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/src/bundles/chat/libs/types/types.ts b/backend/src/bundles/chat/libs/types/types.ts index 92b6f0cbc..0da5cca46 100644 --- a/backend/src/bundles/chat/libs/types/types.ts +++ b/backend/src/bundles/chat/libs/types/types.ts @@ -1,4 +1,3 @@ export { type Message } from './message.type.js'; export { type OpenAIService } from './open-ai-service.type.js'; -export { type SessionChatHistory } from './session-chat-history.js'; export { type GenerateTextRequestDto } from 'shared'; From d76157a1ae168cde2e7e527eeef69ccdfab64ea9 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:21:27 +0300 Subject: [PATCH 27/48] OV-52: * MAX_TOKEN --- backend/src/bundles/chat/libs/constants/max-token.constant.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/bundles/chat/libs/constants/max-token.constant.ts b/backend/src/bundles/chat/libs/constants/max-token.constant.ts index 886179719..dcc301f98 100644 --- a/backend/src/bundles/chat/libs/constants/max-token.constant.ts +++ b/backend/src/bundles/chat/libs/constants/max-token.constant.ts @@ -1,3 +1,3 @@ -const MAX_TOKEN = 2048 as const; +const MAX_TOKEN = 16_000 as const; export { MAX_TOKEN }; From 33b4c70f70ab0525fb26bceea4c114cb8c10a7b0 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:22:41 +0300 Subject: [PATCH 28/48] OV-52: + delete old messages logic --- .../chat/libs/types/open-ai-service.type.ts | 4 +-- backend/src/bundles/chat/open-ai.service.ts | 35 ++++++++++++++++--- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts index f40d25104..a71a9b36f 100644 --- a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts +++ b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts @@ -2,7 +2,6 @@ import { type ValueOf } from 'shared'; import { type OpenAIRole } from '../enums/enums.js'; import { type Message } from './message.type.js'; -import { type SessionChatHistory } from './session-chat-history.js'; type OpenAIService = { generateText(messages: Message[]): Promise; @@ -11,7 +10,8 @@ type OpenAIService = { userMessage: string, role: ValueOf, ): void; - clearChatHistory(session: SessionChatHistory): void; + clearChatHistory(messages: Message[]): void; + deleteOldMessages(messages: Message[], maxTokens: number): void; }; export { type OpenAIService }; diff --git a/backend/src/bundles/chat/open-ai.service.ts b/backend/src/bundles/chat/open-ai.service.ts index 265fe1d4b..96f79a6b9 100644 --- a/backend/src/bundles/chat/open-ai.service.ts +++ b/backend/src/bundles/chat/open-ai.service.ts @@ -1,5 +1,6 @@ import OpenAI, { type OpenAI as OpenAIType } from 'openai'; import { type ValueOf } from 'shared'; +import { type Tiktoken, encoding_for_model } from 'tiktoken'; import { type BaseConfig } from '~/common/config/base-config.package.js'; @@ -8,16 +9,17 @@ import { type OpenAIRole } from './libs/enums/open-ai-role.enum.js'; import { type Message, type OpenAIService as OpenAIServiceModule, - type SessionChatHistory, } from './libs/types/types.js'; class OpenAIService implements OpenAIServiceModule { private config: BaseConfig; private openAi: OpenAIType; + private modelEncoding: Tiktoken; public constructor(config: BaseConfig) { this.config = config; this.openAi = this.initOpenAi(); + this.modelEncoding = encoding_for_model('gpt-4o-mini'); } private initOpenAi = (): OpenAIType => { @@ -39,8 +41,8 @@ class OpenAIService implements OpenAIServiceModule { chatHistory.push(newUserMessage); } - public clearChatHistory(session: SessionChatHistory): void { - session.chatHistory = []; + public clearChatHistory(messages: Message[]): void { + messages.splice(0, messages.length); } public async generateText(messages: Message[]): Promise { @@ -49,9 +51,34 @@ class OpenAIService implements OpenAIServiceModule { model: CHAT_MODEL, max_tokens: MAX_TOKEN, }); - return completion.choices[0]?.message.content || ''; } + + private countTokens(messages: Message[]): number { + return messages.reduce( + (sum, message) => + sum + this.modelEncoding.encode(message.content).length, + 0, + ); + } + + public deleteOldMessages(messages: Message[], maxTokens: number): void { + let totalTokens = this.countTokens(messages); + + while (totalTokens > maxTokens) { + const removedMessage = messages[1]; + + if (!removedMessage) { + break; + } + + messages.splice(1, 1); + + totalTokens -= this.modelEncoding.encode( + removedMessage.content, + ).length; + } + } } export { OpenAIService }; From 6b646bbcdee4f23a96d2d89e08f930cbd288c1ea Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:24:19 +0300 Subject: [PATCH 29/48] OV-52: + delete session handler --- backend/src/bundles/chat/chat.controller.ts | 55 +++++++++++++++++---- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index 25b3c46c8..9d106a52b 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -1,3 +1,5 @@ +import { type FastifySessionObject } from '@fastify/session'; + import { type ApiHandlerOptions, type ApiHandlerResponse, @@ -7,11 +9,9 @@ import { ApiPath } from '~/common/enums/enums.js'; import { HttpCode, HTTPMethod } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; +import { MAX_TOKEN } from './libs/constants/max-token.constant.js'; import { ChatPath, OpenAIRole } from './libs/enums/enums.js'; -import { - type GenerateTextRequestDto, - type SessionChatHistory, -} from './libs/types/types.js'; +import { type GenerateTextRequestDto } from './libs/types/types.js'; import { textGenerationValidationSchema } from './libs/validation-schemas/validation-schemas.js'; import { type OpenAIService } from './open-ai.service.js'; @@ -25,7 +25,7 @@ class ChatController extends BaseController { this.addRoute({ path: ChatPath.ROOT, - method: HTTPMethod.POST, + method: HTTPMethod.PUT, validation: { body: textGenerationValidationSchema, }, @@ -33,7 +33,7 @@ class ChatController extends BaseController { this.generateChatAnswer( options as ApiHandlerOptions<{ body: GenerateTextRequestDto; - session: SessionChatHistory; + session: FastifySessionObject; }>, ), }); @@ -44,16 +44,49 @@ class ChatController extends BaseController { handler: (options) => this.clearChat( options as ApiHandlerOptions<{ - session: SessionChatHistory; + session: FastifySessionObject; + }>, + ), + }); + + this.addRoute({ + path: ChatPath.ROOT, + method: HTTPMethod.POST, + handler: (options) => + this.deleteSession( + options as ApiHandlerOptions<{ + session: FastifySessionObject; }>, ), }); } + private deleteSession( + options: ApiHandlerOptions<{ + session: FastifySessionObject; + }>, + ): ApiHandlerResponse { + const { session } = options; + + session.destroy((error) => { + if (error) { + return { + payload: false, + status: HttpCode.INTERNAL_SERVER_ERROR, + }; + } + }); + + return { + payload: true, + status: HttpCode.OK, + }; + } + private async generateChatAnswer( options: ApiHandlerOptions<{ body: GenerateTextRequestDto; - session: SessionChatHistory; + session: FastifySessionObject; }>, ): Promise { const { body, session } = options; @@ -64,6 +97,8 @@ class ChatController extends BaseController { OpenAIRole.USER, ); + this.openAIService.deleteOldMessages(session.chatHistory, MAX_TOKEN); + const generatedText = await this.openAIService.generateText( session.chatHistory, ); @@ -82,10 +117,10 @@ class ChatController extends BaseController { private clearChat( options: ApiHandlerOptions<{ - session: SessionChatHistory; + session: FastifySessionObject; }>, ): ApiHandlerResponse { - this.openAIService.clearChatHistory(options.session); + this.openAIService.clearChatHistory(options.session.chatHistory); return { payload: true, status: HttpCode.OK, From 1c3f5efd13eb65362ede76f502b4a1ef490f76b2 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 14:54:39 +0300 Subject: [PATCH 30/48] OV-52: * openAi service --- backend/src/bundles/chat/open-ai.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/bundles/chat/open-ai.service.ts b/backend/src/bundles/chat/open-ai.service.ts index 96f79a6b9..6005a2f71 100644 --- a/backend/src/bundles/chat/open-ai.service.ts +++ b/backend/src/bundles/chat/open-ai.service.ts @@ -72,7 +72,7 @@ class OpenAIService implements OpenAIServiceModule { break; } - messages.splice(1, 1); + messages.splice(0, 1); totalTokens -= this.modelEncoding.encode( removedMessage.content, From ff6f18c2ca1488f96b74f77592454d1241b55a0e Mon Sep 17 00:00:00 2001 From: Sergiy Date: Sat, 24 Aug 2024 15:19:54 +0300 Subject: [PATCH 31/48] OV-52: * openAi service --- backend/src/bundles/chat/open-ai.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/bundles/chat/open-ai.service.ts b/backend/src/bundles/chat/open-ai.service.ts index 6005a2f71..afc307b86 100644 --- a/backend/src/bundles/chat/open-ai.service.ts +++ b/backend/src/bundles/chat/open-ai.service.ts @@ -66,7 +66,7 @@ class OpenAIService implements OpenAIServiceModule { let totalTokens = this.countTokens(messages); while (totalTokens > maxTokens) { - const removedMessage = messages[1]; + const removedMessage = messages[0]; if (!removedMessage) { break; From d400b39dbdf89a1e384c0da9c5ff403cab53194e Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 26 Aug 2024 21:31:23 +0300 Subject: [PATCH 32/48] OV-52: + chat service --- backend/src/bundles/chat/char.service.ts | 61 +++++++++++++++++++ .../chat/libs/types/chat-service.type.ts | 16 +++++ backend/src/bundles/chat/libs/types/types.ts | 1 + 3 files changed, 78 insertions(+) create mode 100644 backend/src/bundles/chat/char.service.ts create mode 100644 backend/src/bundles/chat/libs/types/chat-service.type.ts diff --git a/backend/src/bundles/chat/char.service.ts b/backend/src/bundles/chat/char.service.ts new file mode 100644 index 000000000..2753fbe37 --- /dev/null +++ b/backend/src/bundles/chat/char.service.ts @@ -0,0 +1,61 @@ +import { type ValueOf } from 'shared'; +import { type Tiktoken, encoding_for_model } from 'tiktoken'; + +import { type OpenAIRole } from './libs/enums/open-ai-role.enum.js'; +import { + type ChatService as ChatServiceT, + type Message, +} from './libs/types/types.js'; + +class ChatService implements ChatServiceT { + private modelEncoding: Tiktoken; + + public constructor() { + this.modelEncoding = encoding_for_model('gpt-4o-mini'); + } + + public addMessageToHistory( + chatHistory: Message[], + userMessage: string, + role: ValueOf, + ): void { + const newUserMessage = { + content: userMessage, + role, + }; + + chatHistory.push(newUserMessage); + } + + public clearChatHistory(messages: Message[]): void { + messages.splice(0, messages.length); + } + + private countTokens(messages: Message[]): number { + return messages.reduce( + (sum, message) => + sum + this.modelEncoding.encode(message.content).length, + 0, + ); + } + + public deleteOldMessages(messages: Message[], maxTokens: number): void { + let totalTokens = this.countTokens(messages); + + while (totalTokens > maxTokens) { + const removedMessage = messages[0]; + + if (!removedMessage) { + break; + } + + messages.splice(0, 1); + + totalTokens -= this.modelEncoding.encode( + removedMessage.content, + ).length; + } + } +} + +export { ChatService }; diff --git a/backend/src/bundles/chat/libs/types/chat-service.type.ts b/backend/src/bundles/chat/libs/types/chat-service.type.ts new file mode 100644 index 000000000..bed7e3127 --- /dev/null +++ b/backend/src/bundles/chat/libs/types/chat-service.type.ts @@ -0,0 +1,16 @@ +import { type ValueOf } from 'shared'; + +import { type OpenAIRole } from '../enums/enums.js'; +import { type Message } from './message.type.js'; + +type ChatService = { + addMessageToHistory( + chatHistory: Message[], + userMessage: string, + role: ValueOf, + ): void; + clearChatHistory(messages: Message[]): void; + deleteOldMessages(messages: Message[], maxTokens: number): void; +}; + +export { type ChatService }; diff --git a/backend/src/bundles/chat/libs/types/types.ts b/backend/src/bundles/chat/libs/types/types.ts index 0da5cca46..a77276783 100644 --- a/backend/src/bundles/chat/libs/types/types.ts +++ b/backend/src/bundles/chat/libs/types/types.ts @@ -1,3 +1,4 @@ +export { type ChatService } from './chat-service.type.js'; export { type Message } from './message.type.js'; export { type OpenAIService } from './open-ai-service.type.js'; export { type GenerateTextRequestDto } from 'shared'; From 3ef2954dac7fc3d41e93709a9331f464f0b97aa5 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 26 Aug 2024 21:32:48 +0300 Subject: [PATCH 33/48] OV-52: * openAI service --- .../chat/libs/types/open-ai-service.type.ts | 10 ---- backend/src/bundles/chat/open-ai.service.ts | 48 ------------------- 2 files changed, 58 deletions(-) diff --git a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts index a71a9b36f..9963d9ccd 100644 --- a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts +++ b/backend/src/bundles/chat/libs/types/open-ai-service.type.ts @@ -1,17 +1,7 @@ -import { type ValueOf } from 'shared'; - -import { type OpenAIRole } from '../enums/enums.js'; import { type Message } from './message.type.js'; type OpenAIService = { generateText(messages: Message[]): Promise; - addMessageToHistory( - chatHistory: Message[], - userMessage: string, - role: ValueOf, - ): void; - clearChatHistory(messages: Message[]): void; - deleteOldMessages(messages: Message[], maxTokens: number): void; }; export { type OpenAIService }; diff --git a/backend/src/bundles/chat/open-ai.service.ts b/backend/src/bundles/chat/open-ai.service.ts index afc307b86..e863362cb 100644 --- a/backend/src/bundles/chat/open-ai.service.ts +++ b/backend/src/bundles/chat/open-ai.service.ts @@ -1,11 +1,8 @@ import OpenAI, { type OpenAI as OpenAIType } from 'openai'; -import { type ValueOf } from 'shared'; -import { type Tiktoken, encoding_for_model } from 'tiktoken'; import { type BaseConfig } from '~/common/config/base-config.package.js'; import { CHAT_MODEL, MAX_TOKEN } from './libs/constants/constants.js'; -import { type OpenAIRole } from './libs/enums/open-ai-role.enum.js'; import { type Message, type OpenAIService as OpenAIServiceModule, @@ -14,12 +11,10 @@ import { class OpenAIService implements OpenAIServiceModule { private config: BaseConfig; private openAi: OpenAIType; - private modelEncoding: Tiktoken; public constructor(config: BaseConfig) { this.config = config; this.openAi = this.initOpenAi(); - this.modelEncoding = encoding_for_model('gpt-4o-mini'); } private initOpenAi = (): OpenAIType => { @@ -28,23 +23,6 @@ class OpenAIService implements OpenAIServiceModule { }); }; - public addMessageToHistory( - chatHistory: Message[], - userMessage: string, - role: ValueOf, - ): void { - const newUserMessage = { - content: userMessage, - role, - }; - - chatHistory.push(newUserMessage); - } - - public clearChatHistory(messages: Message[]): void { - messages.splice(0, messages.length); - } - public async generateText(messages: Message[]): Promise { const completion = await this.openAi.chat.completions.create({ messages, @@ -53,32 +31,6 @@ class OpenAIService implements OpenAIServiceModule { }); return completion.choices[0]?.message.content || ''; } - - private countTokens(messages: Message[]): number { - return messages.reduce( - (sum, message) => - sum + this.modelEncoding.encode(message.content).length, - 0, - ); - } - - public deleteOldMessages(messages: Message[], maxTokens: number): void { - let totalTokens = this.countTokens(messages); - - while (totalTokens > maxTokens) { - const removedMessage = messages[0]; - - if (!removedMessage) { - break; - } - - messages.splice(0, 1); - - totalTokens -= this.modelEncoding.encode( - removedMessage.content, - ).length; - } - } } export { OpenAIService }; From e0f6a4722138f301eacaa8427d37cdd8c24e4fbd Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 26 Aug 2024 21:34:11 +0300 Subject: [PATCH 34/48] OV-52: * chat controller --- backend/src/bundles/chat/chat.controller.ts | 52 ++++++--------------- backend/src/bundles/chat/chat.ts | 4 +- 2 files changed, 16 insertions(+), 40 deletions(-) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index 9d106a52b..695ff541a 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -9,6 +9,7 @@ import { ApiPath } from '~/common/enums/enums.js'; import { HttpCode, HTTPMethod } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; +import { type ChatService } from './char.service.js'; import { MAX_TOKEN } from './libs/constants/max-token.constant.js'; import { ChatPath, OpenAIRole } from './libs/enums/enums.js'; import { type GenerateTextRequestDto } from './libs/types/types.js'; @@ -17,15 +18,21 @@ import { type OpenAIService } from './open-ai.service.js'; class ChatController extends BaseController { private openAIService: OpenAIService; + private chatService: ChatService; - public constructor(logger: Logger, openAIService: OpenAIService) { + public constructor( + logger: Logger, + openAIService: OpenAIService, + chatService: ChatService, + ) { super(logger, ApiPath.CHAT); this.openAIService = openAIService; + this.chatService = chatService; this.addRoute({ path: ChatPath.ROOT, - method: HTTPMethod.PUT, + method: HTTPMethod.POST, validation: { body: textGenerationValidationSchema, }, @@ -48,39 +55,6 @@ class ChatController extends BaseController { }>, ), }); - - this.addRoute({ - path: ChatPath.ROOT, - method: HTTPMethod.POST, - handler: (options) => - this.deleteSession( - options as ApiHandlerOptions<{ - session: FastifySessionObject; - }>, - ), - }); - } - - private deleteSession( - options: ApiHandlerOptions<{ - session: FastifySessionObject; - }>, - ): ApiHandlerResponse { - const { session } = options; - - session.destroy((error) => { - if (error) { - return { - payload: false, - status: HttpCode.INTERNAL_SERVER_ERROR, - }; - } - }); - - return { - payload: true, - status: HttpCode.OK, - }; } private async generateChatAnswer( @@ -91,19 +65,19 @@ class ChatController extends BaseController { ): Promise { const { body, session } = options; - this.openAIService.addMessageToHistory( + this.chatService.addMessageToHistory( session.chatHistory, body.message, OpenAIRole.USER, ); - this.openAIService.deleteOldMessages(session.chatHistory, MAX_TOKEN); + this.chatService.deleteOldMessages(session.chatHistory, MAX_TOKEN); const generatedText = await this.openAIService.generateText( session.chatHistory, ); - this.openAIService.addMessageToHistory( + this.chatService.addMessageToHistory( session.chatHistory, generatedText, OpenAIRole.ASSISTANT, @@ -120,7 +94,7 @@ class ChatController extends BaseController { session: FastifySessionObject; }>, ): ApiHandlerResponse { - this.openAIService.clearChatHistory(options.session.chatHistory); + this.chatService.clearChatHistory(options.session.chatHistory); return { payload: true, status: HttpCode.OK, diff --git a/backend/src/bundles/chat/chat.ts b/backend/src/bundles/chat/chat.ts index a77b520d5..3e9463ef8 100644 --- a/backend/src/bundles/chat/chat.ts +++ b/backend/src/bundles/chat/chat.ts @@ -1,10 +1,12 @@ import { config } from '~/common/config/config.js'; import { logger } from '~/common/logger/logger.js'; +import { ChatService } from './char.service.js'; import { ChatController } from './chat.controller.js'; import { OpenAIService } from './open-ai.service.js'; const openAIService = new OpenAIService(config); -const chatController = new ChatController(logger, openAIService); +const chatService = new ChatService(); +const chatController = new ChatController(logger, openAIService, chatService); export { chatController }; From 1029592ecfcd7362552fd756da799ce6703f3451 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 26 Aug 2024 22:01:07 +0300 Subject: [PATCH 35/48] OV-52: * chat service --- backend/src/bundles/chat/char.service.ts | 19 ++++++++++--------- .../chat/libs/types/chat-service.type.ts | 1 - 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/backend/src/bundles/chat/char.service.ts b/backend/src/bundles/chat/char.service.ts index 2753fbe37..85646a66f 100644 --- a/backend/src/bundles/chat/char.service.ts +++ b/backend/src/bundles/chat/char.service.ts @@ -27,10 +27,6 @@ class ChatService implements ChatServiceT { chatHistory.push(newUserMessage); } - public clearChatHistory(messages: Message[]): void { - messages.splice(0, messages.length); - } - private countTokens(messages: Message[]): number { return messages.reduce( (sum, message) => @@ -39,22 +35,27 @@ class ChatService implements ChatServiceT { ); } - public deleteOldMessages(messages: Message[], maxTokens: number): void { + public deleteOldMessages( + messages: Message[], + maxTokens: number, + ): Message[] { let totalTokens = this.countTokens(messages); + let updatedMessages = [...messages]; - while (totalTokens > maxTokens) { - const removedMessage = messages[0]; + while (totalTokens > maxTokens && updatedMessages.length > 0) { + const [removedMessage, ...rest] = updatedMessages; + updatedMessages = rest; if (!removedMessage) { break; } - messages.splice(0, 1); - totalTokens -= this.modelEncoding.encode( removedMessage.content, ).length; } + + return updatedMessages; } } diff --git a/backend/src/bundles/chat/libs/types/chat-service.type.ts b/backend/src/bundles/chat/libs/types/chat-service.type.ts index bed7e3127..ac38ed591 100644 --- a/backend/src/bundles/chat/libs/types/chat-service.type.ts +++ b/backend/src/bundles/chat/libs/types/chat-service.type.ts @@ -9,7 +9,6 @@ type ChatService = { userMessage: string, role: ValueOf, ): void; - clearChatHistory(messages: Message[]): void; deleteOldMessages(messages: Message[], maxTokens: number): void; }; From dec288083aa58e1e18fbc81b8c5b88c890d8f41d Mon Sep 17 00:00:00 2001 From: Sergiy Date: Mon, 26 Aug 2024 22:03:35 +0300 Subject: [PATCH 36/48] OV-52: * chat controller --- backend/src/bundles/chat/chat.controller.ts | 42 +++++++++++++++++++-- shared/src/bundles/chat/enums/chat.enum.ts | 2 + 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index 695ff541a..48fca22dd 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -46,7 +46,7 @@ class ChatController extends BaseController { }); this.addRoute({ - path: ChatPath.ROOT, + path: ChatPath.CLEAR, method: HTTPMethod.DELETE, handler: (options) => this.clearChat( @@ -55,6 +55,17 @@ class ChatController extends BaseController { }>, ), }); + + this.addRoute({ + path: ChatPath.END, + method: HTTPMethod.DELETE, + handler: (options) => + this.deleteSession( + options as ApiHandlerOptions<{ + session: FastifySessionObject; + }>, + ), + }); } private async generateChatAnswer( @@ -71,7 +82,10 @@ class ChatController extends BaseController { OpenAIRole.USER, ); - this.chatService.deleteOldMessages(session.chatHistory, MAX_TOKEN); + session.chatHistory = this.chatService.deleteOldMessages( + session.chatHistory, + MAX_TOKEN, + ); const generatedText = await this.openAIService.generateText( session.chatHistory, @@ -94,7 +108,29 @@ class ChatController extends BaseController { session: FastifySessionObject; }>, ): ApiHandlerResponse { - this.chatService.clearChatHistory(options.session.chatHistory); + options.session.chatHistory = []; + return { + payload: true, + status: HttpCode.OK, + }; + } + + private deleteSession( + options: ApiHandlerOptions<{ + session: FastifySessionObject; + }>, + ): ApiHandlerResponse { + const { session } = options; + + session.destroy((error) => { + if (error) { + return { + payload: false, + status: HttpCode.INTERNAL_SERVER_ERROR, + }; + } + }); + return { payload: true, status: HttpCode.OK, diff --git a/shared/src/bundles/chat/enums/chat.enum.ts b/shared/src/bundles/chat/enums/chat.enum.ts index 5580c6237..e6a959781 100644 --- a/shared/src/bundles/chat/enums/chat.enum.ts +++ b/shared/src/bundles/chat/enums/chat.enum.ts @@ -1,5 +1,7 @@ const ChatPath = { ROOT: '/', + END: '/end', + CLEAR: '/clear', } as const; export { ChatPath }; From 053a0dd9212956c67385d125f9e961afe462e2c0 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 00:32:31 +0300 Subject: [PATCH 37/48] OV-52: * move OpenAi service --- backend/src/bundles/chat/char.service.ts | 6 ++++-- backend/src/bundles/chat/chat.controller.ts | 9 ++++++--- backend/src/bundles/chat/chat.ts | 4 +--- backend/src/bundles/chat/libs/types/chat-service.type.ts | 3 ++- backend/src/bundles/chat/libs/types/message.type.ts | 2 +- backend/src/bundles/chat/libs/types/types.ts | 1 - .../open-ai}/libs/constants/chat-model.constant.ts | 0 .../services/open-ai}/libs/constants/constants.ts | 0 .../open-ai}/libs/constants/max-token.constant.ts | 0 .../chat => common/services/open-ai}/libs/enums/enums.ts | 0 .../services/open-ai}/libs/enums/open-ai-role.enum.ts | 0 .../services/open-ai}/libs/types/open-ai-service.type.ts | 2 +- backend/src/common/services/open-ai/libs/types/types.ts | 1 + .../chat => common/services/open-ai}/open-ai.service.ts | 8 +++----- backend/src/common/services/services.ts | 5 ++++- 15 files changed, 23 insertions(+), 18 deletions(-) rename backend/src/{bundles/chat => common/services/open-ai}/libs/constants/chat-model.constant.ts (100%) rename backend/src/{bundles/chat => common/services/open-ai}/libs/constants/constants.ts (100%) rename backend/src/{bundles/chat => common/services/open-ai}/libs/constants/max-token.constant.ts (100%) rename backend/src/{bundles/chat => common/services/open-ai}/libs/enums/enums.ts (100%) rename backend/src/{bundles/chat => common/services/open-ai}/libs/enums/open-ai-role.enum.ts (100%) rename backend/src/{bundles/chat => common/services/open-ai}/libs/types/open-ai-service.type.ts (63%) create mode 100644 backend/src/common/services/open-ai/libs/types/types.ts rename backend/src/{bundles/chat => common/services/open-ai}/open-ai.service.ts (81%) diff --git a/backend/src/bundles/chat/char.service.ts b/backend/src/bundles/chat/char.service.ts index 85646a66f..2c2cb0909 100644 --- a/backend/src/bundles/chat/char.service.ts +++ b/backend/src/bundles/chat/char.service.ts @@ -1,7 +1,9 @@ import { type ValueOf } from 'shared'; import { type Tiktoken, encoding_for_model } from 'tiktoken'; -import { type OpenAIRole } from './libs/enums/open-ai-role.enum.js'; +import { CHAT_MODEL } from '~/common/services/open-ai/libs/constants/constants.js'; +import { type OpenAIRole } from '~/common/services/open-ai/libs/enums/enums.js'; + import { type ChatService as ChatServiceT, type Message, @@ -11,7 +13,7 @@ class ChatService implements ChatServiceT { private modelEncoding: Tiktoken; public constructor() { - this.modelEncoding = encoding_for_model('gpt-4o-mini'); + this.modelEncoding = encoding_for_model(CHAT_MODEL); } public addMessageToHistory( diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index 48fca22dd..26faf4511 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -9,12 +9,15 @@ import { ApiPath } from '~/common/enums/enums.js'; import { HttpCode, HTTPMethod } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; +import { MAX_TOKEN } from '../../common/services/open-ai/libs/constants/max-token.constant.js'; +import { + ChatPath, + OpenAIRole, +} from '../../common/services/open-ai/libs/enums/enums.js'; +import { type OpenAIService } from '../../common/services/open-ai/open-ai.service.js'; import { type ChatService } from './char.service.js'; -import { MAX_TOKEN } from './libs/constants/max-token.constant.js'; -import { ChatPath, OpenAIRole } from './libs/enums/enums.js'; import { type GenerateTextRequestDto } from './libs/types/types.js'; import { textGenerationValidationSchema } from './libs/validation-schemas/validation-schemas.js'; -import { type OpenAIService } from './open-ai.service.js'; class ChatController extends BaseController { private openAIService: OpenAIService; diff --git a/backend/src/bundles/chat/chat.ts b/backend/src/bundles/chat/chat.ts index 3e9463ef8..b87f6795f 100644 --- a/backend/src/bundles/chat/chat.ts +++ b/backend/src/bundles/chat/chat.ts @@ -1,11 +1,9 @@ -import { config } from '~/common/config/config.js'; import { logger } from '~/common/logger/logger.js'; +import { openAIService } from '~/common/services/services.js'; import { ChatService } from './char.service.js'; import { ChatController } from './chat.controller.js'; -import { OpenAIService } from './open-ai.service.js'; -const openAIService = new OpenAIService(config); const chatService = new ChatService(); const chatController = new ChatController(logger, openAIService, chatService); diff --git a/backend/src/bundles/chat/libs/types/chat-service.type.ts b/backend/src/bundles/chat/libs/types/chat-service.type.ts index ac38ed591..508b3ad62 100644 --- a/backend/src/bundles/chat/libs/types/chat-service.type.ts +++ b/backend/src/bundles/chat/libs/types/chat-service.type.ts @@ -1,6 +1,7 @@ import { type ValueOf } from 'shared'; -import { type OpenAIRole } from '../enums/enums.js'; +import { type OpenAIRole } from '~/common/services/open-ai/libs/enums/enums.js'; + import { type Message } from './message.type.js'; type ChatService = { diff --git a/backend/src/bundles/chat/libs/types/message.type.ts b/backend/src/bundles/chat/libs/types/message.type.ts index 1bd4ee658..593eff87b 100644 --- a/backend/src/bundles/chat/libs/types/message.type.ts +++ b/backend/src/bundles/chat/libs/types/message.type.ts @@ -1,6 +1,6 @@ import { type ValueOf } from 'shared'; -import { type OpenAIRole } from '../enums/enums.js'; +import { type OpenAIRole } from '~/common/services/open-ai/libs/enums/enums.js'; type Message = { role: ValueOf; diff --git a/backend/src/bundles/chat/libs/types/types.ts b/backend/src/bundles/chat/libs/types/types.ts index a77276783..f1c0dba0e 100644 --- a/backend/src/bundles/chat/libs/types/types.ts +++ b/backend/src/bundles/chat/libs/types/types.ts @@ -1,4 +1,3 @@ export { type ChatService } from './chat-service.type.js'; export { type Message } from './message.type.js'; -export { type OpenAIService } from './open-ai-service.type.js'; export { type GenerateTextRequestDto } from 'shared'; diff --git a/backend/src/bundles/chat/libs/constants/chat-model.constant.ts b/backend/src/common/services/open-ai/libs/constants/chat-model.constant.ts similarity index 100% rename from backend/src/bundles/chat/libs/constants/chat-model.constant.ts rename to backend/src/common/services/open-ai/libs/constants/chat-model.constant.ts diff --git a/backend/src/bundles/chat/libs/constants/constants.ts b/backend/src/common/services/open-ai/libs/constants/constants.ts similarity index 100% rename from backend/src/bundles/chat/libs/constants/constants.ts rename to backend/src/common/services/open-ai/libs/constants/constants.ts diff --git a/backend/src/bundles/chat/libs/constants/max-token.constant.ts b/backend/src/common/services/open-ai/libs/constants/max-token.constant.ts similarity index 100% rename from backend/src/bundles/chat/libs/constants/max-token.constant.ts rename to backend/src/common/services/open-ai/libs/constants/max-token.constant.ts diff --git a/backend/src/bundles/chat/libs/enums/enums.ts b/backend/src/common/services/open-ai/libs/enums/enums.ts similarity index 100% rename from backend/src/bundles/chat/libs/enums/enums.ts rename to backend/src/common/services/open-ai/libs/enums/enums.ts diff --git a/backend/src/bundles/chat/libs/enums/open-ai-role.enum.ts b/backend/src/common/services/open-ai/libs/enums/open-ai-role.enum.ts similarity index 100% rename from backend/src/bundles/chat/libs/enums/open-ai-role.enum.ts rename to backend/src/common/services/open-ai/libs/enums/open-ai-role.enum.ts diff --git a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts b/backend/src/common/services/open-ai/libs/types/open-ai-service.type.ts similarity index 63% rename from backend/src/bundles/chat/libs/types/open-ai-service.type.ts rename to backend/src/common/services/open-ai/libs/types/open-ai-service.type.ts index 9963d9ccd..5554a67f3 100644 --- a/backend/src/bundles/chat/libs/types/open-ai-service.type.ts +++ b/backend/src/common/services/open-ai/libs/types/open-ai-service.type.ts @@ -1,4 +1,4 @@ -import { type Message } from './message.type.js'; +import { type Message } from '~/bundles/chat/libs/types/types.js'; type OpenAIService = { generateText(messages: Message[]): Promise; diff --git a/backend/src/common/services/open-ai/libs/types/types.ts b/backend/src/common/services/open-ai/libs/types/types.ts new file mode 100644 index 000000000..332335022 --- /dev/null +++ b/backend/src/common/services/open-ai/libs/types/types.ts @@ -0,0 +1 @@ +export { type OpenAIService } from './open-ai-service.type.js'; diff --git a/backend/src/bundles/chat/open-ai.service.ts b/backend/src/common/services/open-ai/open-ai.service.ts similarity index 81% rename from backend/src/bundles/chat/open-ai.service.ts rename to backend/src/common/services/open-ai/open-ai.service.ts index e863362cb..81b3d8556 100644 --- a/backend/src/bundles/chat/open-ai.service.ts +++ b/backend/src/common/services/open-ai/open-ai.service.ts @@ -2,13 +2,11 @@ import OpenAI, { type OpenAI as OpenAIType } from 'openai'; import { type BaseConfig } from '~/common/config/base-config.package.js'; +import { type Message } from '../../../bundles/chat/libs/types/types.js'; import { CHAT_MODEL, MAX_TOKEN } from './libs/constants/constants.js'; -import { - type Message, - type OpenAIService as OpenAIServiceModule, -} from './libs/types/types.js'; +import { type OpenAIService as OpenAIServiceType } from './libs/types/types.js'; -class OpenAIService implements OpenAIServiceModule { +class OpenAIService implements OpenAIServiceType { private config: BaseConfig; private openAi: OpenAIType; diff --git a/backend/src/common/services/services.ts b/backend/src/common/services/services.ts index 2be4c1278..037867ad1 100644 --- a/backend/src/common/services/services.ts +++ b/backend/src/common/services/services.ts @@ -1,5 +1,8 @@ +import { config } from '../config/config.js'; import { CryptService } from './crypt/crypt.service.js'; +import { OpenAIService } from './open-ai/open-ai.service.js'; +const openAIService = new OpenAIService(config); const cryptService = new CryptService(); -export { cryptService }; +export { cryptService, openAIService }; From 6f50b86e63c927f11a468e6ff37c32877dcaa961 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 00:35:28 +0300 Subject: [PATCH 38/48] OV-52: * chat controller --- backend/src/bundles/chat/chat.controller.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index 26faf4511..a892d8b98 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -8,8 +8,8 @@ import { import { ApiPath } from '~/common/enums/enums.js'; import { HttpCode, HTTPMethod } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; +import { MAX_TOKEN } from '~/common/services/open-ai/libs/constants/constants.js'; -import { MAX_TOKEN } from '../../common/services/open-ai/libs/constants/max-token.constant.js'; import { ChatPath, OpenAIRole, From 1dbd3836645a85c02bf4e23a06e587fb8ebc4af2 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 13:29:05 +0300 Subject: [PATCH 39/48] OV-52: * rename --- backend/src/bundles/chat/chat.controller.ts | 2 +- backend/src/bundles/chat/{char.service.ts => chat.service.ts} | 0 backend/src/bundles/chat/chat.ts | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename backend/src/bundles/chat/{char.service.ts => chat.service.ts} (100%) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index a892d8b98..2e3cef8cf 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -15,7 +15,7 @@ import { OpenAIRole, } from '../../common/services/open-ai/libs/enums/enums.js'; import { type OpenAIService } from '../../common/services/open-ai/open-ai.service.js'; -import { type ChatService } from './char.service.js'; +import { type ChatService } from './chat.service.js'; import { type GenerateTextRequestDto } from './libs/types/types.js'; import { textGenerationValidationSchema } from './libs/validation-schemas/validation-schemas.js'; diff --git a/backend/src/bundles/chat/char.service.ts b/backend/src/bundles/chat/chat.service.ts similarity index 100% rename from backend/src/bundles/chat/char.service.ts rename to backend/src/bundles/chat/chat.service.ts diff --git a/backend/src/bundles/chat/chat.ts b/backend/src/bundles/chat/chat.ts index b87f6795f..cf87e093b 100644 --- a/backend/src/bundles/chat/chat.ts +++ b/backend/src/bundles/chat/chat.ts @@ -1,8 +1,8 @@ import { logger } from '~/common/logger/logger.js'; import { openAIService } from '~/common/services/services.js'; -import { ChatService } from './char.service.js'; import { ChatController } from './chat.controller.js'; +import { ChatService } from './chat.service.js'; const chatService = new ChatService(); const chatController = new ChatController(logger, openAIService, chatService); From 222d36e9775262c7abadec2b6bb947e7b4480c00 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 14:23:18 +0300 Subject: [PATCH 40/48] OV-52: + swagger docs --- backend/src/bundles/chat/chat.controller.ts | 83 ++++++++++++++++++++- 1 file changed, 79 insertions(+), 4 deletions(-) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index 2e3cef8cf..c6dd76ed6 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -71,6 +71,33 @@ class ChatController extends BaseController { }); } + /** + * @swagger + * /chat/: + * post: + * description: Returns generated text by Open AI + * requestBody: + * description: User message + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * message: + * type: string + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * type: object + * properties: + * generatedText: + * type: string + */ + private async generateChatAnswer( options: ApiHandlerOptions<{ body: GenerateTextRequestDto; @@ -101,11 +128,31 @@ class ChatController extends BaseController { ); return { - payload: generatedText, + payload: { generatedText }, status: HttpCode.OK, }; } + /** + * @swagger + * /chat/clear: + * delete: + * description: Clears chat history + * requestBody: + * description: User message + * required: false + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * type: object + * properties: + * isCleared: + * type: boolean + */ + private clearChat( options: ApiHandlerOptions<{ session: FastifySessionObject; @@ -113,11 +160,39 @@ class ChatController extends BaseController { ): ApiHandlerResponse { options.session.chatHistory = []; return { - payload: true, + payload: { isCleared: true }, status: HttpCode.OK, }; } + /** + * @swagger + * /chat/end: + * delete: + * description: Clears chat history + * requestBody: + * description: User message + * required: false + * responses: + * 200: + * description: Successful operation + * content: + * application/json: + * schema: + * type: object + * properties: + * isDeleted: + * type: boolean + * 500: + * description: Failed operation + * content: + * application/json: + * schema: + * type: object + * properties: + * isDeleted: + * type: boolean + */ private deleteSession( options: ApiHandlerOptions<{ session: FastifySessionObject; @@ -128,14 +203,14 @@ class ChatController extends BaseController { session.destroy((error) => { if (error) { return { - payload: false, + payload: { isDeleted: false }, status: HttpCode.INTERNAL_SERVER_ERROR, }; } }); return { - payload: true, + payload: { isDeleted: true }, status: HttpCode.OK, }; } From 14cb9f3d1c33fe78b5c8e51f1de0f6ef438b1fd7 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 14:42:04 +0300 Subject: [PATCH 41/48] OV-52: * .env.example --- backend/.env.example | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/backend/.env.example b/backend/.env.example index d9f0d5547..b98e1e61d 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -11,3 +11,13 @@ DB_CONNECTION_STRING=[db_client]://[db_username]:[db_user_password]@localhost:[d DB_DIALECT=pg DB_POOL_MIN=2 DB_POOL_MAX=10 + +# +# OPEN AI +# +OPEN_AI_KEY='' + +# +# SESSION +# +SESSION_KEY="SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY" From 623fee7f8f05e4d6bfdc24fcc88bda104bc1bd80 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 16:36:20 +0300 Subject: [PATCH 42/48] OV-52: - as const --- .../services/open-ai/libs/constants/chat-model.constant.ts | 2 +- .../services/open-ai/libs/constants/max-token.constant.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/src/common/services/open-ai/libs/constants/chat-model.constant.ts b/backend/src/common/services/open-ai/libs/constants/chat-model.constant.ts index 76241089d..385b505d5 100644 --- a/backend/src/common/services/open-ai/libs/constants/chat-model.constant.ts +++ b/backend/src/common/services/open-ai/libs/constants/chat-model.constant.ts @@ -1,3 +1,3 @@ -const CHAT_MODEL = 'gpt-4o-mini' as const; +const CHAT_MODEL = 'gpt-4o-mini'; export { CHAT_MODEL }; diff --git a/backend/src/common/services/open-ai/libs/constants/max-token.constant.ts b/backend/src/common/services/open-ai/libs/constants/max-token.constant.ts index dcc301f98..e403fe4b1 100644 --- a/backend/src/common/services/open-ai/libs/constants/max-token.constant.ts +++ b/backend/src/common/services/open-ai/libs/constants/max-token.constant.ts @@ -1,3 +1,3 @@ -const MAX_TOKEN = 16_000 as const; +const MAX_TOKEN = 16_000; export { MAX_TOKEN }; From 567bd8b087cf075aeec2f6e2df6bfa2eb91ab73c Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 16:45:18 +0300 Subject: [PATCH 43/48] OV-52: * chat enum --- shared/src/bundles/chat/enums/chat.enum.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/shared/src/bundles/chat/enums/chat.enum.ts b/shared/src/bundles/chat/enums/chat.enum.ts index e6a959781..5580c6237 100644 --- a/shared/src/bundles/chat/enums/chat.enum.ts +++ b/shared/src/bundles/chat/enums/chat.enum.ts @@ -1,7 +1,5 @@ const ChatPath = { ROOT: '/', - END: '/end', - CLEAR: '/clear', } as const; export { ChatPath }; From 37664fb46732a17053cff6ce7db73e9f3a8b5a21 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 16:47:35 +0300 Subject: [PATCH 44/48] OV-52: * chat service --- backend/src/bundles/chat/chat.service.ts | 4 ++-- backend/src/bundles/chat/libs/types/chat-service.type.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/bundles/chat/chat.service.ts b/backend/src/bundles/chat/chat.service.ts index 2c2cb0909..d8451196b 100644 --- a/backend/src/bundles/chat/chat.service.ts +++ b/backend/src/bundles/chat/chat.service.ts @@ -20,13 +20,13 @@ class ChatService implements ChatServiceT { chatHistory: Message[], userMessage: string, role: ValueOf, - ): void { + ): Message[] { const newUserMessage = { content: userMessage, role, }; - chatHistory.push(newUserMessage); + return [...chatHistory, newUserMessage]; } private countTokens(messages: Message[]): number { diff --git a/backend/src/bundles/chat/libs/types/chat-service.type.ts b/backend/src/bundles/chat/libs/types/chat-service.type.ts index 508b3ad62..e1371d9b9 100644 --- a/backend/src/bundles/chat/libs/types/chat-service.type.ts +++ b/backend/src/bundles/chat/libs/types/chat-service.type.ts @@ -9,7 +9,7 @@ type ChatService = { chatHistory: Message[], userMessage: string, role: ValueOf, - ): void; + ): Message[]; deleteOldMessages(messages: Message[], maxTokens: number): void; }; From 08d1e70716e818913a5d3c8f4419d9975204ed48 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 16:48:50 +0300 Subject: [PATCH 45/48] OV-52: * chat controller --- backend/src/bundles/chat/chat.controller.ts | 51 ++------------------- 1 file changed, 4 insertions(+), 47 deletions(-) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index c6dd76ed6..ca161c2d9 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -49,18 +49,7 @@ class ChatController extends BaseController { }); this.addRoute({ - path: ChatPath.CLEAR, - method: HTTPMethod.DELETE, - handler: (options) => - this.clearChat( - options as ApiHandlerOptions<{ - session: FastifySessionObject; - }>, - ), - }); - - this.addRoute({ - path: ChatPath.END, + path: ChatPath.ROOT, method: HTTPMethod.DELETE, handler: (options) => this.deleteSession( @@ -106,7 +95,7 @@ class ChatController extends BaseController { ): Promise { const { body, session } = options; - this.chatService.addMessageToHistory( + session.chatHistory = this.chatService.addMessageToHistory( session.chatHistory, body.message, OpenAIRole.USER, @@ -121,7 +110,7 @@ class ChatController extends BaseController { session.chatHistory, ); - this.chatService.addMessageToHistory( + session.chatHistory = this.chatService.addMessageToHistory( session.chatHistory, generatedText, OpenAIRole.ASSISTANT, @@ -135,39 +124,7 @@ class ChatController extends BaseController { /** * @swagger - * /chat/clear: - * delete: - * description: Clears chat history - * requestBody: - * description: User message - * required: false - * responses: - * 200: - * description: Successful operation - * content: - * application/json: - * schema: - * type: object - * properties: - * isCleared: - * type: boolean - */ - - private clearChat( - options: ApiHandlerOptions<{ - session: FastifySessionObject; - }>, - ): ApiHandlerResponse { - options.session.chatHistory = []; - return { - payload: { isCleared: true }, - status: HttpCode.OK, - }; - } - - /** - * @swagger - * /chat/end: + * /chat/: * delete: * description: Clears chat history * requestBody: From 0f6688773627221a89f76f181d882de1810caad6 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Tue, 27 Aug 2024 16:51:42 +0300 Subject: [PATCH 46/48] OV-52: * openai service --- backend/src/common/services/open-ai/open-ai.service.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/src/common/services/open-ai/open-ai.service.ts b/backend/src/common/services/open-ai/open-ai.service.ts index 81b3d8556..980a10f8c 100644 --- a/backend/src/common/services/open-ai/open-ai.service.ts +++ b/backend/src/common/services/open-ai/open-ai.service.ts @@ -1,4 +1,4 @@ -import OpenAI, { type OpenAI as OpenAIType } from 'openai'; +import OpenAI from 'openai'; import { type BaseConfig } from '~/common/config/base-config.package.js'; @@ -8,14 +8,14 @@ import { type OpenAIService as OpenAIServiceType } from './libs/types/types.js'; class OpenAIService implements OpenAIServiceType { private config: BaseConfig; - private openAi: OpenAIType; + private openAi: OpenAI; public constructor(config: BaseConfig) { this.config = config; this.openAi = this.initOpenAi(); } - private initOpenAi = (): OpenAIType => { + private initOpenAi = (): OpenAI => { return new OpenAI({ apiKey: this.config.ENV.APP.OPEN_AI_KEY, }); From a1eeb577ed0c6ad21f53f3a26b124de3a02f1180 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Wed, 28 Aug 2024 13:29:24 +0300 Subject: [PATCH 47/48] OV-52: * .env.example --- backend/.env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/.env.example b/backend/.env.example index 54907ec9d..41fd4ce5e 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -24,9 +24,9 @@ AWS_CLOUDFRONT_DOMAIN_ID=d2tm5q3cg1nlwf # # OPEN AI # -OPEN_AI_KEY='' +OPEN_AI_KEY=SOME_SECRET_KEY # # SESSION # -SESSION_KEY="SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY_SECRET_KEY" +SESSION_KEY=SOME_SECRET_KEY From ded87cc6dd1cd456510aedab0b1121a47c70ba01 Mon Sep 17 00:00:00 2001 From: Sergiy Date: Wed, 28 Aug 2024 20:01:49 +0300 Subject: [PATCH 48/48] OV-52: * exports --- backend/src/bundles/chat/chat.controller.ts | 6 +++--- backend/src/common/plugins/session/session.plugin.ts | 3 +-- backend/src/common/server-application/base-server-app.ts | 2 +- backend/src/common/services/services.ts | 3 ++- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/src/bundles/chat/chat.controller.ts b/backend/src/bundles/chat/chat.controller.ts index ca161c2d9..120e3c906 100644 --- a/backend/src/bundles/chat/chat.controller.ts +++ b/backend/src/bundles/chat/chat.controller.ts @@ -9,12 +9,12 @@ import { ApiPath } from '~/common/enums/enums.js'; import { HttpCode, HTTPMethod } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; import { MAX_TOKEN } from '~/common/services/open-ai/libs/constants/constants.js'; - import { ChatPath, OpenAIRole, -} from '../../common/services/open-ai/libs/enums/enums.js'; -import { type OpenAIService } from '../../common/services/open-ai/open-ai.service.js'; +} from '~/common/services/open-ai/libs/enums/enums.js'; +import { type OpenAIService } from '~/common/services/open-ai/open-ai.service.js'; + import { type ChatService } from './chat.service.js'; import { type GenerateTextRequestDto } from './libs/types/types.js'; import { textGenerationValidationSchema } from './libs/validation-schemas/validation-schemas.js'; diff --git a/backend/src/common/plugins/session/session.plugin.ts b/backend/src/common/plugins/session/session.plugin.ts index 047a7376e..c09beb8c3 100644 --- a/backend/src/common/plugins/session/session.plugin.ts +++ b/backend/src/common/plugins/session/session.plugin.ts @@ -3,8 +3,7 @@ import fastifySession from '@fastify/session'; import fp from 'fastify-plugin'; import { type BaseConfig } from '~/common/config/base-config.package.js'; - -import { ControllerHook } from '../libs/enums/enums.js'; +import { ControllerHook } from '~/common/plugins/libs/enums/enums.js'; type Options = { services: { diff --git a/backend/src/common/server-application/base-server-app.ts b/backend/src/common/server-application/base-server-app.ts index af0cf18be..8cba5608a 100644 --- a/backend/src/common/server-application/base-server-app.ts +++ b/backend/src/common/server-application/base-server-app.ts @@ -17,13 +17,13 @@ import { ServerErrorType } from '~/common/enums/enums.js'; import { type ValidationError } from '~/common/exceptions/exceptions.js'; import { HttpCode, HttpError } from '~/common/http/http.js'; import { type Logger } from '~/common/logger/logger.js'; +import { session } from '~/common/plugins/session/session.plugin.js'; import { type ServerCommonErrorResponse, type ServerValidationErrorResponse, type ValidationSchema, } from '~/common/types/types.js'; -import { session } from '../plugins/plugins.js'; import { type ServerApp, type ServerAppApi, diff --git a/backend/src/common/services/services.ts b/backend/src/common/services/services.ts index 82acc8535..5a657b695 100644 --- a/backend/src/common/services/services.ts +++ b/backend/src/common/services/services.ts @@ -1,4 +1,5 @@ -import { config } from '../config/config.js'; +import { config } from '~/common/config/config.js'; + import { CryptService } from './crypt/crypt.service.js'; import { FileService } from './file/file.service.js'; import { OpenAIService } from './open-ai/open-ai.service.js';