feat: RAG 임베딩 자동 동기화 + AI 서비스 개선
- 부적합 라이프사이클 전 과정에서 Qdrant 임베딩 자동 동기화 - 관리함 5개 저장 함수 + 수신함 상태 변경 시 fire-and-forget sync - 30분 주기 전체 재동기화 안전망 (FastAPI lifespan 백그라운드 태스크) - build_document_text에 카테고리(final_category/category) 포함 - RAG 질의에 DB 통계 집계 지원 (카테고리별/부서별 건수) - Qdrant client.search → query_points API 마이그레이션 - AI 어시스턴트 페이지 권한 추가 (tkuser) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -349,6 +349,20 @@ const AiAPI = {
|
||||
return { available: false };
|
||||
}
|
||||
},
|
||||
syncSingleIssue: async (issueId) => {
|
||||
try {
|
||||
await fetch('/ai-api/embeddings/sync-single', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${TokenManager.getToken()}`
|
||||
},
|
||||
body: JSON.stringify({ issue_id: issueId })
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn('AI 임베딩 동기화 실패 (무시):', e.message);
|
||||
}
|
||||
},
|
||||
syncEmbeddings: async () => {
|
||||
try {
|
||||
const res = await fetch('/ai-api/embeddings/sync', {
|
||||
|
||||
@@ -827,6 +827,7 @@ async function confirmStatus() {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
if (typeof AiAPI !== 'undefined') AiAPI.syncSingleIssue(currentIssueId);
|
||||
const result = await response.json();
|
||||
alert(`상태가 성공적으로 변경되었습니다.\n${result.destination}으로 이동됩니다.`);
|
||||
closeStatusModal();
|
||||
|
||||
@@ -895,6 +895,7 @@ async function saveIssueChanges(issueId) {
|
||||
console.log('Response status:', response.status);
|
||||
|
||||
if (response.ok) {
|
||||
if (typeof AiAPI !== 'undefined') AiAPI.syncSingleIssue(issueId);
|
||||
alert('변경사항이 저장되었습니다.');
|
||||
await loadIssues(); // 목록 새로고침
|
||||
} else {
|
||||
@@ -1507,6 +1508,7 @@ async function saveDetailEdit(issueId) {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
if (typeof AiAPI !== 'undefined') AiAPI.syncSingleIssue(issueId);
|
||||
// 성공 시 이슈 데이터 업데이트
|
||||
issue.final_description = combinedDescription;
|
||||
|
||||
@@ -1873,6 +1875,7 @@ async function saveIssueFromModal(issueId) {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
if (typeof AiAPI !== 'undefined') AiAPI.syncSingleIssue(issueId);
|
||||
// 저장 성공 후 데이터 새로고침하고 모달은 유지
|
||||
await initializeManagement(); // 페이지 새로고침
|
||||
|
||||
@@ -2197,6 +2200,7 @@ async function saveAndCompleteIssue(issueId) {
|
||||
});
|
||||
|
||||
if (saveResponse.ok) {
|
||||
if (typeof AiAPI !== 'undefined') AiAPI.syncSingleIssue(issueId);
|
||||
alert('부적합이 수정되고 최종 완료 처리되었습니다.');
|
||||
closeIssueEditModal();
|
||||
initializeManagement(); // 페이지 새로고침
|
||||
@@ -2226,6 +2230,7 @@ async function finalConfirmCompletion(issueId) {
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
if (typeof AiAPI !== 'undefined') AiAPI.syncSingleIssue(issueId);
|
||||
alert('부적합이 최종 완료 처리되었습니다.');
|
||||
closeIssueEditModal();
|
||||
initializeManagement(); // 페이지 새로고침
|
||||
|
||||
Reference in New Issue
Block a user