์ด๋ฒˆ ํŽธ์€ Hugging Face Agents Course์˜ ํ•ต์‹ฌ์ธ โ€œ์ƒ๊ฐ(Reason) โ†’ ๋„๊ตฌ ์‹คํ–‰(Act) โ†’ ๊ด€์ฐฐ(Observe)โ€ ๋ฃจํ”„๋ฅผ ์ดˆ๋ณด์ž ๊ด€์ ์—์„œ ์ •ํ™•ํžˆ ์žก๋Š” ๋ณธํŽธ์ด๋‹ค.
ํ•ต์‹ฌ์€ ์–ด๋ ต์ง€ ์•Š๋‹ค.

์—์ด์ „ํŠธ ํ’ˆ์งˆ์€ ๋ชจ๋ธ ํฌ๊ธฐ๋ณด๋‹ค ๋„๊ตฌ ์ •์˜์™€ ์„ฑ๊ณต ํŒ์ • ๊ธฐ์ค€์—์„œ ๋จผ์ € ์˜ฌ๋ผ๊ฐ„๋‹ค.

ํ•œ ์ค„ ๊ฒฐ๋ก 

ReAct ๋ฃจํ”„๋ฅผ ๋ˆˆ์œผ๋กœ ํ™•์ธ ๊ฐ€๋Šฅํ•œ ๋กœ๊ทธ(step)์™€ ๋ช…ํ™•ํ•œ ํˆด ์ž…์ถœ๋ ฅ ๊ณ„์•ฝ์œผ๋กœ ์šด์˜ํ•˜๋ฉด, ์ดˆ๋ณด์ž๋„ โ€œ์™œ ์ด ๋‹ต์ด ๋‚˜์™”๋Š”์ง€โ€ ์ถ”์  ๊ฐ€๋Šฅํ•œ ์—์ด์ „ํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

flowchart TD
  A[์‚ฌ์šฉ์ž ์งˆ๋ฌธ] --> B[Agent Reason]
  B --> C{ํ•„์š” ๋„๊ตฌ ์„ ํƒ}
  C -->|search_web| D[DuckDuckGo ๊ฒ€์ƒ‰]
  C -->|calc_margin| E[๋งˆ์ง„ ๊ณ„์‚ฐ]
  D --> F[Observation]
  E --> F
  F --> G[๋‹ค์Œ step ํŒ๋‹จ]
  G -->|์ถฉ๋ถ„| H[์ตœ์ข… ๋‹ต๋ณ€]
  G -->|๋ถ€์กฑ| B

์‹ค์Šต ๋ชฉํ‘œ

  1. smolagents์—์„œ ๋„๊ตฌ 2๊ฐœ(search_web, calc_margin)๋ฅผ ๋ถ™์ธ๋‹ค.
  2. ์—์ด์ „ํŠธ๊ฐ€ ๋„๊ตฌ๋ฅผ ์„ ํƒํ•ด ์‹คํ–‰ํ•˜๋Š” ReAct ํ๋ฆ„์„ ๋กœ๊ทธ๋กœ ํ™•์ธํ•œ๋‹ค.
  3. ์‹ค๋ฌด ๊ธฐ์ค€์˜ ์„ฑ๊ณต ํŒ์ •(์ •๋‹ต/๊ทผ๊ฑฐ/์žฌํ˜„์„ฑ)์„ ์ฒดํฌํ•œ๋‹ค.

์ค€๋น„๋ฌผ

  • Python 3.10+
  • Hugging Face Access Token (๊ถŒ์žฅ)
    • ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ช…: HF_TOKEN
  • ๊ฒฝ๋กœ: .../Agent/๐Ÿค— HF-Agents-Course/downloads

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

  • ๋„๊ตฌ: ํ„ฐ๋ฏธ๋„, pip
  • ์ž…๋ ฅ: ํŒŒ์ด์ฌ ๊ฐ€์ƒํ™˜๊ฒฝ
  • ์‹คํ–‰๋ช…๋ น:
cd "/home/tw2/Documents/n8n/data/shared/syn/8.quartz/Agent/๐Ÿค— HF-Agents-Course/downloads"
python3 -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
pip install smolagents duckduckgo-search
  • ์„ฑ๊ณตํŒ์ •:
    • python -c "import smolagents; print('ok')"๊ฐ€ ok ์ถœ๋ ฅ

2) ์‹ค์Šต ์ฝ”๋“œ ์ž‘์„ฑ

  • ๋„๊ตฌ: ํŒŒ์ผ ํŽธ์ง‘๊ธฐ
  • ์ž…๋ ฅ: ์•„๋ž˜ ์ฝ”๋“œ
  • ์‹คํ–‰๋ช…๋ น:
