LiteLLM에서 가드레일 마이그레이션¶
LiteLLM 프록시 가드레일(Python CustomGuardrail 클래스와 훅)을 Continuum Router의 가드레일 프로바이더로 옮기는 방법을 다룹니다. 각 프로바이더의 전체 옵션은 가드레일을 참고하세요.
개념 매핑¶
| LiteLLM 개념 | Continuum 대응 |
|---|---|
CustomGuardrail 클래스와 apply_guardrail | webhook 프로바이더: 클래스를 작은 HTTP 서비스로 실행해 로직을 그대로 유지합니다. 프로세스 내 플러그인은 지원하지 않습니다 |
async_pre_call_hook의 마스킹·변환 로직 | pii 프로바이더(default_action: mask, phase: sanitize, 내장 스캐너와 options.custom_entities), 또는 서비스가 transform 구간을 반환하면 webhook |
async_pre_call_hook의 차단 로직 | custom_classifier(일반 chat 모델 + 정책 프롬프트), self_hosted_classifier(가드 모델 템플릿), 또는 webhook(운영자가 실행하는 규칙 서비스) |
async_moderation_hook | stages: [input]의 inspect 프로바이더(openai_moderation, 분류기). 호출과 병렬로 실행되지 않고 dispatch 전에 실행됩니다 |
async_post_call_success_hook | stages: [output] (출력 게이팅) |
async_post_call_streaming_iterator_hook | 스트리밍 출력 게이팅이 내장되어 있습니다(별도 구현 불필요) |
| NER 서비스(Microsoft Presidio) | pii 프로바이더의 Presidio 호환 external.endpoint |
mode: pre_call / during_call / post_call | stages: [input, output]. phase(sanitize 또는 inspect)는 한 단계 안에서 프로바이더의 실행 순서를 정하며, 실행 시점이 아닙니다. during_call 입력 패스는 없으며, 입력 프로바이더는 dispatch 전에 한 번 실행됩니다 |
default_on | guardrails.enabled: true와 프로바이더의 enabled(기본값 true). 활성화된 프로바이더는 게이트되는 모든 요청에서 실행되며, 요청별 클라이언트 opt-in은 없습니다 |
| 키별 가드레일 | 모델별 guardrails.routes와 Hub 티어 정책 |
| 화이트리스트/바이패스 | guardrails.bypass_api_keys (가드레일을 완전히 건너뛰는 키) |
Continuum의 판정 순서(차단/마스킹/변환)와 카테고리, 실패 동작(on_error), 시간 예산은 가드레일의 Concepts와 Providers 절에 정리되어 있습니다.
단계별 이전¶
- 훅의 역할을 분류합니다: 텍스트를 고치는 훅은
pii나webhook으로, 판정만 하는 훅은 분류기로 옮깁니다. 판정 로직이 이미 운영자가 실행하는 코드라면webhook을 씁니다. pii훅이면 대상 엔티티를 정리하고 내장 스캐너(email,ssn,kr_rrn등)와 커스텀 정규식(options.custom_entities)으로 매핑합니다. Presidio NER 서비스를 쓰고 있었다면external.endpoint로 연결합니다.- 차단 훅이면 정책을 한 문장의 plain-language 정책 프롬프트로 옮겨
custom_classifier에 넣거나, granite_guardian/llama_guard 같은 가드 모델 템플릿이 맞으면self_hosted_classifier를 씁니다. 기존 코드를 그대로 쓰려면 HTTP 서비스로 감싸webhook으로 연결합니다. mode를stages로 옮깁니다. pre_call은[input], post_call은[output], 둘 다면[input, output]입니다.litellm_config.yaml의 가드레일 목록을guardrails.providers[]로 옮기고,guardrails.enabled: true와 필요한routes를 설정합니다.- 모드를 정합니다.
guardrails.mode의 기본값은monitor이며, 판정을 기록만 하고 차단이나 마스킹은 하지 않습니다. 먼저monitor로 실행해 기존 훅과 판정을 비교한 뒤,mode: enforce로 바꿉니다.
작업 예제¶
LiteLLM의 사번 마스킹 훅(정규식으로 EMP-\d{6}을 마스킹하고 이메일은 마스킹, 주민등록번호는 차단하던 훅)은 다음 한 블록으로 옮겨집니다.
guardrails:
enabled: true
mode: enforce
providers:
- name: pii-redaction
type: pii
enabled: true
phase: sanitize
stages: [input, output]
options:
default_action: mask
actions:
email: mask
ssn: block
kr_rrn: block
employee_id: mask
placeholder_format: "[REDACTED:{TYPE}]"
custom_entities:
- name: employee_id
pattern: '(?-u:\b)EMP-\d{6}(?-u:\b)'
context_words: ["employee", "사번"]
context_window: 64
on_error: fail_open
이 구성의 동작:
mode: enforce가 판정을 실제로 적용합니다. 기본값인monitor모드에서는 아무것도 마스킹하거나 차단하지 않습니다.email,employee_id는[REDACTED:{TYPE}]로 마스킹되고({TYPE}은 대문자로 바꾼 엔티티 유형),ssn,kr_rrn은 요청을 차단합니다.phase: sanitize는inspect프로바이더보다 먼저 마스킹하므로, 나중에 추가한 분류기도 원본 값을 보지 않습니다.- 내장 스캐너는 외부 의존성 없이 로컬에서 실행되고, 검출된 원본 값은 기록되지 않습니다.
employee_id는 커스텀 정규식 엔티티로,context_words가 인접한 단어를 보고 오탐을 줄입니다.
차단 정책이 하나 더 필요하면(예: 경쟁사 언급 차단) 같은 providers 목록에 custom_classifier를 추가합니다.
- name: competitor-guard
type: custom_classifier
enabled: true
endpoint: "http://127.0.0.1:11434/v1/chat/completions"
stages: [input]
options:
model: "granite3.1-dense:8b"
policy_prompt: |
Mark content unsafe if it mentions a competitor's product by name.
default_category: competitor_mention
대응이 없는 것¶
- 프로세스 내 Python 플러그인: Continuum에는 코드를 넣을 확장 지점이 없습니다. 훅의 로직은 위 프로바이더 유형 중 하나로 옮겨야 합니다. 고객 목록, 체크섬, 사전 대조처럼 코드로만 표현되는 정책은 별도 서비스로 두고
webhook으로 연결합니다. 라우터는{stage, model, texts}를 보내고 작은 판정 객체를 읽으므로, 서비스가 chat 모델이나 Presidio 분석기를 흉내 낼 필요가 없습니다. chat 모양의 요청을 기대하는 엔드포인트는custom_classifier를 쓸 수 있습니다. during_call입력 패스: 입력 프로바이더는 dispatch 전에 한 번 실행됩니다. 스트리밍 도중 입력 검사는 없습니다.