์ด๋ฒˆ ํŽธ์—์„œ๋Š” smolagents์˜ ๊ณ„ํš ์ฃผ๊ธฐ(planning interval) ๊ฐœ๋…์„ ์‹ค๋ฌด ๊ด€์ ์—์„œ ๋‹ค๋ฃฌ๋‹ค.
ํ•ต์‹ฌ์€ ๊ฐ„๋‹จํ•˜๋‹ค.

  • ๊ณ„ํš์„ ๋„ˆ๋ฌด ์ž์ฃผ ๋‹ค์‹œ ์„ธ์šฐ๋ฉด ๋А๋ฆฌ๊ณ  ๋น„์šฉ์ด ๋Š˜์–ด๋‚œ๋‹ค.
  • ๊ณ„ํš์„ ๋„ˆ๋ฌด ๋Šฆ๊ฒŒ ๊ฐฑ์‹ ํ•˜๋ฉด ์‹คํŒจ๋ฅผ ์˜ค๋ž˜ ๋Œ๊ณ  ๊ฐ„๋‹ค.

์ฆ‰, โ€œ๋ช‡ ์Šคํ…๋งˆ๋‹ค ๊ณ„ํš์„ ์žฌ์ˆ˜๋ฆฝํ• ์ง€โ€๋ฅผ ์—…๋ฌด ์„ฑ๊ฒฉ์— ๋งž๊ฒŒ ์กฐ์ ˆํ•ด์•ผ ํ•œ๋‹ค.

  • ์ด์ „ ํŽธ: ๐Ÿค— 19. ์‹ค์ŠตํŽธ 05
  • ๋‹ค์Œ ํŽธ ์˜ˆ๊ณ : ์‹คํŒจ ๋กœ๊ทธ๋ฅผ ๊ทผ๊ฑฐ๋กœ ์ž๋™ ์žฌ์‹œ๋„ ์ •์ฑ…(์žฌ๊ณ„ํš + ๋„๊ตฌ ํด๋ฐฑ) ์„ค๊ณ„

ํ•œ ์ค„ ๋ชฉํ‘œ

๋™์ผํ•œ ์ž‘์—…์„ planning_interval ๊ฐ’๋งŒ ๋ฐ”๊ฟ” 2ํšŒ ์‹คํ–‰ํ•˜๊ณ , ์‹คํ–‰ ์‹œ๊ฐ„ยท์Šคํ… ์ˆ˜ยท์„ฑ๊ณต๋ฅ  ๋ณ€ํ™”๋ฅผ ๋น„๊ตํ•ด ์šด์˜ ๊ธฐ๋ณธ๊ฐ’์„ ์ •ํ•œ๋‹ค.

flowchart TD
  A[์‚ฌ์šฉ์ž ์ž‘์—… ์š”์ฒญ] --> B[CodeAgent ์‹คํ–‰]
  B --> C{planning_interval ๋„๋‹ฌ?}
  C -- ์•„๋‹ˆ์˜ค --> D[ํ˜„์žฌ ๊ณ„ํš ์œ ์ง€ + ๋‹ค์Œ ๋„๊ตฌ ์‹คํ–‰]
  C -- ์˜ˆ --> E[๊ณ„ํš ์žฌ์ˆ˜๋ฆฝ]
  E --> D
  D --> F{์™„๋ฃŒ/์‹คํŒจ}
  F -- ์™„๋ฃŒ --> G[์ตœ์ข… ๊ฒฐ๊ณผ + ์ง€ํ‘œ ๊ธฐ๋ก]
  F -- ์‹คํŒจ --> H[์‹คํŒจ ์›์ธ ๊ธฐ๋ก ํ›„ ์žฌ์‹คํ–‰ ์ •์ฑ… ๊ฒ€ํ† ]

0) ์‹ค์Šต ๋ฒ”์œ„

  • ๋ฒ”์œ„ ํฌํ•จ
    • planning_interval=1 ๊ณผ planning_interval=3 ๋น„๊ต ์‹คํ–‰
    • ๊ฐ™์€ ์ž…๋ ฅ/๊ฐ™์€ ๋„๊ตฌ/๊ฐ™์€ ๋ชจ๋ธ๋กœ ๊ณต์ • ๋น„๊ต
    • ์„ฑ๊ณต ์—ฌ๋ถ€ + ์ฒ˜๋ฆฌ ์‹œ๊ฐ„ + ๋กœ๊ทธ ๊ฑด์ˆ˜ ์ €์žฅ
  • ๋ฒ”์œ„ ์ œ์™ธ
    • ์™ธ๋ถ€ DB/๋ฒกํ„ฐ์Šคํ† ์–ด
    • ๋ณต์žกํ•œ ๋ฉ€ํ‹ฐ์—์ด์ „ํŠธ ์˜ค์ผ€์ŠคํŠธ๋ ˆ์ด์…˜

