[KT AIVLE SCHOOL] 2차 미니프로젝트

2025. 5. 12. 16:01·KT에이블스쿨

🧠미니 프로젝트

25/05/8-25/05/12 걸쳐서 2차 미니 프로젝트가 진행되었습니다.

 

이번 2차 미니 프로젝트에서 저희 주제는 AI 면접관 Agent 구축 이었습니다.

취업 준비를 할 때, 면접준비라는게 채용 과정에서 가장 부담스럽지만 연습하는 것이 쉽지 않습니다. 또한 면접 후 개인 피드백이 없다보니 자신이 무엇을 잘 하고 못 하는지 알 수 없는 문제가 있습니다. 이러한 문제를 해결하기 위하여 개인화된 질문과 답변에 대한 피드백을 해주는 AI 면접관 Agent 시스템 구축하는 프로젝트를 진행합니다.  LangChain, RAG, AI Agent를 사용하여 LLM 기반 Text인식, 요약 및 생성을 활용하고 LangGraph를 활용하여 AI Agent 구축하는 것이 목표입니다. 

 

 

 

핵심기술요소

  • LangGraph 기반 Agent 흐름 설계
  • LLM 기반 질문 생성 
  • 사전 준비 : 이력서 요약 ㅡ> 전략 수립
  • 면접 절차 : 질문 생성 ㅡ> 사용자 응답 ㅡ> 추가 질문 ㅡ> 평가 및 최종 피드백

 

LLM (AI 면접관 Agent의 핵심 Brain)

  • OpenAI / GPT-4o mini

 

LangGraph (Agent 구축 도구)

  • LangGraph란 LLM과 Tool을 노드로 구성해 순차 또는 분기적으로 실행
  • 복잡한 흐름을 시각적으로 구성 가능 
  • 조건 분기 및 반복 처리 지원 ㅡ>에이전트 구현에 최적화

 

 

 

 

🧠Mission 1

 

 

✨Mission1? 

AI 면접관 기본 기능으로 전체 틀 구성하기 

  • 1) 면접 사전 준비 절차 구현
    • 이력서/자소서 인식
    • State 정의서류분석
    • 요약 및 키워드 도출(LLM)
    • 질문 전략 수립(LLM)
  • 2)  위의 항목을 각각 함수나 클래스로 구성한 후 , 하나의 함수로 묶기

 

 

 

 ✨ 과정

 

 

 

🧹  (2) State 선언

 

class InterviewState(TypedDict):
    # 고정 정보
    resume_text: str
    resume_summary: str
    resume_keywords: List[str]
    question_strategy: Dict[str, Dict]

    # 인터뷰 로그
    current_question: str
    current_answer: str
    current_strategy: str
    conversations: List[Dict[str, str]]
    evaluations : List[Dict[str, str]]
    next_step : str
    reflection_status: str
    report: str
    strategy_status: Dict[str, StrategyStatusDict]

 

 

 

 

 

 

 

 

🧹  (3) Resume 분석

 

개인화된 질문을 뽑기 위해 이력서 핵심 내용 및 키워드 추출

 

입출력

  • 입력 : 자소서 text
  • 출력 : 핵심 요약 str, 주요 키워드 List

 

처리

  • 프롬프트 탬플릿을 구성하여 LLM 활용 처리

 

resume_analyze_llm = ChatOpenAI(model = "gpt-4o-mini", temperature = 0)

analyze_prompt = ChatPromptTemplate.from_messages([
          ("system", "너는 채용 지원자의 이력서 및 자기소개서를 바탕으로 심화된 질문을 생성하기 위해서 {step}하는 전문가야"),
          ("human", "나는 면접관인데 지원자의 이력서 및 자기소개서를 면접 평가를 위해 {step}해줘\n 자기소개서:{resume_text}"),
          ("system", "{format_instructions}")
      ])

def summary_resume(resume_text: str) -> str:
    summary_messages = analyze_prompt.format_messages(
        step = "요약",
        resume_text = resume_text,
        format_instructions = "Return the response as a plain string."
    )
    summary_response = resume_analyze_llm.invoke(summary_messages)
    return summary_response.content

def keyword_resume(resume_text: str) -> List[str]:
    parser = CommaSeparatedListOutputParser()
    keyword_messages = analyze_prompt.format_messages(
        step = "지원자의 기술, 경험, 관심사에 대한 키워드 도출",
        resume_text = resume_text,
        format_instructions = parser.get_format_instructions()
    )
    keyword_response = resume_analyze_llm.invoke(keyword_messages)
    return parser.parse(keyword_response.content)

