기존에 돌던 봇을 다시 만드는 일이었다. 금융 콘텐츠를 수집해 요약해서 메신저로 보내는 봇인데 새로 짜기 전에 그 봇이 실제로 보낸 메시지를 일주일치 전부 읽었다.
Table of contents
Open Table of contents
여섯 종류의 결함
타이어 제조사의 사업 요약이 글로벌 1위 메모리 반도체 기업이라는 문장으로 나간 환각이 있었는데 그 회사와 아무 관계가 없는 내용이다.
같은 날 시가총액이 세 가지 값으로 나온 단위 불일치도 있었는데 억과 조가 섞였고 발행주식수도 표기 단위가 제각각이었다. 영업이익은 단위가 아예 붙지 않은 경우가 있어서 억인지 조인지 원인지를 알 수 없었다.
같은 날 낮과 밤에 같은 종목이 두 번 나간 중복 전송과 그 두 번 사이에 시가총액이 달라진 값 표류도 함께 있었다. 장이 끝난 뒤인데 값이 바뀌었다. 마지막으로 이름 앞부분이 같은 다른 회사가 각각 다른 종목코드로 나간 오식별이 있었다.
하나의 공통 원인
여섯을 늘어놓고 보니 전부 언어 모델이 수치를 읽고 쓰게 한 데서 나왔다. 수집한 원문을 모델에 통째로 넣고 요약과 주요 지표 정리를 함께 시킨 구조라 모델이 본문에서 숫자를 뽑아 다시 쓴다. 그 과정에서 억이 조가 되고 단위가 떨어지고 없는 사실이 붙는다.
종목 식별도 마찬가지였다. 이름으로 매칭하니 앞부분이 같은 다른 회사가 걸렸다. 여섯 가지 증상이 여섯 가지 문제가 아니라 한 결정에서 파생된 것이었다.
경계 기준
새 구현에서는 코드가 할 일과 모델이 할 일을 처음부터 갈라 두었다. 재무 수치의 파싱과 단위 정규화와 포맷, 종목코드로 하는 식별, 중복 판정, 시점 판정은 코드가 한다. 핵심 요약과 질의응답 정리와 한줄평은 모델이 한다.
기준 자체는 단순하다. 틀렸는지 아닌지를 기계적으로 판정할 수 있는 일이면 코드가 한다. 시가총액이 3조인지 3만억인지는 판정할 수 있고 요약이 좋은지는 판정할 수 없다.
이 경계는 취향이 아니라 여섯 결함이 만들어 준 실증적 근거다. 모델을 안 믿어서가 아니라 저 여섯이 전부 판정 가능한 영역에서 났기 때문이다.
원문 보관의 근거
중복 전송과 값 표류는 다른 결론도 하나 만들어 줬다. 원문을 저장해야 한다는 것이다.
잘못 나간 내용을 고치려면 그 요약의 바탕이 된 원문이 필요하다. 원문이 있으면 재요약해서 정정본을 보내면 되지만 없으면 다시 수집해야 하고 그 사이 원본이 바뀌었으면 다시 수집한 것도 그때와 다르다. 기존 봇은 요약만 저장하고 원문을 버려서 값 표류가 났을 때 어느 쪽이 맞는지 확인할 방법이 없었다.
제목에 굳은 내부 표기
부수적으로 하나 더 봤는데 메시지 제목이 종목명과 실적 브리핑 뒤에 최종 포맷이라는 문구를 달고 나가고 있었다.
그것은 개발 중에 여러 포맷을 시험하면서 붙인 내부 표기인데 그대로 굳어서 몇 달째 받는 쪽에 나가고 있었다. 받는 쪽에는 아무 의미가 없는 문구라 새 구현에서 뺐다.
표본과 전수의 차이
이 조사에서 내가 한 실수도 적어 둔다. 처음에 메시지 5건만 열어 보고 결함을 정리한 뒤 기록에 실측이라고 적었다가 지적을 받았다. 5건은 표본이지 실측이 아니다.
일주일 전 구간을 다시 읽으니 여섯 가지 중 셋이 그때 처음 드러났다. 중복 전송과 값 표류와 오식별은 5건 안에 없었다. 하루치 안에서는 중복이 안 보이고 값 표류는 두 시점을 비교해야 보이며 오식별은 다른 종목이 같이 나와야 보인다. 표본으로는 구조상 안 보이는 결함이 있고 그런 것들이 대개 더 중요하다.
정리
- 언어 모델에 수치를 읽고 쓰게 하면 환각과 단위 불일치와 단위 붕괴가 난다
- 이름으로 대상을 식별하게 하면 오식별이 나므로 식별자로 조회한다
- 여러 증상이 한 결정에서 파생된 것인지 먼저 본다
- 틀렸는지 기계적으로 판정 가능하면 코드가 한다
- 수치와 식별자와 중복 판정은 코드가 하고 요약과 평은 모델이 한다
- 원문을 저장한다. 없으면 잘못 나간 것을 정정할 수 없다
- 개발 중 표기가 굳어 나가고 있지 않은지 본다
- 표본으로 구조상 안 보이는 결함이 있다