Spaces:
Running
Running
AuthorBot commited on
Commit Β·
1c77285
1
Parent(s): 9eb7e65
Fix: book readiness check uses chunk_count+chroma_id as real truth; add stuck-book detection + Re-upload button in admin
Browse files
app/admin/templates/admin.html
CHANGED
|
@@ -1041,16 +1041,21 @@ function renderBooks(books) {
|
|
| 1041 |
const coverBg = b.cover_thumbnail
|
| 1042 |
? `background-image:url('/covers/${b.cover_thumbnail?.split('/data/covers/')[1] || ''}');background-size:cover;background-position:center;`
|
| 1043 |
: `background:linear-gradient(135deg,hsl(${Math.abs(hashCode(b.title))%360},65%,72%),hsl(${(Math.abs(hashCode(b.title))+60)%360},55%,62%));display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:700;color:#fff;`;
|
| 1044 |
-
|
|
|
|
|
|
|
| 1045 |
<td><div style="width:40px;height:56px;border-radius:6px;overflow:hidden;flex-shrink:0;${coverBg}">${b.cover_thumbnail ? '' : esc(b.title.charAt(0))}</div></td>
|
| 1046 |
-
<td><div class="fw-600">${esc(b.title)}</div></td>
|
| 1047 |
<td><span class="text-muted text-sm">${esc(b.genre || 'β')}</span></td>
|
| 1048 |
-
<td><span class="badge badge-${b.status}">${b.status}</span></td>
|
| 1049 |
<td>${b.chunk_count || 0}</td>
|
| 1050 |
<td style="max-width:200px;" class="truncate text-xs text-muted">${esc(b.ai_summary || 'β')}</td>
|
| 1051 |
-
<td style="display:flex;gap:4px;">
|
| 1052 |
-
|
| 1053 |
-
|
|
|
|
|
|
|
|
|
|
| 1054 |
</td>
|
| 1055 |
</tr>`;
|
| 1056 |
}).join('');
|
|
@@ -1086,6 +1091,15 @@ async function executeDeleteBook(id, title) {
|
|
| 1086 |
try { await apiDelete(`/admin/${authorSlug}/books/${id}`); closeModal(); toast('Book deleted', 'success'); loadBooks(); } catch(e) { toast(e.message, 'error'); }
|
| 1087 |
}
|
| 1088 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1089 |
/* ββ UPLOAD ββ */
|
| 1090 |
const uploadZone = document.getElementById('upload-zone');
|
| 1091 |
const fileInput = document.getElementById('file-input');
|
|
|
|
| 1041 |
const coverBg = b.cover_thumbnail
|
| 1042 |
? `background-image:url('/covers/${b.cover_thumbnail?.split('/data/covers/')[1] || ''}');background-size:cover;background-position:center;`
|
| 1043 |
: `background:linear-gradient(135deg,hsl(${Math.abs(hashCode(b.title))%360},65%,72%),hsl(${(Math.abs(hashCode(b.title))+60)%360},55%,62%));display:flex;align-items:center;justify-content:center;font-size:18px;font-weight:700;color:#fff;`;
|
| 1044 |
+
const stuck = !['ready','active'].includes(b.status) && !(b.chunk_count > 0 && b.chroma_collection_id);
|
| 1045 |
+
const stuckBadge = stuck ? `<span title="Indexing stalled β delete and re-upload" style="cursor:help;">β οΈ</span>` : '';
|
| 1046 |
+
return `<tr${stuck ? ' style="opacity:0.75;"' : ''}>
|
| 1047 |
<td><div style="width:40px;height:56px;border-radius:6px;overflow:hidden;flex-shrink:0;${coverBg}">${b.cover_thumbnail ? '' : esc(b.title.charAt(0))}</div></td>
|
| 1048 |
+
<td><div class="fw-600">${esc(b.title)}</div>${stuck ? '<div class="text-xs" style="color:var(--yellow-dark);">Indexing stalled</div>' : ''}</td>
|
| 1049 |
<td><span class="text-muted text-sm">${esc(b.genre || 'β')}</span></td>
|
| 1050 |
+
<td><span class="badge badge-${b.status}">${b.status}</span> ${stuckBadge}</td>
|
| 1051 |
<td>${b.chunk_count || 0}</td>
|
| 1052 |
<td style="max-width:200px;" class="truncate text-xs text-muted">${esc(b.ai_summary || 'β')}</td>
|
| 1053 |
+
<td style="display:flex;gap:4px;flex-wrap:wrap;">
|
| 1054 |
+
${stuck
|
| 1055 |
+
? `<button class="btn btn-primary btn-sm" onclick="repairBook('${b.id}','${esc(b.title)}')">π Re-upload</button>`
|
| 1056 |
+
: `<label class="btn btn-secondary btn-sm" style="cursor:pointer;margin:0;"><input type="file" accept="image/*" style="display:none;" onchange="uploadCover('${b.id}',this)">π·</label>`
|
| 1057 |
+
}
|
| 1058 |
+
<button class="btn btn-danger btn-sm" onclick="confirmDeleteBook('${b.id}','${esc(b.title)}')">π</button>
|
| 1059 |
</td>
|
| 1060 |
</tr>`;
|
| 1061 |
}).join('');
|
|
|
|
| 1091 |
try { await apiDelete(`/admin/${authorSlug}/books/${id}`); closeModal(); toast('Book deleted', 'success'); loadBooks(); } catch(e) { toast(e.message, 'error'); }
|
| 1092 |
}
|
| 1093 |
|
| 1094 |
+
async function repairBook(id, title) {
|
| 1095 |
+
showModal('π Re-upload Required',
|
| 1096 |
+
`<div class="modal-sub">The book <strong>${esc(title)}</strong> got stuck during indexing (the server restarted mid-process).<br><br>
|
| 1097 |
+
The fix is simple: <strong>delete it and re-upload the file</strong>. Indexing now runs in the background and will complete reliably.</div>`,
|
| 1098 |
+
`<button class="btn btn-secondary" onclick="closeModal()">Cancel</button>
|
| 1099 |
+
<button class="btn btn-danger" onclick="closeModal(); executeDeleteBook('${id}','${esc(title)}'); setTimeout(()=>nav('upload'),500);">π Delete & Go to Upload</button>`
|
| 1100 |
+
);
|
| 1101 |
+
}
|
| 1102 |
+
|
| 1103 |
/* ββ UPLOAD ββ */
|
| 1104 |
const uploadZone = document.getElementById('upload-zone');
|
| 1105 |
const fileInput = document.getElementById('file-input');
|
app/services/rag_pipeline.py
CHANGED
|
@@ -764,7 +764,12 @@ async def _no_context_response(
|
|
| 764 |
|
| 765 |
if len(books) == 1:
|
| 766 |
book = books[0]
|
| 767 |
-
if
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 768 |
text = (
|
| 769 |
f"{book.title} is still being indexed β give it a minute and ask again. "
|
| 770 |
"I'll be able to answer detailed questions once processing finishes."
|
|
|
|
| 764 |
|
| 765 |
if len(books) == 1:
|
| 766 |
book = books[0]
|
| 767 |
+
# Book is answerable if embeddings exist in ChromaDB β status field may be stale
|
| 768 |
+
book_is_ready = (
|
| 769 |
+
book.status in ("ready", "active")
|
| 770 |
+
or (book.chunk_count and book.chunk_count > 0 and book.chroma_collection_id)
|
| 771 |
+
)
|
| 772 |
+
if not book_is_ready:
|
| 773 |
text = (
|
| 774 |
f"{book.title} is still being indexed β give it a minute and ask again. "
|
| 775 |
"I'll be able to answer detailed questions once processing finishes."
|