ReAct(Reasoning + Acting)
Reasoning + Acting - 생각한 후 도구를 사용하고, 결과를 관찰하는 순환 구조
Contents
생각(Thought)과 행동(Action), 관찰(Observation)을 순환하며 외부 도구로 추론을 보강하는 에이전트 패턴이다.
개념
ReAct는 추론(Reasoning)과 행동(Acting)을 결합한 에이전트 프레임워크이다. 생각한 후 외부 도구를 사용하고, 결과를 관찰하는 순환 구조를 가진다.
동작 구조
- Thought -- 현재 상황을 분석하고 다음 단계를 계획한다
- Action -- 외부 도구를 호출한다 (검색, 계산 등)
- Observation -- 행동 결과를 수신한다
- 목표를 달성할 때까지 1-3 단계를 반복한다
예시
질문: "롯데월드타워의 높이는?"
Thought: 롯데월드타워 높이를 알아야 함. 검색 필요. Action: [Search] "롯데월드타워 높이" Observation: 554.5미터
Thought: 정보를 얻었음. 답변 가능. Answer: 554.5미터
다단계 추론 예시
질문: "한국에서 가장 높은 건물과 두 번째로 높은 건물의 높이 차이는?"
Thought: 먼저 가장 높은 건물을 알아야 한다. Action: [Search] "한국 가장 높은 건물" Observation: 롯데월드타워 (554.5m)
Thought: 두 번째로 높은 건물도 알아야 한다. Action: [Search] "한국 두 번째로 높은 건물" Observation: 해운대 LCT 더샵 (411.6m)
Thought: 이제 차이를 계산할 수 있다. Action: [Calculate] 554.5 - 411.6 Observation: 142.9
Answer: 142.9미터
장점
| 장점 | 설명 |
|---|---|
| 검증 가능성 | 어떤 도구를 사용했는지 투명 |
| 최신 정보 | 검색으로 실시간 정보 접근 |
| 투명성 | 추론 과정이 명확 |
| 확장성 | 새로운 도구 쉽게 추가 |
Chain of Thought(CoT)만으로는 해결할 수 없는 문제
질문: "오늘 서울 날씨는?"
CoT만 사용: Thought: 서울은 한국의 수도이고... Answer: 서울은 사계절이 뚜렷하여... (할루시네이션)
ReAct 사용: Thought: 실시간 날씨 정보가 필요하다 Action: [Search] "오늘 서울 날씨" Observation: 맑음, 기온 -2°C Answer: 오늘 서울은 맑고, 기온은 영하 2도이다.
성능
ReAct는 단독으로 항상 최고는 아니다. 추론 위주인 HotpotQA에서는 CoT가 더 낫고, ReAct는 CoT Self-Consistency(CoT-SC)와 결합할 때 가장 좋다. 반면 사실 검증 벤치마크인 FEVER에서는 ReAct가 CoT를 앞선다. 아래는 ReAct 논문이 보고한 PaLM-540B 기준 수치다.
| 벤치마크 | CoT | ReAct | ReAct + CoT-SC |
|---|---|---|---|
| HotpotQA (EM, Exact Match) | 29.4 | 27.4 | 35.1 |
| FEVER (정확도) | 56.3 | 60.9 | 64.6 |
벤치마크마다 우열이 갈린다. 외부 관찰(ReAct)과 내부 추론(CoT)을 결합하면 양쪽 약점을 보완한다.
사용 가능한 도구들
| 도구 | 용도 | 예시 |
|---|---|---|
| Search | 정보 검색 | 최신 뉴스, 사실 확인 |
| Calculate | 수학 계산 | 복잡한 연산 |
| Wikipedia | 백과사전 조회 | 개념 설명 |
| Code | 코드 실행 | 프로그래밍 작업 |
| Calendar | 날짜 계산 | 요일, 기간 계산 |
한계
-
복잡한 다단계 도구 사용 시 실패 가능
- 도구 사용 순서가 복잡해지면 오류 증가
-
잘못된 경로에서 회복 어려움
- 한 번 잘못된 방향으로 가면 되돌리기 어려움
-
도구 의존성
- 적절한 도구가 없으면 해결 불가
Reflexion과의 결합
ReAct의 한계를 극복하기 위해 Reflexion과 결합할 수 있다:
1차 시도 Thought: 검색하자 Action: [Search] "잘못된 검색어" Observation: 관련 없는 결과 -- 실패
Reflexion: "검색어가 너무 모호했다. 더 구체적으로 검색해야 한다."
2차 시도 Thought: 더 구체적인 검색어 사용 Action: [Search] "구체적인 검색어" Observation: 정확한 결과 -- 성공
구현 패턴
아래 react_loop 함수는 ReAct의 Thought-Action-Observation 순환 구조를 구현한 것이다. max_iterations 파라미터는 무한 루프를 방지하기 위한 최대 반복 횟수를 지정하며, 기본값 5는 대부분의 다단계 추론 문제를 처리하기에 충분하다. 각 반복에서 LLM이 사고(Thought)를 생성하고, 행동(Action)을 결정하면 해당 도구([Search], [Calculate] 등)를 실행한다. 그 관찰 결과(Observation)를 context에 누적하고, 목표를 달성하면 최종 답변을 반환한다.
def react_loop(question, max_iterations=5):
context = f"Question: {question}\n"
for i in range(max_iterations):
# Thought 생성
thought = llm.generate(context + "Thought:")
context += f"Thought: {thought}\n"
# Action 결정
action = llm.generate(context + "Action:")
if action.startswith("[Search]"):
result = search(action.query)
elif action.startswith("[Calculate]"):
result = calculate(action.expression)
else:
break
context += f"Action: {action}\n"
context += f"Observation: {result}\n"
# 최종 답변 생성
answer = llm.generate(context + "Answer:")
return answer관련 개념
- Chain of Thought (CoT): 기반 기술 (추론만)
- Reflexion: 실패 복구 추가
- LATS: 트리 탐색 결합
- Toolformer: 도구 사용 자동 학습
정리
ReAct는 Thought-Action-Observation을 순환하며 외부 도구로 추론을 보강하는 패턴이다. 추론만으로는 메울 수 없는 실시간 정보와 사실 검증을 도구 호출로 채우고, 어떤 도구를 썼는지 과정이 드러나 검증이 쉽다. 다만 도구 사용 순서가 복잡해지면 실패하고, 잘못된 경로에서 회복이 어렵다. 추론 위주 문제는 CoT가 낫고, 사실 검증이나 최신 정보가 필요한 문제에서 ReAct의 이점이 크다. 실패 복구가 필요하면 Reflexion, 탐색이 필요하면 LATS와 결합하는 식으로 보강한다.