// audit.jsx — AI 가상 심사관: 트랙 문서를 심사관 관점으로 검토 → 지적사항 리포트 const { Icon, Pill, Button } = window.RAlly; const SEV = { Critical: { label: 'Critical', bg: '#f3ded7', fg: '#b94a2c' }, Major: { label: 'Major', bg: '#fbf0d8', fg: '#9a6a12' }, Minor: { label: 'Minor', bg: '#e7e3da', fg: '#5a6068' }, }; const Audit = ({ go }) => { const [res, setRes] = React.useState(null); const [busy, setBusy] = React.useState(false); const [useLlm, setUseLlm] = React.useState(false); const runAudit = () => { setBusy(true); setRes(null); window.RAlly.resolveTrackId().then((tid) => { if (!tid) { setBusy(false); return; } fetch('/api/track/' + tid + '/audit', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ use_llm: useLlm }), }).then((r) => r.json()).then((d) => { setRes(d); setBusy(false); }).catch(() => setBusy(false)); }); }; const c = res ? res.counts : null; return (
AI 가상 심사관 식약처 심사 관점
가상 심사 — 제출 전 지적사항 점검
생성된 문서를 심사관 관점에서 검토해 요건 누락·문서 간 불일치·미완 증거를 미리 찾아냅니다. 구조·완전성 기계 검토이며 실제 심사 통과를 보장하지 않습니다 — RA 검토가 필요합니다.
{busy && (
{useLlm ? '문서를 검토하고 요건 반영을 LLM으로 정밀 확인하는 중… (수십 초~)' : '문서를 검토하는 중…'}
)} {res && (
{/* 종합 판정 */}
{res.verdict}
{['Critical', 'Major', 'Minor'].map((s) => ( {SEV[s].label} {c[s]} ))}
{res.llm_used && 🤖 LLM 정밀}
{res.summary}
{/* 지적사항 목록 */} {res.findings.length === 0 && (
지적사항이 없습니다.
)} {res.findings.map((f) => (
{f.severity} {f.id} {f.category} · {f.doc} 근거 {f.basis}
{f.title}
{f.detail}
{f.authority ? (
권위 근거 · {f.authority}
) : null}
{f.recommendation}
))}
)} {!res && !busy && (
가상 심사 시작 버튼을 눌러 현재 트랙의 문서를 심사관 관점으로 점검하세요.
)}
); }; window.RAlly.Audit = Audit;