RAG2026-5일19차시 · Node 이해10 / 19← 이전목차다음 →MetaContents

19차시. Node 이해

7. 실습 ③ — Fallback 노드 만들기

출처: 원본 PDF 19차시_Node이해.pdf 15쪽 · 쪽 그림 15쪽

검색에 실패했을 때 안전하게 마무리하는 노드입니다.

📝 src/nodes/fallback.py

Python
import config

def fallback_node(state: dict) -> dict:
    # 근거를 찾지 못했을 때 안내 메시지를 만든다
    tried = state.get("tried_queries", [])

    msg = config.MSG_NO_DOC
    if tried:
        msg += f"\n(시도한 검색어: {', '.join(tried)})"
    msg += "\n질문을 조금 더 구체적으로 바꿔 다시 물어봐 주세요."

    return {
        "answer": msg,
        "grade":  "giveup",
        "log":    ["[fallback] 안내 메시지 반환"],
    }

if __name__ == "__main__":
    print(fallback_node({"question": "대표이사 이름은?"})["answer"])

실행 결과 예시 (코드를 읽고 만든 예상 화면입니다. 실제 실행 결과, 특히 모델의 답은 다를 수 있습니다)

출력
관련 자료를 찾지 못했습니다.
질문을 조금 더 구체적으로 바꿔 다시 물어봐 주세요.

💡 Fallback도 노드입니다
"실패 처리"라고 해서 특별하지 않습니다.
State를 받아 answer를 채우는 평범한 노드입니다.
이렇게 노드로 만들어두면
31차시에서 더 정교하게 확장하기 쉽습니다.
(예: 유사 질문 추천, 담당자 연결 안내)

7-1) 지금까지 만든 노드 정리

출력
src/
├── nodes/
│   ├── __init__.py
│   ├── retrieve.py     → retrieve_node    (검색)
│   ├── generate.py     → generate_node    (생성)
│   └── fallback.py     → fallback_node    (안내)
├── config.py
├── indexer.py
├── prompts.py
└── graph_state.py      → RAGState         (18차시)

실습 코드 · 19/config.py

실습 코드: 실습/src/19/config.py · 위의 원본 PDF 19차시 15쪽 「7-1) 지금까지 만든 노드 정리」과 이어집니다.

Python
# ============================================================
# 19차시 | Node 이해
# 교안: 19차시_Node이해.pptx
# 역할: 검색·생성 노드가 읽을 상수(경로, 모델, 점수 기준, 안내 문장)를 모아 둔다.
# 입력: 없음
# 출력: 없음. 다른 파일의 노드가 이 이름을 읽는다.
#
#   State  = 이 파일에는 없다. 노드는 config.TOP_K, MIN_SCORE, MSG_NO_DOC 를 읽는다.
#   Node   = 이 파일에는 없다.
#   그래프 = 없다.
#
# 흐름
#   (그래프 없음)
#   DOC_PATH / CHUNK_*  → 인덱스 만들 때
#   EMBED_MODEL / INDEX_PATH / TOP_K / MIN_SCORE → retrieve 노드
#   LLM_MODEL / PROMPT_VER / MSG_* → generate, fallback 노드
# ============================================================

# ?????????????????????????????????????????????
#  RAG 설정
#  최종 결정 : 2026-08-03
#  근거      : 14차시 벤치마크 (질문 20개 기준)
#              기준선 60% → 최종 90% (+30%p)
# ?????????????????????????????????????????????
# ── 문서 처리 ──
DOC_PATH      = "../../data/manual.pdf"
CHUNK_SIZE    = 500      # 500→300: +10%p, 토큰 33% 절감
CHUNK_OVERLAP = 50       # chunk_size의 10%
# ── 임베딩 · 저장소 ──
EMBED_MODEL   = "text-embedding-3-small"   # ⚠ 변경 시 인덱스 재생성 
INDEX_PATH    = "faiss_index"
# ── 검색 ──
TOP_K         = 5        # 3→5: +10%p (k=8은 노이즈로 하락) 
MIN_SCORE     = 0.1     # 9차시 실측값
SEARCH_TYPE   = "similarity"
# ── 생성 ──
LLM_MODEL = "gpt-4o-mini"
TEMPERATURE = 0
PROMPT_VER = "v3"
MAX_RETRY = 3
USE_LLM_CLASSIFY = True

