OutputAdapter

OutputAdapter

한 컴포넌트의 출력이 다른 컴포넌트의 입력에 매끄럽게 들어맞도록 돕는 컴포넌트예요. Jinja 표현식으로 이 적응(adaptation)이 어떻게 일어날지 정의해요.

출처: 문서

본문

OutputAdapter를 쓰려면 다음을 포함한 적응 규칙을 지정해야 해요.

  • template: 입력 데이터를 어떻게 적응할지 정의하는 Jinja 템플릿 문자열.
  • output_type: 출력 데이터의 유형(예: str, List[int]..). 실제 출력 유형을 바꾸지는 않고, 다른 컴포넌트와의 연결을 검증하는 데만 필요해요.
  • custom_filters: 템플릿에서 쓸 커스텀 Jinja 필터의 선택적 사전.

변수

OutputAdapter는 실행 전에 모든 템플릿 변수가 있어야 하며, 파이프라인 연결 시점에 템플릿 변수가 하나라도 없으면 오류를 발생시켜요.

from haystack.components.converters import OutputAdapter


adapter = OutputAdapter(template="Hello {{name}}!", output_type=str)

안전하지 않은 동작

OutputAdapter는 내부적으로 Jinja로 template을 렌더링하는데, 기본적으로 이는 안전한 동작이에요. 다만 출력 유형이 문자열, 바이트, 숫자, 튜플, 목록, 딕셔너리, 집합, 불리언, None, Ellipsis(...), 그리고 이 구조의 조합으로 제한돼요.

ChatMessage, Document, Answer 같은 다른 유형을 쓰려면 unsafe init 인자를 True로 설정해서 안전하지 않은 템플릿 렌더링을 켜야 해요.

주의하세요. 켜면 안전하지 않을 수 있고, template이 최종 사용자가 커스터마이즈할 수 있는 문자열이라면 원격 코드 실행으로 이어질 수 있어요.

더 알아보기 (Learn more)

단독으로 쓰기

이 컴포넌트는 주로 파이프라인에서 쓰도록 만들어졌어요.

이 예제에서 OutputAdapter는 문서 배열의 첫 번째 문서의 content 필드를 그대로 출력해요.

from haystack import Document
from haystack.components.converters import OutputAdapter


adapter = OutputAdapter(template="{{ documents[0].content }}", output_type=str)
input_data = {"documents": [Document(content="Test content")]}
expected_output = {"output": "Test content"}

assert adapter.run(**input_data) == expected_output

파이프라인에서 쓰기

아래 예제는 OutputAdapter로 목록의 첫 번째 문서를 대문자화하는 간단한 파이프라인을 보여줘요. 필요하면 미리 정의된 Jinja filters도 사용할 수 있어요.

from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter


@component
class DocumentProducer:
    @component.output_types(documents=dict)
    def run(self):
        return {"documents": [Document(content="haystack")]}


pipe = Pipeline()
pipe.add_component(
    name="output_adapter",
    instance=OutputAdapter(
        template="{{ documents[0].content | capitalize}}",
        output_type=str,
    ),
)
pipe.add_component(name="document_producer", instance=DocumentProducer())
pipe.connect("document_producer", "output_adapter")

result = pipe.run(data={})

assert result["output_adapter"]["output"] == "Haystack"

자체 커스텀 필터를 정의해서 init 메서드로 OutputAdapter 인스턴스에 추가하고 템플릿에서 사용할 수도 있어요. 그 예제를 볼게요.

from haystack import Pipeline, component, Document
from haystack.components.converters import OutputAdapter


def reverse_string(s):
    return s[::-1]


@component
class DocumentProducer:
    @component.output_types(documents=dict)
    def run(self):
        return {"documents": [Document(content="haystack")]}


pipe = Pipeline()
pipe.add_component(
    name="output_adapter",
    instance=OutputAdapter(
        template="{{ documents[0].content | reverse_string}}",
        output_type=str,
        custom_filters={"reverse_string": reverse_string},
    ),
)

pipe.add_component(name="document_producer", instance=DocumentProducer())
pipe.connect("document_producer", "output_adapter")

result = pipe.run(data={})

assert result["output_adapter"]["output"] == "kcatsyah"