dain.son(손다인)‐정리 및 계획 - 100-hours-a-week/3-team-ssammu-wiki GitHub Wiki

요약

CareerBee 서비스

  • IT 기업의 위치 및 상세 정보를 알 수 있음 → RAG 기법
  • 일일 CS 대회 문제 → AI API로 1000여 개 문제 생성
  • 면접 피드백: 사용자 답변에 대한 실시간 AI 피드백 제공
    • 면접 질문-사용자 답변-피드백 데이터 1000여 개 생성 후 파인튜닝
  • 이력서 자동 생성: 사용자 정보 활용 Langgraph 에이전트가 질문 생성 → 정보 충분 판단 → 추가 정보 수집 → 이력서 생성 로직 구현

AI Engineering

  • 모델 API 설계
  • 모델 성능 비교 (속도, VRAM 효율, GPU 비용, 응답 품질 - GPT 평가)
    • 동시 요청 부하 실험 (실험 환경 세팅 후 성능 지표 측정)
    • 평균 지연 시간 약 26초, 추론 처리량 약 0.038 req/sec, GPU 사용률 약 90%, 메모리 사용량 약 20GB, 32개 까지는 안정 작동
    • Mistral-7b-Instruct-v0.3 → aya-exapnse-8b
  • 서비스 아키텍처 모듈화 : AI 서버 내에서도 기능별 모듈 구조 분리 설계
  • RAG, LangChain, LangGraph 기반 AI Agent 적용 설계 및 구현
  • FastAPI 서버 기능 구현 및 Spring과의 통신 테스트 (진행 중)

향후 계획

  • MCP 활용 AI Agent 구현
  • Grafana, Prometheus 모니터링 시스템

기능별 문서화

AI 면접 피드백 기능 구현

🎯 핵심 개요

사용자의 면접 답변에 대해 LLM 기반 자연어 피드백을 자동 생성하는 기능.
비정형 답변에 대해 정확성, 구체성, 보완점 중심의 평가 문장을 LLM이 직접 생성.
파인튜닝된 aya-expanse-8b 모델과 LangChain, aiohttp 비동기 추론을 기반으로 설계.

🏗️ 시스템 아키텍처

FastAPI → Feedback API → LLM (aya-expanse-8b via vLLM) → 피드백 텍스트 반환

핵심 구성요소:

  • FastAPI: 피드백 API 서버
  • VLLM 서버: 모델 추론 처리 (aya-expanse-8b)
  • LLM 프롬프트: Few-shot 기반 질문/답변/피드백 예시 + 사용자 입력
  • 비동기 처리: aiohttp 기반 비동기 API 요청 처리

🚀 주요 기능

1. 피드백 생성 (/feedback/create)

POST /api/v1/feedback/create
→ 입력: 질문 + 사용자 답변
→ 출력: 피드백 문장 (LLM이 생성한 자연어)

예시 입력/출력

Request:
{
  "question": "LSTM이 기울기 소실 문제를 해결하는 핵심 구조적 특징을 설명해주세요.",
  "answer": "LSTM은 RNN보다 좋아서 기울기 소실이 안 생깁니다."
}

Response:
{
  "feedback": "피드edback: LSTM이 RNN보다 개선된 점을 언급했지만, 질문의 핵심인 구조적 특징에 대한 설명이 없습니다. LSTM은 셀 상태와 게이트 메커니즘을 통해 정보 흐름을 조절하여 기울기 소실을 완화합니다. 이러한 구조에 대한 이해를 보이면 더 나은 답변이 될 것입니다."
}

🧠 LLM 프롬프트 설계 방식

[질문]
(면접 질문 예시)
[답변]
(지원자 답변 예시)
[피드백]
(LLM이 생성할 기준 피드백 예시)

...

[질문]
(사용자 질문)
[답변]
(사용자 답변)
이 답변에 대해 다음 기준을 바탕으로 간결하게 구체적인 피드백을 3~5문장으로 작성해주세요:
- 답변이 질문의 핵심을 이해하고 있는지
- 틀린 내용이나 부족한 설명이 있는지
- 어떤 내용을 보완하면 더 좋은 답변이 되는지

시스템 역할 (System Role):

당신은 컴퓨터공학 면접관입니다. 질문에 대한 지원자의 답변을 보고 어떤 점이 보완되면 좋겠는지 친절하게 피드백해주세요.

🔧 서비스 구현 코드 요약

1. 프롬프트 생성

def build_feedback_prompt(question: str, answer: str) -> str:
    # few-shot 예시 + 사용자 질문/답변을 조합해 LLM 입력 프롬프트 생성

2. 비동기 추론 요청

