ν μ€λ‘ λ§νλ©΄, μμ΄μ νΈ νμ§μ βμ λμκ°λ€βκ° μλλΌ βλ°λ³΅ μ€νν΄λ κ°μ κΈ°μ€μΌλ‘ ν΅κ³Όνλ€βλ‘ κ΄λ¦¬ν΄μΌ νλ€.
μ΄λ² λ³ΈνΈμ smolagents κΈ°λ° μμ΄μ νΈμ λꡬ ν
μ€νΈ + νκ° λ£¨ν(eval) λ₯Ό λΆμ¬ μ€λ¬΄ λ°°ν¬ μ μ λ’°λλ₯Ό ν보νλ λ°©λ²μ λ€λ£¬λ€.
μ μ§κΈ νκ° λ£¨νκ° νμνκ°
- μμ΄μ νΈλ κ°μ μ§λ¬Έμλ λꡬ νΈμΆ μμκ° λ¬λΌμ§ μ μλ€.
- κ²°κ³Ό λ¬Έμ₯μ΄ μμ°μ€λ¬μλ, μ λ΅ μ‘°κ±΄μ λμΉ μ μλ€.
- λ°λΌμ λ³Έλ¬Έ μμ± μ΄μ μ μλ νμ κΈ°μ€(μ±κ³΅/μ€ν¨) μ λ¨Όμ κ³ μ ν΄μΌ νλ€.
flowchart LR A[μμ² μ λ ₯] --> B[CodeAgent μ€ν] B --> C[λꡬ νΈμΆ λ‘κ·Έ μμ§] C --> D{νκ° κ·μΉ ν΅κ³Ό?} D -->|Yes| E[λ°°ν¬ ν보] D -->|No| F[ν둬ννΈ/λꡬ μμ ] F --> B
μ€μ΅ λͺ©ν
smolagentsλ‘ κ°λ¨ν μ 무 μμ΄μ νΈλ₯Ό λ§λ λ€.- λꡬ λ¨μ ν μ€νΈ(selfcheck)λ₯Ό ν΅κ³Όμν¨λ€.
- μν κ³Όμ μ μΌλ‘ νκ°(eval) μ μλ₯Ό κ³μ°νλ€.
- ν΅κ³Ό κΈ°μ€ λ―Έλ¬ μ μμ ν¬μΈνΈλ₯Ό λ°λ‘ μ°Ύλλ€.
1) μ€λΉ: ν΄λ/νκ²½/ν¨ν€μ§
Step 1-1. μμ ν΄λ μμ±
- λꡬ: ν°λ―Έλ
- μ λ ₯: μμ
- μ€νλͺ λ Ή:
mkdir -p ~/hf-agents-day15 && cd ~/hf-agents-day15- μ±κ³΅νμ :
pwdκ²°κ³Όκ°~/hf-agents-day15
Step 1-2. κ°μνκ²½ + ν¨ν€μ§ μ€μΉ
- λꡬ: Python 3.10+
- μ λ ₯: μμ
- μ€νλͺ λ Ή:
python3 -m venv .venv
source .venv/bin/activate
pip install -U smolagents- μ±κ³΅νμ :
python -c "import smolagents; print('OK')"μΆλ ₯μ OKκ° λμ€λ©΄ ν΅κ³Ό.
Step 1-3. λͺ¨λΈ ν€ μ€μ
- λꡬ: νκ²½λ³μ
- μ
λ ₯:
HF_TOKENλλ OpenAI νΈν ν€ - μ€νλͺ λ Ή:
export HF_TOKEN="hf_xxx"
# λλ
export OPENAI_API_KEY="sk-xxx"- μ±κ³΅νμ : ν€κ° λΉμ΄ μμ§ μμ (
echo ${HF_TOKEN:+set})
2) μμ μ½λ μμ± (λꡬ + μμ΄μ νΈ + νκ°)
μλ νμΌμ κ·Έλλ‘ μ μ₯νλ€.
day15_eval_loop.py
import json
from dataclasses import dataclass
from typing import List, Dict
from smolagents import CodeAgent, HfApiModel, tool
@tool
def shipping_cost(weight_kg: float, distance_km: int, urgent: bool = False) -> str:
"""무κ²/거리/κΈ΄κΈ μ¬λΆλ‘ λ°°μ‘λΉλ₯Ό κ³μ°νλ€."""
base = 2500
weight_fee = int(weight_kg * 400)
distance_fee = int(distance_km * 3)
urgent_fee = 3000 if urgent else 0
total = base + weight_fee + distance_fee + urgent_fee
return json.dumps({"total_krw": total}, ensure_ascii=False)
@tool
def policy_lookup(topic: str) -> str:
"""κ°λ¨ν λ΄λΆ μ μ±
μ‘°ν λꡬ"""
table = {
"refund": "κ°λ΄ μ 7μΌ μ΄λ΄ μ μ‘ νλΆ κ°λ₯",
"delivery": "νμΌ 15μ μ΄μ μ£Όλ¬Έμ λΉμΌ μΆκ³ ",
"warranty": "μ μμ ν κΈ°λ³Έ λ³΄μ¦ 1λ
"
}
return table.get(topic.lower(), "μ μ±
μμ")
def build_agent():
model = HfApiModel("Qwen/Qwen2.5-72B-Instruct")
return CodeAgent(
tools=[shipping_cost, policy_lookup],
model=model,
max_steps=6,
)
def selfcheck_tools() -> Dict:
s1 = json.loads(shipping_cost(2.0, 100, False))
s2 = policy_lookup("refund")
return {
"shipping_tool_ok": s1["total_krw"] == 3600,
"policy_tool_ok": "νλΆ" in s2,
}
@dataclass
class Case:
q: str
must_include: List[str]
def run_eval(agent, cases: List[Case]) -> Dict:
results = []
passed = 0
for c in cases:
out = str(agent.run(c.q))
ok = all(token in out for token in c.must_include)
passed += 1 if ok else 0
results.append({"question": c.q, "ok": ok, "output": out})
score = passed / len(cases)
return {
"total": len(cases),
"passed": passed,
"score": round(score, 2),
"pass": score >= 0.67,
"results": results,
}
if __name__ == "__main__":
tool_state = selfcheck_tools()
print("[SELFHECK]", json.dumps(tool_state, ensure_ascii=False))
agent = build_agent()
eval_cases = [
Case(
q="λ¬΄κ² 2kg, 거리 100km μΌλ° λ°°μ‘λΉλ₯Ό κ³μ°ν΄μ€.",
must_include=["3600"],
),
Case(
q="νλΆ μ μ±
μμ½ν΄μ€.",
must_include=["7μΌ", "νλΆ"],
),
Case(
q="λ¬΄κ² 1kg, 거리 50km, κΈ΄κΈ λ°°μ‘λΉ κ³μ° ν ν μ€ μμ½.",
must_include=["6050"],
),
]
report = run_eval(agent, eval_cases)
print("[EVAL]", json.dumps(report, ensure_ascii=False, indent=2))3) μ€ν: selfcheck β eval
Step 3-1. λꡬ λ¨μ μ κ²
- λꡬ:
day15_eval_loop.py - μ λ ₯: μμ
- μ€νλͺ λ Ή:
python day15_eval_loop.py- μ±κ³΅νμ :
[SELFHECK](μ€νμ κ·Έλλ‘ μΆλ ₯λ μ μμ) κ²°κ³Όμμ μλ λ λ€trueshipping_tool_okpolicy_tool_ok
Step 3-2. νκ° κ²°κ³Ό νμΈ
- λꡬ: κ°μ μ€ν λ‘κ·Έμ
[EVAL]JSON - μ λ ₯: λ΄μ₯ 3κ° ν μ€νΈ μΌμ΄μ€
- μ€νλͺ λ Ή: Step 3-1κ³Ό λμΌ
- μ±κ³΅νμ :
score >= 0.67pass: true
4) μ΄λ³΄μμ© ν΄μ€ (μ½κ² μ΄ν΄νκΈ°)
@toolν¨μλ μμ΄μ νΈκ° κΊΌλ΄ μ°λ μμ κ³μ°κΈ°/μ¬μ μ΄λ€.selfcheck_tools()λ λκ΅¬κ° λ§κ°μ§μ§ μμλμ§ νμΈνλ κΈ°λ³Έ 건κ°κ²μ§μ΄λ€.run_eval()μ μ§λ¬Έ λ¬Άμμ λλ €λ³΄κ³ , μ ν΄λ ν€μλκ° μλμ§λ‘ ν΅κ³Όλ₯Ό μ νλ μ±μ κΈ°λ€.
μ¦, βν λ² μλ λ°λͺ¨βκ° μλλΌ βλ§€λ² ν΅κ³Όνλ μμ€ν βμΌλ‘ λ°κΎΈλ κ³Όμ μ΄ νκ° λ£¨νλ€.
5) μ€λ¬΄ μ μ© ν¬μΈνΈ
- λ¦΄λ¦¬μ¦ κ²μ΄νΈ: λ°°ν¬ μ
scoreλ―Έλ¬μ΄λ©΄ μλ μ€λ¨. - νκ· λ°©μ§: ν둬ννΈ μμ νμλ κΈ°μ‘΄ μΌμ΄μ€λ₯Ό λ€μ λλ € νμ§ νλ½ κ°μ§.
- μ΄μ λ‘κ·Έ νμ€ν:
[SELFHECK],[EVAL]κ°μ΄ νμ± κ°λ₯ν κ³ μ ν€λ₯Ό λλ©΄ λμ보λ μ°λμ΄ μ¬μ. - ν
μ€νΈ μΌμ΄μ€ λΆλ¦¬: μ΄ν
eval_cases.jsonνμΌλ‘ λΆλ¦¬ν΄ νμμ 곡λ κ΄λ¦¬.
체ν¬λ¦¬μ€νΈ
- κ°μνκ²½ μμ±/νμ±ν μλ£
-
smolagentsimport μ±κ³΅ -
HF_TOKENλλ API ν€ μ€μ μλ£ - selfcheck 2κ° νλͺ© true
- eval score 0.67 μ΄μ
- μ€ν¨ μΌμ΄μ€ 1κ° μ΄μ μμΈ κΈ°λ‘
μ°Έκ³ λ§ν¬ (μ°μ μμ)
- https://github.com/huggingface/agents-course
- https://huggingface.co/learn/agents-course
- https://huggingface.co/docs/smolagents
μμ±ν AI νμ© κ³ μ§
μ΄ λ¬Έμλ μμ±ν AIλ₯Ό νμ©ν΄ μ΄μμ μμ±νκ³ , μμ μ½λ/μ μ°¨/ννμ μ¬λ κ²ν ν νμ νλ€.