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))
<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>
+ <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>
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,
},
}
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'
private tasksService = inject(TasksService)
private toastService = inject(ToastService)
private permissionsService = inject(PermissionsService)
+ private settingsService = inject(SettingsService)
public SystemStatusItemStatus = SystemStatusItemStatus
public PaperlessTaskName = PaperlessTaskName
return this.permissionsService.isSuperUser()
}
+ get aiEnabled(): boolean {
+ return this.settingsService.get(SETTINGS_KEYS.AI_ENABLED)
+ }
+
public ngOnInit() {
this.versionMismatch =
environment.production &&
{
private documentsService = inject(DocumentService)
private route = inject(ActivatedRoute)
+ private tagService = inject(TagService)
private correspondentService = inject(CorrespondentService)
private documentTypeService = inject(DocumentTypeService)
private router = inject(Router)
OK = 'OK',
ERROR = 'ERROR',
WARNING = 'WARNING',
+ DISABLED = 'DISABLED',
}
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
}
}
)
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"])
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
sanity_check,
{"scheduled": False, "raise_on_error": False},
),
+ PaperlessTask.TaskName.LLMINDEX_UPDATE: (
+ update_llm_index,
+ {"scheduled": False, "rebuild": False},
+ ),
}
def get_queryset(self):
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,
"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,
},
},
)