"use client"; import { useState, useEffect, useCallback } from "react"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui"; import { Button } from "@/components/ui"; import { RAGEngine, RAGConfig } from "@/rag"; import { DocumentUploader } from "./document-uploader"; import { KnowledgeEditor } from "./knowledge-editor"; import { RAGManager } from "./rag-manager"; import { useKeyboardShortcuts, createAdminShortcuts, } from "@/hooks/useKeyboardShortcuts"; import { useConfirmationDialog, confirmDelete, confirmAction, } from "@/components/ui/confirmation-dialog"; import { useDebounce } from "@/hooks/usePerformance"; interface KnowledgeManagementProps { ragConfig?: RAGConfig; } type TabType = "documents" | "knowledge" | "management" | "overview"; export function KnowledgeManagement({ ragConfig }: KnowledgeManagementProps) { const [activeTab, setActiveTab] = useState("overview"); const [ragEngine, setRAGEngine] = useState(null); const [isInitializing, setIsInitializing] = useState(true); const [error, setError] = useState(null); const [stats, setStats] = useState({ totalDocuments: 0, totalKnowledgeEntries: 0, totalChunks: 0, lastActivity: null as string | null, }); // Confirmation dialog for destructive actions const { showConfirmation, ConfirmationDialog } = useConfirmationDialog(); // Debounced search for better performance const [searchTerm, setSearchTerm] = useState(""); const debouncedSearch = useDebounce(searchTerm, 300); useEffect(() => { initializeRAGEngine(); }, [ragConfig]); const initializeRAGEngine = async () => { try { setIsInitializing(true); setError(null); // Use provided config or create default const config: RAGConfig = ragConfig || { embeddingModel: "text-embedding-ada-002", chunkSize: 1000, chunkOverlap: 200, vectorStorePath: "./vector_store", llmConfig: { modelName: "gpt-4", temperature: 0.7, maxTokens: 2000, apiKey: process.env.OPENAI_API_KEY || "", }, supabaseConfig: { url: process.env.NEXT_PUBLIC_SUPABASE_URL || "", anonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || "", bucket: "documents", }, }; const engine = new RAGEngine(config); await engine.initialize(); setRAGEngine(engine); await loadStats(engine); } catch (err) { console.error("RAG Engine 초기화 실패:", err); setError( `RAG 시스템 초기화에 실패했습니다: ${ err instanceof Error ? err.message : "알 수 없는 오류" }` ); } finally { setIsInitializing(false); } }; const loadStats = async (engine: RAGEngine) => { try { const ragStats = await engine.getStats(); // Load knowledge entries from localStorage const knowledgeEntries = localStorage.getItem("knowledge-entries"); const knowledgeCount = knowledgeEntries ? JSON.parse(knowledgeEntries).length : 0; setStats({ totalDocuments: ragStats.documentCount, totalKnowledgeEntries: knowledgeCount, totalChunks: ragStats.chunkCount, lastActivity: new Date().toISOString(), }); } catch (err) { console.error("통계 로드 실패:", err); } }; const handleDocumentUploaded = async () => { if (ragEngine) { await loadStats(ragEngine); } }; const handleKnowledgeUpdated = async () => { if (ragEngine) { await loadStats(ragEngine); } }; const handleRetrain = async () => { if (!ragEngine) return; try { // Clear and reinitialize the vector store await ragEngine.clear(); await ragEngine.initialize(); await loadStats(ragEngine); } catch (err) { console.error("재훈련 실패:", err); setError( `재훈련에 실패했습니다: ${ err instanceof Error ? err.message : "알 수 없는 오류" }` ); } }; // Enhanced retrain with confirmation const handleRetrainWithConfirmation = useCallback(() => { confirmAction( showConfirmation, "시스템 재훈련", "RAG 시스템을 재훈련하면 모든 벡터 데이터가 다시 생성됩니다. 계속하시겠습니까?", handleRetrain, "재훈련" ); }, [showConfirmation]); // Clear all data with confirmation const handleClearData = useCallback(() => { confirmDelete(showConfirmation, "모든 데이터", async () => { if (ragEngine) { await ragEngine.clear(); await loadStats(ragEngine); } }); }, [showConfirmation, ragEngine]); // Keyboard shortcuts const shortcuts = createAdminShortcuts({ onRefresh: () => ragEngine && loadStats(ragEngine), onEscape: () => setActiveTab("overview"), onNew: () => setActiveTab("documents"), onSearch: () => { // Focus search input if available const searchInput = document.querySelector( 'input[type="search"]' ) as HTMLInputElement; if (searchInput) searchInput.focus(); }, }); useKeyboardShortcuts(shortcuts); const tabs = [ { id: "overview" as TabType, name: "개요", icon: "📊" }, { id: "documents" as TabType, name: "문서 관리", icon: "📄" }, { id: "knowledge" as TabType, name: "지식 편집", icon: "✏️" }, { id: "management" as TabType, name: "RAG 관리", icon: "⚙️" }, ]; if (isInitializing) { return (

RAG 시스템을 초기화하고 있습니다...

); } if (error || !ragEngine) { return (
초기화 오류

{error || "RAG 엔진을 초기화할 수 없습니다."}

); } return (
{/* Header */} 🧠 지식 베이스 관리 시스템

RAG 기반 챗봇을 위한 통합 지식 베이스 관리 시스템입니다. 문서 업로드, 지식 편집, 품질 모니터링을 한 곳에서 관리할 수 있습니다.

{/* Quick Stats */}
{stats.totalDocuments}
총 문서
{stats.totalKnowledgeEntries}
지식 항목
{stats.totalChunks}
텍스트 청크
{stats.lastActivity ? "활성" : "비활성"}
시스템 상태
{/* Navigation Tabs */}
{tabs.map((tab) => ( ))}
{/* Tab Content */}
{activeTab === "overview" && (
시스템 개요

주요 기능

  • 문서 업로드 및 자동 처리
  • 마크다운 기반 지식 편집
  • 검색 품질 모니터링
  • 자동 지식 격차 분석

시스템 상태

벡터 저장소: 활성
임베딩 모델: text-embedding-ada-002
검색 엔진: 하이브리드
마지막 업데이트: {stats.lastActivity ? new Date(stats.lastActivity).toLocaleString() : "N/A"}
빠른 액션
)} {activeTab === "documents" && ( )} {activeTab === "knowledge" && ( )} {activeTab === "management" && ( )}
{/* Confirmation Dialog */}
); }