async def generate_feedback(question: str, answer: str) -> str:
    async with aiohttp.ClientSession(...) as session:
        async with session.post(
            url=f"{VLLM_URL}/v1/chat/completions",
            json={
                "model": MODEL_NAME,
                "messages": [
                    {"role": "system", "content": SYSTEM_ROLE},
                    {"role": "user", "content": prompt}
                ],
                ...
            }
        ) as response:
            result = await response.json()
            return result["choices"][0]["message"]["content"].strip()

🛠️ 해결한 주요 문제

문제 해결방법
VLLM 연결 불안정 타임아웃 설정 + 예외 처리 (aiohttp.ClientTimeout)
비정형 프롬프트 구성 Few-shot 방식으로 예시 입력 + 명확한 기준 제시
동기 API 응답 지연 aiohttp를 사용한 비동기 처리
LLM 응답 문장 중단 방지 "문장 도중에 끊지 말고, 의미 단위로 마무리" 프롬프트 명시

📊 테스트 결과

✅ 단일 요청 평균 응답 시간: 1.5초 (L4 GPU 기준)
✅ 프롬프트에 따른 LLM 피드백 품질: 수작업 기준 90% 이상 만족
✅ 비동기 요청/응답 처리: 안정적
✅ 예외 발생 시 graceful fallback: 성공

📡 API 명세

피드백 생성

POST /api/v1/feedback/create

✅ 요청 예시

{
  "question": "트랜잭션의 ACID 특성에 대해 설명해주세요.",
  "answer": "ACID는 트랜잭션이 안정적으로 수행되기 위한 성질입니다."
}

✅ 응답 예시

{
  "feedback": "피드백: ACID의 전반적인 목적은 언급했으나, 각 특성(원자성, 일관성, 고립성, 지속성)에 대한 설명이 생략되어 아쉽습니다. 각 특성에 대해 간단히 정의하고, 예를 들어 설명해주면 더 신뢰감 있는 답변이 될 것입니다."
}

🎉 주요 성과

  • 자연어 피드백 생성 자동화 성공
  • aya-expanse-8b 기반 vLLM 추론 최적화
  • LLM 비동기 추론 처리 시스템 설계
  • 컴퓨터공학 면접에 특화된 few-shot 템플릿 구성
  • 확장 가능하고 유연한 프롬프트 기반 설계

🚀 기술 스택

  • Backend: FastAPI, Python 3.11
  • LLM: aya-expanse-8b (vLLM)
  • Async HTTP: aiohttp
  • Infra: GCP L4 GPU, Docker
  • Prompt Engineering: Few-shot 예시 기반

📋 빠른 실행

# 의존성 설치
pip install -r requirements.txt

# vLLM 서버 실행 (port: 8001)
python -m vllm.entrypoints.openai.api_server --model /mnt/ssd/aya-expanse-8b --port 8001

# FastAPI 실행
uvicorn app.main:app --reload --port 8000

# API 테스트
curl -X POST http://localhost:8000/api/v1/feedback/create \\
  -H "Content-Type: application/json" \\
  -d '{"question": "TCP와 UDP의 차이점은?", "answer": "TCP는 느리지만 신뢰성이 높고, UDP는 빠릅니다."}'

결과: AI가 자동으로 면접 답변에 피드백을 생성하는 기능을 구현 완료.
질문 유형이 다양해져도 few-shot 방식으로 유연하게 대응 가능하며, 실제 면접 연습 또는 기업 면접관의 보조 도구로 활용 가능.

LangGraph 기반 이력서 에이전트 구현

🎯 핵심 개요

LangGraph + Redis를 활용한 대화형 이력서 생성 에이전트를 구현. 다단계 질문-답변을 통해 개인화된 이력서를 자동 생성하는 시스템.

🏗️ 시스템 아키텍처

  • 고급 이력서 생성 첫번째 흐름
sequenceDiagram
    participant User
    participant Frontend
    participant Spring
    participant FastAPI
    participant Redis
    participant Kafka
    participant SSE

    User->>Frontend: 고급 이력서 생성 요청
    Frontend->>Spring: POST /api/v1/advanced-resume/init
    Spring->>Spring: member_id 확인 및 인증
    Spring->>FastAPI: POST /resume/agent/init (member_id 포함)

    FastAPI->>FastAPI: 초기 ResumeAgentState 구성
    FastAPI->>FastAPI: LLM 호출 → 질문 생성
    FastAPI->>Redis: SET resume:{member_id} = 상태
    FastAPI-->>Spring: 생성된 question + member_id 반환

    Spring->>Kafka: ResumeQuestionGenerated 이벤트 발행 (member_id + question)

    Kafka-->>SSE: 메시지 소비
    SSE-->>Frontend: SSE 푸시 (member_id 기반)

    Note over Frontend: 사용자에게 질문 표시
  • 고급 이력서 생성 두번째 흐름