1) ํ™˜๊ฒฝ ์ค€๋น„

  • ๋„๊ตฌ: ํ„ฐ๋ฏธ๋„
  • ์ž…๋ ฅ: Python 3.10+, ๊ฐ€์ƒํ™˜๊ฒฝ
  • ์‹คํ–‰๋ช…๋ น:
mkdir -p ~/hf-agents-lab20
cd ~/hf-agents-lab20
python3 -m venv .venv
source .venv/bin/activate
pip install -U smolagents litellm
  • ์„ฑ๊ณตํŒ์ •:
python -V
pip show smolagents | head -n 5
  • Python ๋ฒ„์ „ ์ถœ๋ ฅ
  • smolagents ํŒจํ‚ค์ง€ ์ •๋ณด๊ฐ€ ๋ณด์ด๋ฉด ์„ฑ๊ณต

2) ๋ชจ๋ธ ์„ค์ •

  • ๋„๊ตฌ: ํ„ฐ๋ฏธ๋„
  • ์ž…๋ ฅ: API ํ‚ค, ๋ชจ๋ธ ID
  • ์‹คํ–‰๋ช…๋ น:
export OPENAI_API_KEY="YOUR_API_KEY"
export MODEL_ID="openai/gpt-4o-mini"
  • ์„ฑ๊ณตํŒ์ •:
echo "$MODEL_ID"
python - <<'PY'
import os
print("OPENAI_API_KEY set:", bool(os.getenv("OPENAI_API_KEY")))
PY
  • OPENAI_API_KEY set: True ํ™•์ธ

3) ์‹คํ—˜ ์ฝ”๋“œ ์ž‘์„ฑ (planning_interval ๋น„๊ต)

  • ๋„๊ตฌ: ์—๋””ํ„ฐ/ํ„ฐ๋ฏธ๋„
  • ์ž…๋ ฅ: ์•„๋ž˜ ์ฝ”๋“œ
  • ์‹คํ–‰๋ช…๋ น:
cat > lab20_planning_interval_compare.py <<'PY'
from __future__ import annotations
 
import json
import os
import time
from pathlib import Path
 
from smolagents import CodeAgent, LiteLLMModel, tool
 
OUT = Path("run_metrics.json")
 
@tool
def search_kb(topic: str) -> str:
    """topic ๊ด€๋ จ ์šด์˜ ํŒ 3๊ฐœ๋ฅผ ๋ฌธ์ž์—ด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค."""
    kb = {
        "incident": [
            "1) ์ƒํ™ฉ ์š”์•ฝ์„ ๋จผ์ € ๊ณ ์ •ํ•œ๋‹ค",
            "2) ๋‹ด๋‹น์ž/๊ธฐํ•œ/๋‹ค์Œ ์•ก์…˜์„ ๋ถ„๋ฆฌํ•œ๋‹ค",
            "3) ๊ณ ๊ฐ ์˜ํ–ฅ๋„๋ฅผ ์ˆซ์ž๋กœ ๋ช…์‹œํ•œ๋‹ค",
        ],
        "release": [
            "1) ๋ณ€๊ฒฝ์ ์€ ์‚ฌ์šฉ์ž ์˜ํ–ฅ ๊ธฐ์ค€์œผ๋กœ ์ •๋ฆฌ",
            "2) ๋กค๋ฐฑ ์กฐ๊ฑด์„ ๋ฐฐํฌ ์ „ ํ™•์ •",
            "3) ๋ฐฐํฌ ์งํ›„ 30๋ถ„ ๊ด€์ฐฐ ์ง€ํ‘œ ์ง€์ •",
        ],
    }
    key = topic.lower().strip()
    items = kb.get(key, ["๊ด€๋ จ ํŒ ์—†์Œ"])
    return "\n".join(items)
 
 