# ── 메시지 ──
MSG_NO_DOC = "관련 자료를 찾지 못했습니다."
MSG_ERROR = "일시적인 오류가 발생했습니다. 잠시 후 다시 시도해주세요."

실행 결과 샘플 (교안 기록. API 키가 필요한 코드는 키 없이 맞춘 예시이고, 모델의 답은 실행할 때마다 달라집니다)

출력
===== 실행 결과 샘플 =====
실행: cd 실습/src/19
      python config.py
(실제 실행 출력)
(표준 출력 없음. 상수만 정의한다.)

코드 해설

검색·생성 노드가 읽을 상수(경로, 모델, 점수 기준, 안내 문장)를 모아 둔다. 입력은 없음이고, 출력은 없음. 다른 파일의 노드가 이 이름을 읽는다.

주석에 적힌 흐름입니다.

출력
흐름
(그래프 없음)
DOC_PATH / CHUNK_*  → 인덱스 만들 때
EMBED_MODEL / INDEX_PATH / TOP_K / MIN_SCORE → retrieve 노드
LLM_MODEL / PROMPT_VER / MSG_* → generate, fallback 노드

코드 앞에서 고정해 두는 말입니다.

  • 19차시 | Node 이해
  • 교안: 19차시_Node이해.pptx
  • State = 이 파일에는 없다. 노드는 config.TOP_K, MIN_SCORE, MSG_NO_DOC 를 읽는다.
  • Node = 이 파일에는 없다.
  • 그래프 = 없다.

함수로 나누지 않고 위에서 아래로 실행됩니다.

  • DOC_PATH = "../../data/manual.pdf" — 19차시 | Node 이해 교안: 19차시_Node이해.pptx 역할: 검색·생성 노드가 읽을 상수(경로, 모델, 점수 기준, 안내 문장)를 모아 둔다. 입력: 없음 출력: 없음. 다른 파일의 노드가 이 이름을 읽는다. State = 이 파일에는 없다. 노드는 config.TOP_K, MIN_SCORE, MSG_NO_DOC 를 읽는다. Node = 이 파일에는 없다. 그래프 = 없다. 흐름 (그래프 없음) DOC_PATH / CHUNK_* → 인덱스 만들 때 EMBED_MODEL / INDEX_PATH / TOP_K / MIN_SCORE → retrieve 노드 LLM_MODEL / PROMPT_VER / MSG_* → generate, fallback 노드 ????????????????????????????????????????????? RAG 설정 최종 결정 : 2026-08-03 근거 : 14차시 벤치마크 (질문 20개 기준) 기준선 60% → 최종 90% (+30%p) ????????????????????????????????????????????? ── 문서 처리 ──
  • EMBED_MODEL = "text-embedding-3-small" # ⚠ 변경 시 인덱스 재생성 — ── 임베딩 · 저장소 ──
  • TOP_K = 5 # 3→5: +10%p (k=8은 노이즈로 하락) — ── 검색 ──
  • LLM_MODEL = "gpt-4o-mini" — ── 생성 ──
  • MSG_NO_DOC = "관련 자료를 찾지 못했습니다." — ── 메시지 ──

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

실습 코드 · 19/retrieve.py

실습 코드: 실습/src/19/retrieve.py · 위의 원본 PDF 19차시 15쪽 「7-1) 지금까지 만든 노드 정리」과 이어집니다.

Python
# ============================================================
# 19차시 | Node 이해
# 교안: 19차시_Node이해.pptx
# 역할: 질문과 비슷한 문서만 골라 State에 넣는 검색 노드.
#       그래프에 넣기 전, 함수만 직접 호출해 본다.
# 입력: State의 question 또는 query, 없으면 top_k 는 config.TOP_K
# 출력: documents, scores, retrieval_ok, log
#
#   State  = 이 함수가 받는 딕셔너리 한 장. 공유 노트에서 필요한 칸만 읽는다.
#   Node   = retrieve_node. 고친 칸만 return 한다.
#   reducer = log 는 그래프에 넣을 때 리스트를 이어 붙이도록 정의되어 있다.
#            그래서 log 는 문자열 하나가 아니라 한 칸짜리 리스트로 돌려준다.
#   이 파일에는 Edge / compile / invoke 가 없다. __main__ 이 함수를 직접 호출한다.
#
# 흐름 (그래프 없이 함수 한 번)
#   state(question) → retrieve_node → documents, scores, retrieval_ok, log
# ============================================================

