닭불고기 소개에 닭이 들어갔다고 검사에 걸렸습니다. 조리 단계에는 닭을 쓰는 내용이 있었는데, 재료 목록에서 닭이 빠져 있었습니다. 검사 코드는 그 목록만 보고 소개 문구가 없는 재료를 지어냈다고 판정했습니다.
유튜브 요리 영상을 레시피로 정리하는 앱 VidDish를 만들며 겪은 일입니다. 영상에서 추출한 재료와 조리 단계를 바탕으로 짧은 요리 이름과 설명을 만들고, 추천 카드에 쓰기 전에 검사하도록 해뒀습니다. 당시 개발용 문구 292개 중 67개가 실패했습니다. 닭불고기는 그중 하나였습니다.
실패한 문구를 고치려면 우선 무엇이 틀렸는지 알아야 했습니다. 목록에서 빠진 닭을 소개에서도 빼버리면 검사는 통과할지 몰라도, 닭불고기 설명은 더 이상해집니다.
재료 목록을 정답으로 놓고 있었다
처음 붙인 검사는 단순했습니다. 소개에 나오는 재료를 레시피의 재료 목록에서 찾았습니다. 닭고기와 감자로 만드는 요리 설명에 갑자기 새우가 등장한다면 걸러내려는 것이었습니다.
그런데 재료 목록도 AI가 영상에서 추출한 결과였습니다. 그 앞 단계에서 누락이 생길 수 있었습니다. 죽의 쌀이 목록에는 없고 조리 단계에만 있는 사례도 나왔습니다.
이때 소개 문구를 다시 생성하는 게 맞을까요. 쌀을 언급하지 않는 죽 설명을 받아도 빠진 재료는 돌아오지 않습니다. 추출 과정에서 생긴 문제를 소개 문구의 오류로 세고 있었습니다.
그렇다고 검사 전체를 풀 수는 없었습니다. 실제로 근거 없는 재료를 넣은 문구도 걸러야 했습니다. 실패한 자료를 전부 대조하고, 어떤 조건 때문에 걸렸는지부터 나눠봤습니다.
예외를 여덟 개 더 붙이려다가
검토하던 수정안에는 예외 여덟 가지가 있었습니다. 요리 이름에 들어간 말은 허용하고, 밥과 함께 내라는 표현은 따로 처리하고, 다르게 부르는 재료명도 추가하는 식이었습니다. 대소문자나 복수형을 잘못 읽는 버그 수정도 섞여 있었습니다.
그대로 적용하면 실패가 67개에서 20개로 줄었습니다. 꽤 많이 줄었지만 수정안을 보고 다시 물었습니다.
저런 규칙이 계속 늘어날텐데. 저걸로 충분해?
새 요리에서 다른 표현이 나오면 또 예외를 붙여야 할 것 같았습니다. 허용 범위를 넓히는 것도 조심스러웠습니다. 쌀이나 밀가루가 있으면 떡이라는 표현까지 허용하는 안을 시험했더니, 일부러 잘못된 내용을 넣은 시험에서 놓치는 수가 늘었습니다. 쌀이 있다고 해서 그 요리를 떡이라고 소개해도 되는 것은 아니니까요.
개별 표현을 더 넣기 전에 기준을 고쳤습니다. 재료 목록에서 못 찾았으면 조리 단계에서도 찾아보기로 했습니다. 거기에 근거가 있으면 소개 문구는 통과시키고, 목록에서 빠진 재료가 있다는 메모를 남겼습니다.
닭불고기라면 소개에 닭이 나오는 것은 허용하되, 닭이 빠진 재료 목록은 점검 대상으로 남는 방식입니다. 문구를 고칠 일과 추출 결과를 고칠 일이 비로소 갈렸습니다.
같은 자료를 다시 검사하니 14개가 남았다
기준을 바꾸면서 검사 코드의 버그 네 종류도 고쳤습니다. One-Pot처럼 대문자가 섞이면 한 냄비라는 표현을 다르게 읽던 문제, 복수형과 조리 기법 표현을 잘못 처리하던 문제, 조개살을 일반적인 고기 표현으로 읽던 문제였습니다.
그 뒤 같은 292개를 다시 검사하니 실패는 14개였습니다. 단어를 더 추가하면 두 개를 더 통과시킬 수 있었지만 거기까지 늘리지는 않았습니다. 남은 사유를 기록해두고, 이후 자료에서도 같은 표현이 반복해서 걸리는지 보기로 했습니다.
통과가 늘었으니 놓치는 오류도 확인해야 했습니다. 기존에 통과하던 문구 225개에 지어낸 재료를 넣어봤고, 새 검사도 225개를 모두 잡았습니다. 앞서 넓은 예외를 넣었을 때와 달리 이 시험에서는 검출 수가 줄지 않았습니다.
다만 이 검사가 아는 재료 표현에는 한계가 있습니다. 영어 이름과 설명을 등록된 재료 표현으로 대조하므로, 모르는 재료명으로 지어낸 내용은 놓칠 수 있습니다. 조리 단계 자체가 잘못 추출돼 있어도 통과할 수 있고요.
통과율이 올라갔다는 숫자는 그 범위에서 읽어야 합니다. 이번에는 모델에 문구를 새로 쓰게 하지 않았습니다. 이미 있던 문구를 다른 기준으로 검사한 것이므로, 실패가 줄었다고 모델의 정답률이 올랐다고 할 수는 없습니다.
코드 수정 뒤에도 추천에서 빠져 있던 문구들
검사 코드를 고친 뒤에도 할 일이 남았습니다. 문구마다 생성 당시의 통과·실패 판정이 저장돼 있었고, 추천은 그 값을 읽었습니다. 검사 함수를 수정해도 예전에 실패라고 저장한 값은 그대로였습니다.
기존 문구를 다시 검사해 저장된 판정도 바꿨습니다. 새로 문구를 만들지 않으니 모델을 호출할 필요는 없었습니다. 대신 문구를 만들 때 쓴 재료나 단계가 그사이 바뀐 자료는 제외했습니다. 예전 자료를 보고 쓴 문구를 새 레시피에 그대로 승인할 수는 없으니까요.
어떤 값이 바뀔지 먼저 확인하고 한 건부터 반영했습니다. 나머지를 적용한 뒤 다시 읽어 대조했고, 개발 환경에서 통과 278개·실패 14개를 확인했습니다. 같은 작업을 한 번 더 돌렸을 때는 추가로 바뀌는 항목이 없었습니다.
이렇게 소개 문구를 막던 오탐은 줄였습니다. 그래도 닭불고기의 재료 목록에는 여전히 닭을 채워야 했습니다. 문구가 맞는다고 레시피까지 완전해지는 건 아니었습니다. 그 누락을 고치는 일은 앞선 추출 과정에 남겨뒀습니다.