1. 서비스 요구사항


면접 서비스에 왜 랭그래프가 필요할까?


<aside>

랭그래프란 무엇일까


랭그래프는 간단하게 LLM을 호출할때 그래프 형태로 호출한다는 것이다.

우리가 일반 선형 구조와 그래프 구조의 차이를 살펴보자.

일반 선형 구조는 하나의 노드에서 다른 노드로 이동하는 방향이 한 방향 밖에 없다.

이와 반면 그래프는 하나의 노드에서 다른 노드를 선택해서 이동할 수 있다. 즉 조건 분기 처리가 되는것이다.

</aside>

<aside>

면접 서비스


AI를 통해 면접을 보면 면접관님들이 주는 질문에 대해 우리들은 응답을 한다.

하지만 면접은 질문과 응답 뿐 아니라, 질문이 이해가 안될때 또는 추가 정보가 필요할때 이를 질의하면서 질문을 만들어가는 과정일 수도 있다. 즉 단순히 응답만 하는 구조가 아닌 상호작용의 구조이다. 또한 잘 모를수도 있다.

  1. 질문에 대한 응답
  2. 질문 구체화 (ex : 트래픽이 몰린다고 하셨는데, 쓰기 트래픽인지 읽기 트래픽인지 알 수 있을까요?)
  3. 응답 못함 (ex: 잘 모르겠습니다) </aside>

<aside>

랭그래프로 분기 처리를 하자


랭그래프를 통해 질문과 응답 과정에서 사용자의 응답을 통해 사용자가 질문에 대한 응답을 하려고 하는지, 질문을 구체화하려고 하는 것인지, 응답을 할 수 없는 상황인지를 체크하고 이에 따라 다른 LLM 응답을 생성할 필요가 있다.

</aside>

2. 프로세스


rag_graph.png

<aside>

1️⃣ 상태 정의 하기


<aside>

그래프가 있고 노드 간선이 있다면 결국 START에서 END로 가는 주체가 존재해야 한다.

그 주체를 START에서 END로 이동하면서 가지고 있어야 할 상태를 가지고 있고, 그 과정에서 상태 변화도 발생한다.

class AgentState(TypedDict):
    query: str
    ai_question: str
    session_id: str
    prompt_type: int
    time: int
    history: list
    lastAiMessage: str
    answer: st

</aside>

2️⃣ 사용자 응답 분석을 ai_question 생성


<aside>

pre_process과정에서 ai_question이라는 정보를 생성한다.

이 정보를 통해 추후 사용자의 응답에 대한 평가가 들어간다.

즉 ai_question을 통해 사용자의 응답이 질문에 대한 응답인지, 질문을 구체화하는 과정인지, 추가 힌트가 필요한지에 대한 판단을 진행하는 것이다.

def pre_process(self, state: AgentState) -> AgentState:
    history = state.get("history", [])
    if history:
        last_entry = history[-1]
        ai_answer = last_entry.get("ai", "")
        state["ai_question"] = ai_answer
    return state

</aside>

3️⃣ 현재 조건에 따라 조건 분기 생성


<aside>

해당 서비스는 기본적으로 사용자에게 4번의 LLM 호출이 일어난다.

아래에서 2번과 3번은 동일한 과정이다. 즉 질문에 대한 꼬리 질문을 생성하기 위한 과정이다.

  1. 사용자가 키워드를 입력하면 LLM을 통해 면접 질문을 생성한다.
  2. 사용자가 면접 질문에 대한 응답을 하면 그에 맞춰 LLM이 추가 질문을 생성하거나, 질문을 구체화해준다.
  3. 사용자가 면접 질문에 대한 응답을 하면 그에 맞춰 LLM이 추가 질문을 생성하거나, 질문을 구체화해준다.
  4. 사용자의 응답에 따라 LLM이 사용자에게 필요한 개념을 정리해준다.

이렇게 함으로 첫대화나 마지막 대화의 경우 바로 응답을 생성하게 한다.

그 외의 경우는 사용자의 응답의 의도를 파악하여 적절한 질문을 생성한다.

def progress_evaluation(self, state: AgentState) -> Literal['generate', 'user_response_evaluation']:
    history = state['history']

    history_length = len(history)

    # 첫 대화인 경우
    if history_length == 0:
        return "generate"

    # 마지막 대화인 경우
    if history_length >= 6:
        return 'generate'

    return 'user_response_evaluation'

</aside>