01. ReAct 패턴 직접 구현
개요
이번 세션에서는 프레임워크나 라이브러리 없이 순수 Python만으로 ReAct (Reasoning + Acting) 패턴을 직접 구현합니다. 이를 통해 AI 에이전트가 내부적으로 어떻게 작동하는지 정확히 이해할 수 있습니다.
ReAct란?
ReAct는 LLM이 다음을 번갈아 수행하는 패턴입니다:
- Thought - 다음에 무엇을 할지 추론
- Action - 정보를 얻기 위해 도구 호출
- Observation - 결과 수신 및 처리
핵심 개념
에이전트 루프
# ReAct 루프 의사코드
while not done:
response = llm.generate(messages)
if "Final Answer" in response:
return parse_final_answer(response)
action = parse_action(response)
observation = execute_tool(action)
messages.append(observation)시스템 프롬프트 설계
시스템 프롬프트는 매우 중요합니다—LLM에게 응답 형식을 정확히 알려줍니다:
당신은 도구를 사용할 수 있는 AI 에이전트입니다.
사용 가능한 도구:
1. calculate[expression] - 수학 계산 수행
2. search[query] - 정보 검색
응답 형식:
Thought: [추론 과정]
Action: [도구_이름][인자]정규식 파싱
정규식을 사용하여 LLM의 자유 형식 텍스트 출력에서 구조화된 정보를 추출합니다:
import re
def parse_action(text):
pattern = r"Action:\s*(\w+)\[(.+?)\]"
match = re.search(pattern, text)
if match:
return match.group(1), match.group(2)
return None실습
노트북에서 다음을 수행합니다:
- 도구 정의 -
calculate와search함수 생성 - 시스템 프롬프트 설계 - LLM을 위한 지시사항 작성
- 파서 구현 - LLM 출력에서 액션 추출
- 에이전트 클래스 구축 -
ReActAgent로 모두 통합 - 테스트 & 디버깅 - 다양한 쿼리 실행 및 동작 분석
이 접근법의 한계
⚠️
이 기본 구현에는 다음 세션에서 해결할 한계점들이 있습니다.
| 문제 | 설명 |
|---|---|
| 취약한 파싱 | LLM 출력이 달라지면 정규식이 실패 |
| 타입 안전성 없음 | 인자가 검증되지 않음 |
| 에러 처리 | 도구 실패를 우아하게 처리하지 못함 |
다음 단계
세션 2: Tool Calling에서 다음을 사용하여 이러한 문제를 해결합니다:
- Pydantic으로 타입 안전 스키마
- OpenAI Function Calling으로 구조화된 출력
- 적절한 에러 처리