LangChain 챗봇8장 · 최종 프로젝트4 / 12← 이전목차다음 →MetaContents

8장. 최종 프로젝트

설계서 쓰기

집을 지을 때는 벽돌을 쌓기 전에 설계도부터 그립니다. 몇 명이 살지, 방은 몇 개인지, 물과 전기는 어디로 들어오는지, 다 지은 뒤 무엇을 확인할지 적어 두어야 짓는 도중에 길을 잃지 않습니다. 챗봇도 코드를 쓰기 전에 설계서 한 장을 씁니다. 누가 무엇을 묻는지, 어떤 문서로 답하는지, 어떤 부품을 넣는지, 무엇으로 잘 되었는지 잴지를 적습니다.

누가·무엇을, 쓸 문서, 넣을 부품, 평가 방법의 네 칸을 나란히 놓은 설계서 비교 그림

네 상자가 설계서의 네 칸입니다. 첫째 파랑 상자는 사용자와 자주 받을 질문, 둘째 보라 상자는 답의 근거가 될 문서, 셋째 하늘 상자는 넣을 부품(문서 검색, 대화 기억, 도구, 화면), 넷째 회청 상자는 평가 질문과 정답, 범위 밖 질문에 할 말입니다. 여기서 몇 명이 사는지가 사용자, 물과 전기가 들어오는 곳이 문서, 방의 배치가 부품, 다 지은 뒤의 점검이 평가입니다. 비유와 다른 점은, 집의 설계도는 한 번 그리면 잘 바꾸지 않지만 챗봇의 설계서는 시연과 피드백을 거치며 여러 번 고친다는 것입니다.

설계서의 칸

칸적을 것프로젝트 1의 예
이름챗봇의 이름솔마루상사 규정 도우미
사용자누가 묻나솔마루상사 직원
자주 받을 질문3개 이상재택근무 며칠, 출장비 얼마, 휴가 신청 기한
문서답의 근거, 쪽수, 나누는 단위solmaru_rules.pdf 3쪽, 조항 단위 12조각
부품넣을 것과 뺄 것, 까닭문서 검색과 웹 화면은 넣고, 대화 기억은 뺀다(규정 질문은 한 번에 끝나는 일이 많다)
범위 밖 질문답하지 않을 것과 그때 할 말"규정에서 찾지 못했습니다. 인사팀에 물어 주세요."
평가평가 질문 수, 정답 위치, 잴 것질문 10개와 정답 조항, hit@1·hit@3, 범위 밖 질문 3개

넣을 부품 고르기

부품배운 장넣는 때빼도 되는 때
문서 검색(RAG)6장답이 문서에 있다답이 짧은 표 하나로 끝난다
대화 기억4장"그럼 그건요?" 처럼 이어 묻는다질문이 한 번에 끝난다
도구5장계산하거나 표에서 찾아야 한다(요금, 남은 자리)글만 읽으면 답이 된다
구조화 출력4장답을 다른 프로그램이 받아 쓴다사람이 읽기만 한다
웹 화면7장다른 사람이 써 본다(시연)혼자 시험만 한다

짧은 예시

4장에서 배운 Pydantic 으로 설계서의 칸을 틀로 정해 두면, 빠진 칸을 코드가 찾아 줍니다. 초안에 일부러 세 군데를 비웠습니다.

Python
from pydantic import BaseModel, Field, ValidationError


class BotDesign(BaseModel):
    """챗봇 설계서의 칸. 칸이 빠지거나 기준에 못 미치면 오류가 난다"""
    name: str
    users: str                                        # 누가 묻나
    questions: list[str] = Field(min_length=3)        # 자주 받을 질문(3개 이상)
    documents: list[str] = Field(min_length=1)        # 답의 근거가 될 문서(1개 이상)
    parts: list[str]                                  # 넣을 부품
    out_of_scope: str                                 # 답하지 않을 것과 그때 할 말
    eval_count: int = Field(ge=10)                    # 평가 질문 수(10개 이상)


draft = {
    "name": "솔마루상사 규정 도우미",
    "users": "솔마루상사 직원",
    "questions": ["재택근무는 며칠까지 되나요?", "출장비는 얼마인가요?"],
    "documents": ["solmaru_rules.pdf"],
    "parts": ["문서 검색", "웹 화면"],
    "eval_count": 5,
}
try:
    BotDesign(**draft)
except ValidationError as e:
    # errors(): 어긴 칸마다 칸 이름(loc)과 까닭(msg)을 담은 사전 목록
    for err in e.errors():
        print(err["loc"][0], "→", err["msg"])
출력
questions → List should have at least 3 items after validation, not 2
out_of_scope → Field required
eval_count → Input should be greater than or equal to 10
출력뜻
questions → List should have at least 3 items…자주 받을 질문을 2개만 적었다. min_length=3(가장 짧은 길이 3) 에 못 미친다
out_of_scope → Field required범위 밖 질문에 할 말을 적지 않았다. 기본값이 없는 칸이라 꼭 있어야 한다
eval_count → Input should be greater than or equal to 10평가 질문을 5개로 적었다. ge=10(greater than or equal, 10 이상) 에 못 미친다

오류 글은 pydantic 이 영어로 냅니다. 칸 이름과 함께 찍으면 무엇을 고칠지 바로 보입니다. 설계서를 사람이 읽는 문서로만 두지 않고 이렇게 틀로 두면, 팀이 함께 쓸 때도 빠진 칸이 없게 됩니다.

코드가 의미하는 것

이 코드는 설계도의 빈칸을 검사관이 하나씩 짚어 주는 일을 흉내 냅니다. 설계서의 칸과 기준을 클래스로 정하고, 초안 사전을 넣어 보고, 어긴 칸을 모아 찍는 세 동작입니다.

코드하는 일챗봇에서 뜻하는 것
class BotDesign(BaseModel)설계서의 칸과 자료형을 정한다설계서를 사람이 읽는 글에서 코드가 검사할 수 있는 틀로 바꿉니다. 4장의 구조화 출력에서 쓴 것과 같은 Pydantic 틀입니다
Field(min_length=3), Field(ge=10)칸마다 최소 기준을 단다"자주 받을 질문 3개 이상", "평가 질문 10개 이상"이라는 팀의 약속을 코드로 적은 것입니다
out_of_scope: str기본값이 없어 꼭 채워야 하는 칸이 된다범위 밖 질문에 할 말을 빼먹은 설계서는 통과하지 못합니다
e.errors()어긴 칸을 한꺼번에 모아 준다첫 오류에서 멈추지 않고 고칠 곳을 한 번에 보여 줍니다

결과에서 읽을 것은 두 가지입니다.

  • 세 칸이 걸렸습니다. questions(2개), out_of_scope(없음), eval_count(5)의 세 줄이 일부러 비운 세 군데와 꼭 맞습니다.
  • 칸 이름이 고칠 곳입니다. err["loc"][0] 로 칸 이름을 앞에 찍었기 때문에 영어 오류 글을 다 읽지 않아도 어느 칸을 고칠지 압니다.

주의할 점

  • "범위 밖 질문에 할 말"은 가장 자주 빠지는 칸입니다. 이 칸이 없으면 챗봇은 모르는 것도 그럴듯하게 지어냅니다.
  • 평가 질문은 코드를 쓰기 전에 만듭니다. 챗봇을 다 만든 뒤에 질문을 만들면, 챗봇이 잘 답하는 질문만 고르기 쉽습니다.
← 이전 절8장 · 최종 프로젝트 진행 방법다음 절 →8장 · 1~7장의 부품을 한 앱으로 묶는 짜임