import os
import sys

import config
import datetime

# ------------------------------------------------------------
# 10차시에 만든 indexer.py를 사용하기 위해 경로를 추가합니다.
# ------------------------------------------------------------
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
INDEXER_DIR = os.path.join(CURRENT_DIR, "..", "10")

sys.path.insert(0, INDEXER_DIR)

from indexer import get_store

# ------------------------------------------------------------
# 저장된 벡터 저장소를 불러옵니다.
# ------------------------------------------------------------
store = get_store()

# ============================================================
# Retriever Node
# ============================================================
# 노드 retrieve_node
#   읽기: query (없으면 question), top_k (없으면 config.TOP_K)
#   쓰기: documents, scores, retrieval_ok, log
def retrieve_node(state: dict) -> dict:
    """질문과 관련된 문서를 검색합니다."""

    # query가 있으면 사용하고, 없으면 원래 question을 사용합니다.
    query = state.get("query")

    if not query:
        query = state["question"]

    # top_k가 있으면 사용하고, 없으면 기본값을 사용합니다.
    top_k = state.get("top_k", config.TOP_K)

    # 질문과 유사한 문서를 검색합니다.
    results = store.similarity_search_with_relevance_scores(
        query,
        k=top_k
    )

    # 기준 점수 이상인 문서만 저장합니다.
    documents = []

    for document, score in results:
        if score >= config.MIN_SCORE:
            documents.append(document)

    # 검색된 모든 문서의 점수를 저장합니다.
    scores = []

    for document, score in results:
        scores.append(round(score, 3))

    # 기준을 통과한 문서가 있는지 확인합니다.
    retrieval_ok = len(documents) > 0

    # 실행 내용을 로그로 남깁니다.
    log_message = (
        f"[retrieve] '{query}' → "
        f"{len(documents)}/{len(results)}건 통과"
    )

    # 변경할 State 값만 반환합니다.
    return {
        "documents": documents,
        "scores": scores,
        "retrieval_ok": retrieval_ok,
        "log": [log_message],
    }

# ============================================================
# Retriever Node 단독 테스트
# ============================================================
if __name__ == "__main__":

    # 테스트용 State를 만듭니다.
    state = {
        "question": "환불은 며칠 이내인가요?"
    }

    # 그래프 없이 Retriever Node만 직접 실행합니다.
    result = retrieve_node(state)

    # 검색 결과를 확인합니다.
    print("통과 문서:", len(result["documents"]))
    print("점수      :", result["scores"])
    print("검색 성공 :", result["retrieval_ok"])
    print("로그      :", result["log"][0])

실행 결과 샘플 (교안 기록. API 키가 필요한 코드는 키 없이 맞춘 예시이고, 모델의 답은 실행할 때마다 달라집니다)

출력
===== 실행 결과 샘플 =====
실행: cd 실습/src/19
      python retrieve.py
예시 출력 (API 키 필요, 실행하지 않음)
통과 문서: (건수 미기록)
점수      : (유사도 점수 미기록)
검색 성공 : (미기록)
로그      : (미기록)
질문 '환불은 며칠 이내인가요?' 에 대해 이후 기록은 grade pass, rewrites 0, elapsed 6.69 이다.
그 기록은 이 파일의 print 가 아니다. 점수 숫자는 적지 않는다.

코드 해설

질문과 비슷한 문서만 골라 State에 넣는 검색 노드.입니다. 입력은 State의 question 또는 query, 없으면 top_k 는 config.TOP_K이고, 출력은 documents, scores, retrieval_ok, log입니다.

주석에 적힌 흐름입니다.

출력
흐름 (그래프 없이 함수 한 번)
state(question) → retrieve_node → documents, scores, retrieval_ok, log

코드 앞에서 고정해 두는 말입니다.

  • 19차시 | Node 이해
  • 교안: 19차시_Node이해.pptx
  • 그래프에 넣기 전, 함수만 직접 호출해 본다.
  • State = 이 함수가 받는 딕셔너리 한 장. 공유 노트에서 필요한 칸만 읽는다.
  • Node = retrieve_node. 고친 칸만 return 한다.
  • reducer = log 는 그래프에 넣을 때 리스트를 이어 붙이도록 정의되어 있다.
  • 그래서 log 는 문자열 하나가 아니라 한 칸짜리 리스트로 돌려준다.
  • 이 파일에는 Edge / compile / invoke 가 없다. __main__ 이 함수를 직접 호출한다.

