
나의 어시스턴트 만들기: AI 에이전트에게 내 파일 찾는 법 가르치기
요약
LangChain과 LangGraph를 활용하여 로컬 파일을 검색하고 관리하는 개인용 AI 에이전트 구축 사례를 소개합니다. 파일 시스템 와처를 통해 인덱스를 자동으로 업데이트하며, 데스크톱 위젯 형태로 실용적인 사용성을 제공합니다.
핵심 포인트
- LangChain과 LangGraph를 이용한 실용적인 에이전트 설계
- Qdrant 벡터 DB와 Groq 모델을 활용한 의미론적 검색 구현
- 파일 시스템 와처를 통한 자동 인덱싱 업데이트 기능
- Flet 기반의 데스크톱 위젯 UI 적용
참고: 이 포스트는 프로젝트의 V1 버전을 다룹니다. 이것은 제가 매일 사용하는 실제 작동하는 어시스턴트이며, 완성된 제품은 아닙니다. 현재 V2를 개발 중이며, 이에 대한 여러분의 아이디어를 진심으로 환영합니다 (자세한 내용은 마지막 부분에 설명합니다).
이것을 만든 이유
저는 아마 대부분의 사람들이 그러하듯 에이전트 AI (agentic AI) 학습을 시작했습니다. 강의를 보고, LangChain과 LangGraph의 기초 개념들을 하나씩 익혀 나갔습니다: 상태 (state), 노드 (nodes), 엣지 (edges), 도구 (tools), 메모리 (memory), 인간 참여 (human-in-the-loop), 가드레일 (guardrails). 실제로 무언가를 만들기 전까지 배워야 할 구조적 틀이 매우 많으며, 어느 시점이 되면 튜토리얼 프로젝트에 대한 갈증이 사라지게 됩니다. 저는 다시는 열어보지 않을 또 다른 "명세서-to-API 에이전트" 데모를 만들고 싶지 않았습니다. 저는 실제로 사용할 수 있는 무언가를 원했습니다.
그래서 저는 제가 실제로 겪고 있는 문제, 즉 다운로드(Downloads), 바탕화면(Desktop), 문서(Documents) 폴더에 너무 많은 파일이 흩어져 있고 어디에 무엇이 있는지 기억나지 않는 문제를 선택했습니다. 그 결과물인 my-assistant는 항상 위에 떠 있는 데스크톱 위젯으로, 제가 일상적인 영어로 "TaskFlow의 승인 프로세스에 대해 무엇을 썼지?" 또는 "지난주 타임시트 열어줘"라고 물어보면 파일을 찾아줍니다.
실제로 하는 일
내부적으로 이것은 하나의 AI 에이전트입니다 (아래에서 더 자세히 설명하겠지만, 에이전트 군집(swarm)은 아닙니다). LangChain과 LangGraph로 구축되었으며, 의미론적 검색 (semantic search)을 위한 로컬 벡터 데이터베이스 (Qdrant)와 실제 추론을 위한 Groq 호스팅 모델을 기반으로 합니다. 이 에이전트는 6가지 도구를 가지고 있습니다: 내용으로 검색, 파일명으로 검색, 파일 또는 폴더 열기, 인덱싱된 파일 개수 세기, 인덱싱된 폴더 목록 표시, 그리고 새로운 파일 인덱싱하기입니다. Flet 기반의 UI가 이 모든 것을 감싸서 제 데스크톱에 항상 떠 있는 작은 채팅 위젯으로 만들어 줍니다.
제가 가장 자랑스럽게 생각하는 부분은 검색 기능이 아니라, 인덱스(index)가 스스로 살아 움직인다는 점입니다. 백그라운드 파일 시스템 와처(file-system watcher)가 제가 새로운 파일을 다운로드하거나, 기존 문서를 수정하거나, 파일을 삭제할 때 이를 감지하여 제가 수동으로 명령어를 실행하지 않아도 자동으로 인덱스를 업데이트합니다. "내 새로운 PDF들을 인덱싱해줘"라고 요청하면 그렇게 수행할 수도 있고, 그냥 백그라운드에서 조용히 작동하게 둘 수도 있습니다.
여러 개가 아닌 단 하나의 에이전트 — 그리고 제가 이를 이해하는 데 시간이 걸린 이유
초기에 저는 폴더 스캔, 텍스트 추출, 청킹 (chunking), 임베딩 (embedding), 저장과 같은 "단계가 많은 긴 프로세스"를 수행하려면 여러 개의 에이전트가 협력해야 한다고 가정했습니다. 하지만 그렇지 않았으며, 왜 그렇지 않은지를 파악하는 과정은 이 프로젝트 전체에서 가장 유용한 교훈 중 하나였습니다.
에이전트가 필요한지 여부를 실제로 결정하는 것은 프로세스의 단계 수가 아니라, 특정 단계가 모호한 입력에 대해 판단 (judgment)을 필요로 하는지 여부입니다. PDF에서 텍스트를 추출하는 방법은 매번 단 한 가지의 정확한 방법만 존재합니다. 청킹 (chunking), 임베딩 (embedding), 벡터 스토어 (vector store)에 기록하는 것도 마찬가지입니다. 이 중 그 어떤 것도 LLM의 추론 (reasoning)을 필요로 하지 않으며, 결정론적 파이프라인 (deterministic pipeline)이 필요할 뿐입니다. 진정한 모호함이 나타나는 유일한 지점은 바로 맨 앞부분, 즉 제가 채팅창에 무언가를 입력했을 때 제가 실제로 의도한 바가 무엇인지 해석하는 단계입니다. 그것이 에이전트적 영역 (agentic surface area)의 전부입니다. 그 이후의 모든 것은 배관 (plumbing) 작업일 뿐입니다.
이러한 관점의 재정립은 멀티 에이전트 (multi-agent) 설계가 실제로 가치가 있는 시점에 대해 제가 생각하는 방식을 바꾸어 놓았습니다. "단계가 많으니까"가 아니라, "어떤 하위 작업이 나머지 작업들과 진정으로 다른 종류의 판단이나 페르소나 (persona)를 필요로 하는가"를 기준으로 삼게 된 것입니다. 이것이 실제로 어디에 적용될 수 있는지에 대해서는 V2에서 더 자세히 다루겠습니다.
저에게 가장 많은 것을 가르쳐준 디버깅 이야기들
진행 과정에서 몇 가지 문제가 발생했는데, 결과적으로는 한 번에 성공했던 부분들보다 이 문제들이 저에게 더 많은 것을 가르쳐 주었습니다.
내 가상 환경을 조용히 집어삼킨 인덱스. 저의 제외 로직(exclusion logic)은 이름이 정확히 venv 또는 .venv인 폴더만 확인했습니다. 그러다 venv_rag라는 이름의 폴더를 발견했고, 그 결과 관련 없는 프로젝트의 수백 개 site-packages 파일들이 검색 결과에 나타났습니다. 해결책은 더 많은 정확한 이름 확인을 추가하는 것이 아니었습니다. pyvenv.cfg 파일의 존재 여부를 통해 구조적으로 가상 환경을 감지하도록 만드는 것이었으며, 이렇게 하면 사용자가 이름을 무엇으로 짓든 상관없게 됩니다.
"저장 폴더가 이미 다른 인스턴스에 의해 사용 중입니다." 채팅 에이전트와 독립적으로 실행되는 백그라운드 와처(watcher)를 추가하자, 두 프로세스가 동시에 동일한 로컬 Qdrant 데이터베이스에 각각 별도의 연결을 시도하는 일이 가끔 발생했습니다. 단일 순차적 에이전트(single sequential agent)에게는 문제가 없지만, 두 개의 독립적인 스레드가 동일한 임베디드 데이터베이스(embedded database)에 접근하는 순간 오류가 발생합니다. 해결책은 호출마다 새로운 연결을 만드는 대신, 공유 싱글톤 연결(shared singleton connection)을 사용하는 것이었습니다.
멈추지 않고 허우적거리는 에이전트. Word 문서 안에 숨겨진 표에 대해 물었을 때, 에이전트는 첫 번째 검색 결과에 만족하지 못하고 관련 없는 도구들을 호출하기 시작했습니다. 파일을 다시 인덱싱하려 하거나, Word에서 문서를 물리적으로 열려고 시도하는 등, 단순히 찾을 수 없다고 말하는 대신 도구들 사이를 맴돌며 허우적거렸습니다. 원시 데이터베이스 쿼리(raw database query)로 깊이 파고들어 확인한 실제 근본 원인은 거의 웃음이 나올 정도였습니다. 콘텐츠는 처음부터 그곳에 있었습니다. 단지 특정 문구에 대해 검색 결과 상위 3위 안에 들지 않았을 뿐입니다. 진짜 해결책은 에이전트가 허우적거리는 대신 멈추고 나에게 알려줄 수 있도록 시스템 프롬프트(system prompt)를 강화하는 것과, 검색당 가져오는 결과의 개수를 늘리는 것이었습니다.
데이터가 오래되지 않았다는 점은 조용히 맞아떨어졌지만, 그 이면의 추론(reasoning)은 지어낸 것이었습니다. 특정 폴더의 내용에 대해 물었을 때, 에이전트는 정확한 파일 개수를 알려주었지만, 왜 하위 폴더를 보여줄 수 없는지에 대해 실제로는 존재하지 않는 제약 사항을 근거로 꾸며낸 설명을 내놓았습니다. 이는 기술적으로 정답인 답변이라 할지라도 확신에 찬 틀린 추론이 동반될 수 있음을 상기시켜 주는 좋은 사례이며, 두 가지 모두를 확인해 볼 가치가 있다는 점을 보여줍니다.
**인덱싱(indexing)된 적도 없는 파일을
만약 여러분이 이와 유사한 것을 구축했거나, 개인용 파일 어시스턴트(personal file assistant)에 진심으로 원하는 기능이 있다면, 댓글을 남기거나 연락해 주세요. 이 프로젝트는 여전히 진행 중(work in progress)이며, 그것이 바로 이 작업의 핵심입니다.
GitHub :- https://github.com/IsaacNatarajan/My-Assistant/tree/main
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기