def run_once(interval: int) -> dict:
    model = LiteLLMModel(model_id=os.getenv("MODEL_ID", "openai/gpt-4o-mini"))
    agent = CodeAgent(
        model=model,
        tools=[search_kb],
        max_steps=8,
        planning_interval=interval,
    )
 
    task = (
        "incident ์ฃผ์ œ์— ๋Œ€ํ•ด search_kb ๋„๊ตฌ๋ฅผ ํ™œ์šฉํ•ด "
        "ํŒ€ ๊ณต์ง€์šฉ 3์ค„ ์š”์•ฝ์„ ๋งŒ๋“ค๊ณ , ๋งˆ์ง€๋ง‰ ์ค„์— ์ฒดํฌ๋ฆฌ์ŠคํŠธ 2๊ฐœ๋ฅผ ๋ถ™์—ฌ๋ผ."
    )
 
    t0 = time.perf_counter()
    ok = True
    error = ""
    output_text = ""
 
    try:
        result = agent.run(task)
        output_text = str(result)
    except Exception as e:
        ok = False
        error = f"{type(e).__name__}: {e}"
 
    elapsed = round(time.perf_counter() - t0, 3)
 
    return {
        "planning_interval": interval,
        "success": ok,
        "elapsed_sec": elapsed,
        "output_preview": output_text[:300],
        "error": error,
    }
 
 
def main() -> None:
    runs = [run_once(1), run_once(3)]
    OUT.write_text(json.dumps(runs, ensure_ascii=False, indent=2), encoding="utf-8")
    print(f"saved: {OUT}")
    for r in runs:
        print(r)
 
 
if __name__ == "__main__":
    main()
PY
  • ์„ฑ๊ณตํŒ์ •:
    • lab20_planning_interval_compare.py ํŒŒ์ผ ์ƒ์„ฑ
    • ์ฝ”๋“œ ๋‚ด planning_interval=interval ํ™•์ธ

4) ์‹คํ–‰ ๋ฐ ์ง€ํ‘œ ์ €์žฅ

  • ๋„๊ตฌ: Python
  • ์ž…๋ ฅ: ๋™์ผ ์ž‘์—…(task), interval 2์ข…(1/3)
  • ์‹คํ–‰๋ช…๋ น:
python lab20_planning_interval_compare.py
cat run_metrics.json
  • ์„ฑ๊ณตํŒ์ •:
    • saved: run_metrics.json ์ถœ๋ ฅ
    • JSON์— planning_interval, success, elapsed_sec ํ‚ค ์กด์žฌ

5) ๊ฒฐ๊ณผ ํŒ๋… ๊ธฐ์ค€(์ดˆ๋ณด์ž์šฉ)

  • ๋„๊ตฌ: ๋ˆˆ์œผ๋กœ ํ™•์ธ + ๊ฐ„๋‹จ ๊ทœ์น™
  • ์ž…๋ ฅ: run_metrics.json
  • ์‹คํ–‰๋ช…๋ น:
python - <<'PY'
import json
rows = json.load(open('run_metrics.json', encoding='utf-8'))
for r in rows:
    print(f"interval={r['planning_interval']} success={r['success']} sec={r['elapsed_sec']}")
 
# ๋‹จ์ˆœ ๊ถŒ์žฅ ๊ทœ์น™
ok_rows = [r for r in rows if r['success']]
if len(ok_rows) == 2:
    faster = min(ok_rows, key=lambda x: x['elapsed_sec'])
    print(f"RECOMMEND: planning_interval={faster['planning_interval']} (์„ฑ๊ณต + ๋” ๋น ๋ฆ„)")
elif len(ok_rows) == 1:
    print(f"RECOMMEND: planning_interval={ok_rows[0]['planning_interval']} (์œ ์ผ ์„ฑ๊ณต)")
else:
    print("RECOMMEND: max_steps/๋„๊ตฌ์ •์˜/ํ”„๋กฌํ”„ํŠธ ์žฌ์ ๊ฒ€ ํ•„์š”")
PY
  • ์„ฑ๊ณตํŒ์ •:
    • RECOMMEND: ... ํ•œ ์ค„์ด ์ถœ๋ ฅ๋˜๋ฉด ํŒ๋… ๋ฃจํ”„ ์ •์ƒ

์™œ ์‹ค๋ฌด์—์„œ ์ค‘์š”ํ•œ๊ฐ€?

  1. ๋น„์šฉ/์ง€์—ฐ ๊ด€๋ฆฌ: ๊ณ„ํš ์žฌ์ˆ˜๋ฆฝ์€ ๋ชจ๋ธ ํ˜ธ์ถœ ๋น„์šฉ๊ณผ ์ง๊ฒฐ๋œ๋‹ค.
  2. ์•ˆ์ •์„ฑ ํ™•๋ณด: ๋„๊ตฌ ์˜ค๋ฅ˜๊ฐ€ ๋‚˜๋Š” ํ™˜๊ฒฝ์—์„œ๋Š” ๋„ˆ๋ฌด ๊ธด ๊ฐ„๊ฒฉ์ด ์‹คํŒจ ๋ณต๊ตฌ๋ฅผ ๋Šฆ์ถ˜๋‹ค.
  3. ์šด์˜ ํ‘œ์ค€ํ™”: ํŒ€๋ณ„ ๊ธฐ๋ณธ๊ฐ’(์˜ˆ: 2 ๋˜๋Š” 3)์„ ์ •ํ•˜๋ฉด ๋””๋ฒ„๊น…์ด ์‰ฌ์›Œ์ง„๋‹ค.