함수와 클래스로 나누어 읽습니다.

  • retrieve_node: Retriever Node 노드 retrieve_node 읽기: query (없으면 question), top_k (없으면 config.TOP_K) 쓰기: documents, scores, retrieval_ok, log

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

실습 코드 · 19/generate.py

실습 코드: 실습/src/19/generate.py · 위의 원본 PDF 19차시 15쪽 「7-1) 지금까지 만든 노드 정리」과 이어집니다.

Python
# ============================================================
# 19차시 | Node 이해
# 교안: 19차시_Node이해.pptx
# 역할: 검색된 문서를 근거로 답변 문자열을 만드는 생성 노드.
# 입력: documents, question
# 출력: answer, insufficient, has_citation, log
#       문서가 없으면 LLM을 부르지 않고 안내 문장을 answer 에 넣는다.
#
#   State  = generate_node 가 받는 공유 노트.
#   Node   = generate_node. build_context 는 노드가 아니라 문서를 문자열로 합치는 도우미.
#   이 파일에는 Edge / compile / invoke(그래프) 가 없다.
#   chain.invoke 는 LangGraph 실행이 아니라 LLM 체인 호출이다.
#
# 흐름 (단독 테스트)
#   question → retrieve_node → generate_node → answer 출력
# ============================================================

import os
import sys
import re

from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

import config

# ------------------------------------------------------------
# 13차시에 만든 prompts.py를 사용하기 위해 경로를 추가합니다.
# ------------------------------------------------------------
CURRENT_DIR = os.path.dirname(os.path.abspath(__file__))
PROMPT_DIR = os.path.join(CURRENT_DIR, "..", "13")

sys.path.insert(0, PROMPT_DIR)

from prompts import PROMPTS

# ------------------------------------------------------------
# .env 파일의 환경 변수를 불러옵니다.
# ------------------------------------------------------------
load_dotenv()

# ------------------------------------------------------------
# 답변 생성에 사용할 LLM 체인을 만듭니다.
# 프롬프트 → LLM → 문자열 변환 순서로 실행됩니다.
# ------------------------------------------------------------
prompt = PROMPTS[config.PROMPT_VER]

llm = ChatOpenAI(
    model=config.LLM_MODEL,
    temperature=config.TEMPERATURE
)

chain = prompt | llm | StrOutputParser()

# ------------------------------------------------------------
# 자료에 답이 없을 때 사용하는 문구입니다.
# ------------------------------------------------------------
NO_INFO = "자료에서 확인할 수 없습니다"

# ============================================================
# 검색 문서를 LLM에게 전달할 문자열로 변환
# ============================================================
# 노드가 아님. 문서 목록을 프롬프트용 문자열로 합친다.
def build_context(documents):
    """검색된 문서들을 하나의 문자열로 합칩니다."""

    parts = []

    # 문서를 하나씩 꺼냅니다.
    for index in range(len(documents)):

        document = documents[index]

        # 문서의 metadata를 가져옵니다.
        metadata = document.metadata

        if not metadata:
            metadata = {}

        # 파일명을 찾습니다.
        filename = metadata.get("filename")

        if not filename:
            filename = metadata.get("file_name")

        if not filename:
            filename = metadata.get("source")

        if not filename:
            filename = "unknown"

        # 페이지 번호를 찾습니다.
        page_no = metadata.get("page_no")

        if page_no is None:
            page_no = metadata.get("page")

        if page_no is None:
            page_no = metadata.get("pageno")

        if page_no is None:
            page_no = "?"

        # 문서 번호는 1번부터 시작합니다.
        document_number = index + 1

        # LLM에게 전달할 문서 내용을 만듭니다.
        text = (
            f"[{document_number}] {filename} p.{page_no}\n"
            f"{document.page_content}"
        )

        parts.append(text)

    # 여러 문서를 구분선으로 연결합니다.
    context = "\n\n---\n\n".join(parts)

    return context

