애플리케이션에서 LLM 이 작업한 결과를 구조화된 형식으로 전달하면 다른 코드가 처리할 수 있어 매우 유용하다.
▶ JSON 출력
JSON 출력은 프런트엔드 코드에 전달하거나 DB 에 저장할 수 있다.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from pydantic import BaseModel, Field
# 1. 응답 구조 정의 (Pydantic 모델)
# 모델이 내보낼 JSON의 '스키마' 역할을 합니다.
class AnswerWithJustification(BaseModel):
answer: str = Field(description="사용자의 질문에 대한 핵심 답변")
justification: str = Field(description="답변에 대한 기술적 근거 또는 이유")
# 2. 모델 설정
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 3. 모델에 구조적 출력 기능 입히기 (핵심!)
# 이 단계를 거치면 llm은 무조건 AnswerWithJustification 형식을 따릅니다.
structured_llm = llm.with_structured_output(AnswerWithJustification)
# 4. 프롬프트 정의
# 여기서는 지구 복잡한 format_instructions를 넣을 필요가 없습니다.
prompt = ChatPromptTemplate.from_messages([
("system", "너는 백엔드 개발 전문가야. 질문에 대해 정확한 답변과 근거를 제공해줘."),
("user", "{question}")
])
# 5. 체인 구성 (파서가 필요 없음!)
chain = prompt | structured_llm
# 6. 실행
question_text = "레이어드 아키텍처(Layered Architecture)의 장점은 뭐야?"
response = chain.invoke({"question": question_text})
# 7. 결과 확인
print("--- 결과 타입 ---")
print(type(response))
with_structured_output 메서드는 선언된 스키마 AnswerWithJustification 를 두가지 용도로 활용한다.
스키마를 JSONSchema 객체로 변환하해 LLM 에 전송한다. 해당 객체는 JSON 데이터의 구조를 기술한다.
스키마는 LLM이 변환한 출력물을 반환하기 전에 그 유효성을 검증한다.
JSON 외에도 CSV나 XML 같은 출력물을 생성하도록 지시할 수 있는데, 이 경우 출력파서가 유용한다.
▶ 출력파서
LLM 응답을 구조화 하는 클래스다. 출력 파서는 아래 두 가지 기능을 수행한다.
- 출력 형식 지정 : 프롬프트에 추가 지시 사항을 삽입해, LLM이 파싱하기 좋은 형식으로 텍스트를 출력하도록 유도한다.
- 출력 검증 및 파싱 : LLM 또는 채팅 모델의 텍스트 출력 겨로가물을 받아 리스트, XML 등의 구조화된 형식으로 가공한다. 불필요한 정보를 제거하고, 불완전한 출력을 수정하며, 파싱한 값을 검증한다.
▷ CSV 출력 파서 예제
CommaSeparatedListOutputParser 파서는 모델이 내놓은 문자열을 파이썬의 list 객체로 변환해준다.
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import CommaSeparatedListOutputParser
# 1. 모델 설정
model = ChatOpenAI(model="gpt-4o", temperature=0)
# 2. CSV 출력 파서 설정
output_parser = CommaSeparatedListOutputParser()
# 3. 프롬프트 템플릿 정의
# get_format_instructions()는 "쉼표로 구분된 리스트로 답해라"라는 지시문을 생성합니다.
prompt = ChatPromptTemplate.from_messages([
("system", "너는 IT 기술 트렌드 전문가야. 사용자가 제시한 주제와 관련된 기술 키워드 5개를 뽑아줘.\n{format_instructions}"),
("user", "{subject}")
])
# 4. LCEL 체인 구성
chain = prompt | model | output_parser
# 5. 실행
# format_instructions를 반드시 입력값으로 넣어줘야 모델이 형식을 지킵니다.
response = chain.invoke({
"subject": "MSA(Microservices Architecture)",
"format_instructions": output_parser.get_format_instructions()
})
# 6. 결과 확인
print("--- 결과 타입 ---")
print(type(response)) # <class 'list'>
print("\n--- 파싱된 리스트 ---")
print(response)
이때 parser 가 내부적으로 어떻게 작동하냐면
1. 모델의 원본 응답 (AIMessage)
먼저 모델은 내부적으로 아래와 같은 문자열을 생성한다.
"Docker, Kubernetes, Kafka, API Gateway, gRPC"
2. 파서의 처리 (OutputParser)
CommaSeparatedListOutputParser 가 쉼표를 기준으로 문자열을 쪼개고, 각 단어의 앞뒤 불필요한 공백을 제거한다.
3. 최종결과
파이썬 코드에서 즉시 사용가능한 리스트 객체가 된다.
['Docker', 'Kubernetes', 'API Gateway', 'gRPC']
랭체인은 CSV, XML 등 다양한 경우에 대응하는 출력 파서를 제공한다.
'LangChain' 카테고리의 다른 글
| [LangChain] 임베딩과 코사인 유사도의 이해 (0) | 2026.04.28 |
|---|---|
| [LangChain] 랭체인의 LCEL 구성 컴파일 (0) | 2026.04.27 |
| [LangChain] 러닝 랭체인 : 랭체인은 무엇인가 ? (0) | 2026.04.20 |