fix: embedding reliability - chunking, truncation, progress bar, shared status
- Text chunking: max 8000 chars per document, large CSV rows split with context header - Text truncation: _embed_text truncates at 8000 chars before sending to model (prevents 400 errors) - Purge before re-embed: deletes old docs by tenancy+date before inserting new ones - Shared embedding status: file-based status (/data/.embed_status/) instead of in-memory dict (fixes multi-worker visibility) - Progress bar: shows green (OK) + red (failures) segments, percentage, processed/total count - Better error logging: extracts readable error message from OCI API errors
This commit is contained in:
@@ -583,6 +583,7 @@ export default function ReportsPage() {
|
||||
const setEmbedTable = store.setRptEmbedTable;
|
||||
const [embedLoading, setEmbedLoading] = useState(''); // '' = idle, 'all' = full embed, section name = section embed
|
||||
const [embedMsg, setEmbedMsg] = useState<{ type: 's' | 'e'; text: string } | null>(null);
|
||||
const [embedProgress, setEmbedProgress] = useState<{ inserted: number; skipped: number; processed: number; total: number } | null>(null);
|
||||
|
||||
/* ── HTML iframe (from store) ── */
|
||||
const showIframe = store.rptShowIframe;
|
||||
@@ -783,23 +784,34 @@ export default function ReportsPage() {
|
||||
|
||||
const pollEmbeddingStatus = useCallback(async (taskId: string) => {
|
||||
setEmbedMsg({ type: 's', text: 'Embedding iniciado...' });
|
||||
setEmbedProgress(null);
|
||||
const poll = setInterval(async () => {
|
||||
try {
|
||||
const s = await reportsApi.embeddingStatus(taskId);
|
||||
if (s.total) {
|
||||
setEmbedProgress({
|
||||
inserted: s.inserted || 0,
|
||||
skipped: (s as unknown as Record<string, number>).skipped || 0,
|
||||
processed: (s as unknown as Record<string, number>).processed || s.inserted || 0,
|
||||
total: s.total,
|
||||
});
|
||||
}
|
||||
if (s.status === 'running') {
|
||||
setEmbedMsg({ type: 's', text: s.message });
|
||||
} else if (s.status === 'done') {
|
||||
clearInterval(poll);
|
||||
setEmbedMsg({ type: 's', text: s.message });
|
||||
setEmbedProgress(null);
|
||||
setEmbedLoading('');
|
||||
} else if (s.status === 'error') {
|
||||
clearInterval(poll);
|
||||
setEmbedMsg({ type: 'e', text: s.message });
|
||||
setEmbedProgress(null);
|
||||
setEmbedLoading('');
|
||||
}
|
||||
} catch { /* keep polling */ }
|
||||
}, 2000);
|
||||
setTimeout(() => { clearInterval(poll); setEmbedLoading(''); }, 300000);
|
||||
setTimeout(() => { clearInterval(poll); setEmbedLoading(''); setEmbedProgress(null); }, 300000);
|
||||
}, []);
|
||||
|
||||
const handleEmbed = async (rid: string) => {
|
||||
@@ -1459,7 +1471,34 @@ export default function ReportsPage() {
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Embed message */}
|
||||
{/* Embed progress + message */}
|
||||
{embedProgress && embedProgress.total > 0 && (() => {
|
||||
const pct = Math.round((embedProgress.processed / embedProgress.total) * 100);
|
||||
const okPct = Math.round((embedProgress.inserted / embedProgress.total) * 100);
|
||||
const failPct = Math.round((embedProgress.skipped / embedProgress.total) * 100);
|
||||
return (
|
||||
<div className="mx-5 mt-3">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-[.65rem] font-medium" style={{ color: 'var(--t2)' }}>
|
||||
{embedProgress.inserted} OK
|
||||
{embedProgress.skipped > 0 && <span style={{ color: 'var(--rd)' }}> / {embedProgress.skipped} falhas</span>}
|
||||
{' '}({embedProgress.processed}/{embedProgress.total})
|
||||
</span>
|
||||
<span className="text-[.65rem] font-bold" style={{ color: embedProgress.skipped > 0 ? 'var(--yl)' : 'var(--gn)' }}>
|
||||
{pct}%
|
||||
</span>
|
||||
</div>
|
||||
<div className="w-full h-2 rounded-full overflow-hidden flex" style={{ background: 'var(--bg2)' }}>
|
||||
{okPct > 0 && (
|
||||
<div className="h-full transition-all duration-500" style={{ width: `${okPct}%`, background: 'var(--gn)' }} />
|
||||
)}
|
||||
{failPct > 0 && (
|
||||
<div className="h-full transition-all duration-500" style={{ width: `${failPct}%`, background: 'var(--rd)' }} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
{embedMsg && (
|
||||
<div
|
||||
className="mx-5 mt-3 flex items-center gap-2 px-3 py-2 rounded-lg text-xs"
|
||||
|
||||
Reference in New Issue
Block a user