소프트웨어 엔지니어에서 AI 엔지니어로 - 파트 3: 도움의 손길 주기
요약
LLM이 외부 도구(Tools)를 사용하여 물리적 행동을 수행하는 원리와 구현 방법을 설명합니다. 모델이 함수 호출을 통해 계산이나 데이터 접근을 수행하는 과정과 효과적인 도구 사용을 위한 Docstring 작성법을 다룹니다.
핵심 포인트
- 모델은 텍스트 예측 모델일 뿐, 도구를 통해 외부 세계와 상호작용함
- 도구 사용은 모델이 JSON 형태의 함수 호출을 생성하고 엔지니어가 이를 실행하는 과정
- Docstring은 모델이 도구를 선택하는 기준이 되므로 '무엇'과 '언제'를 명확히 기술해야 함
- 도구 결과는 컨텍스트 윈도우에 포함되어 모델의 추가 추론에 활용됨
우리가 살펴본 바와 같이, 모델은 개념적으로 매우 단순합니다. 입력 메시지 목록이 들어가면 모델은 출력 메시지를 형성하기 위해 다음 토큰 (token)을 반복적으로 예측합니다. 모델은 인터넷이나 사용자의 데이터베이스, 또는 Slack에 접속할 수 없습니다. 또한 산술 연산을 신뢰성 있게 수행하거나 (민망한 예시가 곧 나옵니다) 'strawberry'에 포함된 'r'의 개수를 알려줄 수도 없습니다. 파트 1에서 언급했듯이, 모델은 글자를 보는 것이 아니라 오직 토큰 ID (token IDs)만을 보기 때문입니다.
그런 의미에서 모델은 몸이 없는 뇌와 같습니다. 문제를 통해 추론하고, 취해야 할 단계를 설명하며, 심지어 셰익스피어의 모든 작품을 암송할 수도 있습니다. 하지만 몸이 없다면 모델은 어떤 행동도 수행할 수 없습니다. 여기서 **도구 (tools)**가 등장하며, 이를 만드는 과정은 일반적인 소프트웨어 엔지니어링 (software engineering)과 매우 유사합니다.
도구의 실제 정체
도구는 프로그래밍 언어의 함수 (functions) 또는 메서드 (methods)일 뿐입니다. 도구 사용이 내부적으로 어떻게 작동하는지는 모델에 따라 다르지만, 개념적으로 살펴보겠습니다. 이는 모델이 사용할 수 있는 도구 목록(catalog)에서 시작되며, 종종 JSON 리스트 형태로 제공됩니다. API에서는 이 목록을 별도의 tools 파라미터로 전달하며, 제공업체(provider)가 이를 대신 주입해 줍니다:
[
{
"name": "multiply",
...
만약 모델이 도구를 사용하기로 결정하면, 그 출력 메시지는 2번째 기사에서 보았던 것과 같은 구조화된 메시지가 됩니다:
{
"name": "multiply",
"arguments": {
...
AI 엔지니어로서 당신의 역할은 이러한 출력을 받아 실제로 동작을 수행하는 (Python) 함수에 전달하는 것입니다. 그런 다음 구조화된 메시지로 응답합니다:
Tool result (multiply):
{
...
이제 도구 결과는 모델의 컨텍스트 윈도우 (context window)의 일부가 되며, 따라서 추가적인 추론을 위해 사용될 수 있습니다.
그렇다면 모델은 어떻게 이를 수행하는 법을 배웠을까요? 모델은 방대한 양의 도구 사용 기록 (tool-use transcripts)을 통해 학습되었으므로, 도구를 요청하고 결과를 다시 읽는 것은 모델이 이미 여러 번 본 패턴입니다. 당신의 도구 목록은 가변적인 부분이며, 말하자면 런타임 설정 (runtime configuration)입니다. 이제 실제 사례를 살펴보겠습니다.
PayIQ의 첫 번째 도구 도입
결제 운영 (Payment operations)에는 결정론적인 산술 (deterministic arithmetic)이 필요하지만, 모델은 신뢰할 수 있는 계산기가 아닙니다. app/tools.py를 생성하세요 (그리고 도구를 임포트할 수 있도록 빈 app/__init__.py 파일도 생성합니다). 우리는 환불 비용을 계산하는 도구를 만들 것입니다.
from langchain_core.tools import tool
@tool
...
Docstring (독스트링)은 어떤 함수를 사용할지 결정하는 프로그래머들에게 항상 중요한 지침이었으며, 이제는 도구 사이에서 선택을 내리는 모델에게도 동일한 역할을 수행합니다. 그리고 모델은 실제로 문서를 읽기 때문에, docstring은 그 어느 때보다 중요하다고 할 수 있습니다.
도구의 docstring을 작성하기 위한 세 가지 팁:
-
무엇(what)뿐만 아니라 언제(when)를 말하세요. "사용자가 (a)... 그리고 (b)...를 제공할 때마다 이것을 사용하세요" — 이것이 바로 모델이 도구 사이에서 선택할 수 있도록 돕는 라우팅 로직 (routing logic)입니다. 계산 내용만을 설명하는 docstring은 '언제' 사용해야 하는지를 운에 맡기게 됩니다.
-
경계(boundaries)를 설정하세요. "수수료 구조를 직접 추측하지 마세요"라는 문구는 도구 정의 전체에서 가장 중요한 로직일 수 있습니다. 수수료 구조를 환각 (hallucinating)하는 것은 계산에 큰 영향을 미칩니다. 또 다른 예로는 사용자가 더 나은 답변을 계속 요구하더라도 비용을 과소평가하지 말라고 모델에게 명시적으로 지시하는 것입니다. 이러한 경계가 없는 어시스턴트들은 실제로 뉴스 헤드라인을 장식하기도 했습니다. 한 자동차 대리점의 챗봇은 설득당해 Chevy Tahoe를 1달러에 팔기로 "동의"했으며, Air Canada는 챗봇이 임의로 만들어낸 환불 정책에 대해 법적 책임을 지게 되었습니다. 경계는 중요합니다.
-
한계에 대해 솔직해지세요. 모든 로직에는 가정이 포함되어 있습니다. 예를 들어, 우리의 간단한 환불 도구는 유로(euro)를 가정하며 여러 통화가 포함된 국가 간 결제는 고려하지 않습니다. 이러한 한계를 명시하는 것은 모델이 계산 결과를 과도하게 신뢰하는 것을 방지하기 때문에 유용합니다. 이러한 한계 사항들은 종종 출력 결과와 함께 사용자에게도 전달됩니다.
우리의 새로운 calculate_refund_cost 도구를 테스트해 봅시다. 방금 작성한 도구를 임포트하고 bind_tools를 사용하여 모델에 바인딩하는 03_tool_manual.py를 생성하세요:
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from app.tools import calculate_refund_cost
...
그러면 다음과 같은 결과를 볼 수 있습니다 (가독성을 위해 긴 텍스트는 생략했습니다):
$ python3 03_tool_manual.py
AIMessage(
...
이 출력은 질문에 대한 답변이 아닙니다. 도구 호출 요청 (tool request)입니다. 애플리케이션 로직은 tool_calls가 설정되어 있는지 확인하고, 도구를 호출한 다음, 그 결과를 다시 모델에 전달하여 대화를 재개해야 합니다. tool_calls는 리스트(list)라는 점에 유의하세요. 모델은 한 번의 턴(turn)에서 여러 개의 도구를 요청할 수 있으므로, 첫 번째 항목만 가져오는 대신 항상 루프(loop)를 돌며 처리해야 합니다.
아래의 스니펫 03_tool_manual_2.py는 모델과 두 번의 라운드를 진행합니다. 먼저 질문을 전달하면 모델이 도구 호출 요청으로 응답하기로 결정합니다. 그다음, 도구 실행 결과로 응답하면 모델이 최종 답변을 제공합니다.
from dotenv import load_dotenv
from langchain.chat_models import init_chat_model
from langchain_core.messages import ToolMessage
...
전문가 팁: 만약 도구에서 예외(exception)가 발생한다면, 해당 예외가 그대로 밖으로 새어 나가게 두지 마세요. 예외를 포착(catch)하여 에러 텍스트를 ToolMessage의 내용(content)으로 다시 보내세요. 그러면 모델은 인자(arguments)를 수정하거나 사용자에게 문제를 설명할 수 있지만, 처리되지 않은 예외는 단순히 해당 턴을 종료시켜 버립니다.
결과는 다음과 같습니다:
$ python3 03_tool_manual_2.py
Here's the breakdown for a full refund on the €480 charge
...
우리의 calculate_refund_cost 도구는 간단한 예시일 뿐이지만, 이러한 도구 사용이 얼마나 강력할 수 있는지 확인하셨기를 바랍니다. 인터넷을 검색하거나, 데이터베이스에서 데이터를 선택하거나, 심지어 이메일을 보내거나 큐(queue)에 메시지를 쓰는 도구를 만들 수도 있습니다. 일반적인 Python 코드로 할 수 있는 모든 것을 이제 모델과 통합할 수 있습니다. 도구 사용은 이 두 세계를 잇는 통합 지점(integration point)입니다.
다음 두 개의 기사에서는 고급 도구 카테고리인 RAG를 통한 지식 검색(knowledge retrieval)과 MCP를 통한 API 통합(API integration)을 깊이 있게 다룹니다. 이러한 세 글자 약어들에 대해 들어보셨을 수도 있는데, 그것들이 실제로 무엇을 의미하는지 배워보겠습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기