]> git.ipfire.org Git - thirdparty/paperless-ngx.git/commitdiff
Add llmindex to systemstatus
authorshamoon <4887959+shamoon@users.noreply.github.com>
Wed, 30 Apr 2025 04:45:34 +0000 (21:45 -0700)
committershamoon <4887959+shamoon@users.noreply.github.com>
Wed, 2 Jul 2025 18:04:54 +0000 (11:04 -0700)
src-ui/src/app/components/admin/settings/settings.component.spec.ts
src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html
src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.spec.ts
src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts
src-ui/src/app/components/document-detail/document-detail.component.ts
src-ui/src/app/data/system-status.ts
src/documents/tasks.py
src/documents/views.py

index c6eeaf896ccef8048219c6efedd8af4afc23c263..ce092364e9eb8fdd688af809564a59784f1fb630 100644 (file)
@@ -314,6 +314,9 @@ describe('SettingsComponent', () => {
         sanity_check_status: SystemStatusItemStatus.ERROR,
         sanity_check_last_run: new Date().toISOString(),
         sanity_check_error: 'Error running sanity check.',
+        llmindex_status: SystemStatusItemStatus.DISABLED,
+        llmindex_last_modified: new Date().toISOString(),
+        llmindex_error: null,
       },
     }
     jest.spyOn(systemStatusService, 'get').mockReturnValue(of(status))
index e3b09ee7e6f540d7c899e71282b373f05939a9bd..d5df7959d033a4e0d2d50d519bb5441c67982535 100644 (file)
                   <h6><ng-container i18n>Error</ng-container>:</h6> <span class="font-monospace small">{{status.tasks.sanity_check_error}}</span>
                 }
               </ng-template>
+              @if (aiEnabled) {
+                <dt i18n>AI Index</dt>
+                <dd class="d-flex align-items-center">
+                  <button class="btn btn-sm d-flex align-items-center btn-dark text-uppercase small" [ngbPopover]="llmIndexStatus" triggers="click mouseenter:mouseleave">
+                    {{status.tasks.llmindex_status}}
+                    @if (status.tasks.llmindex_status === 'OK') {
+                      @if (isStale(status.tasks.llmindex_last_modified)) {
+                        <i-bs name="exclamation-triangle-fill" class="text-warning ms-2 lh-1"></i-bs>
+                      } @else {
+                        <i-bs name="check-circle-fill" class="text-primary ms-2 lh-1"></i-bs>
+                      }
+                    } @else {
+                      <i-bs name="exclamation-triangle-fill" class="ms-2 lh-1"
+                      [class.text-danger]="status.tasks.llmindex_status === SystemStatusItemStatus.ERROR"
+                      [class.text-warning]="status.tasks.llmindex_status === SystemStatusItemStatus.WARNING"
+                      [class.text-muted]="status.tasks.llmindex_status === SystemStatusItemStatus.DISABLED"></i-bs>
+                    }
+                  </button>
+                  @if (currentUserIsSuperUser) {
+                    @if (isRunning(PaperlessTaskName.LLMIndexUpdate)) {
+                      <div class="spinner-border spinner-border-sm ms-2" role="status"></div>
+                    } @else {
+                      <button class="btn btn-sm d-flex align-items-center btn-dark small ms-2" (click)="runTask(PaperlessTaskName.LLMIndexUpdate)">
+                        <i-bs name="play-fill"></i-bs>&nbsp;
+                        <ng-container i18n>Run Task</ng-container>
+                      </button>
+                    }
+                  }
+                </dd>
+                <ng-template #llmIndexStatus>
+                  @if (status.tasks.llmindex_status === 'OK') {
+                    <h6><ng-container i18n>Last Run</ng-container>:</h6> <span class="font-monospace small">{{status.tasks.llmindex_last_modified | customDate:'medium'}}</span>
+                  } @else {
+                    <h6><ng-container i18n>Error</ng-container>:</h6> <span class="font-monospace small">{{status.tasks.llmindex_error}}</span>
+                  }
+                </ng-template>
+              }
             </dl>
           </div>
         </div>
index f9d8b4d68354e413ddf028a32f947f2b7ee7c6a8..6ac1fd34a1d54cfbf044ad827c52c7cf9d05b7f4 100644 (file)
@@ -67,6 +67,9 @@ const status: SystemStatus = {
     sanity_check_status: SystemStatusItemStatus.OK,
     sanity_check_last_run: new Date().toISOString(),
     sanity_check_error: null,
+    llmindex_status: SystemStatusItemStatus.OK,
+    llmindex_last_modified: new Date().toISOString(),
+    llmindex_error: null,
   },
 }
 
index bc027ebbf070be91c29359ba1dec078c9da175b9..19171941cf7ada7cdab3bdd408d344fab45718db 100644 (file)
@@ -12,9 +12,11 @@ import {
   SystemStatus,
   SystemStatusItemStatus,
 } from 'src/app/data/system-status'
+import { SETTINGS_KEYS } from 'src/app/data/ui-settings'
 import { CustomDatePipe } from 'src/app/pipes/custom-date.pipe'
 import { FileSizePipe } from 'src/app/pipes/file-size.pipe'
 import { PermissionsService } from 'src/app/services/permissions.service'
+import { SettingsService } from 'src/app/services/settings.service'
 import { SystemStatusService } from 'src/app/services/system-status.service'
 import { TasksService } from 'src/app/services/tasks.service'
 import { ToastService } from 'src/app/services/toast.service'
