langchain / / 2025. 11. 8. 21:14

[LangChain v1.0] Guardrails

에이전트를 위한 안전성 검사 및 콘텐츠 필터링 구현

Guardrails는 에이전트 실행의 주요 지점에서 콘텐츠를 검증하고 필터링함으로써 안전하고 규정을 준수하는 AI 애플리케이션을 구축하는 데 도움을 줍니다. 민감한 정보를 감지하고, 콘텐츠 정책을 시행하며, 출력을 검증하고, 문제가 발생하기 전에 안전하지 않은 동작을 방지할 수 있습니다.

일반적인 사용 사례는 다음과 같습니다:

  • PII 유출 방지
  • 프롬프트 인젝션 공격 감지 및 차단
  • 부적절하거나 유해한 콘텐츠 차단
  • 비즈니스 규칙 및 규정 준수 요구사항 시행
  • 출력 품질 및 정확성 검증

전략적 지점에서 실행을 가로채기 위해 middleware를 사용하여 가드레일을 구현할 수 있습니다 - 에이전트가 시작하기 전, 완료된 후 또는 모델 및 도구 호출 주변에서 말이죠.

가드레일은 두 가지 상호 보완적인 접근 방식을 사용하여 구현할 수 있습니다:

두 가지 가드레일 접근 방식

결정론적 가드레일(Deterministic guardrails): 정규식 패턴, 키워드 매칭 또는 명시적 검사와 같은 규칙 기반 로직을 사용합니다. 빠르고 예측 가능하며 비용 효율적이지만, 미묘한 위반을 놓칠 수 있습니다.

모델 기반 가드레일(Model-based guardrails): LLM이나 분류기를 사용하여 의미론적 이해로 콘텐츠를 평가합니다. 규칙이 놓치는 미묘한 문제를 포착하지만, 더 느리고 비용이 많이 듭니다.

LangChain은 내장 가드레일(예: PII 감지, human-in-the-loop)과 두 접근 방식 중 하나를 사용하여 커스텀 가드레일을 구축하기 위한 유연한 미들웨어 시스템을 모두 제공합니다.

내장 가드레일

PII 감지

LangChain은 대화에서 개인 식별 정보(PII)를 감지하고 처리하기 위한 내장 미들웨어를 제공합니다. 이 미들웨어는 이메일, 신용카드, IP 주소 등과 같은 일반적인 PII 유형을 감지할 수 있습니다.

PII 감지 미들웨어는 규정 준수 요구사항이 있는 의료 및 금융 애플리케이션, 로그를 정리해야 하는 고객 서비스 에이전트, 그리고 일반적으로 민감한 사용자 데이터를 처리하는 모든 애플리케이션에 유용합니다.

PII 미들웨어는 감지된 PII를 처리하기 위한 여러 전략을 지원합니다:

전략 설명 예시
redact [REDACTED_TYPE]으로 교체 [REDACTED_EMAIL]
mask 부분적으로 가림 (예: 마지막 4자리) ****-****-****-1234
hash 결정론적 해시로 교체 a8f5f167...
block 감지 시 예외 발생 오류 발생
from langchain.agents import create_agent
from langchain.agents.middleware import PIIMiddleware


agent = create_agent(
    model="gpt-4o",
    tools=[customer_service_tool, email_tool],
    middleware=[
        # 모델로 전송하기 전에 사용자 입력의 이메일을 삭제
        PIIMiddleware(
            "email",
            strategy="redact",
            apply_to_input=True,
        ),
        # 사용자 입력의 신용카드 마스킹
        PIIMiddleware(
            "credit_card",
            strategy="mask",
            apply_to_input=True,
        ),
        # API 키 차단 - 감지되면 오류 발생
        PIIMiddleware(
            "api_key",
            detector=r"sk-[a-zA-Z0-9]{32}",
            strategy="block",
            apply_to_input=True,
        ),
    ],
)

# 사용자가 PII를 제공하면 전략에 따라 처리됩니다
result = agent.invoke({
    "messages": [{"role": "user", "content": "My email is john.doe@example.com and card is 4532-1234-5678-9010"}]
})

내장 PII 유형 및 구성

내장 PII 유형:

  • email - 이메일 주소
  • credit_card - 신용카드 번호 (Luhn 검증됨)
  • ip - IP 주소
  • mac_address - MAC 주소
  • url - URL

구성 옵션:

매개변수 설명 기본값
pii_type 감지할 PII 유형 (내장 또는 커스텀) 필수
strategy 감지된 PII 처리 방법 ("block", "redact", "mask", "hash") "redact"
detector 커스텀 감지 함수 또는 정규식 패턴 None (내장 사용)
apply_to_input 모델 호출 전에 사용자 메시지 확인 True
apply_to_output 모델 호출 후에 AI 메시지 확인 False
apply_to_tool_results 실행 후 도구 결과 메시지 확인 False

PII 감지 기능에 대한 전체 세부 정보는 middleware 문서를 참조하세요.

Human-in-the-Loop

