Output Parser
(1) 개념
- Output Parser는 Model이 생성한 출력 결과를 원하는 형태로 변환해주는 구성요소입니다.
- LCEL에서 Parser는 보통 Model 뒤에서 응답을 문자열, JSON 등 특정 형식으로 가공합니다.
- 즉, Parser는 Model의 응답을 애플리케이션에서 다루기 쉬운 형태로 정리하는 역할을 담당합니다.
(2) 예시
ChatOpenAI와 같은 Chat Model의 응답은 보통AIMessage객체입니다.- 먼저, Parser를 사용하지 않은 답변을 출력해보면 아래와 같습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
AIMessage(
content='LCEL의 Parser는 텍스트 데이터를 분석하여...',
additional_kwargs={'refusal': None},
response_metadata={'token_usage':
{'completion_tokens': 96,
'prompt_tokens': 30,
'total_tokens': 126,
'completion_tokens_details':
{'accepted_prediction_tokens': 0,
'audio_tokens': 0,
'reasoning_tokens': 0,
'rejected_prediction_tokens': 0
},
'prompt_tokens_details':
{'audio_tokens': 0, 'cached_tokens': 0}},
'model_provider': 'openai',
'model_name': 'gpt-4o-mini-2024-07-18',
'system_fingerprint': '...',
'id': '...',
'service_tier': 'default',
'finish_reason': 'stop',
'logprobs': None},
id='..',
tool_calls=[],
invalid_tool_calls=[],
usage_metadata={
'input_tokens': 30,
'output_tokens': 96,
'total_tokens': 126,
'input_token_details':
{'audio': 0,
'cache_read': 0
},
'output_token_details': {'audio': 0, 'reasoning': 0}})
- 이때
StrOutputParser를 이용하면 응답 본문만 문자열로 쉽게 추출할 수 있습니다. - 즉, Parser를 사용하면 모델의 출력을 후속 처리에 적합한 형태로 변환할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from langchain_openai import ChatOpenAI
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import StrOutputParser
import os
# model 준비
os.environ["OPENAI_API_KEY"] = "my API Key..."
model = ChatOpenAI(model="gpt-4o-mini")
# prompt 준비
system_prompt = "{topic}에 대해 초보자도 이해할 수 있도록 3문장으로 설명하시오"
prompt = PromptTemplate.from_template(system_prompt)
# parser 준비
parser = StrOutputParser()
# chain 준비
chain = prompt | model | parser
# 추론
result = chain.invoke({"topic" : "LCEL의 Parser"})
print(result)
1
2
3
LCEL의 Parser는 텍스트 데이터를 분석하여 의미 있는 정보를 추출하는 프로그램입니다.
입력된 문장을 구성하는 단어와 구문을 이해하고, 그 관계를 파악하여 구조화된 데이터를 생성합니다.
이 과정을 통해 사용자에게 유용한 결과를 제공하고, 다양한 언어 처리 작업을 지원합니다.
(3) 종류
StrOutputParser: LLM의 응답에서 메타데이터를 제외하고 순수하게 메시지 내용(content)만 문자열로 추출JsonOutputParser: LLM의 응답을 JSON 형식으로 변환. 보통 프롬프트에 원하는 JSON 스키마를 함께 전달하여 LLM으로부터 JSON형식의 답변을 받아올 떄 사용JsonOutputKeyToolsParser: OpenAI와 같은 모델이 Tool Calling을 할 때, 도구 중 특정 키값에 해당하는 인자만 JSON 형태로 출력PydanticToolsParser: 모델의 도구 호출 결과를 Pydantic 모델 객체로 변환XMLOutputParser: LLM의 응답에서 XML 태그 형식을 찾아 파싱함.CommaSeparatedListOutputParser: 콤마로 구분된 문자열 응답을 Python 리스트 형식으로 변환BaseOutputParser: 모든 출력 파서의 최상위 추상 클래스BaseLLMOutputParser: BaseOutputParser 의 하위 클래스
(4) 각 OutputParser 예시
- JsonOutputParser : 응답을 dictionary 형태로 변환하기 쉬워집니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import JsonOutputParser
from langchain_openai import ChatOpenAI
import os
os.environ["OPENAI_API_KEY"] = "my API Key..."
model = ChatOpenAI(model="gpt-4o-mini")
parser = JsonOutputParser()
prompt = PromptTemplate.from_template("""
다음 질문에 답하고, 반드시 JSON 형식으로만 출력하세요.
질문: {question}
출력 형식:
{
{
"question": "질문 내용",
"answer": "질문에 대한 답변"
}
}
""")
chain = prompt | model | parser
result = chain.invoke({"question": "LCEL은 무엇인가요?"})
print(result)
1
2
3
4
5
# 출력 예시
{
'question': 'LCEL은 무엇인가요?',
'answer': 'LCEL은 LangChain Expression Language의 약자로, LangChain에서 체인을 선언적으로 연결하기 위한 표현 방식입니다.'
}
- PydanticOutputParser : 출력 형식을 엄격하게 관리할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
from pydantic import BaseModel, Field
from langchain_core.prompts import PromptTemplate
from langchain_core.output_parsers import PydanticOutputParser
from langchain_openai import ChatOpenAI
import os
os.environ["OPENAI_API_KEY"] = "my API Key..."
class AnswerSchema(BaseModel):
question: str = Field(description="사용자의 질문")
answer: str = Field(description="질문에 대한 답변")
parser = PydanticOutputParser(pydantic_object=AnswerSchema)
model = ChatOpenAI(model="gpt-4o-mini")
prompt = PromptTemplate.from_template("""
다음 질문에 답하세요.
질문: {question}
{format_instructions}
""")
prompt = prompt.partial(format_instructions=parser.get_format_instructions())
chain = prompt | model | parser
result = chain.invoke({"question": "Prompt Template은 무엇인가요?"})
print(result)
1
2
3
# 출력 예시
question='Prompt Template은 무엇인가요?'
answer='Prompt Template은 변수 값을 삽입해 재사용 가능한 프롬프트를 만들기 위한 템플릿입니다.'
(5) Parser를 이용하는 이유
- Model의 출력은 그대로 사용하기 어려울 수 있으므로, 원하는 형태로 변환 필요
- 어떤 때는 문자열, 또 다른 상황에서는 JSON 등 상황에 따라 필요한 응답 구조를 사용
- 이를 통해 후속 코드에서 결과를 쉽게 재사용할 수 있음
- LCEL에서는
prompt | model | parser형태로 연결해서 사용
Comments