langchain / / 2024. 8. 26. 17:55

[langchain] StrOutputParser, JsonOutputParser 이해하기

StrOutputParser

StrOutputParser는 LangChain 생태계 내에서 간단하지만 강력한 도구이다. 이 파서의 주된 역할은 LLM이나 ChatModel에서 나오는 언어 모델의 출력을 문자열 형식으로 변환하는 것이다. 이 변환은 애플리케이션에서 일관된 출력 형식을 유지하거나, 이후의 처리 또는 최종 사용자에게 표시하기 위해 매우 중요하다.

  • LLM 출력의 경우: 모델의 출력이 이미 문자열 형식인 경우, StrOutputParser는 이 문자열을 수정 없이 그대로 통과시킨다.
  • ChatModel 출력의 경우: 출력이 ChatModel 메시지일 때, StrOutputParser는 메시지의 .content 속성을 추출하여 최종 출력이 문자열 형식이 되도록 한다.

이 파서는 특히 모델의 원시 출력을 특정 용도에 맞게 간소화하거나 포맷팅해야 하는 상황에서 유용하다. 예를 들어, 보고서를 생성하거나 애플리케이션의 다른 구성 요소에 데이터를 전달하거나, 사용자에게 읽기 쉬운 형식으로 정보를 표시하는 등의 경우에 사용된다.

사용 예제

LangChain 애플리케이션에 StrOutputParser를 통합하는 것은 간단하다. 다음은 이를 체인 내에서 활용하는 기본적인 예이다.

우선, StrOutParser를 사용하지 않는 기본 호출을 해보자.

model = ChatOpenAI(temperature=0)
prompt = PromptTemplate(template="{query}")
chain = prompt | model

response = chain.invoke({"query": "한국의 수도는?"})
print(response)

실행결과

content='서울입니다.' response_metadata={'token_usage': {'completion_tokens': 5, 'prompt_tokens': 15, 'total_tokens': 20}, 'model_name': 'gpt-3.5-turbo-0125', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-c4b66f5c-31a9-45f2-9635-d11677bce4fd-0' usage_metadata={'input_tokens': 15, 'output_tokens': 5, 'total_tokens': 20}

응답이 AIMessage로 위의 내용을 포함해서 내려온다.

대부분의 경우 response_metadata은 필요가 없고 content의 내용만 필요하다.
그래서 response.content를 사용하면 되지만 StrOutputParser를 통해 출력해보자.

model = ChatOpenAI(temperature=0)
prompt = PromptTemplate(template="{query}")
chain = prompt | model | StrOutputParser()

response = chain.invoke({"query": "한국의 수도는?"})
print(response)

실행결과

서울입니다.

이 예제에서 체인은 프롬프트, LLM, 그리고 StrOutputParser를 결합하여 모델의 출력을 문자열로 처리하고 변환한다. 이처럼 간단하면서도 유연한 구조 덕분에 StrOutputParser는 LangChain 툴킷에서 없어서는 안 될 도구이다.

JsonOutputParser

이 출력 파서를 사용하면 사용자가 임의의 JSON 스키마를 지정하고, LLM에게 해당 스키마에 맞는 출력을 요청할 수 있다.

하지만, 대형 언어 모델은 완벽한 추상화 도구가 아니기 때문에 주의가 필요하다.

사용 예제 (invoke)

from dotenv import load_dotenv
from langchain.prompts import PromptTemplate
from langchain_core.output_parsers import (
    JsonOutputParser,
)
from langchain_core.pydantic_v1 import Field
from langchain_openai import ChatOpenAI
from pydantic import BaseModel

load_dotenv()

model = ChatOpenAI(temperature=0)


class CapitalModel(BaseModel):
    country: str = Field(description="country")
    capital: str = Field(description="capital")


query = "한국의 수도는?"
parser = JsonOutputParser(pydantic_object=CapitalModel)
prompt = PromptTemplate(
    template="Answer the user query.\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

chain = prompt | model | parser

def invoke():
    response = chain.invoke({"query": query})
    print(response)

invoke()

실행결과

{'country': 'South Korea', 'capital': 'Seoul'}

stream으로 실행

for s in chain.stream({"query": query}):
    print(s)

실행결과

{}
{'country': ''}
{'country': 'South'}
{'country': 'South Korea'}
{'country': 'South Korea', 'capital': ''}
{'country': 'South Korea', 'capital': 'Se'}
{'country': 'South Korea', 'capital': 'Seoul'}

pydantic 없이 실행

model = ChatOpenAI(temperature=0)


query = "한국의 수도는?"
parser = JsonOutputParser()
prompt = PromptTemplate(
    template="Answer the user query.\n{format_instructions}\n{query}\n",
    input_variables=["query"],
    partial_variables={"format_instructions": parser.get_format_instructions()},
)

chain = prompt | model | parser


def invoke():
    response = chain.invoke({"query": query})
    print(response)


invoke()


def stream():
    for s in chain.stream({"query": query}):
        print(s)

stream()

invoke 결과

{'answer': '서울'}

Stream 결과

{}
{'answer': ''}
{'answer': '서'}
{'answer': '서울'}

참고

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유