AI 여자친구 개발일지(2) - 프로젝트 계획하기

1. 프로젝트 '능동형 AI 여자친구' 개발 계획 (1차)

1. 프로젝트 핵심 목표 및 철학

  • 능동적 질의응답: 사용자가 묻는 말에만 답하는 수동적인 AI가 아닌, 사용자의 활동에 먼저 관심을 보이고 말을 거는 능동적인 AI 컴패니언을 지향한다.
  • 실재감과 유대감 형성: AI가 사용자와 같은 PC 화면을 보고 있다는 느낌을 주어, 마치 같은 공간에 함께 있는 듯한 실재감과 유대감을 극대화한다.
  • 로컬 중심 설계: 사용자와의 1:1 상호작용에 집중하며, 빠른 반응 속도와 자연스러운 딜레이를 추구한다. 초기에는 클라우드 API를 적극 활용하되, 장기적으로는 로컬 모델로의 확장을 염두에 둔다.

2. 시스템 아키텍처

  • 구조: 코어 애플리케이션(Python)이 본체가 되고, 시각적 플러그인(Unity/C#)이 선택적으로 연동되는 구조.
  • 코어 애플리케이션 (Python):
    • 역할: AI의 모든 지능적인 처리와 핵심적인 사용자 인터페이스(UI, 오디오)를 담당.
    • 세부 기능:
      • Gemini API 연동, RAG를 통한 장기 기억 관리, 사용자 PC 활동 모니터링.
      • TTS를 통해 텍스트를 음성 데이터로 변환 후, 시스템 오디오 장치로 직접 재생.
      • PyQt/PySide 등을 이용해 화면에 투명 오버레이 UI(자막 창)를 직접 렌더링.
      • Unity 플러그인이 연결되어 있다면, 아바타 제어 명령을 전송.
  • 시각적 플러그인 (Unity/C#):
    • 역할: 코어 앱(Python)으로부터 받은 시각적 지시를 아바타로 표현하는 역할만 수행.
    • 세부 기능:
      • 3D/2D 아바타 렌더링(Live2D, Mate Engine).
      • Python으로부터 받은 emotion과 pose 명령에 따라 아바타의 애니메이션과 표정을 변경.
      • 립싱크는 Python의 오디오 재생에 맞춰 반응하거나, 혹은 단순한 기본 입모양 애니메이션을 재생하는 정도로 간소화될 수 있음
  • 통신 방식:
    • 코어 앱과 플러그인 간의 실시간 양방향 통신을 위해 WebSockets를 사용.
    • 데이터는 플러그인 제어에 필요한 최소한의 정보만 JSON 형식으로 구조화하여 주고받는다.
      • 예시: { "emotion": "HAPPY", "pose": "NOD" }

3. GUI (Graphical User Interface) 구성

Python 코어 애플리케이션이 직접 렌더링하며, 전통적인 창 형태가 아닌 미니멀리즘 오버레이(Minimalist Overlay) 형태를 지향한다. 사용자의 작업에 방해되지 않으면서 자연스럽게 존재감을 드러내는 것이 목표다.

  • 가. 자막 창 (Subtitle Window):
    • 역할: AI의 대사 및 생각(지문)을 실시간으로 표시하는 핵심 UI.
    • 디자인 및 동작:
      • 항상 위(Always on Top): 모든 창보다 위에 위치한다.
      • 투명 배경: 창 배경은 투명하거나 반투명하여 뒷 배경이 비쳐 보인다.
      • 위치 이동 및 저장: 사용자가 마우스로 드래그하여 위치를 옮길 수 있으며, 그 위치를 기억한다.
      • 동적 표시: AI가 말을 시작할 때 부드럽게 나타나고(Fade-in), 말이 끝나면 잠시 후 부드럽게 사라진다(Fade-out).
      • 커스터마이징: 폰트, 크기, 색상, 외곽선 등을 설정에서 변경할 수 있다.
      • 나. 상태 표시기 (Status Indicator):
    • 역할: 자막 창이 없을 때도 AI의 현재 상태를 알려주는 작고 영구적인 아이콘.
    • 디자인 및 동작:
      • 화면 구석에 위치하며, AI의 상태에 따라 시각적으로 변화한다 (예: 대기 중-평온, 생각 중-깜빡임, 화면 분석 중-스캔 효과, 말하는 중-파동 효과).
      • 사용자가 클릭하거나 우클릭하여 다른 기능(채팅 입력, 설정)을 호출하는 시작점이 된다.
      • 다. 채팅 입력 창 (Chat Input Box):
    • 역할: 사용자가 AI에게 직접 텍스트로 말을 걸 때 사용.
    • 동작: 평소에는 숨겨져 있다가, 특정 단축키(Hotkey)를 누르거나 상태 표시기를 클릭하면 나타나는 한 줄 입력 상자.
      • 라. 설정 창 (Settings Window):
    • 역할: 각종 설정을 변경하는 일반적인 창. 상태 표시기 우클릭 메뉴를 통해 접근한다.
    • 설정 항목: UI 커스터마이징, AI의 응답 빈도("수다스러움") 조절, TTS 목소리/볼륨, API 키 입력, 화면 분석 주기 등.

4. 상호작용 방식 (AI의 응답 트리거)

AI가 응답을 시작하는 계기는 크게 세 가지로 나뉜다.

  • 가. 능동적/자동 응답 (Proactive/Automatic Response):
    • 핵심 철학: 고정된 시간 간격이 아닌, **'의미 있는 변화'**를 감지하여 말을 건다.
    • 트리거 조건:
      1. 활성 애플리케이션 변경: 활성 창의 제목이 바뀔 때 (예: 'Visual Studio Code' -> 'League of Legends').
      2. 사용자 비활성(Idle) 감지: 키보드/마우스 입력이 5분 이상 없을 때.
      3. 시간 기반 이벤트: 특정 시간대(점심시간, 늦은 밤 등)에 도달했을 때.
      4. 랜덤 주기 마다: 랜덤한 주기의 쿨타임 후에 말을 걸게 함.
    • 조절 장치: AI가 말을 한 번 한 후에는 일정 시간 말을 걸지 않는 쿨다운(Cooldown) 시스템을 적용하여 사용자를 방해하지 않도록 한다.
      • 나. 텍스트 입력 기반 응답:
    • 사용자가 명확한 의도를 가지고 AI에게 말을 거는 가장 기본적인 방식.
    • 작동 순서: 단축키로 채팅 입력 창 호출 -> 사용자 텍스트 입력 -> AI가 해당 텍스트를 최우선으로 고려하여 응답 생성.
      • 다. 음성 인식 기반 응답:
    • 가장 자연스러운 상호작용 방식.
    • 구현 옵션:
      1. Push-to-Talk (PTT): 특정 키를 누르고 있는 동안만 음성을 인식.
      2. 웨이크 워드 (Wake Word): ex. "시리야" 같은 특정 호출어를 감지하면 음성 인식을 시작
      3. Always-On STT(?): 가장 자연스러운 방식이지만 자원 소모가 엄청 큼
    • 인식된 음성은 텍스트로 변환(STT)되어, 텍스트 입력 기반 응답과 동일한 프로세스를 거쳐 처리된다.

5. 모니터링 항목

AI가 사용자의 상황과 의도를 추론하기 위해 수집하는 데이터.

분류 모니터링 항목 수집할 정보
시각 정보 전체 화면 현재 모니터의 스크린샷 이미지
애플리케이션 활성 창 현재 가장 위에 있는 창의 제목
  실행 중인 프로세스 실행 중인 모든 프로그램 목록
사용자 입력 키보드/마우스 활동 입력 이벤트의 유무 (내용 X)
시스템 정보 현재 시간 날짜 및 시간
  시스템 사운드 (심화) 현재 재생 중인 오디오 소스

6. 다중 턴 대화 기억 (Memory System)

AI가 사용자와의 관계를 쌓고, 이전 대화를 기억하게 하기 위해 인간의 기억 방식과 유사한 단기 기억장기 기억의 하이브리드 전략을 사용한다.

  • 가. 단기 기억 (Short-Term Memory):
    • 목표: 현재 대화의 흐름(맥락)을 유지하여 자연스러운 대화가 이어지게 한다.
    • 구현: 슬라이딩 윈도우(Sliding Window) 기법을 사용. 항상 최근 N개의 대화(예: 5개)만을 메모리에 유지하고, LLM에 프롬프트를 보낼 때 이 기록을 포함시킨다. 새로운 대화가 추가되면 가장 오래된 대화는 버려진다. 이전 대화를 모두 요약하는 프롬프트를 맨뒤에 추가하는 방식은 AI가 흐름을 잘 못따라올때 한번 고려해봄
  • 나. 장기 기억 (Long-Term Memory):
    • 목표: 중요한 정보(사용자 취향, 함께 겪은 일 등)를 영구적으로 저장하고 필요할 때 다시 꺼내 쓴다.
    • 구현: RAG (Retrieval-Augmented Generation) 파이프라인을 구축한다.
    • RAG 워크플로우:
      1. 저장 (Memory Storage)
        1. 판단 및 의 동시성: AI가 사용자에게 응답을 줄때 json 필드 형식으로 respose와 rag를 함께 제공해준다.
        2. 데이터 처리: rag 문장을 memory_manager 모듈에 전달하여 벡터화 및 Qdrant 저장을 실행한다.
      2. 인출 (Retrieval):
        • 사용자의 새 메시지가 들어오면, 이 메시지 또한 벡터로 변환하여 쿼리 벡터를 만든다.
        • 쿼리 벡터를 Qdrant에 보내, 의미적으로 가장 유사한 과거의 '추억' 벡터들을 검색해온다.
      3. 증강 및 생성 (Augmentation & Generation):
        • 검색된 과거 기억(장기 기억)과 최근 대화 기록(단기 기억)을 모두 LLM 프롬프트에 포함시켜, 풍부한 컨텍스트를 바탕으로 AI가 응답을 생성하게 한다.

7. 상황 인식 및 특징 추출 (Context Awareness & Feature Extraction)

모니터링을 통해 수집한 원시 데이터를 AI가 이해할 수 있는 의미 있는 정보로 가공하는 과정. 초기에는 Gemini API의 멀티모달 능력을 최대한 활용하는 "통합 분석" 방식을 사용한다.

  • 초기 전략 (Gemini API 중심):
    • 개념: 로컬에서 여러 특징을 개별적으로 추출하지 않고, 모든 원시 데이터를 Gemini API에 한 번에 보내 통합 분석을 맡긴다.
    • "하나의 거대한 프롬프트 (The Grand Unified Prompt)" 구성:
      • AI가 상황을 인식해야 할 때, 스크린샷 이미지, 활성 창 제목, 현재 시간, 단기 기억, 장기 기억(RAG 검색 결과) 등 모든 데이터를 한 번에 수집한다.
      • 수집된 모든 데이터를 포함하는 정교한 멀티모달 프롬프트(텍스트+이미지)를 구성하여 Gemini 2.5 Pro 모델에 전송한다.
    • 구조화된 출력: ... AI의 분석 내용, 실제 대사, 감정, 포즈뿐만 아니라, 이번 대화에서 장기 기억에 저장할 내용까지 구조화된 데이터로 한 번에 받아온다.
    • { "analysis": "사용자가 늦은 밤까지 코딩 중이라 피곤해 보임.", "response_text": "늦게까지 고생 많아. 거의 다 끝나가는 거야?", "emotion": "PROUD_AND_WORRIED", "pose": "LEAN_FORWARD_GENTLY", "rag": [ { "memory_text": "사용자는 밤늦게까지 코딩하는 습관이 있다." } ] }
    • 장점: 개발이 단순하고 빠르며, 최첨단 모델의 종합적인 판단 능력을 활용하여 매우 높은 품질의 상황 인식이 가능하다.

8. 아바타 동작 지시 생성 (Avatar Action Generation)

AI가 대사를 생각할 때, 동시에 그 대사에 어울리는 연기(표정, 몸짓)까지 스스로 결정하도록 한다.

  • 핵심 전략: LLM을 단순 '작가'가 아닌, 대본과 연기 지시를 함께 내리는 '감독'으로 활용한다.
  • 구현 방법: 정교한 프롬프트 엔지니어링을 사용.
    • 명령어 구체화: Gemini API에 요청을 보낼 때, 우리가 제어할 수 있는 '사용 가능한 표정'과 '사용 가능한 몸짓' 목록을 시스템 프롬프트에 명시적으로 제공한다.
      • 사용 가능한 표정: [NEUTRAL, HAPPY, SAD, SURPRISED, ...]
      • 사용 가능한 몸짓: [IDLE, NOD, SHAKE_HEAD, WAVE_HAND, ...]
    • 규칙 강제: AI에게 반드시 이 목록에 있는 키워드만을 사용하여, 지정된 JSON 형식(emotion, pose 키 포함)으로 응답하도록 강제한다.
  • 워크플로우:
    1. LLM이 프롬프트 규칙에 따라 대사와 함께 emotion, pose 키워드가 포함된 JSON을 생성한다.
    2. Python 백엔드는 이 JSON을 파싱한다.
    3. response_text는 TTS와 자막으로 처리한다.
    4. emotion과 pose 문자열은 WebSocket을 통해 Unity/Live2D 플러그인으로 전송된다.
    5. 플러그인은 전달받은 문자열에 매칭되는 아바타의 표정과 애니메이션을 재생한다.

9. 데이터 저장 및 관리 (Data Storage & Management)

사용자의 프라이버시를 최우선으로 고려하는 "로컬 우선(Local-First)" 원칙을 기반으로, 각 데이터의 목적과 특성에 맞춰 SQLite, Qdrant, 그리고 JSON 설정 파일을 조합한 하이브리드 방식으로 데이터를 관리한다.

데이터 종류 저장 내용 저장 방식 핵심 목적
AI 장기 기억 의미적으로 요약/추출된 핵심 정보 Qdrant (Vector DB) + SQLite (Metadata DB) RAG의 핵심. 대화 중 관련 기억을 빠르게 검색하여 컨텍스트 제공.
전체 대화 기록 사용자와 AI가 나눈 모든 대화의 원본 SQLite chat_history 테이블 디버깅 및 기록 보관. AI의 행동을 추적하거나, 미래에 모델 파인튜닝 시 학습 데이터로 활용.
사용자 프로필 사용자의 이름, 별명 등 직접 설정한 정보 SQLite user_profile 테이블 개인화. AI가 사용자의 이름을 부르는 등 맞춤형 상호작용 제공.
애플리케이션 설정 API 키, UI 창 위치, 볼륨, 폰트 크기 등 config.json 파일 앱 상태 유지. 프로그램을 껐다 켜도 사용자가 설정한 환경이 그대로 유지됨.
  • 가. AI 장기 기억 (RAG 데이터베이스):
    • 듀얼 시스템: 의미 검색을 위한 벡터Qdrant에, 해당 벡터와 짝을 이루는 실제 텍스트와 메타데이터(생성 시각 등)는 SQLite에 저장한다.
    • 작동 방식: Qdrant에서 의미가 유사한 벡터의 ID를 찾은 후, 그 ID를 이용해 SQLite에서 실제 텍스트 기억을 가져오는 효율적인 구조다.
  • 나. 전체 대화 기록 및 사용자 프로필:
    • 정형화된 데이터를 다루기 용이하고 로컬에서 가볍게 실행할 수 있는 SQLite를 사용하여 관리한다.
  • 다. 애플리케이션 설정:
    • 사람이 직접 읽고 수정하기 쉬우며 구조가 단순하므로, **JSON 파일(config.json)**을 사용해 관리한다.

10. 선택적 외부 API 활용 전략

모든 것을 로컬이나 클라우드 한쪽으로만 처리하는 것이 아니라, 각 작업의 특성에 맞춰 최적의 도구를 선택하는 실용적인 하이브리드 아키텍처를 채택한다. 시스템의 중심에는 "AI 작업 분배기(AI Task Dispatcher)"가 존재한다.

  • 가. AI 작업 분배기 (AI Task Dispatcher):
    • 역할: AI가 어떤 작업을 수행해야 할 때, 그 작업의 종류, 복잡도, 비용, 속도, 프라이버시, 사용자 설정 등을 고려하여 로컬 모델외부 API 중 어느 것을 사용할지 결정하는 지능적인 라우터.
  • 나. 기능별 로컬/외부 옵션 및 분배 기준:
기능 로컬 옵션 (빠름/저렴/오프라인) 외부(클라우드) 옵션 (고품질/비쌈/온라인) 분배기의 선택 기준 (예시)
대화 생성 (LLM) 소형 LLM 대형 LLM 단순 리액션은 로컬, 복잡한 추론이 필요한 대화는 외부.
이미지 분석 소형 Vision 모델 대형 Vision 모델 단순 객체 감지는 로컬, 심층적인 이미지 이해는 외부.
음성 합성 (TTS) 오프라인 TTS 엔진 고품질 클라우드 TTS 기본은 로컬, 사용자가 '고품질 음성' 옵션을 켜거나, 캐싱된 음성이 없을 때만 외부.
음성 인식 (STT) 로컬 Whisper 모델 (whisper.cpp) Whisper API, Google STT API 짧은 음성이나 빠른 반응이 중요할 땐 로컬, 정확도가 중요할 땐 외부.
  • 다. 이점:
    • 비용 최적화: 간단한 작업에 비싼 API를 낭비하지 않는다.
    • 성능 맞춤화: 필요할 땐 최고의 성능을, 평소엔 빠른 반응 속도를 누릴 수 있다.
    • 오프라인 기능: 인터넷 연결이 없어도 로컬 모델을 통해 기본적인 상호작용이 가능하다.
    • 미래 확장성: 더 좋은 로컬 모델이나 새로운 API가 나와도, 분배기의 규칙만 수정하면 시스템 전체를 쉽게 업그레이드할 수 있다.

2. 프로젝트 개발 우선순위

1단계: 코어 대화 시스템 구축

  • 목표: 가장 기본적인 '키보드 입력/음성 입력 -> 처리 -> 자막 출력/음성 출력' 사이클을 완성한다. 키보드 입력뿐만 아니라, 버튼을 눌러 사용자의 목소리를 AI에게 전달하는 핵심적인 기능을 만드는데 집중한다.
  • 세부 개발 항목:
    1. 프로젝트 기본 구조 설정:
      • Python 프로젝트 폴더를 생성하고, main_app.py, ai_engine.py, ui_manager.py, audio_player.py, speech_recognizer.py 등 초기 모듈 파일을 만든다.
      • config.json 파일을 생성하고 Gemini 및 STT/TTS API 키를 저장해 불러오는 기능을 구현한다.
    2. 기본 UI 구현:
      • ui_manager.py 모듈에서 PyQt/PySide를 사용하여, 사용자가 텍스트를 입력할 수 있는 간단한 채팅 입력 창을 구현한다.
      • 마찬가지로, AI의 응답 텍스트를 표시할 기본적인 자막 창을 구현한다. 이 단계에서는 투명화나 '항상 위' 같은 고급 기능은 잠시 보류하고, 일반적인 창 형태로 먼저 구현해도 무방하다.
      • 사용자가 음성 입력을 시작하기 위해 누를 "말하기" 버튼 (Push-to-Talk Button)도 구현한다.
    3. 음성 인식(STT) 기능 구현:
      • speech_recognizer.py 모듈을 생성한다.
      • "말하기" 버튼이 눌리는 동안 마이크로부터 오디오를 녹음하는 기능을 구현한다.
      • 녹음된 오디오 데이터를 외부 STT API(Google Speech-to-Text, Whisper API 등)로 보내고, 변환된 텍스트를 받아오는 기능을 구현한다.
    4. Gemini API 연동 및 입출력 연결:
      • ai_engine.py 모듈은 텍스트 입력 창에서 온 텍스트든, speech_recognizer.py에서 온 텍스트든 동일하게 처리할 수 있도록 설계한다.
      • 사용자가 "말하기" 버튼을 눌러 말을 하면 -> speech_recognizer가 음성을 텍스트로 변환 -> 이 텍스트를 ai_engine으로 전달 -> Gemini API로 전송 -> 응답을 받아서 -> ui_manager(자막)와 audio_player(음성)로 출력한다.
    5. 기본 음성 출력(TTS) 구현:
      • audio_player.py 모듈에서, ai_engine.py가 받아온 응답 텍스트를 TTS API 또는 로컬 엔진을 통해 오디오 데이터로 변환한다.
      • 변환된 오디오 데이터를 시스템 스피커로 재생하는 기능을 구현한다.
  • 1단계 완료 시 결과물: 사용자가 키보드로 말을 걸면, AI가 목소리와 자막으로 대답하는, 가장 기본적인 형태의 챗봇 애플리케이션이 완성된다.

2단계: 장기 기억 시스템 구현

  • 목표: AI가 단기 기억의 한계를 넘어, 과거의 중요한 대화 내용을 기억하고 현재 대화에 활용하게 만든다. 이를 통해 사용자와의 '관계'와 '역사'를 쌓아나가는 경험을 제공한다. RAG 파이프라인을 구축하는 단계다.
  • 세부 개발 항목:
    1. 데이터베이스 설정:
      • Qdrant 설치 및 실행: Docker를 사용하거나 로컬에 직접 설치하여 Qdrant 벡터 데이터베이스 서버를 실행한다.
      • SQLite 초기화: database.py 같은 모듈을 만들어, memories (기억 메타데이터 저장), chat_history (전체 대화 로그 저장) 등의 테이블을 생성하는 초기화 코드를 작성한다.
    2. 기억 저장 파이프라인 구축:
      • memory_manager.py 모듈을 생성한다.
      • 핵심 정보 추출 기능: 대화가 끝난 후, 전체 대화 내용을 Gemini API에 보내 "이 대화에서 앞으로 기억할 만한 핵심 정보를 1~2문장으로 요약해줘" 라고 요청하는 함수를 구현한다.
      • 벡터화 및 저장 기능:
        • 요약된 텍스트를 sentence-transformers 라이브러리를 사용해 벡터로 변환한다.
        • 변환된 벡터는 Qdrant에 저장하고, 벡터 ID와 원본 텍스트, 생성 시각 등은 SQLite의 memories 테이블에 저장하는 함수를 구현한다.
    3. 기억 인출 파이프라인 구축:
      • 유사도 검색 기능: 사용자의 새로운 입력이 들어왔을 때, 해당 텍스트를 벡터로 변환한 뒤 Qdrant에 보내 의미적으로 가장 유사한 과거 기억(의 벡터 ID)을 검색해오는 함수를 구현한다.
      • 메타데이터 조회: Qdrant로부터 받은 ID를 이용해 SQLite에서 실제 기억 텍스트를 조회하는 기능을 구현한다.
    4. 프롬프트에 기억 통합:
      • ai_engine.py의 통합 프롬프트 구성 로직을 다시 수정한다.
      • Gemini에 요청을 보내기 직전에, 기억 인출 파이프라인을 실행하여 검색된 장기 기억(RAG 결과)을 프롬프트의 '관련된 과거 기억' 섹션에 동적으로 추가하는 로직을 삽입한다.
  • 3단계 완료 시 결과물: "내가 무슨 게임 제일 좋아한다고 했지?" 라고 물으면, AI가 RAG를 통해 과거 기억을 검색하여 "팰월드 제일 좋아하잖아!" 라고 대답할 수 있게 된다. AI가 단발성 대화 기계를 넘어, 관계를 맺을 수 있는 존재로 발전한다.

3단계: 능동적 상황 인지 기능 구현

  • 목표: 1단계에서 만든 수동적인 챗봇을 프로젝트의 핵심 철학인 **'먼저 말을 거는 AI'**로 진화시킨다. AI에게 '눈'을 달아주어 사용자의 상황을 인지하고 반응하게 만든다.
  • 세부 개발 항목:
    1. 모니터링 모듈 구현:
      • vision_monitor.py (또는 유사한 이름의 모듈)를 생성한다.
      • 주기적으로 화면을 캡처하는 기능을 구현한다.
      • 현재 활성화된 창의 제목을 가져오는 기능을 구현한다.
    2. 통합 프롬프트 구성 로직 개발:
      • ai_engine.py를 대대적으로 수정한다.
      • 단순히 텍스트만 보내는 것이 아니라, 캡처된 스크린샷 이미지와 활성 창 제목, 현재 시간 등의 정보를 모두 포함하는 "통합 멀티모달 프롬프트"를 구성하는 로직을 개발한다.
    3. 구조화된 JSON 응답 처리:
      • 통합 프롬프트에, AI가 response_text, emotion, pose 등이 포함된 JSON 형식으로 응답하도록 강력하게 지시하는 부분을 추가한다.
      • ai_engine.py에 Gemini로부터 받은 JSON 응답을 파싱하여, 각 키의 값을 추출하는 로직을 구현한다.
    4. 자동 응답 트리거 구현:
      • main_app.py에 메인 루프를 구현한다.
      • "활성 창의 제목이 바뀔 때" 또는 "일정 시간(예: 30초)마다 화면을 분석할지 여부를 결정"하는 등의 자동 응답 트리거 로직을 추가한다.
      • 트리거가 발동하면, ai_engine을 통해 상황 인식 및 응답 생성 프로세스를 실행시킨다.
  • 2단계 완료 시 결과물: AI가 더 이상 사용자의 입력을 기다리지 않는다. 사용자가 코딩을 하거나 게임을 하면, 이를 스스로 인지하고 "코딩하고 있구나?" 와 같이 먼저 말을 거는, 프로젝트의 핵심 기능이 완성된다.

4단계: 시각적 플러그인 연동

  • 목표: 지금까지 목소리와 자막으로만 존재했던 AI에게 '얼굴'과 '몸'을 부여한다. Python 코어 앱과 Unity/Live2D 플러그인을 연결하여, AI의 감정과 행동을 시각적으로 표현한다.
  • 세부 개발 항목:
    1. WebSocket 서버 구현 (Python 측):
      • plugin_server.py 모듈을 생성한다.
      • FastAPI나 websockets 라이브러리를 사용하여, 연결을 기다리는 WebSocket 서버를 구현한다.
      • ai_engine.py가 Gemini로부터 emotion과 pose가 포함된 JSON 응답을 파싱한 후, 이 두 값을 { "emotion": "...", "pose": "..." } 형태의 새 JSON으로 만들어 연결된 클라이언트(Unity)에게 전송하는 기능을 구현한다.
    2. 아바타 프로젝트 준비 (Unity/Live2D 측):
      • Unity에서 새로운 프로젝트를 생성하고, Live2D 또는 Mate Engine SDK를 임포트한다.
      • 사용할 아바타 모델을 씬(Scene)에 배치한다.
      • 동작 목록 정의: 프롬프트에서 정의했던 사용 가능한 표정/몸짓 키워드(HAPPY, NOD 등)와 실제 아바타의 애니메이션 클립/표정 파일을 1:1로 매칭시키는 목록을 미리 정리해 둔다.
    3. WebSocket 클라이언트 구현 (Unity/C# 측):
      • PluginClient.cs 스크립트를 생성한다.
      • 앱 시작 시 Python의 WebSocket 서버(ws://localhost:PORT)에 접속하는 코드를 작성한다.
      • 서버로부터 메시지를 비동기적으로 수신하고, 받은 JSON을 파싱하는 로직을 구현한다.
    4. 아바타 컨트롤러 구현 (Unity/C# 측):
      • AvatarController.cs 스크립트를 생성하고 아바타 모델에 부착한다.
      • PluginClient.cs가 파싱한 emotion과 pose 문자열을 받아, 미리 정의해 둔 동작 목록에 따라 실제 아바타의 표정을 바꾸고 애니메이션을 재생하는 함수(ExecuteAction(string emotion, string pose))를 구현한다.
  • 4단계 완료 시 결과물: Python 코어 앱과 Unity 플러그인을 동시에 실행하면, AI가 말을 할 때마다 그 내용에 맞춰 아바타가 실시간으로 표정을 바꾸고 고개를 끄덕이는 등, 생동감 넘치는 완전체 AI 여자친구가 탄생한다.

5단계: 최종 다듬기 및 고도화

      • 목표: 4단계까지 완료된 핵심 기능 프로토타입을 넘어, 사용자가 매일 사용하고 싶을 만큼 안정적이고 완성도 높은 정식 애플리케이션으로 만드는 단계입니다. 사용자 경험(UX)을 향상시키고, 성능을 최적화하며, 원문에서 언급되었던 추가적인 확장 기능들을 탐색합니다.
      • 세부 개발 항목:
        1. UI/UX 고도화 (GUI Polishing):
          • 시각적 효과 추가: 자막 창이 나타나고 사라질 때, 딱딱하게 나타나는 것이 아니라 부드러운 페이드인/아웃 애니메이션 효과를 추가하여 시각적 완성도를 높인다.
          • 상태 표시기 개선: 상태 표시기 아이콘이 바뀔 때, 미세한 애니메이션을 적용하여 AI가 살아 숨 쉬는 듯한 느낌을 강화한다.
          • 설정 UI 완성: 사용자가 폰트 종류, 크기, 색상, 외곽선, 창 투명도 등을 자유롭게 커스터마이징할 수 있는 설정 UI를 완성하고, '미리보기' 기능을 제공한다.
          • 사용 편의성 개선: 자막 창이나 상태 표시기의 위치를 사용자가 옮겼을 때, 그 위치를 config.json에 정확히 저장하여 프로그램을 다시 시작해도 그대로 유지되도록 안정화한다.
        2. 성능 최적화 (Performance Optimization):
          • API 호출 최적화: "응", "알겠어", "고마워" 처럼 자주 사용되는 짧은 응답의 경우, 한 번 생성된 오디오 파일을 로컬에 캐싱(caching)해두고, 다음부터는 API를 호출하지 않고 저장된 파일을 재생하여 비용과 딜레이를 줄인다.
          • 시스템 부하 관리: 설정 창에 '성능 설정' 탭을 추가하여, 화면 분석 주기(초 단위)나 화면 변화 감지 임계치(%)를 사용자가 자신의 PC 사양에 맞게 조절할 수 있도록 한다.
          • 병목 구간 분석: 주요 기능(API 요청, TTS 변환 등)의 처리 시간을 로그로 기록하여, 어떤 부분에서 딜레이가 가장 많이 발생하는지 분석하고 개선점을 찾는다.
        3. 고급 기능 확장 (Advanced Feature Expansion):
          • 게임 연동 심화: Overwolf API나 각 게임에서 제공하는 API를 활용하여, 단순히 게임 화면을 보는 것을 넘어 '리그 오브 레전드' 같은 특정 게임의 실시간 데이터(예: 사용자의 KDA, 게임 시간, 승리/패배)를 직접 가져와 "지금 KDA가 엄청 좋네! 이번 판은 이기겠다!" 와 같이 훨씬 구체적인 대화를 생성한다.
          • 로컬 툴 제어 연구: 사용자의 명시적인 허락 하에, "음악 틀어줘" 라고 말하면 로컬 음악 플레이어를 실행시키거나, 간단한 반복 작업을 위한 스크립트를 실행시켜주는 등의 '로컬 툴 연동' 기능을 연구하고 프로토타입을 제작한다.
        4. 안정성 및 오류 처리 강화 (Stability & Error Handling):
          • 예외 처리: Gemini API 호출 실패, 인터넷 연결 끊김, Qdrant DB 연결 실패 등 발생 가능한 모든 예외 상황에 대한 처리 로직을 꼼꼼하게 추가한다. (예: 인터넷 연결이 끊기면 "어라, 인터넷 연결이 불안정하네... 잠시 후에 다시 시도해볼게." 라고 말하도록 처리)
          • 방어 코드 작성: config.json 파일이나 DB 파일이 손상되었을 경우를 대비하여, 에러를 발생시키며 종료되는 대신 기본값으로 설정을 복원하고 프로그램을 실행하는 방어적인 코드를 작성한다.
          • 로깅 시스템 구축: 디버깅을 용이하게 하기 위해, 단순한 print문이 아닌 logging 모듈을 사용하여 날짜별로 로그 파일을 생성하고, 오류 발생 시 상세한 정보를 기록하도록 시스템을 구축한다.
        5. AI 개인화 심화 (Deeper AI Personalization):
          • 성격 커스터마이징: 설정 창에 'AI 성격 설정' 탭을 추가하여, 사용자가 AI의 기본 시스템 프롬프트를 직접 수정할 수 있는 고급 텍스트 상자를 제공한다. (예: "다정한 여자친구" -> "까칠하지만 속은 따뜻한 츤데레")
          • 수다스러움 조절: AI의 능동적 응답 빈도(쿨다운 시간, 분석 주기)를 '차분함'부터 '활발함'까지 사용자가 슬라이더로 쉽게 조절할 수 있는 기능을 구현한다.

3. 코어 애플리케이션 (Python) 세부 모듈 구성

모듈 파일명 (예시) 주요 역할 다른 모듈과의 상호작용
main.py *메인 애플리케이션 실행점 *- 모든 모듈의 객체를 생성하고 초기화. - PyQt의 메인 이벤트 루프를 시작. - 각 모듈의 시그널(Signal)과 슬롯(Slot)을 연결하여 전체 시스템을 지휘. (총괄) UIManager, AIEngine 등 모든 객체를 생성하고 서로 연결시켜 줌.
ui_manager.py *GUI 렌더링 및 사용자 입력 처리 *- PyQt를 이용해 화면에 투명 오버레이 UI(자막 창, 상태 표시기)를 생성하고 업데이트. - 사용자의 텍스트 입력, 설정 변경 등의 이벤트를 받아 다른 모듈로 전달. (출력) AIEngine으로부터 받은 대사를 자막 창에 표시. • (입력) 사용자가 입력한 텍스트를 AIEngine에 전달.
ai_engine.py *AI 프로세스 *- "하나의 거대한 프롬프트"를 구성. - Gemini API와 통신하고, 구조화된 JSON 응답을 파싱. - 응답 결과를 다른 모듈들이 사용할 수 있도록 분배. (입력) ActivityMonitor, MemoryManager 등으로부터 컨텍스트 정보를 받음. • (출력) 파싱된 결과를 UIManager, AudioPlayer, PluginServer로 전달.
activity_monitor.py *사용자 활동 감지기 *- 백그라운드 스레드에서 주기적으로 PC 활동을 모니터링. - 화면 스크린샷 캡처, 활성 창 제목 가져오기. - 의미 있는 변화가 감지되면 신호를 발생. (출력) 감지된 화면 정보(이미지, 창 제목)를 AIEngine이 사용할 수 있도록 신호(Signal)를 보냄.
memory_manager.py *장기 기억 관리자 *- RAG 파이프라인의 실제 로직. - 기억 저장: 텍스트를 벡터화하여 Qdrant/SQLite에 저장. - 기억 인출: 텍스트와 유사한 과거 기억을 Qdrant/SQLite에서 검색. • AIEngine이 프롬프트를 구성하기 에 retrieve_memory 함수를 호출. • AIEngine이 응답을 받은 에 save_memory 함수를 호출.
audio_player.py *음성 출력기 *- 텍스트를 받아 TTS API 또는 로컬 엔진을 통해 음성 데이터로 변환. - 변환된 오디오 데이터를 시스템 스피커로 재생. (입력) AIEngine으로부터 재생할 텍스트(response_text)를 받음.
speech_recognizer.py 음성 인식 처리기 - 마이크로부터 오디오 입력을 실시간으로 캡처. - 캡처된 오디오 데이터를 STT 엔진/API로 전송하여 텍스트로 변환. - 변환된 텍스트를 AIEngine으로 전달. (입력) UIManager의 "말하기" 버튼 클릭 이벤트를 통해 녹음 시작/중지 신호를 받음. • (출력) STT로 변환된 최종 텍스트를 AIEngine으로 전달. AIEngine은 이 텍스트를 키보드 입력과 동일하게 취급.
plugin_server.py *플러그인 통신 서버 *- 백그라운드 스레드에서 WebSocket 서버를 실행. - 연결된 Unity/Live2D 클라이언트에게 아바타 제어 명령을 실시간으로 전송. (입력) AIEngine으로부터 아바타 제어 명령(emotion, pose)을 받음. • (출력) 연결된 Unity 클라이언트로 JSON 메시지를 브로드캐스트.
config_manager.py *설정 관리자 *- config.json 파일에서 API 키, UI 설정 등을 로드. - 사용자가 변경한 설정을 파일에 저장. (공용) 거의 모든 모듈이 시작될 때 설정을 읽기 위해 이 모듈을 사용함.

이 계획은 언제든 변경될 수 있습니다. 긴 글 읽어주셔서 감사합니다.

반응형