@@ -41,6 +43,7 @@ export class SystemStatusDialogComponent implements OnInit {
   private tasksService = inject(TasksService)
   private toastService = inject(ToastService)
   private permissionsService = inject(PermissionsService)
+  private settingsService = inject(SettingsService)
 
   public SystemStatusItemStatus = SystemStatusItemStatus
   public PaperlessTaskName = PaperlessTaskName
@@ -56,6 +59,10 @@ export class SystemStatusDialogComponent implements OnInit {
     return this.permissionsService.isSuperUser()
   }
 
+  get aiEnabled(): boolean {
+    return this.settingsService.get(SETTINGS_KEYS.AI_ENABLED)
+  }
+
   public ngOnInit() {
     this.versionMismatch =
       environment.production &&
index 337cba668217049d33bc068418cac03f7b8e37b6..8d2f32ac9891ece2ca202059ab854bd6bf10e703 100644 (file)
@@ -182,6 +182,7 @@ export class DocumentDetailComponent
 {
   private documentsService = inject(DocumentService)
   private route = inject(ActivatedRoute)
+  private tagService = inject(TagService)
   private correspondentService = inject(CorrespondentService)
   private documentTypeService = inject(DocumentTypeService)
   private router = inject(Router)
index 698382154e6d3425abe923c15374c784528ccdae..dc18677a5eb0b421c2dcf60dc92cfe0cd999a2bb 100644 (file)
@@ -7,6 +7,7 @@ export enum SystemStatusItemStatus {
   OK = 'OK',
   ERROR = 'ERROR',
   WARNING = 'WARNING',
+  DISABLED = 'DISABLED',
 }
 
 export interface SystemStatus {
@@ -43,5 +44,8 @@ export interface SystemStatus {
     sanity_check_status: SystemStatusItemStatus
     sanity_check_last_run: string // ISO date string
     sanity_check_error: string
+    llmindex_status: SystemStatusItemStatus
+    llmindex_last_modified: string // ISO date string
+    llmindex_error: string
   }
 }
index d0d2bd95bcbe9d2dca536ed9af02d44c282d8427..8841d8518c828b7aec4f07d9d16a88faccac26a3 100644 (file)
@@ -558,12 +558,18 @@ def llmindex_index(
         )
         from paperless_ai.indexing import update_llm_index
 
-        result = update_llm_index(
-            progress_bar_disable=progress_bar_disable,
-            rebuild=rebuild,
-        )
-        task.status = states.SUCCESS
-        task.result = result
+        try:
+            result = update_llm_index(
+                progress_bar_disable=progress_bar_disable,
+                rebuild=rebuild,
+            )
+            task.status = states.SUCCESS
+            task.result = result
+        except Exception as e:
+            logger.error("LLM index error: " + str(e))
+            task.status = states.FAILURE
+            task.result = str(e)
+
         task.date_done = timezone.now()
         task.save(update_fields=["status", "result", "date_done"])
 
index 61b4af2143d79c2ed9dfdd53e815e755a9da61da..2e8ca85c5b278cdbbc0d9162d6b75956eed28500 100644 (file)
@@ -185,6 +185,7 @@ from paperless.serialisers import UserSerializer
 from paperless.views import StandardPagination
 from paperless_ai.ai_classifier import get_ai_document_classification
 from paperless_ai.chat import stream_chat_with_documents
+from paperless_ai.indexing import update_llm_index
 from paperless_ai.matching import extract_unmatched_names
 from paperless_ai.matching import match_correspondents_by_name
 from paperless_ai.matching import match_document_types_by_name
@@ -2465,6 +2466,10 @@ class TasksViewSet(ReadOnlyModelViewSet):
             sanity_check,
             {"scheduled": False, "raise_on_error": False},
         ),
+        PaperlessTask.TaskName.LLMINDEX_UPDATE: (
+            update_llm_index,
+            {"scheduled": False, "rebuild": False},
+        ),
     }
 
     def get_queryset(self):
@@ -2970,6 +2975,31 @@ class SystemStatusView(PassUserMixin):
             last_sanity_check.date_done if last_sanity_check else None
         )
 
+        ai_config = AIConfig()
+        if not ai_config.llm_index_enabled:
+            llmindex_status = "DISABLED"
+            llmindex_error = None
+            llmindex_last_modified = None
+        else:
+            last_llmindex_update = (
+                PaperlessTask.objects.filter(
+                    task_name=PaperlessTask.TaskName.LLMINDEX_UPDATE,
+                )
+                .order_by("-date_done")
+                .first()
+            )
+            llmindex_status = "OK"
+            llmindex_error = None
+            if last_llmindex_update is None:
+                llmindex_status = "WARNING"
+                llmindex_error = "No LLM index update tasks found"
+            elif last_llmindex_update and last_llmindex_update.status == states.FAILURE:
+                llmindex_status = "ERROR"
+                llmindex_error = last_llmindex_update.result
+            llmindex_last_modified = (
+                last_llmindex_update.date_done if last_llmindex_update else None
+            )
+
         return Response(
             {
                 "pngx_version": current_version,
@@ -3007,6 +3037,9 @@ class SystemStatusView(PassUserMixin):
                     "sanity_check_status": sanity_check_status,
                     "sanity_check_last_run": sanity_check_last_run,
                     "sanity_check_error": sanity_check_error,
+                    "llmindex_status": llmindex_status,
+                    "llmindex_last_modified": llmindex_last_modified,
+                    "llmindex_error": llmindex_error,
                 },
             },
         )