Reflexion ๋ ผ๋ฌธ ๋ฆฌ๋ทฐ (Language agents with verbal reinforcement learning)
Reflexion: Language Agents with Verbal Reinforcement Learning
ํด๋น ๋ ผ๋ฌธ์ NeurIPS 2023์์ ๋ฐํ๋ ๋ ผ๋ฌธ์ผ๋ก 2025.02.16 ๊ธฐ์ค 1,108ํ ์ธ์ฉ๋ ๋ ผ๋ฌธ์ ๋๋ค. ์ต๊ทผ ๊ธฐ์ ์ฐ๊ณ ํด์ปคํค ํ๋ก์ ํธ์์ Agent ๊ธฐ๋ฅ ๊ตฌํ์ ๋งก๊ฒ ๋์๋๋ฐ, ๊ธฐ์ ์ฐ๊ณ ํน์ฑ ์ Fine-Tuning์ด ๋ถ๊ฐ๋ฅํ๊ณ API๋ง ์ฌ์ฉ์ด ๊ฐ๋ฅํ์ต๋๋ค. ์ด๋ฌํ ์ ํ๋ ํ๊ฒฝ์์ Agent์ ์๋ต ์ฑ๋ฅ์ ์ต๋๋ก ๋์ด์ฌ๋ฆด ๋ฐฉ๋ฒ์ ์ฐพ๋ ์ค, Reflexion ๋ ผ๋ฌธ์ ์ ํ๊ฒ ๋์์ต๋๋ค.
๋ฐฐ๊ฒฝ
์ต๊ทผ ReAct, SayCan, Toolformer๋ฑ ๋ค์ํ Agent ๋ฐฉ๋ฒ๋ก ์ด ๋์ค๋ฉด์ ์์จ ์์ฌ๊ฒฐ์ ์์ด์ ํธ์ ํ์ฉ ๊ฐ๋ฅ์ฑ์ด ๋งค์ฐ ๋์์ก์ต๋๋ค.
ํ์ง๋ง ์ด๋ฌํ ์์ฌ๊ฒฐ์ ์์ด์ ํธ๋ ๋งค์ฐ ํฐ ๋ชจ๋ธ๊ณผ ๋ฐฉ๋ํ ํ๋ผ๋ฏธํฐ ์๋ฅผ ํ์ฉํ๊ธฐ ๋๋ฌธ์ ์ ํต์ ์ธ ๊ฐํํ์ต ๋ฐฉ๋ฒ์ ํ์ฉํ๊ธฐ์๋ ๋งค์ฐ ๋ง์ ๋น์ฉ๊ณผ ์ด๋ ค์์ด ์์ต๋๋ค.
Reflexion
๋ฐ๋ผ์ ๋
ผ๋ฌธ์ ์ ์๋ Reflexion์ด๋ผ๋ ์ธ์ด์ ๊ฐํ ๋ฐฉ๋ฒ๋ก ์ ์ ์ํ์์ต๋๋ค.
์ด๋ ์์ด์ ํธ๊ฐ ํ๊ฒฝ์ ํตํด ์ป์ ํผ๋๋ฐฑ(์ซ์ ํน์ ํ
์คํธ)์ ํ
์คํธ ์์ฝ ํํ์ ์ธ์ด์ ํผ๋๋ฐฑ์ผ๋ก ๋ณํํ ๋ค, ์ด๋ฅผ LLM ์์ด์ ํธ์ ๋ค์ ์๋์ ์ถ๊ฐ ์ปจํ
์คํธ๋ก ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์
๋๋ค.
์์ ๊ทธ๋ฆผ์ ํตํด Reflexion์ ์งํ ๊ณผ์ ์ ์์ธํ ์ค๋ช ํ๊ฒ ์ต๋๋ค.
- t = 0์ผ ๋๋ ๊ธฐ์กด์ Agent์ ๋์ผํ๊ฒ Actor๋ชจ๋ธ์ ํตํด Task๋ฅผ ์งํํฉ๋๋ค.
- Actor๋ชจ๋ธ์ ํตํด ๋์จ Action์ Environment์ ์ํธ์์ฉ ํ ๋ค Task์ ๋ํ ๊ฒฐ๊ณผ๊ฐ Trajectory(Obs์ Reward)์ ํํ๋ก ๋์ค๊ฒ ๋ฉ๋๋ค.
- ์ด๋ฌํ Trajectory๋ฅผ Evaluator ๋ชจ๋ธ์ ์ ๋ ฅ์ผ๋ก ์ฌ์ฉํ์ฌ ํด๋น Task๊ฐ ์ฑ๊ณตํ๋์ง ์คํจํ๋ ์ง๋ฅผ ํ์ธํฉ๋๋ค.
- ์คํจํ ๊ฒฝ์ฐ, ํด๋น Trajectory์ Evaluator๋ฅผ ํตํด ๋์จ ๊ฒฐ๊ณผ๋ฅผ Self-reflection ๋ชจ๋ธ์ ์ ๋ ฅ์ผ๋ก ํ์ฉํ์ฌ ์ธ์ด์ ํผ๋๋ฐฑ์ ์์ฑํฉ๋๋ค.
- ์ด๋ฅผ Experience๋ก Memory์ ์ ์ฅํ์ฌ Actor ๋ชจ๋ธ์ ๋ค์ ์๋์ ์ ๋ ฅ์ผ๋ก ํ์ฉํฉ๋๋ค.
Reflexion ์์
-
- Decision making Task์์ ์ผ๋ฐ์ ์ธ ์คํจ ์ฌ๋ก์ ๋ํด ๋ฏธ๋ฆฌ ์ ์๋ Heuristic์ผ๋ก Evaluation์ ์งํํ ๋ค Reflection์ ํตํด pan์ด ํด๋น ๋ฒ๋์ ์๋ค๋ ์๊ธฐ ํผ๋๋ฐฑ์ ๋ง๋ค์ด ๋ด๊ณ ๋ค์ ์๋์์ ์ฑ๊ณตํ ์์์ ๋๋ค.
-
- Programming Task์์ ์ ๋ ํ ์คํธ์ ๊ฒฐ๊ณผ๋ฅผ ํ์ฉํ์ฌ Evaluation์ ์งํํ ๋ค Reflection์ผ๋ก ๊ดํธ์ ์ด ๊ฐ์๋ง ํ์ธํ๋ ๊ฒ์ด ๋ฌธ์ ์๋ค๋ผ๋ ์๊ธฐ ํผ๋๋ฐฑ์ ๋ง๋ค์ด ๋ด๊ณ ๋ค์ ์๋์์ ์ฑ๊ณตํ ์์์ ๋๋ค.
-
- Reasoning Task์์ ํ๊ฒฝ์ ํตํด ์ป์ด์ง Binary Reward๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Reflction์ ์งํํ์ฌ ์๋ชป๋ ์ ๋ณด๋ฅผ ํ์ ํ๊ณ ๋ค์ ์๋์์ ์ฑ๊ณตํ ์์์ ๋๋ค.
-
- ์์์๋ ๋์ค์ง ์์์ง๋ง Ecaluation์ผ๋ก LLM์ ํ์ฉํ ์๋ ์์ต๋๋ค.
๋ค๋ฅธ ์๊ธฐ ํผ๋๋ฐฑ ๋ชจ๋ธ๊ณผ์ ์ฐจ์ด์
๊ฒฐ๊ณผ
- Decision making
- Reasoning
- Programming
- WebShop Limitation
- WebShop Task์์๋ ๋จ์ํ๋ ํ๊ฒฝ์ผ๋ก ์ธํด ์ ํํ ์๊ธฐ ํผ๋๋ฐฑ์ ์์ฑํด๋ด์ง ๋ชปํ๋ ๊ฒฐ๊ณผ๋ฅผ ์ป์์ต๋๋ค.
์ฝ๋ ๊ตฌํ
WebShop์ ๋ฐ๋ชจ ํ๊ฒฝ(product 1000๊ฐ)์ ๊ตฌ์ถํ ๋ค ReAct + Reflexion Agent๋ฅผ GitHub ์คํ์์ค ์ฝ๋๋ฅผ ์ฐธ๊ณ ํ์ฌ ๊ตฌํํด๋ณด๊ณ ์ฝ๋์ ํ๋กฌํํธ๋ฅผ ์์ ํ๋ฉด์ ์ฑ๋ฅ์ ์ง์ ํ ์คํธ ํด๋ณด์์ต๋๋ค.
- long-term ๋ฉ๋ชจ๋ฆฌ ์ ๋ฐ์ดํธ ๋ถ๋ถ (์ต๋ 3๊ฐ๊น์ง memory ํ์ฉ)
def update_memory(trial_log_path: str, env_configs: list[dict[str, Any]]) -> list[dict[str, Any]]:
"""Updates the given env_config with the appropriate reflections."""
with open(trial_log_path) as f:
full_log: str = f.read()
env_logs: list[str] = full_log.split('#####\n\n#####')
if len(env_logs) != len(env_configs):
raise ValueError(f'bad: {len(env_logs)}, {len(env_configs)}')
for i, env in enumerate(env_configs):
# if unsolved, get reflection and update env config
if not env['is_success']:
if len(env['memory']) > 3:
memory: list[str] = env['memory'][-3:]
else:
memory: list[str] = env['memory']
reflection_query: str = _generate_reflection_query(env_logs[i], memory)
reflection: str = get_completion(reflection_query) # type: ignore
env_configs[i]['memory'] += [reflection]
return env_configs
- reflection ์์ฑ ๋ถ๋ถ (2๊ฐ์ Few shot example ํ์ฉ)
def _generate_reflection_query(log_str: str, memory: list[str]) -> str:
"""Allows the Agent to reflect upon a past experience."""
scenario: str = _get_scenario(log_str)
query: str = (
"You will be given the history of a past experience in which you were placed in an environment and given a task to complete. "
"You were unsuccessful in completing the task. Do not summarize your environment, but rather think about the strategy and path "
"you took to attempt to complete the task. Devise a concise, new plan of action that accounts for your mistake with reference "
"to specific actions that you should have taken. There are two examples below.\n\n"
f"{FEW_SHOT_EXAMPLES}\n\n"
f"Instruction: {scenario}"
)
if len(memory) > 0:
query += '\n\nPlans from past attempts:\n'
for i, m in enumerate(memory):
query += f'Trial #{i}: {m}\n'
query += "\n\nNew plan:"
return query
์ฝ๋ ๊ฒฐ๊ณผ
- ๋น๋ก 1,000 ์ํ๋ง์ ๊ฐ์ง ๋ฐ๋ชจ WebShop ํ๊ฒฝ์ด์ง๋ง ReAct๋ง์ ์ฌ์ฉํ Agent์ ๋นํด์ ์ฑ๊ณต ๋น์จ๊ณผ ์ค์ฝ์ด ์ ์๋ฅผ ์๋ฏธ์๊ฒ ์ฌ๋ฆด ์ ์๋ค๋ ์ฌ์ค์ ํ์ธํ์์ต๋๋ค.
- ์๊ธฐ ํผ๋๋ฐฑ์ ๋ง๋ค์ด๋ด๋ ๋ถ๋ถ์์ ์ ์ ํ ํ๋กฌํํธ๋ฅผ ํ์ฉํ๋ฉด ์ฑ๋ฅ์ด ๊ทน๋ํ๋ ์ ์๋ค๋ ์ฌ์ค์ ์๊ฒ ๋์์ต๋๋ค.