LangChain은 민감한 작업을 실행하기 전에 사람의 승인을 요구하는 내장 미들웨어를 제공합니다. 이것은 높은 위험성이 있는 결정에 대한 가장 효과적인 가드레일 중 하나입니다.

Human-in-the-loop 미들웨어는 금융 거래 및 이체, 프로덕션 데이터 삭제 또는 수정, 외부 당사자에게 통신 전송, 그리고 중요한 비즈니스 영향이 있는 모든 작업과 같은 경우에 유용합니다.

from langchain.agents import create_agent
from langchain.agents.middleware import HumanInTheLoopMiddleware
from langgraph.checkpoint.memory import InMemorySaver
from langgraph.types import Command


agent = create_agent(
    model="gpt-4o",
    tools=[search_tool, send_email_tool, delete_database_tool],
    middleware=[
        HumanInTheLoopMiddleware(
            interrupt_on={
                # 민감한 작업에 대한 승인 요구
                "send_email": True,
                "delete_database": True,
                # 안전한 작업 자동 승인
                "search": False,
            }
        ),
    ],
    # 중단 간에 상태 유지
    checkpointer=InMemorySaver(),
)

# Human-in-the-loop은 지속성을 위해 스레드 ID가 필요합니다
config = {"configurable": {"thread_id": "some_id"}}

# 에이전트는 민감한 도구를 실행하기 전에 일시 중지되고 승인을 기다립니다
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Send an email to the team"}]},
    config=config
)

result = agent.invoke(
    Command(resume={"decisions": [{"type": "approve"}]}),
    config=config  # 일시 중지된 대화를 재개하기 위해 동일한 스레드 ID 사용
)

승인 워크플로우 구현에 대한 전체 세부 정보는 human-in-the-loop 문서를 참조하세요.

커스텀 가드레일

더 정교한 가드레일을 위해 에이전트가 실행되기 전이나 후에 실행되는 커스텀 미들웨어를 만들 수 있습니다. 이를 통해 검증 로직, 콘텐츠 필터링 및 안전성 검사를 완전히 제어할 수 있습니다.

Before Agent 가드레일

각 호출의 시작 부분에서 한 번 요청을 검증하기 위해 "before agent" 훅을 사용합니다. 이것은 인증, 속도 제한 또는 처리가 시작되기 전에 부적절한 요청을 차단하는 것과 같은 세션 수준 검사에 유용합니다.

클래스 구문

from typing import Any

from langchain.agents.middleware import AgentMiddleware, AgentState, hook_config
from langgraph.runtime import Runtime

class ContentFilterMiddleware(AgentMiddleware):
    """결정론적 가드레일: 금지된 키워드를 포함하는 요청을 차단합니다."""

    def __init__(self, banned_keywords: list[str]):
        super().__init__()
        self.banned_keywords = [kw.lower() for kw in banned_keywords]

    @hook_config(can_jump_to=["end"])
    def before_agent(self, state: AgentState, runtime: Runtime) -> dict[str, Any] | None:
        # 첫 번째 사용자 메시지 가져오기
        if not state["messages"]:
            return None

        first_message = state["messages"][0]
        if first_message.type != "human":
            return None

        content = first_message.content.lower()

        # 금지된 키워드 확인
        for keyword in self.banned_keywords:
            if keyword in content:
                # 모든 처리 전에 실행 차단
                return {
                    "messages": [{
                        "role": "assistant",
                        "content": "I cannot process requests containing inappropriate content. Please rephrase your request."
                    }],
                    "jump_to": "end"
                }

        return None

# 커스텀 가드레일 사용
from langchain.agents import create_agent

agent = create_agent(
    model="gpt-4o",
    tools=[search_tool, calculator_tool],
    middleware=[
        ContentFilterMiddleware(
            banned_keywords=["hack", "exploit", "malware"]
        ),
    ],
)

# 이 요청은 모든 처리 전에 차단됩니다
result = agent.invoke({
    "messages": [{"role": "user", "content": "How do I hack into a database?"}]
})

데코레이터 구문

from typing import Any

from langchain.agents.middleware import before_agent, AgentState, hook_config
from langgraph.runtime import Runtime

banned_keywords = ["hack", "exploit", "malware"]

@before_agent(can_jump_to=["end"])
def content_filter(state: AgentState, runtime: Runtime) -> dict[str, Any] | None:
    """결정론적 가드레일: 금지된 키워드를 포함하는 요청을 차단합니다."""
    # 첫 번째 사용자 메시지 가져오기
    if not state["messages"]:
        return None

    first_message = state["messages"][0]
    if first_message.type != "human":
        return None

    content = first_message.content.lower()

    # 금지된 키워드 확인
    for keyword in banned_keywords:
        if keyword in content:
            # 모든 처리 전에 실행 차단
            return {
                "messages": [{
                    "role": "assistant",
                    "content": "I cannot process requests containing inappropriate content. Please rephrase your request."
                }],
                "jump_to": "end"
            }

    return None

