Integrate mistral vision analysis into PDF figure extraction flow

- Image extraction now immediately followed by per-figure mistral analysis
  no manual button click needed: extract → analyze runs as one atomic flow
- Progress shows "이미지 분석 1/5..." inline with prep step
- Captions + 제외 filtering available before outline generation
- "🔍 재분석" button retained for manual uploads / re-run on failures

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
kim
2026-06-02 15:04:47 +09:00
co-authored by Claude Sonnet 4.6
parent 0391e7d2cf
commit 557e328610
+19 -4
View File
@@ -343,7 +343,7 @@ body{background:var(--bg);color:var(--text);font-family:'Segoe UI',system-ui,san
<div style="flex:2;min-width:0">
<div style="display:flex;align-items:center;gap:8px;margin-bottom:6px">
<span style="font-size:10px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:.04em">캡처 이미지 <span id="imgcnt"></span></span>
<button id="btn-analyze-imgs" onclick="analyzeImages()" style="font-size:11px;color:#10b981;background:rgba(16,185,129,.1);border:1px solid #10b981;border-radius:5px;padding:2px 8px;cursor:pointer;flex-shrink:0" title="AI(mistral vision)가 각 이미지 내용 분석 — 아웃라인 생성 시 정확한 슬라이드 배치에 활용">🔍 이미지 분석</button>
<button id="btn-analyze-imgs" onclick="analyzeImages()" style="font-size:11px;color:#10b981;background:rgba(16,185,129,.1);border:1px solid #10b981;border-radius:5px;padding:2px 8px;cursor:pointer;flex-shrink:0" title="미분석 이미지를 mistral vision으로 재분석 (준비 실행 시 자동 처리됨)">🔍 재분석</button>
<label style="display:flex;align-items:center;gap:4px;font-size:11px;color:var(--brand2);background:rgba(99,102,241,.1);border:1px solid var(--brand);border-radius:5px;padding:2px 8px;cursor:pointer;flex-shrink:0" title="이미지 파일 업로드">
<input type="file" id="img-upload-input" accept="image/*" multiple style="display:none" onchange="handleImgUpload(this.files)">
+ 이미지 업로드
@@ -1992,7 +1992,7 @@ async function startPrep() {
setMsg(2,key+' 이미지 추출...','var(--brand2)');
}
// 이미지 자동 추출 (토글 ON일 때만)
// 이미지 자동 추출 + mistral vision 분석 (토글 ON일 때만)
if(autoExtractImages && pdfPath){
prepLog[key].img='running'; updProg(key);
setMsg(2,paperLabel(key)+' 이미지 추출...','var(--brand2)');
@@ -2000,18 +2000,33 @@ async function startPrep() {
const exr=await fetch('/api/pptx/extract-images',{...jh(),method:'POST',body:JSON.stringify({pdf_path:pdfPath,project:prepProject})});
const exd=await exr.json();
let added=0;
const newImgs=[];
if(exd.success&&exd.data?.files){
const pname=isUpload?(pdfPath.split('/').pop()||'').replace(/\.pdf$/i,''):key;
for(const f of exd.data.files){
const url='/api/files/'+f;
if(!extractedImages.find(img=>img.url===url)){
extractedImages.push({url,label:pname+': '+f.split('/').pop(),pdf:pdfPath});
const entry={url,label:pname+': '+f.split('/').pop(),pdf:pdfPath};
extractedImages.push(entry);
newImgs.push(entry);
added++;
}
}
}
prepLog[key].img='done'; prepLog[key].imgCount=added;
renderImgGrid();
// mistral vision으로 새로 추출된 이미지 즉시 분석
for(let ni=0;ni<newImgs.length;ni++){
const nim=newImgs[ni];
if(imageCaptions[nim.url]) continue;
setMsg(2,`${paperLabel(key)} 이미지 분석 ${ni+1}/${newImgs.length}...`,'var(--brand2)');
try{
const ar=await fetch('/api/pptx/analyze-image',{...jh(),method:'POST',body:JSON.stringify({url:nim.url,label:nim.label,project:prepProject})});
const ad=await ar.json();
if(ad.caption) imageCaptions[nim.url]=ad.caption;
}catch{}
renderImgGrid();
}
prepLog[key].img='done'; prepLog[key].imgCount=added;
}catch(e2){ prepLog[key].img='fail'; }
updProg(key);
} else {