나만의 RAG Chatbot 만들기 – 5. Agent 만들기
오늘은 챗봇에서 더 나아가서 Agent를 만들어보겠습니다. 이전 강의는 아래 포스팅을 참고해보세요.
Agent란?
여러가지 툴을 활용해서 AI가 자동으로 문제를 해결하는 것을 Agent라고 합니다. 챗봇이 수동적인 처리라면 Agent는 보다 능동적으로 처리합니다

아래 코드는 이제 실제 Chatbot에서 사용할 함수(Tools)을 임의로 설정하고, 이 것을 LLM이 본인이 원하는 함수를 선택해서 답변을 하는 형태로 만들어 보도록 하겠습니다.
import json # 데이터를 주고받을 때 표준 형식인 JSON을 처리합니다.
from openai import AzureOpenAI # Azure에서 제공하는 OpenAI 인터페이스를 사용합니다.
import sys # 시스템 관련 파라미터 제어용입니다.
import io # 입출력 스트림 처리를 위해 가져왔습니다.
from dotenv import load_dotenv # .env 파일에 숨겨둔 API 키를 읽어옵니다.
import os # 운영체제 환경 변수에 접근합니다.
load_dotenv() # .env 파일을 활성화합니다.
ENDPOINT = os.getenv("ENDPOINT") # Azure 엔드포인트 URL을 가져옵니다.
API_KEY = os.getenv("API_KEY") # 보안을 위해 따로 저장한 API 키를 가져옵니다.
API_TYPE = os.getenv("API_TYPE") # API의 유형을 설정합니다.
API_VERSION = os.getenv("API_VERSION") # 사용할 API의 버전(날짜 형식)을 가져옵니다.
# 1. Azure OpenAI 설정: 통신을 위한 클라이언트 객체를 만듭니다.
client = AzureOpenAI(
azure_endpoint=ENDPOINT,
api_key=API_KEY,
api_version=API_VERSION
)
deployment_name = "gpt-4.1" # Azure 포털에서 내가 만든 배포 모델 이름입니다.
# 2. 실제 실행될 함수(Tools) 정의: AI가 필요할 때 호출할 '진짜' 파이썬 함수입니다.
def get_weather(city):
weather_map = {"도쿄": "흐림, 18도", "파리": "맑음, 22도", "뉴욕": "눈, -2도"}
result = weather_map.get(city, f"{city}의 날씨 정보를 찾을 수 없습니다.")
print(f"[시스템 로그] 날씨 조회 중: {city} -> {result}")
return result
def get_exchange_rate(currency_code):
rates = {"JPY": 9.2, "USD": 1340.5, "EUR": 1460.0}
result = rates.get(currency_code.upper(), 1.0)
print(f"[시스템 로그] 환율 조회 중: {currency_code} -> {result}")
return result
# 3. 모델에게 알려줄 도구 정보(Metadata): AI가 읽을 '도구 사용 설명서'입니다.
tools = [
{
"type": "function", # 이 도구의 타입은 함수입니다.
"function": {
"name": "get_weather", # 호출할 함수의 이름입니다.
"description": "특정 도시의 현재 날씨와 온도를 가져옵니다.", # 언제 이 함수를 써야 하는지 AI에게 알려줍니다.
"parameters": { # 함수에 필요한 입력값(인자) 정의입니다.
"type": "object",
"properties": {
"city": {"type": "string", "description": "도시 이름 (예: 도쿄, 파리)"}
},
"required": ["city"], # 이 값은 반드시 있어야 한다는 뜻입니다.
},
},
},
{
"type": "function",
"function": {
"name": "get_exchange_rate",
"description": "원화(KRW) 대비 해당 통화의 환율을 가져옵니다.",
"parameters": {
"type": "object",
"properties": {
"currency_code": {"type": "string", "description": "통화 코드 (예: JPY, USD, EUR)"}
},
"required": ["currency_code"],
},
},
}
]
# 4. 에이전트 실행 루프
def run_travel_agent(user_prompt):
# 대화 기록을 설정합니다. 시스템 역할과 사용자의 질문을 담습니다.
messages = [
{"role": "system", "content": "너는 유능한 여행사 직원이야. 도구를 사용해 정확한 정보를 제공해줘."},
{"role": "user", "content": user_prompt}
]
# 첫 번째 호출: 모델이 사용자의 질문을 분석하고 "어떤 도구가 필요한가?"를 결정합니다.
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
tools=tools, # 위에서 만든 도구 설명서를 같이 보냅니다.
tool_choice="auto" # 모델이 알아서 도구 사용 여부를 결정하게 합니다.
)
response_message = response.choices[0].message # 모델의 첫 번째 응답 메시지입니다.
tool_calls = response_message.tool_calls # 모델이 "이 함수들을 실행해줘"라고 요청한 목록입니다.
# 모델이 도구 사용(Function Calling)을 결정했다면 (tool_calls가 비어있지 않다면)
if tool_calls:
# 모델의 '도구 호출 요청' 메시지를 대화 기록(messages)에 추가합니다.
# 이 단계가 있어야 나중에 모델이 "내가 무엇을 요청했었지?"를 알 수 있습니다.
messages.append(response_message)
# 모델이 요청한 각 도구 호출(tool_call)을 하나씩 꺼냅니다.
for tool_call in tool_calls:
function_name = tool_call.function.name # 호출할 함수의 이름 (예: 'get_weather')
# 모델이 보낸 인자값(JSON 문자열)을 파이썬 딕셔너리로 변환합니다.
function_args = json.loads(tool_call.function.arguments)
# 함수 이름에 따라 실제 파이썬 함수를 매칭하여 실행합니다.
if function_name == "get_weather":
# get_weather 함수를 호출하고 결과를 저장합니다.
function_response = get_weather(function_args.get("city"))
elif function_name == "get_exchange_rate":
# 환율 함수를 호출합니다. 메시지에 넣기 위해 결과값을 문자열(str)로 바꿉니다.
function_response = str(get_exchange_rate(function_args.get("currency_code")))
# [중요] 도구 실행 결과를 대화 기록에 추가합니다.
messages.append({
"tool_call_id": tool_call.id, # 어떤 요청에 대한 결과인지 ID로 매칭합니다.
"role": "tool", # 메시지 역할을 'tool'로 지정합니다.
"name": function_name, # 실행된 함수 이름을 적습니다.
"content": function_response, # 함수의 실제 리턴값(결과)입니다.
})
# 두 번째 호출: 도구 실행 결과가 포함된 전체 메시지를 모델에게 다시 보냅니다.
second_response = client.chat.completions.create(
model=deployment_name,
messages=messages # 질문 + 도구 호출 요청 + 도구 실행 결과가 모두 담긴 리스트입니다.
)
# 모델이 모든 정보를 종합해서 만든 최종 자연어 답변을 반환합니다.
return second_response.choices[0].message.content
# 도구를 쓸 필요가 없는 질문(예: "안녕?")이었다면 첫 번째 응답을 그대로 반환합니다.
return response_message.content
# 5. 테스트 실행: 복합적인 질문을 던져봅니다.
test_prompt = "도쿄 날씨 알려주고, 10,000엔을 환전하면 한화로 얼마인지 계산해줘."
print(f"최종 답변: {run_travel_agent(test_prompt)}")
이를 실행하면 아래처럼 최종 답변이 나옵니다.