# 커스텀 가드레일 사용
from langchain.agents import create_agent

agent = create_agent(
    model="gpt-4o",
    tools=[search_tool, calculator_tool],
    middleware=[content_filter],
)

# 이 요청은 모든 처리 전에 차단됩니다
result = agent.invoke({
    "messages": [{"role": "user", "content": "How do I hack into a database?"}]
})

After Agent 가드레일

사용자에게 반환하기 전에 최종 출력을 한 번 검증하기 위해 "after agent" 훅을 사용합니다. 이것은 모델 기반 안전성 검사, 품질 검증 또는 완전한 에이전트 응답에 대한 최종 규정 준수 스캔에 유용합니다.

클래스 구문

from langchain.agents.middleware import AgentMiddleware, AgentState, hook_config
from langgraph.runtime import Runtime
from langchain_core.messages import AIMessage
from langchain.chat_models import init_chat_model
from typing import Any

class SafetyGuardrailMiddleware(AgentMiddleware):
    """모델 기반 가드레일: LLM을 사용하여 응답 안전성을 평가합니다."""

    def __init__(self):
        super().__init__()
        self.safety_model = init_chat_model("gpt-4o-mini")

    @hook_config(can_jump_to=["end"])
    def after_agent(self, state: AgentState, runtime: Runtime) -> dict[str, Any] | None:
        # 최종 AI 응답 가져오기
        if not state["messages"]:
            return None

        last_message = state["messages"][-1]
        if not isinstance(last_message, AIMessage):
            return None

        # 모델을 사용하여 안전성 평가
        safety_prompt = f"""Evaluate if this response is safe and appropriate.
        Respond with only 'SAFE' or 'UNSAFE'.

        Response: {last_message.content}"""

        result = self.safety_model.invoke([{"role": "user", "content": safety_prompt}])

        if "UNSAFE" in result.content:
            return {
                "messages": [{
                    "role": "assistant",
                    "content": "I cannot provide that response. Please rephrase your request."
                }],
                "jump_to": "end"
            }

        return None

# 안전성 가드레일 사용
from langchain.agents import create_agent

agent = create_agent(
    model="gpt-4o",
    tools=[search_tool, calculator_tool],
    middleware=[SafetyGuardrailMiddleware()],
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "How do I make explosives?"}]
})

데코레이터 구문

from langchain.agents.middleware import after_agent, AgentState, hook_config
from langgraph.runtime import Runtime
from langchain_core.messages import AIMessage
from langchain.chat_models import init_chat_model
from typing import Any

safety_model = init_chat_model("gpt-4o-mini")

@after_agent(can_jump_to=["end"])
def safety_guardrail(state: AgentState, runtime: Runtime) -> dict[str, Any] | None:
    """모델 기반 가드레일: LLM을 사용하여 응답 안전성을 평가합니다."""
    # 최종 AI 응답 가져오기
    if not state["messages"]:
        return None

    last_message = state["messages"][-1]
    if not isinstance(last_message, AIMessage):
        return None

    # 모델을 사용하여 안전성 평가
    safety_prompt = f"""Evaluate if this response is safe and appropriate.
    Respond with only 'SAFE' or 'UNSAFE'.

    Response: {last_message.content}"""

    result = safety_model.invoke([{"role": "user", "content": safety_prompt}])

    if "UNSAFE" in result.content:
        return {
            "messages": [{
                "role": "assistant",
                "content": "I cannot provide that response. Please rephrase your request."
            }],
            "jump_to": "end"
        }

    return None

# 안전성 가드레일 사용
from langchain.agents import create_agent

agent = create_agent(
    model="gpt-4o",
    tools=[search_tool, calculator_tool],
    middleware=[safety_guardrail],
)

result = agent.invoke({
    "messages": [{"role": "user", "content": "How do I make explosives?"}]
})

여러 가드레일 결합

미들웨어 배열에 추가하여 여러 가드레일을 쌓을 수 있습니다. 순서대로 실행되어 계층화된 보호를 구축할 수 있습니다:

from langchain.agents import create_agent
from langchain.agents.middleware import PIIMiddleware, HumanInTheLoopMiddleware

agent = create_agent(
    model="gpt-4o",
    tools=[search_tool, send_email_tool],
    middleware=[
        # 레이어 1: 결정론적 입력 필터 (before agent)
        ContentFilterMiddleware(banned_keywords=["hack", "exploit"]),

        # 레이어 2: PII 보호 (모델 전후)
        PIIMiddleware("email", strategy="redact", apply_to_input=True),
        PIIMiddleware("email", strategy="redact", apply_to_output=True),

        # 레이어 3: 민감한 도구에 대한 사람의 승인
        HumanInTheLoopMiddleware(interrupt_on={"send_email": True}),

        # 레이어 4: 모델 기반 안전성 검사 (after agent)
        SafetyGuardrailMiddleware(),
    ],
)

추가 자료


출처: https://docs.langchain.com/oss/python/langchain/guardrails


Langchain v1.0

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