def analyze_resume(state: InterviewState) -> InterviewState:
    resume = state["resume_text"]
    # return 코드는 제공합니다.
    return {
        **state,
        "resume_summary": summary_resume(resume),
        "resume_keywords": keyword_resume(resume)
    }

 

 

 


🧹
  (4) 질문 전략 수립 (LLM)

 

 

개인화된 질문을 뽑기 위하여 질문 전략을 수립합니다.
입출력
  • 입력: 핵심 요약 str, 주요 키워드 List
  • 출력 : 3가지 분야에 대한 전략 수립

처리

프롬프트 템플릿 구성하여 LLM 처리

 

class QuestionStrategy(BaseModel):
    strategy: str = Field(..., description = "분야에 따른 질문 생성 전략")
    example: List[str] = Field(..., description = "전략에 따른 예시 질문 최소 2개")

class InterviewStrategy(BaseModel) :
    expertise: QuestionStrategy = Field(..., description = "경력 및 경험에 대한 영역")
    motivation: QuestionStrategy = Field(..., description = "동기 및 커뮤니케이션에 대한 영역")
    logical_thinking: QuestionStrategy = Field(..., description = "논리적 사고에 대한 영역")

def generate_question_strategy(state: InterviewState) -> InterviewState:
    prompt_messages = [
        ("system", "너는 채용 지원자를 평가하는 면접관이야"),
        ("human", "자기소개서 분석 정보에 맞춰 질문 전략을 수립해줘.\n자기소개서 요약:{resume_summary}\n\n 자기소개서 키워드: {resume_keywords}"),
    ]

    input_fields = {
        'resume_summary': state["resume_summary"],
        'resume_keywords': state["resume_keywords"]
    }

    strategy_dict = invoke_pydantic_chain(
        InterviewStrategy,
        prompt_messages,
        input_fields,
        temperature = 0.3
    )

    # 전략 상태 초기화
    strategy_status = {}
    for field in strategy_dict:
        strategy_status[field] = {
            'step': 0,
            'isdone': False
        }
    # return 코드는 제공합니다.
    return {
        **state,
        "question_strategy": strategy_dict,
        "strategy_status": strategy_status
    }

 

 

 

 

🧹  (5) 사전 준비 절차를 하나의 함수로 묶기

 

사전 준비 절차가 1회성으로 실행되도록 각 단계를 하나의 함수로 묶음

 

 

입출력

  • 입력 : 이력서/자소서 파일
  • 출력 : State

 

처리

def preProcessing_Interview(file_path: str) -> InterviewState:
    # 여기에 코드를 완성합니다.
    resume_text = extract_text_from_file(file_path)
    state: InterviewState = {
        "resume_text": resume_text,
        "resume_summary": '',
        "resume_keywords": [],
        "question_strategy": {},

        "current_question": '',
        "current_answer": '',
        "current_strategy": '',
        "conversations": [],
        "evaluations": [],
        "next_step" : '',
        "visited_strategy": [],
        "reflection_status": ''
    }

    state = analyze_resume(state)

    state = generate_question_strategy(state)

    selected_question = state["question_strategy"]["expertise"]['example'][0]
    # return 코드는 제공합니다.
    return {
            **state,
            "current_question": selected_question,
            "current_strategy": "expertise"
            }

 

 

 

 

 

 

 

 

 

 

 

🧠Mission 2

 

 

✨ Mission2?

면접 절차 구현

  • 답변 입력
  • 답변 평가 : 관점 별 상,중,하 평가
  • 인터뷰 진행 여부 판단
  • 질문 생성
  • 최종 출력

 

✨ 과정

  • 답변에 대한 평가 : 면접자의 답변이 적절한지 평가 (LLM,파서)
  • 인터뷰 진행 검토 : 인터뷰가 길어지지 않도록 진행 제한 (if~else로만 구현)
  • 질문 생성 : 이전 질문 답변을 검토한 후 추가 심화 질문 생성 (LLM)
  • 인터뷰 피드백 보고서 : 인터뷰를 종료하며, 인터뷰 내용과 평가내용 화면 출력
  • 면접 Agent : 사용자 답변 입력 ~ 질문 출력/종료 까지 한 Agent로 구성 (Agent)

 

 

 

 

🧠Mission 3

고도화 과정 진행

 

 

 