최종 실행시 아래와 같은 메시지를 보여줍니다.
@beapple ➜ /workspaces/LLMTest (main) $ /home/codespace/.python/current/bin/python /workspaces/LLMTest/07.agent.py
[시스템 로그] 날씨 조회 중: 도쿄 -> 흐림, 18도
[시스템 로그] 환율 조회 중: JPY -> 9.2
최종 답변: 도쿄의 현재 날씨는 흐림이며, 기온은 18도입니다.
10,000엔을 현재 환율(1엔 = 9.2원)로 환전하면 한화로 약 92,000원이 됩니다. (10,000 x 9.2 = 92,000원)
마지막으로 Streamlit으로 배포하는 것을 알아보겠습니다.
Streamlit 배포
해당 간단하게 만든 파이썬을 Streamlit으로 배포할 수 있습니다.
해당 사이트에 접속하시면 되구요.
그 전에 Codespace에서 커밋을 해서 github로 파일을 옮겨야 합니다.
좌측 3번째에 있는 현재 변경사항이 9인 깃허브 아이콘을 누르시고,
변경내용을 꼭 적어야 반영되니 변경 내용 적고 커밋을 눌러줍니다.

이후 Streamlit으로 이동한다음 메인화면에서 Cloud를 눌러서 배포해보도록 하겠습니다.

간단하게 회원가입 및 github와 연동을 진행하고 우측 상단에 위치한 Create App을 눌러서 앱을 만듭니다.

이 때 가장 좌측에 있는 github를 활용한 앱을 배포하기로 하구요.

오늘 공부한 파이썬 파일을 선택해 줍니다.

deploy를 누르면 최종적으로 배포가 됩니다.
원하는 도메인은 선택해도 되고 아니면 난수로 만들어진 streamlit.app 도메인으로 생성됩니다.
그럼 잘 사용하세요.