# ============================================================
# Generator Node
# ============================================================
# 노드 generate_node
#   읽기: documents, question
#   쓰기: answer, insufficient, has_citation, log
def generate_node(state: dict) -> dict:
    """검색된 문서를 근거로 답변을 생성합니다."""

    # Retriever Node가 저장한 문서를 가져옵니다.
    documents = state.get("documents")

    if not documents:
        documents = []

    # 검색 문서가 없으면 LLM을 호출하지 않습니다.
    if len(documents) == 0:
        return {
            "answer": config.MSG_NO_DOC,
            "insufficient": True,
            "has_citation": False,
            "log": ["[generate] 근거 없음 - 생성 생략"],
        }

    # 검색 문서를 LLM에게 전달할 문자열로 만듭니다.
    context = build_context(documents)

    # 사용자의 원래 질문을 가져옵니다.
    question = state["question"]

    # 문서와 질문을 LLM에게 전달하여 답변을 생성합니다.
    # 여기의 invoke 는 그래프 실행이 아니라 프롬프트|LLM|문자열 체인 호출이다.
    answer = chain.invoke({
        "context": context,
        "question": question,
    })

    # 답변에서 [1], [2]와 같은 인용 번호를 찾습니다.
    found_numbers = re.findall(r"\[(\d+)\]", answer)

    # 찾은 인용 번호를 숫자로 변환합니다.
    citation_numbers = []

    for number in found_numbers:
        citation_numbers.append(int(number))

    # 인용 번호가 정상인지 검사합니다.
    has_citation = False

    if len(citation_numbers) > 0:
        has_citation = True

        # 존재하지 않는 문서 번호가 있으면 비정상입니다.
        for number in citation_numbers:
            if number < 1 or number > len(documents):
                has_citation = False
                break

    # 자료 부족 문구가 답변에 있는지 확인합니다.
    insufficient = NO_INFO in answer

    # 로그에 표시할 인용 상태를 정합니다.
    if has_citation:
        citation_status = "정상"
    else:
        citation_status = "미확인"

    # 생성 결과를 State에 반영할 수 있도록 반환합니다.
    return {
        "answer": answer,
        "insufficient": insufficient,
        "has_citation": has_citation,
        "log": [
            f"[generate] {len(answer)}자 생성 "
            f"(인용 {citation_status})"
        ],
    }

# ============================================================
# Generator Node 단독 테스트
# ============================================================
if __name__ == "__main__":

    # 앞에서 만든 Retriever Node를 가져옵니다.
    from retrieve import retrieve_node

    # 테스트용 State를 만듭니다.
    state = {
        "question": "환불은 며칠 이내인가요?"
    }

    # 먼저 Retriever Node를 실행합니다.
    retrieve_result = retrieve_node(state)

    # 검색 결과를 기존 State에 추가합니다.
    state.update(retrieve_result)

    # 검색 결과를 이용하여 Generator Node를 실행합니다.
    generate_result = generate_node(state)

    # 생성된 답변을 출력합니다.
    print(generate_result["answer"])

실행 결과 샘플 (교안 기록. API 키가 필요한 코드는 키 없이 맞춘 예시이고, 모델의 답은 실행할 때마다 달라집니다)

출력
===== 실행 결과 샘플 =====
실행: cd 실습/src/19
      python generate.py
예시 출력 (API 키 필요, 실행하지 않음)
(answer 문자열 한 덩어리를 출력한다. 본문은 기록되어 있지 않다.)
질문 '환불은 며칠 이내인가요?' 의 이후 기록은 grade pass, rewrites 0, elapsed 6.69 이다.
그 세 값은 이 파일의 print 가 아니다. 점수와 답변 문장은 적지 않는다.

코드 해설

검색된 문서를 근거로 답변 문자열을 만드는 생성 노드.입니다. 입력은 documents, question이고, 출력은 answer, insufficient, has_citation, log입니다.

주석에 적힌 흐름입니다.

출력
흐름 (단독 테스트)
question → retrieve_node → generate_node → answer 출력

코드 앞에서 고정해 두는 말입니다.

  • 19차시 | Node 이해
  • 교안: 19차시_Node이해.pptx
  • 문서가 없으면 LLM을 부르지 않고 안내 문장을 answer 에 넣는다.
  • State = generate_node 가 받는 공유 노트.
  • Node = generate_node. build_context 는 노드가 아니라 문서를 문자열로 합치는 도우미.
  • 이 파일에는 Edge / compile / invoke(그래프) 가 없다.
  • chain.invoke 는 LangGraph 실행이 아니라 LLM 체인 호출이다.

