Sfoglia il codice sorgente

Refactor of OpenAI Client

Shun Miyazawa 1 anno fa
parent
commit
26f2be5794

+ 17 - 11
apps/app/src/server/routes/apiv3/ai-integration/rebuild-vector-store.ts

@@ -1,3 +1,4 @@
+import { ErrorV3 } from '@growi/core/dist/models';
 import type { Request, RequestHandler } from 'express';
 import type { ValidationChain } from 'express-validator';
 
@@ -27,20 +28,25 @@ export const rebuildVectorStoreHandlersFactory: RebuildVectorStoreFactory = (cro
     accessTokenParser, loginRequiredStrictly, adminRequired, certifyAiService, validator, apiV3FormValidator,
     async(req: Request, res: ApiV3Response) => {
 
-      const vectorStoreId = configManager.getConfig('crowi', 'app:openaiVectorStoreId');
+      try {
+        const client = new OpenaiClient();
 
-      const client = new OpenaiClient();
+        // Delete an existing VectorStoreFile
+        const vectorStoreFileData = await client.getVectorStoreFiles();
+        const vectorStoreFiles = vectorStoreFileData?.data;
+        if (vectorStoreFiles != null && vectorStoreFiles.length > 0) {
+          vectorStoreFiles.forEach(async(vectorStoreFile) => {
+            await client.deleteVectorStoreFiles(vectorStoreFile.id);
+          });
+        }
 
-      // Delete an existing VectorStoreFile
-      const vectorStoreFileData = await client.getVectorStoreFiles(vectorStoreId);
-      const vectorStoreFiles = vectorStoreFileData?.data;
-      if (vectorStoreFiles != null && vectorStoreFiles.length > 0) {
-        vectorStoreFiles.forEach(async(vectorStoreFile) => {
-          await client.deleteVectorStoreFiles(vectorStoreId, vectorStoreFile.id);
-        });
-      }
+        return res.apiv3({});
 
-      return res.apiv3({});
+      }
+      catch (err) {
+        logger.error(err);
+        return res.apiv3Err(new ErrorV3('Vector Store rebuild failed'));
+      }
     },
   ];
 };

+ 32 - 7
apps/app/src/server/service/openai-client-delegator.ts

@@ -9,8 +9,15 @@ export default class OpenaiClient {
 
   private isOpenai: boolean;
 
+  private openaiVectorStoreId: string;
+
   constructor() {
-    const aiServiceType = configManager?.getConfig('crowi', 'app:aiServiceType');
+    const aiEnabled = configManager.getConfig('crowi', 'app:aiEnabled');
+    const aiServiceType = configManager.getConfig('crowi', 'app:aiServiceType');
+
+    if (!aiEnabled) {
+      throw new Error('I_ENABLED is not true');
+    }
 
     if (aiServiceType == null || !aiServiceTypes.includes(aiServiceType)) {
       throw new Error('AI_SERVICE_TYPE is missing or contains an invalid value');
@@ -18,19 +25,37 @@ export default class OpenaiClient {
 
     this.isOpenai = aiServiceType === serviceType.OPEN_AI;
 
-    // TODO: Support for @azure/openai
-    this.client = new OpenAI({ apiKey: configManager?.getConfig('crowi', 'app:openaiApiKey') });
+    // Retrieve OpenAI related values from environment variables
+    if (this.isOpenai) {
+      const apiKey = configManager.getConfig('crowi', 'app:openaiApiKey');
+      const vectorStoreId = configManager.getConfig('crowi', 'app:openaiVectorStoreId');
+
+      const isValid = [apiKey, vectorStoreId].every(value => value != null);
+      if (!isValid) {
+        throw new Error("Environment variables required to use OpenAI's API are not set");
+      }
+
+      this.openaiVectorStoreId = vectorStoreId;
+
+      // initialize client
+      this.client = new OpenAI({ apiKey });
+    }
+
+    // Retrieve Azure OpenAI related values from environment variables
+    else {
+      //
+    }
   }
 
-  async getVectorStoreFiles(vectorStoreId: string): Promise<OpenAI.Beta.VectorStores.Files.VectorStoreFilesPage | null> {
+  async getVectorStoreFiles(): Promise<OpenAI.Beta.VectorStores.Files.VectorStoreFilesPage | null> {
     return this.isOpenai
-      ? this.client.beta.vectorStores.files.list(vectorStoreId)
+      ? this.client.beta.vectorStores.files.list(this.openaiVectorStoreId)
       : null;
   }
 
-  async deleteVectorStoreFiles(vectorStoreId: string, fileId: string): Promise<OpenAI.Beta.VectorStores.Files.VectorStoreFileDeleted | null> {
+  async deleteVectorStoreFiles(fileId: string): Promise<OpenAI.Beta.VectorStores.Files.VectorStoreFileDeleted | null> {
     return this.isOpenai
-      ? this.client.beta.vectorStores.files.del(vectorStoreId, fileId)
+      ? this.client.beta.vectorStores.files.del(this.openaiVectorStoreId, fileId)
       : null;
   }