ソースを参照

Merge pull request #9214 from weseek/feat/154701-delete-vector-store-file-when-deleting-pages2

feat: Delete vector store file when deleting pages
Yuki Takei 1 年間 前
コミット
04ec42813b

+ 29 - 24
apps/app/src/server/service/openai/openai.ts

@@ -27,6 +27,7 @@ const logger = loggerFactory('growi:service:openai');
 
 export interface IOpenaiService {
   createVectorStoreFile(pages: PageDocument[]): Promise<void>;
+  deleteVectorStoreFile(pageId: Types.ObjectId): Promise<void>;
   rebuildVectorStoreAll(): Promise<void>;
   rebuildVectorStore(page: PageDocument): Promise<void>;
 }
@@ -88,33 +89,35 @@ class OpenaiService implements IOpenaiService {
 
   }
 
-  private async deleteVectorStoreFile(page: PageDocument): Promise<void> {
+  async deleteVectorStoreFile(pageId: Types.ObjectId): Promise<void> {
     // Delete vector store file and delete vector store file relation
-    const vectorStoreFileRelation = await VectorStoreFileRelationModel.findOne({ pageId: page._id });
-    if (vectorStoreFileRelation != null) {
-      const deletedFileIds: string[] = [];
-      for (const fileId of vectorStoreFileRelation.fileIds) {
-        try {
-          // eslint-disable-next-line no-await-in-loop
-          const deleteFileResponse = await this.client.deleteFile(fileId);
-          logger.debug('Delete vector store file', deleteFileResponse);
-          deletedFileIds.push(fileId);
-        }
-        catch (err) {
-          logger.error(err);
-        }
-      }
-
-      const undeletedFileIds = vectorStoreFileRelation.fileIds.filter(fileId => !deletedFileIds.includes(fileId));
+    const vectorStoreFileRelation = await VectorStoreFileRelationModel.findOne({ pageId });
+    if (vectorStoreFileRelation == null) {
+      return;
+    }
 
-      if (undeletedFileIds.length === 0) {
-        await vectorStoreFileRelation.remove();
-        return;
+    const deletedFileIds: string[] = [];
+    for (const fileId of vectorStoreFileRelation.fileIds) {
+      try {
+        // eslint-disable-next-line no-await-in-loop
+        const deleteFileResponse = await this.client.deleteFile(fileId);
+        logger.debug('Delete vector store file', deleteFileResponse);
+        deletedFileIds.push(fileId);
       }
+      catch (err) {
+        logger.error(err);
+      }
+    }
+
+    const undeletedFileIds = vectorStoreFileRelation.fileIds.filter(fileId => !deletedFileIds.includes(fileId));
 
-      vectorStoreFileRelation.fileIds = undeletedFileIds;
-      await vectorStoreFileRelation.save();
+    if (undeletedFileIds.length === 0) {
+      await vectorStoreFileRelation.remove();
+      return;
     }
+
+    vectorStoreFileRelation.fileIds = undeletedFileIds;
+    await vectorStoreFileRelation.save();
   }
 
   async rebuildVectorStoreAll() {
@@ -141,8 +144,10 @@ class OpenaiService implements IOpenaiService {
   }
 
   async rebuildVectorStore(page: PageDocument) {
-    await this.deleteVectorStoreFile(page);
-    await this.createVectorStoreFile([page]);
+    if (page._id != null) {
+      await this.deleteVectorStoreFile(page._id);
+      await this.createVectorStoreFile([page]);
+    }
   }
 
 }

+ 4 - 1
apps/app/src/server/service/page/index.ts

@@ -1901,6 +1901,10 @@ class PageService implements IPageService {
 
       // Leave bookmarks without deleting -- 2024.05.17 Yuki Takei
     ]);
+
+    const openaiService = getOpenaiService();
+    const deleteVectorStoreFilePromises = pageIds.map(pageId => openaiService?.deleteVectorStoreFile(pageId));
+    await Promise.allSettled(deleteVectorStoreFilePromises);
   }
 
   // delete multiple pages
@@ -1913,7 +1917,6 @@ class PageService implements IPageService {
     await this.deleteCompletelyOperation(ids, paths);
 
     this.pageEvent.emit('syncDescendantsDelete', pages, user); // update as renamed page
-
     return;
   }