cat > day11_react_toolflow.py <<'PY'
from smolagents import CodeAgent, InferenceClientModel, tool
 
@tool
def calc_margin(revenue: float, cost: float) -> str:
    """๋งค์ถœ๊ณผ ๋น„์šฉ์œผ๋กœ ๋งˆ์ง„์œจ(%)์„ ๊ณ„์‚ฐํ•œ๋‹ค."""
    if revenue <= 0:
        return "error: revenue must be > 0"
    margin = ((revenue - cost) / revenue) * 100
    return f"margin={margin:.2f}%"
 
@tool
def search_web(query: str) -> str:
    """์›น ๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์š”์•ฝ ๋ฌธ์ž์—ด์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค."""
    from duckduckgo_search import DDGS
    with DDGS() as ddgs:
        results = list(ddgs.text(query, max_results=3))
    if not results:
        return "๊ฒ€์ƒ‰ ๊ฒฐ๊ณผ ์—†์Œ"
    lines = []
    for i, r in enumerate(results, 1):
        title = r.get("title", "(no title)")
        href = r.get("href", "")
        body = (r.get("body", "") or "")[:120]
        lines.append(f"{i}. {title} | {href} | {body}")
    return "\n".join(lines)
 
model = InferenceClientModel()  # HF_TOKEN ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์‚ฌ์šฉ ๊ถŒ์žฅ
agent = CodeAgent(
    tools=[search_web, calc_margin],
    model=model,
    max_steps=6,
)
 
if __name__ == "__main__":
    task = (
        "ํ•œ๊ตญ SaaS ์Šคํƒ€ํŠธ์—…์˜ 2026๋…„ AI ์—์ด์ „ํŠธ ๋„์ž… ํŠธ๋ Œ๋“œ๋ฅผ 3์ค„๋กœ ์š”์•ฝํ•˜๊ณ , "
        "์›”๋งค์ถœ 12000000์›/์›”๋น„์šฉ 8400000์›์˜ ๋งˆ์ง„์œจ๋„ ํ•จ๊ป˜ ๊ณ„์‚ฐํ•ด์ค˜."
    )
    result = agent.run(task)
    print("\n=== FINAL ===")
    print(result)
PY
  • ์„ฑ๊ณตํŒ์ •:
    • day11_react_toolflow.py ํŒŒ์ผ ์ƒ์„ฑ ํ™•์ธ

3) ์—์ด์ „ํŠธ ์‹คํ–‰ + ReAct ๋‹จ๊ณ„ ํ™•์ธ

  • ๋„๊ตฌ: day11_react_toolflow.py
  • ์ž…๋ ฅ: ๊ธฐ๋ณธ task ๋ฌธ์ž์—ด
  • ์‹คํ–‰๋ช…๋ น:
export HF_TOKEN="<your_hf_token>"
python day11_react_toolflow.py
  • ์„ฑ๊ณตํŒ์ •:
    • ์ถœ๋ ฅ์— ๊ฒ€์ƒ‰ ๊ทผ๊ฑฐ(๋งํฌ/์š”์•ฝ) + margin=30.00% ํฌํ•จ
    • ์—์ด์ „ํŠธ๊ฐ€ 1ํšŒ ์ด์ƒ ๋„๊ตฌ ํ˜ธ์ถœํ•œ ๋กœ๊ทธ ํ™•์ธ

4) ์„ฑ๊ณต/์‹คํŒจ ํŒ์ •ํ‘œ (์‹ค๋ฌดํ˜•)

  • ์ •์ƒ ์„ฑ๊ณต
    • ๋งˆ์ง„์œจ์ด ์ •ํ™•ํžˆ 30.00%
    • ํŠธ๋ Œ๋“œ ์š”์•ฝ์ด 3์ค„ ์ด๋‚ด
    • ์ตœ์†Œ 1๊ฐœ ๊ทผ๊ฑฐ ๋งํฌ ํฌํ•จ
  • ๋ถ€๋ถ„ ์„ฑ๊ณต
    • ๊ณ„์‚ฐ์€ ์ •ํ™•ํ•˜์ง€๋งŒ ๊ทผ๊ฑฐ ๋งํฌ ๋ˆ„๋ฝ
  • ์‹คํŒจ
    • ๋„๊ตฌ ํ˜ธ์ถœ ์—†์ด ์ผ๋ฐ˜๋ก  ๋‹ต๋ณ€๋งŒ ์ถœ๋ ฅ
    • ๊ณ„์‚ฐ๊ฐ’ ์˜ค์ฐจ(ยฑ0.01% ์ดˆ๊ณผ)

