diff --git a/src-ui/src/app/components/admin/settings/settings.component.spec.ts b/src-ui/src/app/components/admin/settings/settings.component.spec.ts index c6eeaf896..ce092364e 100644 --- a/src-ui/src/app/components/admin/settings/settings.component.spec.ts +++ b/src-ui/src/app/components/admin/settings/settings.component.spec.ts @@ -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)) diff --git a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html index 94c4ef22d..4f91a4f43 100644 --- a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html +++ b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.html @@ -243,6 +243,43 @@
Error:
{{status.tasks.sanity_check_error}} } + @if (aiEnabled) { +
AI Index
+
+ + @if (currentUserIsSuperUser) { + @if (isRunning(PaperlessTaskName.LLMIndexUpdate)) { +
+ } @else { + + } + } +
+ + @if (status.tasks.llmindex_status === 'OK') { +
Last Run:
{{status.tasks.llmindex_last_modified | customDate:'medium'}} + } @else { +
Error:
{{status.tasks.llmindex_error}} + } +
+ } diff --git a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.spec.ts b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.spec.ts index 28a0889ab..b77bb3ff8 100644 --- a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.spec.ts +++ b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.spec.ts @@ -52,6 +52,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, }, } diff --git a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts index c7ba3c57a..73f78856b 100644 --- a/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts +++ b/src-ui/src/app/components/common/system-status-dialog/system-status-dialog.component.ts @@ -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' @@ -46,13 +48,18 @@ export class SystemStatusDialogComponent { return this.permissionsService.isSuperUser() } + get aiEnabled(): boolean { + return this.settingsService.get(SETTINGS_KEYS.AI_ENABLED) + } + constructor( public activeModal: NgbActiveModal, private clipboard: Clipboard, private systemStatusService: SystemStatusService, private tasksService: TasksService, private toastService: ToastService, - private permissionsService: PermissionsService + private permissionsService: PermissionsService, + private settingsService: SettingsService ) {} public close() { diff --git a/src-ui/src/app/data/system-status.ts b/src-ui/src/app/data/system-status.ts index 698382154..dc18677a5 100644 --- a/src-ui/src/app/data/system-status.ts +++ b/src-ui/src/app/data/system-status.ts @@ -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 } } diff --git a/src/documents/tasks.py b/src/documents/tasks.py index 5a37cb94d..1eda904bd 100644 --- a/src/documents/tasks.py +++ b/src/documents/tasks.py @@ -537,12 +537,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"]) diff --git a/src/documents/views.py b/src/documents/views.py index b255e1bdf..15ab287ec 100644 --- a/src/documents/views.py +++ b/src/documents/views.py @@ -183,6 +183,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 @@ -2406,6 +2407,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): @@ -2897,6 +2902,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, @@ -2934,6 +2964,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, }, }, )