sequenceDiagram
    participant User
    participant Frontend
    participant Spring
    participant FastAPI
    participant Redis
    participant S3
    participant Kafka
    participant SSE

    User->>Frontend: 질문에 대한 답변 입력
    Frontend->>Spring: POST /api/v1/advanced-resume/update\n+ member_id + 답변

    Spring->>FastAPI: POST /resume/agent/update\n+ member_id + 답변
    FastAPI->>Redis: GET resume:{member_id}
    Redis-->>FastAPI: 기존 상태 반환
    FastAPI->>FastAPI: 상태 업데이트 (답변 누적)

    alt 조건 미충족 (질문 필요)
        FastAPI->>FastAPI: 다음 질문 생성 (LLM 호출)
        FastAPI->>Redis: SET resume:{member_id} = 상태
        FastAPI-->>Spring: { memberId: 3, isComplete: false, question }

        Spring->>Kafka: Produce ResumeQuestionGenerated(member_id, question)

    else 조건 충족 (이력서 작성 완료)
        FastAPI->>FastAPI: 이력서 생성 (Markdown + .docx)
        FastAPI->>S3: PUT 이력서 파일
        S3-->>FastAPI: object_key 반환
        FastAPI->>Redis: DEL resume:{member_id}
        FastAPI-->>Spring: { memberId: 3, isComplete: true, resumeObjectKey }

        Spring->>Kafka: Produce ResumeCompleted(member_id, resume_url)
    end

    Kafka-->>SSE: 메시지 소비
    SSE-->>Frontend: SSE 푸시 (질문 또는 이력서 URL)

핵심 구성요소:

  • LangGraph: 대화형 워크플로우 엔진
  • Redis: 상태 관리 및 동시성 제어
  • LLM: 질문 생성 및 이력서 작성 (VLLM/OpenAI)

🚀 주요 기능

1. 에이전트 초기화 (/resume/agent/init)

# 사용자 정보 → 첫 질문 생성 → Redis 저장
POST /api/v1/resume/agent/init
Response: {"member_id": 1001, "question": "..."}

2. 에이전트 업데이트 (/resume/agent/update)

# 답변 처리 → LangGraph 실행 → 다음 질문 OR 완료
POST /api/v1/resume/agent/update
Response: {"member_id": 1001, "isComplete": true, "resumeObjectKey": "..."}

🔧 LangGraph 워크플로우

graph = StateGraph(ResumeAgentState)
graph.add_node("receive_answer", ReceiveAnswerNode)     # 답변 처리
graph.add_node("check_completion", CheckCompletionNode) # 완료 판단
graph.add_node("generate_question", GenerateQuestionNode) # 질문 생성
graph.add_node("create_resume", CreateResumeNode)      # 이력서 생성

💾 Redis 상태 관리

class RedisClient:
    async def save_state(self, member_id, state):
        # datetime 직렬화 문제 해결: default=str
        state_json = json.dumps(state.to_redis_dict(), default=str)
        
    async def acquire_lock(self, member_id):
        # 동시성 제어: Redis SET NX EX
        return self.redis_client.set(lock_key, value, nx=True, ex=30)

🛠️ 해결한 주요 문제

문제 해결방법
DateTime 직렬화 오류 json.dumps(..., default=str)
응답 스키마 불일치 Pydantic alias="isComplete"
VLLM 연결 불안정 OpenAI fallback + 에러 처리
동시 요청 처리 Redis 락 메커니즘

📊 테스트 결과

✅ Redis 연결/CRUD: 성공
✅ init → update 플로우: 성공 (3회 질문-답변)
✅ S3 파일 업로드: 성공
✅ 동시성 제어: 성공
📄 최종 결과: resume/resume_agent_20250708_102544.docx

📡 API 명세 (핵심)

초기화

POST /api/v1/resume/agent/init
{
  "member_id": 1001,
  "inputs": { "email": "...", "preferred_job": "AI 엔지니어", ... }
}
→ { "member_id": 1001, "question": "첫 번째 질문" }

업데이트

POST /api/v1/resume/agent/update
{ "member_id": 1001, "answer": "사용자 답변" }
→ { "member_id": 1001, "isComplete": false, "question": "다음 질문" }
→ { "member_id": 1001, "isComplete": true, "resumeObjectKey": "s3-key" }

🎉 주요 성과

  • SpringBoot → FastAPI 성공적 이전
  • 대화형 AI 에이전트 구현 완료
  • Redis 기반 상태 관리 시스템 구축
  • 전체 플로우 테스트 통과
  • S3 연동 및 파일 업로드 완료

🚀 기술 스택

  • Backend: FastAPI, Python 3.11
  • AI Framework: LangGraph
  • State: Redis
  • LLM: VLLM/OpenAI
  • Storage: AWS S3

📋 빠른 실행

# 환경 설정
pip install -r requirements.txt

# Redis 시작
redis-server

# FastAPI 서버 실행
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

# 테스트 실행
python tests/test_init_update_flow.py

결과: 확장 가능하고 안정적인 AI 기반 이력서 생성 시스템 구축 완료