์ดˆ๋ณด์ž ๊ด€์  ํ•ต์‹ฌ ์„ค๋ช…

  • @tool ๋ฐ์ฝ”๋ ˆ์ดํ„ฐ: โ€œ์ด ํ•จ์ˆ˜๋Š” ์—์ด์ „ํŠธ๊ฐ€ ํ˜ธ์ถœ ๊ฐ€๋Šฅํ•œ ์™ธ๋ถ€ ๋Šฅ๋ ฅโ€์ด๋ผ๊ณ  ๋“ฑ๋กํ•˜๋Š” ์„ ์–ธ์ด๋‹ค.
  • CodeAgent: ์ž์—ฐ์–ด ๊ณ„ํš + ์ฝ”๋“œ ์‹คํ–‰ ๊ธฐ๋ฐ˜์œผ๋กœ tool์„ ๊ณ ๋ฅด๋Š” ์—์ด์ „ํŠธ.
  • max_steps: ๋ฌดํ•œ ๋ฃจํ”„ ๋ฐฉ์ง€ ์•ˆ์ „์žฅ์น˜. ์šด์˜์—์„  4~8 ์‚ฌ์ด๋ฅผ ๋จผ์ € ๊ถŒ์žฅ.

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

  1. ๋„๊ตฌ ๊ณ„์•ฝ์„ ์งง๊ณ  ๋ช…ํ™•ํ•˜๊ฒŒ
    • ์ž…๋ ฅ ํƒ€์ž…/์ถœ๋ ฅ ํฌ๋งท์„ ๊ณ ์ •ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ๊ธ‰๊ฐํ•œ๋‹ค.
  2. ์„ฑ๊ณต ํŒ์ • ์ž๋™ํ™”
    • ๊ณ„์‚ฐํ˜• ํƒœ์Šคํฌ๋Š” ๊ธฐ๋Œ€๊ฐ’ ๋น„๊ต(assert)๋กœ ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ๋ฅผ ๋งŒ๋“ ๋‹ค.
  3. ๊ทผ๊ฑฐ ๊ฐ•์ œ ํ”„๋กฌํ”„ํŠธ
    • โ€œ์ตœ์†Œ 1๊ฐœ URL ํฌํ•จโ€ ๊ฐ™์€ ์ •์ฑ…์„ ๋„ฃ์œผ๋ฉด ๋ณด๊ณ ์„œ ์‹ ๋ขฐ๋„๊ฐ€ ์˜ฌ๋ผ๊ฐ„๋‹ค.

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

  1. 401 Unauthorized (HF ์ถ”๋ก )
    • ์›์ธ: HF_TOKEN ๋ˆ„๋ฝ/๊ถŒํ•œ ๋ฌธ์ œ
    • ํ•ด๊ฒฐ: ํ† ํฐ ์žฌ๋ฐœ๊ธ‰ ํ›„ export HF_TOKEN=...
  2. No module named duckduckgo_search
    • ์›์ธ: ๊ฐ€์ƒํ™˜๊ฒฝ ๋ฏธํ™œ์„ฑํ™”
    • ํ•ด๊ฒฐ: source .venv/bin/activate ํ›„ ์žฌ์„ค์น˜
  3. ๊ฒ€์ƒ‰์€ ๋˜๋Š”๋ฐ ๊ณ„์‚ฐ์ด ํ‹€๋ฆผ
    • ์›์ธ: revenue/cost ์ˆœ์„œ ๋ฐ˜๋Œ€๋กœ ์ „๋‹ฌ
    • ํ•ด๊ฒฐ: ํ•จ์ˆ˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜์™€ ํ˜ธ์ถœ๊ฐ’ ์ˆœ์„œ ์žฌํ™•์ธ

๋‹ค์Œ ํŽธ ์˜ˆ๊ณ 

๋‹ค์Œ ๋ณธํŽธ์—์„œ๋Š” ToolCallingAgent์™€ ์ •์ฑ… ๊ฐ€๋“œ๋ ˆ์ผ์„ ๊ฒฐํ•ฉํ•ด, โ€œ๋„๊ตฌ๋ฅผ ์“ธ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ ์•„๋ฌด๊ฑฐ๋‚˜ ๋ชป ์“ฐ๊ฒŒ ์ œํ•œํ•˜๋Š”โ€ ์šด์˜ํ˜• ํŒจํ„ด์œผ๋กœ ํ™•์žฅํ•œ๋‹ค.

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

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

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

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