์‹ค๋ฌด ์ ์šฉ ํฌ์ธํŠธ

  • ๊ณ ๊ฐ ์‘๋‹ตํ˜•(์งง๊ณ  ๋น ๋ฅธ ๋‹ต๋ณ€): planning_interval์„ ํฌ๊ฒŒ(์˜ˆ: 3~4) ์‹œ์ž‘
  • ์ •ํ™•๋„ ์šฐ์„ ํ˜•(๋ณต์žกํ•œ ๋„๊ตฌ ์ฒด์ธ): planning_interval์„ ์ž‘๊ฒŒ(์˜ˆ: 1~2) ์‹œ์ž‘
  • ๋ฐ˜๋“œ์‹œ **์ž‘์—…๋ณ„ ๋ฒค์น˜๋งˆํฌ ํŒŒ์ผ(run_metrics.json)**์„ ๋‚จ๊ฒจ ํšŒ๊ท€๋ฅผ ๋น„๊ต

ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

  1. ์‹คํ–‰์ด ์ง€๋‚˜์น˜๊ฒŒ ๋А๋ฆผ
  • ์›์ธ: planning ์žฌ์ˆ˜๋ฆฝ์ด ๋„ˆ๋ฌด ์žฆ์Œ
  • ์กฐ์น˜: planning_interval 1โ†’3์œผ๋กœ ์˜ฌ๋ ค ์žฌ์ธก์ •
  1. ์ •๋‹ต ํ’ˆ์งˆ์ด ํ”๋“ค๋ฆผ
  • ์›์ธ: ์žฌ๊ณ„ํš ์ฃผ๊ธฐ๊ฐ€ ๋„ˆ๋ฌด ๊ธธ์–ด ์ค‘๊ฐ„ ์˜ค๋ฅ˜๋ฅผ ๋ฐฉ์น˜
  • ์กฐ์น˜: planning_interval 4โ†’2๋กœ ๋‚ฎ์ถ”๊ณ  max_steps๋ฅผ ํ•จ๊ป˜ ์กฐ์ •
  1. ๋ชจ๋ธ ์ธ์ฆ ์˜ค๋ฅ˜(401/429)
  • ์›์ธ: API ํ‚ค/์ฟผํ„ฐ ๋ฌธ์ œ
  • ์กฐ์น˜:
echo ${OPENAI_API_KEY:+SET}
# ํ•„์š” ์‹œ ํ‚ค ์žฌ๋ฐœ๊ธ‰ ํ›„ ์žฌ์„ค์ •

์ฒดํฌ๋ฆฌ์ŠคํŠธ

  • ๋™์ผํ•œ ์ž…๋ ฅ์œผ๋กœ interval 2์ข… ๋น„๊ต ์™„๋ฃŒ
  • run_metrics.json ์ €์žฅ ํ™•์ธ
  • ์„ฑ๊ณต๋ฅ /์‹œ๊ฐ„ ๊ธฐ์ค€์œผ๋กœ ๊ธฐ๋ณธ๊ฐ’ ๊ฒฐ์ •
  • ํŒ€ ๊ณต์šฉ ๋ฌธ์„œ์— ๊ธฐ๋ณธ๊ฐ’๊ณผ ๊ทผ๊ฑฐ ๊ธฐ๋ก

์ฐธ๊ณ  ๋งํฌ (์šฐ์„ ์ˆœ์œ„)

  1. https://github.com/huggingface/agents-course
  2. https://huggingface.co/learn/agents-course
  3. https://huggingface.co/docs/smolagents

์ƒ์„ฑํ˜• AI ํ™œ์šฉ ๊ณ ์ง€

์ด ๋ฌธ์„œ๋Š” ์ƒ์„ฑํ˜• AI๋กœ ์ดˆ์•ˆ์„ ์ž‘์„ฑํ•˜๊ณ , ์‚ฌ๋žŒ ๊ฒ€ํ† ๋ฅผ ํ†ตํ•ด ์‹ค์Šต ์žฌํ˜„์„ฑ(๋„๊ตฌ/์ž…๋ ฅ/๋ช…๋ น/์„ฑ๊ณตํŒ์ •), ๋งํฌ, ๋ฌธ์„œ ํ˜•์‹์„ ํ™•์ธํ•ด ํ™•์ •ํ–ˆ๋‹ค.