diff --git a/B01_Dashboard/B01_Dashboard_Knowledge_Chat.py b/B01_Dashboard/B01_Dashboard_Knowledge_Chat.py index cea3a1c2a..d9b0a0477 100644 --- a/B01_Dashboard/B01_Dashboard_Knowledge_Chat.py +++ b/B01_Dashboard/B01_Dashboard_Knowledge_Chat.py @@ -17,7 +17,7 @@ from common_util.common_util_auth import verify_session router = APIRouter(prefix="/knowledge-chat", tags=["B01_KnowledgeChat"]) KNOWLEDGE = Path(__file__).resolve().parents[1] / "resources" / "knowledge" -EXCLUDED = ("실무문서", "stmate", "다산소프트", "technical_info") +EXCLUDED = ("실무문서", "stmate", "다산소프트") MODEL = "gemini-3.8-flash" logger = logging.getLogger(__name__) @@ -27,17 +27,18 @@ class ChatRequest(BaseModel): def _allowed(path: Path) -> bool: - return path.suffix.lower() == ".md" and not any( - excluded in part.casefold() - for part in path.relative_to(KNOWLEDGE).parts - for excluded in EXCLUDED + original = KNOWLEDGE / "original" + return ( + path.suffix.lower() == ".md" + and path.resolve().is_relative_to(original.resolve()) + and not any(part.casefold() in EXCLUDED for part in path.relative_to(original).parts[:-1]) ) @lru_cache(maxsize=1) def _sections() -> list[tuple[str, str]]: sections = [] - for path in KNOWLEDGE.rglob("*.md"): + for path in (KNOWLEDGE / "original").rglob("*.md"): if not _allowed(path): continue relative = path.relative_to(KNOWLEDGE).as_posix() diff --git a/resources/tester/test_b01_knowledge_chat.py b/resources/tester/test_b01_knowledge_chat.py index be1d819c6..9f566b925 100644 --- a/resources/tester/test_b01_knowledge_chat.py +++ b/resources/tester/test_b01_knowledge_chat.py @@ -93,19 +93,22 @@ def test_gemini_timeout_is_reported(monkeypatch): assert "시간 초과" in error.value.detail -def test_chat_searches_all_knowledge_markdown_except_excluded_folders(monkeypatch, tmp_path): +def test_chat_reads_only_original_except_excluded_folders(monkeypatch, tmp_path): public = tmp_path / "original" / "법률" guide = tmp_path / "technical_info" + outside = tmp_path / "별도자료" private = tmp_path / "original" / "실무문서" stmate = tmp_path / "original" / "원가계산" / "STmate" dasan = tmp_path / "original" / "원가계산" / "다산소프트" public.mkdir(parents=True) guide.mkdir() + outside.mkdir() private.mkdir() stmate.mkdir(parents=True) dasan.mkdir() (public / "현행.md").write_text("# 임도 기준\n" + "임도 설치 기준 내용 " * 10, encoding="utf-8") (guide / "_검토.md").write_text("# 임도 기준\n기술정보 안내 " * 10, encoding="utf-8") + (outside / "자료.md").write_text("# 임도 기준\n별도 자료 " * 10, encoding="utf-8") (private / "사례.md").write_text("# 임도 기준\n비공개 사례 " * 10, encoding="utf-8") (stmate / "자료.md").write_text("# 임도 기준\nSTmate 자료 " * 10, encoding="utf-8") (dasan / "자료.md").write_text("# 임도 기준\n다산소프트 자료 " * 10, encoding="utf-8") @@ -149,4 +152,5 @@ def test_chat_searches_all_knowledge_markdown_except_excluded_folders(monkeypatc assert "STmate" not in sent["prompt"] assert "다산소프트" not in sent["prompt"] assert "기술정보 안내" not in sent["prompt"] + assert "별도 자료" not in sent["prompt"] chat._sections.cache_clear()