작품을 만들다 보면 가끔 이런 걸 받습니다. "NSFW로 거절되었습니다."
처음 당하면 좀 당황스럽습니다. 야한 걸 만든 적이 없는데 왜 이러지 싶고, 내가 뭘 잘못했나 싶기도 하고요.
저희도 지금까지 세 번 겪었습니다. 이번에 실제 응답을 열어서 뭐가 일어난 건지 확인해 봤고, 그 기록을 정리합니다.
NSFW는 Not Safe For Work의 약자입니다. 원래는 "회사에서 열면 곤란한 것" 정도의 인터넷 은어였는데, 지금은 생성 도구에서 성적인 것·폭력적인 것·기타 정책 위반을 통칭하는 말로 쓰입니다.
중요한 건 이겁니다. NSFW 거절은 사람이 내린 도덕적 판단이 아닙니다. 분류기가 내린 확률적 판정이에요.
그리고 그 분류기는 내 의도를 모릅니다. 프롬프트에 담긴 단어와 만들어질 그림만 봅니다. "고전 조각을 찍은 미술관 도록 사진"이라는 제 머릿속 계획은 분류기가 볼 수 없어요.
지난번 조각 연작에서 재료만 아홉 번 바꾸는 실험을 했습니다. 자세·조명·받침·갤러리를 전부 고정하고 재료 문장만 갈아 끼웠어요.
대리석은 통과했습니다.
밀랍은 거절됐습니다.
두 프롬프트를 나란히 놓으면 이렇습니다. 다른 건 재료를 설명한 한 문장뿐이에요.
A life-size sculpture of a human figure curled tightly on its side with knees drawn to the chest and arms wrapped around the shins, face tucked down and hidden. Carved from white Carrara MARBLE: ... Plain concrete plinth in a bare gallery, even north light. Photorealistic
A life-size sculpture of a human figure curled tightly on its side with knees drawn to the chest and arms wrapped around the shins, face tucked down and hidden. Modelled in pale WAX: ... Plain concrete plinth in a bare gallery, even north light. Photorealistic
성적인 단어는 하나도 없습니다. 두 작업은 0.4초 간격으로 제출됐고요.
실제 API 응답을 열어 봤습니다.
status: "nsfw"result_url: nullresult_json: nullmeta: nulldebug: null
두 가지를 알 수 있습니다.
nsfw는 일반 실패(failed)와 다른 별도 상태입니다. 오류가 아니라 판정이에요이유를 안 주는 건 아마 의도된 설계일 겁니다. 어디가 걸렸는지 알려주면 그걸 피해 가는 방법도 같이 알려주는 셈이니까요. 불편하지만 이해는 갑니다.
여기서부터는 제 추측입니다. 내부 구현을 볼 수 없으니 관찰에서 거꾸로 짚어본 것뿐이에요.
웅크린 인체 조각은 미술사에서 아주 흔한 형식입니다. 그런데 분류기가 보는 건 "사람 형상 + 옷 없음 + 살색"이에요. 미술관인지 아닌지는 그다음 문제고요.
실제로 대리석과 콘크리트는 통과했는데 밀랍만 걸린 게 이 가설과 맞습니다. 밀랍은 반투명하고 살색에 가까운 재료거든요. 돌은 명백히 돌인데 밀랍은 피부처럼 보일 수 있습니다.
이건 가설이라기보다 관찰된 사실에 가깝습니다. 거의 같은 프롬프트 아홉 개 중 여덟 개는 통과하고 하나만 걸렸으니까요. 모델(과 그 앞단의 필터)마다 기준이 다릅니다.
예전에 클레이 연작에서도 두 번 걸린 적이 있습니다. 하나는 이겁니다.
지금 보시는 건 다시 만든 버전이에요. 처음 프롬프트에는 kids가 들어 있었고 거절됐습니다. 클레이 인형 꽃집인데요.
이건 오히려 옳은 설계라고 생각합니다. 아동과 관련된 판정은 임계값을 훨씬 보수적으로 잡는 게 맞아요. 오탐이 좀 생기더라도요.
아래에 해결 방법을 적을 텐데, 그 전에 분명히 해둘 게 있습니다.
이 글은 필터를 뚫는 법이 아닙니다. 실제로 만들면 안 되는 걸 만들려고 우회하는 건 여기 없고, 권하지도 않습니다.
여기서 다루는 건 오탐입니다. 성적 의도가 전혀 없는 작업이 걸렸을 때 그림 자체를 명확하게 바꿔서 오해를 없애는 방법이에요. 우회가 아니라 수정입니다.
그리고 한 가지 더. 여러 번 고쳐도 계속 걸린다면 그것도 신호입니다. 내가 만들려는 게 정말 내가 생각한 그건지 다시 볼 만해요. 분류기가 매번 그렇게 본다면, 다른 사람도 그렇게 볼 수 있다는 뜻이니까요.
밀랍상은 긴 튜닉을 입힌 형상으로 다시 만들었습니다. 자세와 재료 설명은 그대로 두고요.
A life-size art sculpture of a clothed human figure wearing a simple long tunic, curled on its side ... face tucked down and hidden by the fabric ... folds of the tunic sculpted in the wax ...
한 번에 통과했습니다. 그리고 결과적으로 원래 계획보다 나아졌어요 — 옷 주름이 밀랍의 손자국과 잘 어울려서 재료 설명이 오히려 강해졌습니다.
이게 중요한 점입니다. 좋은 우회는 작품을 손상시키지 않습니다. 손상된다면 방법이 틀린 거예요.
클레이 꽃집은 kids를 빼고 with no people로 바꿔서 해결했습니다. 애초에 클레이 인형이 주인공이라 사람이 필요 없었어요.
프롬프트를 다시 읽어 보면 없어도 되는 단어가 의외로 많습니다.
fine art sculpture documentation photograph, museum catalogue photograph 같은 장르 선언을 앞에 붙이면 도움이 됩니다.
다만 이건 확실한 방법이 아닙니다. 밀랍상 첫 시도에도 갤러리·받침·조명이 다 들어 있었는데 걸렸어요. 보조 수단으로만 쓰세요.
임계값이 다르니까 다른 모델에서는 통과할 수 있습니다. 실제로 저희 아홉 장 중 여덟 장은 다른 모델에서 아무 문제 없이 나왔고요.
다만 이건 판정이 틀렸다고 확신할 때만 쓸 수 있는 방법입니다. 모델을 갈아치우면서 될 때까지 돌리는 건 방법이 아니라 회피예요.
전에 기타줄 진동 영상이 계속 실패했을 때 소리굽쇠로 바꿔서 같은 아이디어를 살린 적이 있습니다. NSFW에도 같은 방법이 통합니다.
"이 개념을 다른 대상으로 표현할 수 있나?"를 물어보세요. 대개는 있고, 종종 원래보다 낫습니다.
이 일을 겪고 나서 생각이 좀 바뀌었습니다. 처음엔 "멀쩡한 걸 왜 막지" 싶었는데, 응답을 뜯어보고 나니 맥락을 모르는 분류기가 보수적으로 판정하는 게 당연하다는 쪽으로 기울었어요.
오탐이 짜증나긴 합니다. 그런데 반대 방향의 실수보다는 이쪽이 낫습니다. 그리고 저희 경우엔 고치고 나서 더 좋아졌으니까 손해도 아니었고요.
여러분도 NSFW로 걸린 경험 있으시면 어떤 프롬프트였는지 알려주세요. 사례가 쌓이면 어떤 단어가 위험한지 목록을 만들 수 있을 것 같습니다 🍠
이 글에서 추측이라고 적은 부분들을 공개된 연구로 확인해 봤습니다. 대부분 이미 문서화된 현상이었고, 필터의 실제 메커니즘까지 밝혀져 있더군요 — CLIP 잠재 공간에서 17개 위험 개념과의 코사인 유사도를 재는 구조입니다.
특히 "kids" 한 단어가 왜 전체 판정을 예민하게 만드는지, 왜 모델마다 결과가 다른지가 설명됐습니다. 자세한 건 후속 글에 적었습니다.
이 글에 두 군데 틀린 곳이 있어 바로잡습니다. 재현 실험을 해보고 알았습니다.
그래서 첫 단계가 하나 늘었습니다 — 일단 두세 번 다시 돌려 보세요. 반복해서 걸릴 때만 원인을 의심하면 됩니다. 자세한 실험 결과는 이 글에 있습니다.