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

19차시. Node 이해

6. 실습 ② — Generate 노드 만들기

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

📝 src/nodes/generate.py

Python
import re
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
import config
from prompts import PROMPTS
load_dotenv()

_chain = (PROMPTS[config.PROMPT_VER]
          | ChatOpenAI(model=config.LLM_MODEL,
                       temperature=config.TEMPERATURE)
          | StrOutputParser())

NO_INFO = "자료에서 확인할 수 없습니다"

def _build_context(docs):
    return "\n\n---\n\n".join(
        f"[{i}] {d.metadata['filename']} p.{d.metadata['page_no']}\n"
        f"{d.page_content}"
        for i, d in enumerate(docs, 1))

def generate_node(state: dict) -> dict:
    # 생성만 담당한다.
    docs = state.get("documents") or []

    if not docs:
        return {"answer": config.MSG_NO_DOC,
                "insufficient": True,
                "has_citation": False,
                "log": ["[generate] 근거 없음 — 생성 생략"]}

    answer = _chain.invoke({"context": _build_context(docs),
                            "question": state["question"]})

    nums  = [int(n) for n in re.findall(r"\[(\d+)\]", answer)]
    cited = bool(nums) and all(1 <= n <= len(docs) for n in nums)

    return {
        "answer":       answer,
        "insufficient": NO_INFO in answer,
        "has_citation": cited,
        "log":          [f"[generate] {len(answer)}자 생성 "
                         f"(인용 {'정상' if cited else '미확인'})"],
    }
if __name__ == "__main__":
    from nodes.retrieve import retrieve_node
    s = {"question": "환불은 며칠 이내인가요?"}
    s.update(retrieve_node(s))          # 검색 먼저
    print(generate_node(s)["answer"])   # 생성 테스트

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

출력
환불은 상품 수령 후 7일 이내에 신청하실 수 있습니다 [1]. 단순 변심의 경우 왕복 배송비는 고객 부담입니다 [1].

🔗 노드를 이어서 테스트하는 방법
그래프를 만들지 않아도
딕셔너리에 update로 합치면 됩니다.
s.update(retrieve_node(s))
s.update(generate_node(s))
LangGraph가 하는 일도 결국 이것입니다.
이렇게 손으로 해보면 그래프의 동작이 이해됩니다.

← 이전 절19차시 · 5. 실습 ① — Retrieve 노드 만들기다음 절 →19차시 · 7. 실습 ③ — Fallback 노드 만들기