함수와 클래스로 나누어 읽습니다.

  • build_context: 검색 문서를 LLM에게 전달할 문자열로 변환 노드가 아님. 문서 목록을 프롬프트용 문자열로 합친다.
  • generate_node: Generator Node 노드 generate_node 읽기: documents, question 쓰기: answer, insufficient, has_citation, log

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

실습 코드 · 19/fallback.py

실습 코드: 실습/src/19/fallback.py · 위의 원본 PDF 19차시 15쪽 「7-1) 지금까지 만든 노드 정리」과 이어집니다.

Python
# ============================================================
# 19차시 | Node 이해
# 교안: 19차시_Node이해.pptx
# 역할: 검색이 실패했을 때 안내 문장을 answer 에 넣고 grade 를 giveup 으로 둔다.
# 입력: tried_queries (없으면 빈 리스트로 본다)
# 출력: answer, grade, log
#
#   State  = fallback_node 가 받는 공유 노트.
#   Node   = fallback_node. 검색이나 LLM을 부르지 않는다.
#   그래프 = 이 파일에는 없다. __main__ 이 함수를 직접 호출한다.
#
# 흐름
#   state → fallback_node → answer, grade="giveup", log
# ============================================================

import config

# ============================================================
# Fallback Node
# ============================================================
# 노드 fallback_node
#   읽기: tried_queries
#   쓰기: answer, grade, log
def fallback_node(state: dict) -> dict:
    """검색에 실패했을 때 안내 메시지를 만듭니다."""

    # 지금까지 시도한 검색어를 가져옵니다.
    tried_queries = state.get("tried_queries", [])

    # 기본 안내 메시지를 가져옵니다.
    message = config.MSG_NO_DOC

    # 시도한 검색어가 있으면 안내 메시지에 추가합니다.
    if tried_queries:
        tried_text = ", ".join(tried_queries)
        message += f"\n(시도한 검색어: {tried_text})"

    # 사용자가 다시 질문할 수 있도록 안내합니다.
    message += "\n질문을 조금 더 구체적으로 바꿔 다시 물어봐 주세요."

    # 변경할 State 값만 반환합니다.
    return {
        "answer": message,
        "grade": "giveup",
        "log": ["[fallback] 안내 메시지 반환"],
    }

# ============================================================
# Fallback Node 단독 테스트
# ============================================================
if __name__ == "__main__":

    # 테스트용 State를 만듭니다.
    state = {
        "question": "대표이사 이름은?"
    }

    # 그래프 없이 Fallback Node만 직접 실행합니다.
    result = fallback_node(state)

    # 만들어진 안내 메시지를 출력합니다.
    print(result["answer"])

실행 결과 샘플 (교안 기록. API 키가 필요한 코드는 키 없이 맞춘 예시이고, 모델의 답은 실행할 때마다 달라집니다)

출력
===== 실행 결과 샘플 =====
실행: cd 실습/src/19
      python fallback.py
(실제 실행 출력)
관련 자료를 찾지 못했습니다.
질문을 조금 더 구체적으로 바꿔 다시 물어봐 주세요.
테스트 State에 tried_queries 가 없어 시도 검색어 줄은 붙지 않는다.
이후 기록에서 '대표이사' 질문은 grade giveup, rewrites 2, elapsed 3.41 이다.
rewrites 와 elapsed 는 이 파일의 print 가 아니다.

코드 해설

검색이 실패했을 때 안내 문장을 answer 에 넣고 grade 를 giveup 으로 둔다. 입력은 tried_queries (없으면 빈 리스트로 본다)이고, 출력은 answer, grade, log입니다.

주석에 적힌 흐름입니다.

출력
흐름
state → fallback_node → answer, grade="giveup", log

코드 앞에서 고정해 두는 말입니다.

  • 19차시 | Node 이해
  • 교안: 19차시_Node이해.pptx
  • State = fallback_node 가 받는 공유 노트.
  • Node = fallback_node. 검색이나 LLM을 부르지 않는다.
  • 그래프 = 이 파일에는 없다. __main__ 이 함수를 직접 호출한다.

함수와 클래스로 나누어 읽습니다.

  • fallback_node: Fallback Node 노드 fallback_node 읽기: tried_queries 쓰기: answer, grade, log

파일 맨 아래 실행 결과 샘플 주석은 실행되지 않습니다. 화면 출력은 다음 절에 다시 적어 두었습니다.

← 이전 절19차시 · 6. 실습 ② — Generate 노드 만들기다음 절 →19차시 · 8. 노드 명세서 만들기