✨ 과정

  • 답변에 대한 평가고도화 : LLM이 자동 평가한 결과에 대해 스스로 점검하는 과정 추가
  • 인터뷰 진행 검토 고도화 : current_strategy에서 계속 질문할지, 혹은 다음 전략으로 넘어갈지 여부
  • 질문 생성 고도화 : 질문을 일관된 방향으로 만들기 위해 질문 DB를 구축하고 RAG 사용하여 유사 질문 검색 후 프롬프트 참조에 포함하도록 함
  • 인터뷰 피드백 보고서 : 단순한 대화 출력이 아닌 면접자가 개선할 수 있는 피드백 제공
  • Gradio: ai모델이나 파이썬 함수를 웹 인터페이스로 아주 쉽게 만들 수 있는 프레임워크를 사용하여 면접과정 진행에 도움을 줌

 

 

 

이 과정에서 저는 질문 생성 고도화를 담당하였고, 

 

# 1. 임베딩 모델 로드
embedding_function =  OpenAIEmbeddings(model="text-embedding-3-small")
path = "/content/drive/MyDrive/project_genai/"
csv_path = path + "interview_questions.csv"  # 파일명에 맞게 수정
loader = CSVLoader(csv_path, encoding="utf-8")
documents = loader.load()
persist_directory = path + "chroma_db"
collection = Chroma.from_documents(documents, embedding_function, persist_directory=persist_directory)
retriever = collection.as_retriever(search_type = 'mmr', search_kwargs = {"k": 3})

 

ChromaDB를 생성하고

 

# 2. 유사 질문 검색 함수
def retrieve_similar_questions(query_text: str) -> List[str]:
    docs = retriever.invoke(query_text)
    print(docs)
    questions = []
    for doc in docs:
        for line in doc.page_content.split("\n"):
            if line.startswith("question:"):
                questions.append(line.replace("question:", "").strip())
    return questions

 

유사 질문 검색 함수를 활용하여 질문 생성하였을 때, retrieve_similar_questions함수를 불러와 유사 질문 검색을 하고, LLM으로 유사 질문을 참고하여 심층 역량을 확인할 수 있는 질문을 1개 생성하도록 함. ㅡ> current_question에 반환

 

 

 


 

 

 

느낀점

 

아직도 LLM,AGENT등의 코드를 구현하는게 어려워요. 파서 사용, 원하는 내용을 dict형태로 만들어서 state구조에 담는 과정 등을 구현하는 부분이 힘들었습니다.

 

이번에 고도화 작업을 진행할 때 뭘 해결해야하는지 제대로 이해하지 못한 채 진행하여 2시간동안 헛수고(?)를 하고, 2시간이 지나서야 제가 뭘 해결해야하는지 제대로 이해했어요. 이러한 문제는 코테준비를 할 때도 반복되는 것 같아요. 앞으로는 문제를 제대로 읽고 내가 뭘 풀어야 하는지 정리할 필요성을 느낍니다! 

 

그래도 전체적으로는 몇몇 팀원들의 도움을 받아서 최종 통합본을 완성할 수 있었어요. 많이 어려웠기도 했지만 도움도 많이 된 프로젝트 같아요. 

 

 

반응형

'KT에이블스쿨' 카테고리의 다른 글

[KT AIVLE SCHOOL] 3차 미니프로젝트 후기  (0) 2025.05.20
[KT AIVLE SCHOOL] 클라우드  (0) 2025.05.13
[KT AIVLE SCHOOL] KT 에이블스쿨 7기 합격후기  (1) 2025.04.28
[KT AIVLE SCHOOL] AGENT  (0) 2025.04.27
[KT AIVLE SCHOOL] RAG  (1) 2025.04.23
'KT에이블스쿨' 카테고리의 다른 글
  • [KT AIVLE SCHOOL] 3차 미니프로젝트 후기
  • [KT AIVLE SCHOOL] 클라우드
  • [KT AIVLE SCHOOL] KT 에이블스쿨 7기 합격후기
  • [KT AIVLE SCHOOL] AGENT
알리시아코
알리시아코
  • 알리시아코
    CODiary
    알리시아코
  • 전체
    오늘
    어제
    • 분류 전체보기 (162)
      • Spring (5)
      • 프론트엔드 (2)
      • KT에이블스쿨 (37)
      • 졸업프로젝트 (4)
      • JAVA (24)
      • 파이썬 기초 (13)
      • 데이터베이스 (7)
      • 알고리즘 (3)
      • git (0)
      • Fastapi (0)
      • 취업준비(원서) (0)
      • 컴퓨터 네트워크 (27)
      • 안드로이드 앱 (1)
      • 운영체제 (0)
      • LINUX (4)
      • 시스템프로그래밍 (13)
      • 엑셀 (1)
      • 책 (1)
      • 컴퓨터구조+운영체제 (4)
      • 자료구조+알고리즘 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
알리시아코
[KT AIVLE SCHOOL] 2차 미니프로젝트
상단으로

티스토리툴바