게이트웨이를 지우고 배선을 고쳤다
이틀 전에 세운 게이트웨이가 요리 질문에까지 증시 개장일을 붙이고 있었다. 4월에 제지당한 패턴을 그대로 반복했고, 지우고 나니 채팅 품질 문제의 대부분은 모델이 아니라 조용히 무시되는 설정이었다
집에 둔 GPU 장비는 vLLM으로 로컬 모델을 서빙하고, 자동매매 봇과 지인용 채팅 UI가 그 위에 붙어 있다. 이틀 전에 서버 앞에 게이트웨이를 하나 세웠는데, 채팅을 붙이고 받은 첫 평가가 품질이 못 쓸 수준이라는 것이었다. 모델이 나쁜 건지 사이에 낀 것들이 나쁜 건지부터 갈라야 했다.
하려던 것
8월 17일에 서버 앞에 게이트웨이를 하나 세웠다. 8002 포트에서 검색 왕복을 서버가 대신 처리하고, 날짜와 휴장일과 근거 강제 규칙을 프롬프트에 끼워 넣는다. 자동매매 봇이 편하게 부르라고 만든 것이다.
다음 날 지인용 채팅 UI를 그 위에 붙였다. 첫 평가는 “품질은 확실히 못 쓸 수준이다. 어려운 것도 아닌데. 속도는 빠르다”였다.
어떻게 시켰나
모델 탓을 하기 전에 배선을 의심했다.
main.py에 의존성이 엄청나게 많은 거 아냐? 이것 때문에 이상하게 동작하는 거 아냐? 원래 이런 식으로 게이트웨이가 조정하는 게 맞아?
파 보니 도메인 규칙이 모든 요청에 붙고 있었다. 요리 질문에도, 여행 질문에도 “오늘 한국 증시는 정규 개장일이다”가 들어갔다. 다음 날 아침에 한 마디로 정리했다. “게이트웨이도 없애. 원래 안 쓴다며.” 생성 8월 17일 오후 2시, 제거 8월 19일 오후 1시. 수명 이틀이었다.
4월에 똑같은 자리에서 제지당했다. 10화에서 서버 앞에 범용 엔드포인트를 만들려던 걸 끊고 “표준 인터페이스 위에 내 스키마를 얹지 마라”고 적어 뒀다. 넉 달 만에 같은 걸 다시 만들었고, 이번에는 내가 아니라 에이전트가 제안했고, 나는 승인했다.
게이트웨이가 남긴 건 기술 교훈 셋이다. 스트리밍에서 청크를 모았다 내보내면 첫 토큰이 6.2초, 즉시 흘리고 도구 호출 델타만 삼키면 0.22초. 검색 왕복 중에는 나가는 바이트가 없어 Cloudflare 터널의 100초 유휴 타임아웃에 걸리므로 SSE keepalive가 필요하다. 검색 옵션은 tools에 넣는 게 아니라 OpenAI 규격의 web_search_options다.
어디서 막혔나
게이트웨이를 빼도 채팅 품질이 돌아오지 않았다. 이번에는 Open WebUI 쪽이었다. 실측으로 확인한 함정들의 공통점은 틀렸다고 알려 주지 않고 조용히 무시된다는 것이었다.
| 함정 | 증상 |
|---|---|
| 컨테이너 기본 TZ가 UTC | 시각이 9시간 어긋남 |
chat_template_kwargs가 허용 목록 밖 | 띵킹 설정이 조용히 버려짐 |
webSearch를 settings.ui에 넣음 | 무시됨. settings 루트여야 작동 |
| 설정이 DB에 영구 저장 | env를 바꿔도 첫 부팅 값이 이김 |
| 모델 파라미터가 두 번 적용 | 요청 단위 오버라이드를 덮어씀 |
:main 이미지 태그 | 재시작마다 프론트가 바뀜 |
진단 실패도 하나 있었다. “이 모델엔 띵킹이 없다”고 결론 냈는데, vLLM이 델타를 reasoning_content가 아니라 reasoning 키로 보내고 있었다. 엉뚱한 키를 보고 없다고 한 것이다.
어떻게 풀었나
실패한 대화를 하나씩 원인별로 분류시켰다. 결론은 “대부분 모델이 아니라 배선”이었다. 사실 질문에 거절한 사례는 검색 토글이 꺼져 있었고, 날짜 오답은 TZ였고, 띵킹 없음은 키 이름이었다.
Open WebUI를 v0.11.0으로 고정하고, 날짜를 시스템 프롬프트에 주입하고, 시스템 프롬프트 정본을 한 곳에 두고, 검색을 상시로 켰다. 서버는 다시 순수 모델 서빙만 남았다. 8000 포트 하나, OpenAI 호환 API 하나.
배운 점
- 조용히 무시되는 설정이 틀린 설정보다 나쁘다. 틀린 설정은 에러를 준다. 무시되는 설정은 며칠 뒤 “품질이 나쁘다”로 나타난다.
- 래퍼를 두지 않는다는 기준은 두 번째로 확인됐다. 4월에 적었는데도 반복했다. 문서에 적어도 반복된다. 적혀 있으니 이번엔 이틀 만에 끝났다.
- 품질 불만은 배선부터 본다. 모델을 바꾸기 전에 TZ, 설정 키 이름, 검색 토글을 확인한다. 이번엔 전부 배선이었다.
- 설정을 넣었으면 반영됐는지 응답으로 확인한다. 띵킹 설정이 들어갔는지는 추론 텍스트 길이가 0인지로 안다.
- 에이전트가 “편하라고” 만드는 중간 계층은 승인 전에 “그래서 뭐가 좋아지는데”를 묻는다. 10화의 결론을 이번에도 썼어야 했다.