AI

[LLM] Gemini inline tool_code 도구 호출 합성 후처리

jykim23 2026. 7. 10. 09:21
반응형

Gemini inline tool_code 도구 호출 합성 allow-list 후처리

부제: 함수 호출 대신 코드를 뱉는 LLM을 후처리로 붙잡기

챗봇은 LLM에게 도구(함수)를 붙여 준다.
정상이면 LLM이 "이 함수를 이 인자로 불러라"라는 구조화된 호출을 돌려준다.
서버는 그걸 받아 함수를 실행하고 결과를 다시 대화에 넣는다.

그런데 가끔 LLM(Gemini)이 그 약속을 안 지켰다.

함수 대신 코드를 뱉었다

구조화된 호출 대신, 답변 본문에 이런 코드를 그냥 써 버렸다.

<tool_code>
print(calculate_vdot(distance='10K', time='50:00'))
</tool_code>

문제가 두 가지였다.
하나, 이 코드가 사용자 화면에 그대로 노출됐다.
둘, 구조화된 호출이 없으니 서버는 도구를 실행하지 않았다.
사용자는 답 대신 코드 조각을 봤다.

빈도는 낮았다.
전체 응답 8029건 중 5건, 0.062%였다.
다만 특정 조건(짧은 입력에 간단한 계산)에서 짧은 시간에 몰려 터지는 패턴이 있었다.

왜 이러나

원인은 두 갈래로 봤다.
하나는 Gemini가 내장 코드 실행 쪽으로 빠지는 fallback이다.
함수 선언을 붙여 줘도, 조건이 맞으면 native 호출 대신 코드 생성으로 떨어졌다.

다른 하나가 더 고약했다.
한 번 inline으로 나온 코드가 대화 기록에 남으면, 다음 턴에서 LLM이 그걸 보고 따라 했다.
같은 대화 안에서 연속으로 터지던 게 그 증거였다.
LLM이 자기 실수를 학습해 반복하는 셈이다.

이건 우리가 SDK 차원에서 고칠 수 있는 게 아니었다.
그래서 증상을 후처리하기로 했다.

파싱하되, 실행하지 않고 합성한다

핵심 결정은 "코드를 실행하지 않는다"였다.
LLM이 쓴 코드를 그대로 돌리면 임의 코드 실행이라 위험하다.

대신 응답에서 <tool_code>를 파싱해, 함수 이름과 인자만 꺼냈다.
그리고 우리가 실제로 붙여 준 도구 목록(allow-list)에 있는 것만 골라,
제대로 된 도구 호출로 합성했다.
아는 도구가 아니면 버린다. 실행이 아니라 검증된 재구성이다.

동시에 스트리밍 쪽도 막았다.
답이 청크 단위로 흘러가는 중에 그 코드 텍스트가 사용자에게 새어 나가지 않게,
청크에서 걸러 내고 내보냈다.
이미 팀이 UI 지시(a2ui)에서 쓰던 "본문 후처리" 패턴을 도구 호출용으로 넓힌 것이다.

검증은 실제로 그 케이스가 재현되던 대화로 했다.
inline 코드가 화면에 안 나오고, 도구가 정상 실행되는지 확인했다.

정리

  • LLM이 native 함수 호출 대신 본문에 raw 코드를 뱉는 케이스가 낮은 빈도(0.062%)로 있었다
  • 그대로 두면 코드가 사용자에게 노출되고 도구는 실행되지 않는다
  • 코드를 실행하지 않고, 파싱해서 allow-list에 있는 도구만 제대로 된 호출로 합성했다
  • 스트리밍 청크에서도 걸러, 새는 텍스트가 화면에 닿지 않게 했다
  • 한 번 샌 게 기록에 남아 다음 턴이 모방하는 피드백 루프도 함께 끊어야 한다

LLM 제공자를 완전히 믿을 수는 없다.
0.06%라도 사용자에게 코드가 노출되면 안 되는 종류의 실수는, native 출력을 기대하되
새는 케이스를 후처리로 붙잡는다 — 실행이 아니라 검증된 합성으로.

반응형