LangChain 챗봇5장 · LLM 외부 도구 연동4 / 21← 이전목차다음 →MetaContents

5장. LLM 외부 도구 연동

Tool Calling 의 흐름

식당에서 손님이 주문하면, 직원은 직접 요리하지 않고 주문서에 "김치찌개 1, 공깃밥 2"라고 적어 주방에 넘깁니다. 주방이 요리를 내주면 직원이 그것을 손님 상에 올리며 한마디 덧붙입니다. Tool Calling 에서 모델은 주문서를 쓰는 직원입니다. 모델은 도구를 실행하지 않고, "이 도구를 이 값으로 불러 달라"는 주문서(tool_calls)만 돌려줍니다.

질문과 도구 목록 보내기, tool_calls 받기, 우리 코드가 실행하기, ToolMessage 로 돌려주고 최종 답 받기의 네 걸음을 이은 흐름도

네 상자는 질문 하나에 일어나는 차례입니다. 질문과 도구 목록을 모델에 보내면(1), 모델이 글 답 대신 도구 호출 요청을 돌려주고(2), 우리 코드가 그 요청대로 함수를 실행해(3), 결과를 ToolMessage 로 돌려주며 모델을 한 번 더 부르면 최종 답이 나옵니다(4). 모델을 두 번 부른다는 점을 기억해 두세요. 여기서 주문서가 tool_calls, 주방이 우리 코드의 함수, 상에 올린 요리가 ToolMessage 입니다. 비유와 다른 점은, 주문서를 받은 주방은 늘 요리를 하지만 우리 코드는 요청을 검사해서 이상한 요청(없는 도구, 위험한 값)은 실행하지 않을 수 있다는 것입니다.

누가 무엇을 하나

하는 일맡는 쪽이 장에서 쓰는 것
도구 만들기(이름, 설명, 인자)우리 코드@tool
도구 목록 알려 주기우리 코드model.bind_tools([...])
부를 도구와 인자 고르기모델AIMessage.tool_calls
도구 실행하기우리 코드도구.invoke(...)
결과 돌려주기우리 코드ToolMessage
결과를 읽고 답 쓰기모델둘째 model.invoke

짧은 예시

모델이 돌려줄 법한 "도구 호출 요청"을 손으로 만들어, 그 안에 무엇이 들어 있는지 봅니다. 모델은 부르지 않습니다.

Python
from langchain_core.messages import AIMessage

# 모델이 "calc_price 를 이 값으로 불러 달라"고 답했다고 보고 손으로 만든 메시지
ai = AIMessage(
    content="",                       # 도구를 부를 때는 글 답이 비어 있는 일이 많다
    tool_calls=[{"name": "calc_price", "args": {"code": "P01", "adults": 2, "children": 1}, "id": "call_1"}],
)
print("글 답:", repr(ai.content))
for call in ai.tool_calls:
    print("도구:", call["name"], "| 인자:", call["args"], "| 요청 번호:", call["id"], "| 종류:", call["type"])
출력
글 답: ''
도구: calc_price | 인자: {'code': 'P01', 'adults': 2, 'children': 1} | 요청 번호: call_1 | 종류: tool_call

content 는 빈 글자열이고, 할 일은 tool_calls 에 들어 있습니다. 요청 하나에 도구 이름, 인자 사전, 요청 번호가 있고, LangChain 이 type: "tool_call" 을 붙여 줍니다. 진짜 모델이 돌려주는 id 는 call_ 로 시작하는 긴 글자로, 부를 때마다 바뀝니다.

코드가 의미하는 것

이 코드는 식당 직원이 쓴 주문서 한 장을 손으로 만들어 펼쳐 보는 것입니다. 주문서를 만들고, 글 답 칸을 보고, 주문 줄마다 무엇이 적혔는지 읽는 세 동작입니다.

코드하는 일챗봇에서 뜻하는 것
AIMessage(content="", tool_calls=[...])도구 호출 요청이 든 모델의 답을 만든다진짜 모델이 도구를 부르기로 했을 때 돌려주는 메시지와 같은 꼴입니다. 실습 2에서도 이렇게 손으로 만들어 실행기를 시험합니다
{"name": ..., "args": ..., "id": ...}요청 하나에 도구 이름, 인자, 요청 번호를 적는다주문서의 한 줄입니다. 모델이 고르는 것은 이 세 칸뿐이고, 함수를 실행하지는 않습니다
repr(ai.content)글 답을 따옴표째 찍는다빈 글자열이 눈에 보이게 하려는 것입니다. 손님에게 보낼 말이 아직 없다는 뜻입니다
call["type"]LangChain 이 붙인 종류 표시를 읽는다우리가 적지 않은 tool_call 이 붙어 있습니다. LangChain 이 요청을 정해진 꼴로 맞춰 준 것입니다

결과에서 읽을 것은 두 가지입니다.

  • 글 답이 비었습니다. '' 은 모델이 "아직 답할 수 없고, 도구 결과가 먼저 필요하다"고 말한 것과 같습니다. 이 메시지를 받은 우리 코드가 다음 걸음을 이어 가야 합니다.
  • 요청 번호가 짝을 맞출 열쇠입니다. call_1 은 뒤의 "ToolMessage 로 결과 돌려주기" 절에서 결과 메시지에 그대로 옮겨 적힙니다.

주의할 점

  • tool_calls 를 받았다고 끝난 것이 아닙니다. 우리 코드가 실행하고 결과를 돌려주지 않으면 손님은 답을 받지 못합니다.
  • 모델은 도구 이름과 인자를 틀리게 고를 수도 있습니다. 없는 도구 이름이나 잘못된 자료형의 인자가 오면 오류를 내지 말고 "오류: …"를 결과로 돌려주어 모델이 고쳐 부르게 합니다. 실습 2에서 해 봅니다.
← 이전 절5장 · 모델에게 도구가 필요한 까닭다음 절 →5장 · @tool 로 도구 만들기