mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-05-23 12:55:05 +02:00
Adds a check to RAG health to make sure nomad_qdrant is online, if not then the user will be blocked from clicking any buttons in the KB modal until they click the start qdrant button and let the container start There is a new file qdrant_restart_policy_provider.ts, which tries to ensure that the restart policy always exists for the nomad_qdrant container even though the policy should have been there when the container is created.
106 lines
3.7 KiB
TypeScript
106 lines
3.7 KiB
TypeScript
import { RagService } from '#services/rag_service'
|
|
import { EmbedFileJob } from '#jobs/embed_file_job'
|
|
import { inject } from '@adonisjs/core'
|
|
import type { HttpContext } from '@adonisjs/core/http'
|
|
import app from '@adonisjs/core/services/app'
|
|
import { randomBytes } from 'node:crypto'
|
|
import { sanitizeFilename } from '../utils/fs.js'
|
|
import { deleteFileSchema, getJobStatusSchema } from '#validators/rag'
|
|
import logger from '@adonisjs/core/services/logger'
|
|
|
|
@inject()
|
|
export default class RagController {
|
|
constructor(private ragService: RagService) { }
|
|
|
|
public async upload({ request, response }: HttpContext) {
|
|
const uploadedFile = request.file('file')
|
|
if (!uploadedFile) {
|
|
return response.status(400).json({ error: 'No file uploaded' })
|
|
}
|
|
|
|
const randomSuffix = randomBytes(6).toString('hex')
|
|
const sanitizedName = sanitizeFilename(uploadedFile.clientName)
|
|
|
|
const fileName = `${sanitizedName}-${randomSuffix}.${uploadedFile.extname || 'txt'}`
|
|
const fullPath = app.makePath(RagService.UPLOADS_STORAGE_PATH, fileName)
|
|
|
|
await uploadedFile.move(app.makePath(RagService.UPLOADS_STORAGE_PATH), {
|
|
name: fileName,
|
|
})
|
|
|
|
// Dispatch background job for embedding
|
|
const result = await EmbedFileJob.dispatch({
|
|
filePath: fullPath,
|
|
fileName,
|
|
})
|
|
|
|
return response.status(202).json({
|
|
message: result.message,
|
|
jobId: result.jobId,
|
|
fileName,
|
|
filePath: `/${RagService.UPLOADS_STORAGE_PATH}/${fileName}`,
|
|
alreadyProcessing: !result.created,
|
|
})
|
|
}
|
|
|
|
public async getActiveJobs({ response }: HttpContext) {
|
|
const jobs = await EmbedFileJob.listActiveJobs()
|
|
return response.status(200).json(jobs)
|
|
}
|
|
|
|
public async getJobStatus({ request, response }: HttpContext) {
|
|
const reqData = await request.validateUsing(getJobStatusSchema)
|
|
|
|
const fullPath = app.makePath(RagService.UPLOADS_STORAGE_PATH, reqData.filePath)
|
|
const status = await EmbedFileJob.getStatus(fullPath)
|
|
|
|
if (!status.exists) {
|
|
return response.status(404).json({ error: 'Job not found for this file' })
|
|
}
|
|
|
|
return response.status(200).json(status)
|
|
}
|
|
|
|
public async getStoredFiles({ response }: HttpContext) {
|
|
const files = await this.ragService.getStoredFiles()
|
|
return response.status(200).json({ files })
|
|
}
|
|
|
|
public async deleteFile({ request, response }: HttpContext) {
|
|
const { source } = await request.validateUsing(deleteFileSchema)
|
|
const result = await this.ragService.deleteFileBySource(source)
|
|
if (!result.success) {
|
|
return response.status(500).json({ error: result.message })
|
|
}
|
|
return response.status(200).json({ message: result.message })
|
|
}
|
|
|
|
public async getFailedJobs({ response }: HttpContext) {
|
|
const jobs = await EmbedFileJob.listFailedJobs()
|
|
return response.status(200).json(jobs)
|
|
}
|
|
|
|
public async cleanupFailedJobs({ response }: HttpContext) {
|
|
const result = await EmbedFileJob.cleanupFailedJobs()
|
|
return response.status(200).json({
|
|
message: `Cleaned up ${result.cleaned} failed job${result.cleaned !== 1 ? 's' : ''}${result.filesDeleted > 0 ? `, deleted ${result.filesDeleted} file${result.filesDeleted !== 1 ? 's' : ''}` : ''}.`,
|
|
...result,
|
|
})
|
|
}
|
|
|
|
public async scanAndSync({ response }: HttpContext) {
|
|
try {
|
|
const syncResult = await this.ragService.scanAndSyncStorage()
|
|
return response.status(200).json(syncResult)
|
|
} catch (error) {
|
|
logger.error({ err: error }, '[RagController] Error scanning and syncing storage')
|
|
return response.status(500).json({ error: 'Error scanning and syncing storage' })
|
|
}
|
|
}
|
|
|
|
public async health({ response }: HttpContext) {
|
|
const result = await this.ragService.checkQdrantHealth()
|
|
return response.status(200).json(result)
|
|
}
|
|
}
|