๐ค 46. HF Agents Course ์ค์ตํธ 1 - smolagents๋ก ์ฝ์ค ๋ก๋๋งต CLI ๋ง๋ค๊ธฐ
๋ชฉํ: Hugging Face Agents Course ๊ณต์ ์๋ฃ์
smolagents๋ง ์จ์ ์ฝ์ค ๋ก๋๋งต์ ์ค๋ช ํ๊ณ ๋ฐ๋ก ์ค๋ ํ ๊ณผ์ ๊น์ง ์ ์ํ๋ CLI ๋ฏธ๋ ํ๋ก์ ํธ๋ฅผ ์ฌํํ๋ค.
์ด๋ฒ ์ค์ต์ HF Agents Course๊ฐ ๊ฐ์กฐํ๋ ๋ ์ถ์ ๋ฐ๋ก ์์ผ๋ก ํ์ธํ๋ ๋ฐ ๋ง์ถ๋ค.
- ์ฝ์ค๋ ๊ธฐ์ด ์ด๋ก โ ํ๋ ์์ํฌ โ ์ ์ค์ผ์ด์ค โ ์ต์ข ๊ณผ์ ํ๋ฆ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
smolagents๋ ์์ ์ฝ๋๋ก ์์ด์ ํธ์ ๋๊ตฌ๋ฅผ ๋น ๋ฅด๊ฒ ๋ถ์ฌ๋ณด๋ ์ถ๋ฐ์ ์ผ๋ก ์ ํฉํ๋ค.
์ฆ, ์ด๋ฒ ๊ธ์ โ๋ฌธ์๋ฅผ ์ฝ๊ณ ๋โ์ด ์๋๋ผ ๊ณต์ ์ฝ์ค ์๊ฐ ํ์ด์ง๋ฅผ ์ฝ๋ ๋๊ตฌ๋ฅผ ๋ง๋ค๊ณ , ๊ทธ ๋๊ตฌ๋ฅผ ์ฐ๋ ์์ด์ ํธ๊น์ง ์ฐ๊ฒฐํ๋ ์ฒซ ์ค์ตํธ์ด๋ค.
๋ฌด์์ ๋ง๋ค๊น
์ ๋ ฅ:
๋๋ ํ๋ฃจ 40๋ถ๋ง ํฌ์ํ ์ ์์ด. Unit 0, Unit 1, smolagents ์ค ๋ฌด์๋ถํฐ ๋ณด๊ณ ์ค๋ ๋ฐ๋ก ์ด๋ค ์์ ๋ฅผ ์คํํ๋ฉด ์ข์๊น?
์ถ๋ ฅ:
- ์ฝ์ค 3์ค ์์ฝ
- ์ถ์ฒ ํ์ต ์์
- ๊ฐ ํ์ด์ง๋ฅผ ์ ๋จผ์ ๋ด์ผ ํ๋์ง ์ค๋ช
- ์ค๋ ๋ฐ๋ก ์คํํ ๋ช ๋ น 1์ธํธ
- ์์ ์ ์ฒดํฌ๋ฆฌ์คํธ
์ด ์ค์ต์ด ์ข์ ์ด์
- ์ ๋ณด์์ GitHub ์ ์ฅ์ / ๊ณต์ ์ฝ์ค / smolagents ๋ฌธ์๋ก ์ ํํด ๋ต๋ณ ๊ทผ๊ฑฐ๊ฐ ํ๋ค๋ฆฌ์ง ์๋๋ค.
@tool+CodeAgent์กฐํฉ์ ๊ฐ์ฅ ์๊ฒ ๊ฒฝํํ ์ ์๋ค.- ๊ฒฐ๊ณผ๋ฌผ์ด ๋จ์ ๋ฐ๋ชจ๊ฐ ์๋๋ผ ๊ฐ์ธ ํ์ต ์ฝ์น CLI๋ผ์ ์ฌ์ฌ์ฉ ๊ฐ์น๊ฐ ๋๋ค.
์ ์ฒด ํ๋ฆ
flowchart TD Q[์ฌ์ฉ์ ์ง๋ฌธ] --> A[CodeAgent] A --> T[get_official_section ํด] T --> C[๊ณต์ ์ฝ์ค ํ์ด์ง ์ฝ๊ธฐ] C --> S[์น์ ๋ณ ํต์ฌ ์ ๋ณด ์์ถ] S --> R[ํ์ต ์์ + ์ค๋์ ์ค์ต ์ ์]
์ค๋น๋ฌผ
- Python 3.10+
- ํฐ๋ฏธ๋
- ์ธํฐ๋ท ์ฐ๊ฒฐ
- Hugging Face ๊ณ์ ๊ถ์ฅ
- ์ ํ:
HF_TOKENํ๊ฒฝ๋ณ์
Step 1) ์์ ํด๋ ์์ฑ
์ ๋ ฅ
mkdir -p ~/hf-agents-course-handson-01
cd ~/hf-agents-course-handson-01์ฑ๊ณต ํ์
pwd- ์ถ๋ ฅ ๋์ด
hf-agents-course-handson-01์ด๋ฉด ํต๊ณผ.
Step 2) ๊ฐ์ํ๊ฒฝ๊ณผ ํจํค์ง ์ค์น
์ ๋ ฅ
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -U pip
pip install "smolagents[toolkit]" requests beautifulsoup4์ฑ๊ณต ํ์
python -c "import smolagents, requests, bs4; print('install-ok')"install-ok๊ฐ ์ถ๋ ฅ๋๋ฉด ํต๊ณผ.
Step 3) CLI ์ฝ๋ ์์ฑ
roadmap_cli.py ํ์ผ์ ๋ง๋ค๊ณ ์๋ ์ฝ๋๋ฅผ ๋ฃ๋๋ค.
import requests
from bs4 import BeautifulSoup
from smolagents import CodeAgent, InferenceClientModel, tool
OFFICIAL_PAGES = {
"repo": "https://github.com/huggingface/agents-course",
"unit0": "https://huggingface.co/learn/agents-course/en/unit0/introduction",
"unit1": "https://huggingface.co/learn/agents-course/en/unit1/introduction",
"smolagents": "https://huggingface.co/docs/smolagents/index",
}
@tool
def get_official_section(name: str) -> str:
"""Read one official HF Agents Course related page and return a compact summary.
Args:
name: One of repo, unit0, unit1, smolagents.
"""
key = name.strip().lower()
if key not in OFFICIAL_PAGES:
return f"Unknown page: {key}. Choose from: {', '.join(OFFICIAL_PAGES)}"
response = requests.get(OFFICIAL_PAGES[key], timeout=30)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
title = soup.title.get_text(" ", strip=True) if soup.title else key
headings = []
for tag in soup.select("h1, h2, h3"):
text = tag.get_text(" ", strip=True)
if text and text not in headings:
headings.append(text)
if len(headings) >= 8:
break
snippets = []
for tag in soup.select("p, li"):
text = tag.get_text(" ", strip=True)
if len(text) >= 40 and text not in snippets:
snippets.append(text)
if len(snippets) >= 8:
break
return (
f"PAGE: {key}\n"
f"URL: {OFFICIAL_PAGES[key]}\n"
f"TITLE: {title}\n"
f"HEADINGS:\n- " + "\n- ".join(headings) + "\n\n"
f"SNIPPETS:\n- " + "\n- ".join(snippets)
)
model = InferenceClientModel()
agent = CodeAgent(
tools=[get_official_section],
model=model,
max_steps=6,
)
prompt = """
๊ณต์ ํ์ด์ง ์ ๋ณด๋ง ์ฌ์ฉํด์ ํ๊ตญ์ด๋ก ๋ตํด์ค.
์ง๋ฌธ: ๋๋ ํ๋ฃจ 40๋ถ๋ง ํฌ์ํ ์ ์์ด. HF Agents Course๋ฅผ ์ฒ์ ์์ํ๋ ์ฌ๋ ๊ธฐ์ค์ผ๋ก
repo, unit0, unit1, smolagents๋ฅผ ์ฐธ๊ณ ํด
1) 3์ค ์์ฝ
2) ์ถ์ฒ ํ์ต ์์
3) ์ค๋ ๋ฐ๋ก ์คํํ ์ค์ต 1๊ฐ
4) ์์ ์ ์ฒดํฌ๋ฆฌ์คํธ 4๊ฐ
ํ์์ผ๋ก ๋ตํด์ค.
๊ณต์ ํ์ด์ง์์ ์ง์ ํ์ธ๋์ง ์๋ ๋ด์ฉ์ '์ถ์ '์ด๋ผ๊ณ ํ์ํด์ค.
"""
result = agent.run(prompt)
print(result)Step 4) ์ฒซ ์คํ
์คํ ๋ช ๋ น
python roadmap_cli.py์ฑ๊ณต ํ์
์๋ 5๊ฐ๋ฅผ ๋ง์กฑํ๋ฉด ์ฑ๊ณต์ด๋ค.
- ์คํ์ด ์ค๊ฐ ์์ธ ์์ด ๋๋๋ค.
- ์ถ๋ ฅ ๋งจ ์์
3์ค ์์ฝ์ด ์๋ค. ์ถ์ฒ ํ์ต ์์๊ฐ ๋ฒํธ ๋ชฉ๋ก์ผ๋ก ๋์จ๋ค.์ค๋ ๋ฐ๋ก ์คํํ ์ค์ต 1๊ฐ์ ์ค์ ๋ช ๋ น ๋๋ ์ฝ๋ ์คํ ์ ์์ด ์๋ค.- ๊ณต์ ํ์ธ์ด ์ด๋ ค์ด ๋ด์ฉ์
์ถ์ ์ผ๋ก ํ์๋๋ค.
Step 5) ์ง๋ฌธ์ ๋ฐ๊ฟ ๋ค์ ๊ฒ์ฆ
๊ฐ์ ํ์ผ์์ prompt๋ง ์๋์ฒ๋ผ ๋ฐ๊พธ๊ณ ์ฌ์คํํ๋ค.
์ ๋ ฅ
๋๋ ์ด๋ก ์ ๊ธธ๊ฒ ์ฝ๊ธฐ๋ณด๋ค ๋นจ๋ฆฌ ์์ ์์ง์ด๊ณ ์ถ์ด.
Unit 1์ ์ต์ํ์ผ๋ก ๋ณด๊ณ smolagents๋ก ๋์ด๊ฐ๋ ๊ฐ์ฅ ์งง์ ํ์ต ๊ฒฝ๋ก์
์ง๊ธ ๋น์ฅ ์คํํ ์ฝ๋ 1๊ฐ๋ง ์ถ์ฒํด์ค.์คํ ๋ช ๋ น
python roadmap_cli.py์ฑ๊ณต ํ์
smolagents๊ฐ ์ฐ์ ์์์ ํฌํจ๋๋ค.- ๊ฒฝ๋ก๊ฐ 2~3๋จ๊ณ ์ ๋๋ก ์์ถ๋๋ค.
- ์คํํ ์ฝ๋ 1๊ฐ๊ฐ ๋ถ๋ฆฌ๋ผ ์ ์๋๋ค.
Step 6) ๊ฒฐ๊ณผ๋ฅผ ํ์ผ๋ก ์ ์ฅํด ์ฌ์ฌ์ฉ์ฑ ํ์ธ
์ค์ต ๊ฒฐ๊ณผ๋ฅผ ๋งค๋ฒ ๋ณต๋ถํ์ง ์๋๋ก ์ ์ฅ ๋ฆฌ๋ค์ด๋ ์ ๊น์ง ๋ถ์ธ๋ค.
์คํ ๋ช ๋ น
python roadmap_cli.py > latest-roadmap.md์ฑ๊ณต ํ์
ls -lh latest-roadmap.md
sed -n '1,40p' latest-roadmap.md- ํ์ผ์ด ์์ฑ๋๋ค.
- ์ฒซ 40์ค ์์ ์์ฝ/์ถ์ฒ ์์/์ค์ต ํญ๋ชฉ์ด ๋ณด์ธ๋ค.
์ฝ๋์์ ๊ผญ ํ์ธํ ํฌ์ธํธ
1) ๊ณต์ ์ ๋ณด์ ์ ํ
OFFICIAL_PAGES๋ฅผ ๊ณ ์ ํด๋๋ฉด, ์์ด์ ํธ๊ฐ ์์ ๋ธ๋ก๊ทธ๋ ๊ฒ์ ๊ฒฐ๊ณผ๋ก ์์ง ์๊ณ ๊ณต์ ์๋ฃ๋ง ๊ทผ๊ฑฐ๋ก ์ผ๊ฒ ๋๋ค.
2) CodeAgent์ ๋น ๋ฅธ ์คํ์ฑ
smolagents ๋ฌธ์๋ CodeAgent๋ฅผ ๋งค์ฐ ์ ์ ์ฝ๋๋ก ์์ํ ์ ์๋ ์ฅ์ ์ผ๋ก ์๊ฐํ๋ค. ์ด๋ฒ ์ค์ต์ ๊ทธ ์ฅ์ ์ ํ์ต ์ฝ์น CLI๋ก ๋ฐ๋ก ์ฒด๊ฐํ๊ฒ ๋ง๋ ๋ค.
3) ์ฝ์ค ๊ตฌ์กฐ์ ์ค์ต ์ฐ๊ฒฐ
๊ณต์ ์ฝ์ค ์๊ฐ๋ ์ด๋ก ๋ง์ด ์๋๋ผ ํธ์ฆ์จ๊ณผ ๊ณผ์ ์ํ ํ๋ฆ์ ๊ฐ์กฐํ๋ค. ๊ทธ๋์ ์ถ๋ ฅ ํ์๋ ์์ฝ์ผ๋ก ๋๋ด์ง ์๊ณ โ์ค๋ ๋ฐ๋ก ํ ์ค์ตโ์ ํ์๋ก ๋๋ค.
์ค์ ์ฒดํฌ๋ฆฌ์คํธ
- ๊ฐ์ํ๊ฒฝ ํ์ฑํ
-
smolagents,requests,beautifulsoup4์ค์น ํ์ธ -
roadmap_cli.py์ ์ฅ ์๋ฃ - ์ฒซ ์คํ ์ฑ๊ณต
- ์ง๋ฌธ ๋ณ๊ฒฝ ํ ์ฌ์คํ ์ฑ๊ณต
-
latest-roadmap.md์ ์ฅ ์ฑ๊ณต
ํธ๋ฌ๋ธ์ํ
1) ModuleNotFoundError: No module named 'smolagents'
์์ธ:
- ๋ค๋ฅธ ํ์ด์ฌ ์ธํฐํ๋ฆฌํฐ๋ก ์คํํจ
- ๊ฐ์ํ๊ฒฝ์ด ๋นํ์ฑํ๋จ
ํด๊ฒฐ:
source .venv/bin/activate
which python
python -m pip install "smolagents[toolkit]"2) requests.exceptions.ReadTimeout
์์ธ:
- ๋คํธ์ํฌ ์ง์ฐ
- ๊ณต์ ํ์ด์ง ์๋ต ์ง์ฐ
ํด๊ฒฐ:
response = requests.get(OFFICIAL_PAGES[key], timeout=60)timeout์ ๋๋ฆฐ๋ค.- ๋ธ๋ผ์ฐ์ ์์ URL์ด ์ด๋ฆฌ๋์ง ๋จผ์ ํ์ธํ๋ค.
3) 401 ๋๋ ๋ชจ๋ธ ์ธ์ฆ ์ค๋ฅ
์์ธ:
- ์คํ ํ๊ฒฝ์์ Hugging Face Inference ์ธ์ฆ์ด ํ์ํจ
ํด๊ฒฐ:
export HF_TOKEN=hf_xxx_your_token
python roadmap_cli.py- ํ ํฐ ์ค์ ํ ๋ค์ ์คํํ๋ค.
4) ์ถ๋ ฅ์ด ๋๋ฌด ์ผ๋ฐ๋ก ์ ์ผ ๋
์์ธ:
- ํ๋กฌํํธ์์ ๊ณต์ ํ์ด์ง ์ด๋ฆ์ ๋ช ์ํ์ง ์์
- ์ถ๋ ฅ ํ์ ์ ์ฝ์ด ์ฝํจ
ํด๊ฒฐ:
repo, unit0, unit1, smolagents๋ฅผ ์ฐธ๊ณ ํด๋ฌธ์ฅ์ ์ ์งํ๋ค.- ์ถ๋ ฅ ํ์์ ๋ฒํธ ๋ชฉ๋ก์ผ๋ก ๊ณ ์ ํ๋ค.
- ํ์ธ ๋ถ๊ฐ ๋ด์ฉ์
์ถ์ ํ๊ธฐ๋ฅผ ๊ฐ์ ํ๋ค.
5) ๋ณธ๋ฌธ ์ถ์ถ์ด ๋น์ฝํ ๋
์์ธ:
- ํ์ด์ง ๋งํฌ์
๊ตฌ์กฐ๊ฐ ๋ฌ๋ผ
p,li์ ํ์ด ์ถฉ๋ถ์น ์์
ํด๊ฒฐ:
for tag in soup.select("main p, main li, article p, article li, h2, h3"):- ์ ํ์๋ฅผ ๋ ๊ตฌ์ฒดํํ๋ค.
- ํ์ํ๋ฉด
response.text[:2000]๋ฅผ ์ ์ฅํด HTML ๊ตฌ์กฐ๋ฅผ ์ง์ ํ์ธํ๋ค.
6) GitHub ์ ์ฅ์ ํ์ด์ง์์ ๋ด์ฉ์ด ๊ธฐ๋๋ณด๋ค ์งง๊ฒ ์กํ ๋
์์ธ:
- GitHub HTML ๊ตฌ์กฐ ํน์ฑ์ ๋ณธ๋ฌธ ์ถ์ถ์ด ์ ํ๋ ์ ์์
ํด๊ฒฐ:
- ์ ์ฅ์๋ ์ ์ฒด ์ฝ์ค ๊ตฌ์กฐ ํ์ธ์ฉ์ผ๋ก๋ง ์ฐ๊ณ ,
- ์ค์ ์ธ๋ถ ์ค๋ช
์
unit0,unit1,smolagentsํ์ด์ง ๋น์ค์ ๋์ฌ ํ๋กฌํํธ๋ฅผ ์กฐ์ ํ๋ค.
ํ์ฅ ์์ด๋์ด
unit2,unit3,unit4๋ฅผ ์ถ๊ฐํด ์ค๊ธ ํ์ต ๊ฒฝ๋ก ์ถ์ฒ๊ธฐ๋ก ํ์ฅํ๊ธฐ- ์๋ต์ Markdown ํ
ํ๋ฆฟ์ผ๋ก ์ ์ฅํ๋
save_reportํด ์ถ๊ฐํ๊ธฐ DuckDuckGoSearchTool()์ ๋ถ์ฌ ๊ณต์ ์๋ฃ์ ์ปค๋ฎค๋ํฐ ์๋ฃ๋ฅผ ๋ถ๋ฆฌ ๋น๊ตํ๊ธฐ- ์ฌ์ฉ์ ๊ฐ์ฉ ์๊ฐ(20๋ถ/40๋ถ/90๋ถ)์ ๋ฐ๋ผ ๋ค๋ฅธ ํ์ต ๊ฒฝ๋ก๋ฅผ ๋ด๋๊ฒ ๋ง๋ค๊ธฐ
๋ง๋ฌด๋ฆฌ
์ด๋ฒ ์ค์ต์ ํต์ฌ์ ์์ด์ ํธ์๊ฒ โ๋๋ํ๊ฒ ๋ตํ๋ผโ๋ผ๊ณ ๋ง ๋งํ๋ ๊ฒ์ด ์๋๋ค. ๊ณต์ ์๋ฃ๋ฅผ ์ฝ๋ ๋๊ตฌ๋ฅผ ๋จผ์ ๋ง๋ค๊ณ , ๊ทธ ๋๊ตฌ ์์์ ๋ตํ๊ฒ ํ๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋๋ ๊ฒ์ด ํต์ฌ์ด๋ค. ์ด ํ ๋ฒ์ ์ต๊ด์ด ์ดํ Unit 2 ํ๋ ์์ํฌ ์ค์ต๊ณผ ์ต์ข ํ๋ก์ ํธ ํ์ง์ ํฌ๊ฒ ์ข์ฐํ๋ค.
์์ฑํ AI ํ์ฉ ๊ณ ์ง
์ด ๋ฌธ์๋ ์์ฑํ AI๋ฅผ ํ์ฉํด ์ด์ ๊ตฌ์กฐ์ ์์ ์ฝ๋๋ฅผ ์์ฑํ๊ณ , ๊ณต๊ฐ๋ Hugging Face Agents Course ์ ์ฅ์ยท๊ณต์ ์ฝ์ค ํ์ด์งยทsmolagents ๋ฌธ์๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฌ๋์ด ์ฌํ ๋จ๊ณ, ๋ช ๋ น, ์ฑ๊ณต ํ์ , ํธ๋ฌ๋ธ์ํ , ๋งํฌ ๋ฐ์ ์ฌ๋ถ๋ฅผ ๊ฒํ ํด ํธ์งํ์ต๋๋ค.