์ด๋ฒ ํธ์ **โ์น์์ ๊ทผ๊ฑฐ๋ฅผ ์ฐพ๊ณ , 5์ค ๋ธ๋ฆฌํ์ผ๋ก ์ ๋ฆฌํ๋ ๋ฆฌ์์น ์์ด์ ํธโ**๋ฅผ ์ง์ ๋ง๋๋ ๋ฏธ๋ ํ๋ก์ ํธ๋ค.
ํต์ฌ์ ์๋ 4๊ฐ์ง๋ฅผ ์ฌํ ๊ฐ๋ฅํ๊ฒ ๋๋ด๋ ๊ฒ์ด๋ค.
-
๋๊ตฌ ์ค์น์ ์คํ ํ๊ฒฝ ์ค๋น
-
๊ฒ์ ๋๊ตฌ๋ฅผ ๋ถ์ธ
CodeAgent์คํ -
๊ฒฐ๊ณผ๋ฅผ JSON ํ์ผ๋ก ์ ์ฅ
-
์คํจ ํจํด 3๊ฐ์ง ์ด์์ ์ค์ค๋ก ๋ณต๊ตฌ
-
์ด์ ํธ: ๐ค 21. ๋ณธํธ 12
-
๋ค์ ํธ ์๊ณ : ์ค์ตํธ 06-2 (๊ฒ์ฆ ๋ฃจํ ์ถ๊ฐ: ๊ทผ๊ฑฐ ๋งํฌ ๋๋ฝ ์๋ ์ ๊ฒ)
flowchart TD A[์ฌ์ฉ์ ์ฃผ์ ์ ๋ ฅ] --> B[CodeAgent + DuckDuckGoSearchTool ์คํ] B --> C[์น ๊ฒ์/์์ฝ] C --> D[๊ตฌ์กฐํ ๊ฒฐ๊ณผ(JSON) ์์ฑ] D --> E[briefing_result.json ์ ์ฅ] E --> F{๊ฒ์ฆ ํต๊ณผ?} F -- Yes --> G[์๋ฃ] F -- No --> H[ํ๋กฌํํธ/ํ๊ฒฝ ์์ ํ ์ฌ์คํ] H --> B
0) ์ค์ต ๋ชฉํ
์ ๋ ฅ ์ฃผ์ 1๊ฐ๋ฅผ ๋ฃ์ผ๋ฉด, ์์ด์ ํธ๊ฐ ์น ๊ทผ๊ฑฐ๋ฅผ ์ฐพ์ 5์ค ๋ธ๋ฆฌํ + ์ถ์ฒ๋ฅผ JSON์ผ๋ก ์ ์ฅํ๊ฒ ๋ง๋ ๋ค.
1) ํ๊ฒฝ ์ค๋น
- ๋๊ตฌ: ํฐ๋ฏธ๋
- ์ ๋ ฅ: Python 3.10+
- ์คํ๋ช ๋ น:
mkdir -p ~/hf-agents-lab22
cd ~/hf-agents-lab22
python3 -m venv .venv
source .venv/bin/activate
pip install -U smolagents litellm duckduckgo-search- ์ฑ๊ณตํ์ :
python -V
pip show smolagents | head -n 5
pip show duckduckgo-search | head -n 5- Python ๋ฒ์ ์ถ๋ ฅ
smolagents,duckduckgo-searchํจํค์ง ์ ๋ณด๊ฐ ๋ณด์ด๋ฉด ์ฑ๊ณต
2) ๋ชจ๋ธ ์ค์
- ๋๊ตฌ: ํฐ๋ฏธ๋
- ์ ๋ ฅ: API ํค + ๋ชจ๋ธ ID
- ์คํ๋ช ๋ น:
export OPENAI_API_KEY="YOUR_API_KEY"
export MODEL_ID="openai/gpt-4o-mini"- ์ฑ๊ณตํ์ :
python - <<'PY'
import os
print('MODEL_ID =', os.getenv('MODEL_ID'))
print('OPENAI_API_KEY set:', bool(os.getenv('OPENAI_API_KEY')))
PYOPENAI_API_KEY set: Trueํ์ธ
3) ๋ฏธ๋ ํ๋ก์ ํธ ์ฝ๋ ์์ฑ
- ๋๊ตฌ: ์๋ํฐ/ํฐ๋ฏธ๋
- ์ ๋ ฅ: ์๋ ์ฝ๋
- ์คํ๋ช ๋ น:
cat > lab22_research_briefing.py <<'PY'
from __future__ import annotations
import json
import os
from datetime import datetime
from pathlib import Path
from smolagents import CodeAgent, DuckDuckGoSearchTool, LiteLLMModel
OUT = Path("briefing_result.json")
TOPIC = "ํ๊ตญ AI ์์ด์ ํธ ์์ฅ์์ 2026๋
์ ์ค๋ฌด์๊ฐ ๋ฐ๋ก ์ ์ฉํ ๋งํ ํธ๋ ๋ 3๊ฐ์ง"
PROMPT = f"""
์๋ ์ฃผ์ ์ ๋ํด ์น ๊ฒ์ ๊ธฐ๋ฐ์ผ๋ก 5์ค ๋ธ๋ฆฌํ์ ์์ฑํ๋ผ.
์ฃผ์ : {TOPIC}
์ถ๋ ฅ์ ๋ฐ๋์ JSON ๋ฌธ์์ด 1๊ฐ๋ง ๋ฐํ:
{{
"topic": "...",
"summary_5_lines": ["...", "...", "...", "...", "..."],
"sources": [
{{"title": "...", "url": "..."}},
{{"title": "...", "url": "..."}},
{{"title": "...", "url": "..."}}
]
}}
๊ท์น:
- sources๋ ์ต์ 3๊ฐ
- URL์ ์ค์ ์น ์ฃผ์์ฌ์ผ ํจ
- ์ถ์ /ํ๊ฐ ๊ธ์ง, ์ฐพ์ง ๋ชปํ๋ฉด ์ฐพ์ง ๋ชปํ๋ค๊ณ ๋ช
์
"""
def main() -> None:
model = LiteLLMModel(model_id=os.getenv("MODEL_ID", "openai/gpt-4o-mini"))
agent = CodeAgent(
model=model,
tools=[DuckDuckGoSearchTool()],
max_steps=8,
additional_authorized_imports=["json", "datetime"],
)
raw = agent.run(PROMPT)
text = str(raw)
# ๋ชจ๋ธ ์ถ๋ ฅ์ด ์ฝ๋๋ธ๋ก์ผ๋ก ๊ฐ์ธ์ง ์ ์์ด ๋ฐฉ์ด์ ์ผ๋ก ์ฒ๋ฆฌ
text = text.strip()
if text.startswith("```"):
text = text.strip("`")
text = text.replace("json", "", 1).strip()
obj = json.loads(text)
obj["generated_at"] = datetime.now().isoformat(timespec="seconds")
OUT.write_text(json.dumps(obj, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"saved: {OUT}")
print(json.dumps({
"topic": obj.get("topic"),
"summary_count": len(obj.get("summary_5_lines", [])),
"source_count": len(obj.get("sources", [])),
}, ensure_ascii=False))
if __name__ == "__main__":
main()
PY- ์ฑ๊ณตํ์ :
lab22_research_briefing.py์์ฑ- ์ฝ๋์
DuckDuckGoSearchTool,CodeAgentํ์ธ
4) ์คํ ๋ฐ ๊ฒฐ๊ณผ ์ ์ฅ
- ๋๊ตฌ: Python
- ์
๋ ฅ:
TOPIC๋ฌธ์์ด - ์คํ๋ช ๋ น:
python lab22_research_briefing.py
cat briefing_result.json- ์ฑ๊ณตํ์ :
saved: briefing_result.json์ถ๋ ฅ- JSON์
summary_5_lines(5๊ฐ),sources(3๊ฐ ์ด์) ํฌํจ
5) ํ์ง ๊ฒ์ดํธ(์ฌํ ์ฒดํฌ)
- ๋๊ตฌ: Python
- ์
๋ ฅ:
briefing_result.json - ์คํ๋ช ๋ น:
python - <<'PY'
import json
from urllib.parse import urlparse
obj = json.load(open('briefing_result.json', encoding='utf-8'))
assert isinstance(obj.get('summary_5_lines'), list), 'summary_5_lines must be list'
assert len(obj['summary_5_lines']) == 5, 'summary must be exactly 5 lines'
assert isinstance(obj.get('sources'), list) and len(obj['sources']) >= 3, 'sources >= 3 required'
for s in obj['sources']:
u = s.get('url', '')
p = urlparse(u)
assert p.scheme in ('http', 'https') and p.netloc, f'invalid url: {u}'
print('PASS: ํ์ง ๊ฒ์ดํธ ํต๊ณผ')
PY- ์ฑ๊ณตํ์ :
PASS: ํ์ง ๊ฒ์ดํธ ํต๊ณผ์ถ๋ ฅ
ํธ๋ฌ๋ธ์ํ (3๊ฐ ์ด์)
AuthenticationError/ ๋ชจ๋ธ ํธ์ถ ์คํจ
- ์์ธ: API ํค ๋ฏธ์ค์ /์คํ
- ์ ๊ฒ:
python - <<'PY'
import os
print('OPENAI_API_KEY set:', bool(os.getenv('OPENAI_API_KEY')))
print('MODEL_ID:', os.getenv('MODEL_ID'))
PY- ์กฐ์น: ํค ์ฌ์ค์ ํ ๋์ผ ๋ช ๋ น ์ฌ์คํ
ImportError: DuckDuckGoSearchTool
- ์์ธ:
smolagents๊ตฌ๋ฒ์ ๋๋ ํจํค์ง ๋ถ์ผ์น - ์กฐ์น:
pip install -U smolagents duckduckgo-search
python - <<'PY'
from smolagents import DuckDuckGoSearchTool
print('ok')
PY- JSON ํ์ฑ ์คํจ (
json.loads์๋ฌ)
- ์์ธ: ๋ชจ๋ธ์ด ์ค๋ช ๋ฌธ์ฅ์ ์์ด ์ถ๋ ฅ
- ์กฐ์น:
- ํ๋กฌํํธ์
JSON ๋ฌธ์์ด 1๊ฐ๋ง๊ท์น ์ ์ง - ํ์ ์ ์ฝ๋์์ ์ฝ๋๋ธ๋ก/์ก๋ฌธ ์ ๊ฑฐ ํ ํ์ฑ
- ํ๋กฌํํธ์
- ํ์ง ๊ฒ์ดํธ์์ URL ๊ฒ์ฆ ์คํจ
- ์์ธ:
sources.url์ด ๋น ๊ฐ ๋๋ ๋น์ ์ ๋ฌธ์์ด - ์กฐ์น:
- ํ๋กฌํํธ์
URL์ ์ค์ ์น ์ฃผ์๊ท์น ๊ฐํ sources์ต์ ๊ฐ์์ ํ์์ assert๋ก ๊ณ ์
- ํ๋กฌํํธ์
์ฒดํฌ๋ฆฌ์คํธ
-
CodeAgent + DuckDuckGoSearchTool์คํ ์ฑ๊ณต -
briefing_result.json์ ์ฅ ์๋ฃ - 5์ค ์์ฝ + ์ถ์ฒ 3๊ฐ ์ด์ ์ถฉ์กฑ
- ํ์ง ๊ฒ์ดํธ ์คํฌ๋ฆฝํธ PASS
- ํธ๋ฌ๋ธ์ํ 3๊ฐ ์ด์ ์ฌํ/์ ๋ฆฌ
์ฐธ๊ณ ๋งํฌ (์ฐ์ ์์)
- https://github.com/huggingface/agents-course
- https://huggingface.co/learn/agents-course
- https://huggingface.co/docs/smolagents
์์ฑํ AI ํ์ฉ ๊ณ ์ง
์ด ๋ฌธ์๋ ์์ฑํ AI๋ก ์ด์์ ์์ฑํ๊ณ , ์ฌ๋์ด ์ค์ต ์ฌํ์ฑ(๋๊ตฌ/์ ๋ ฅ/์คํ๋ช ๋ น/์ฑ๊ณตํ์ ), ๋งํฌ ์ ํจ์ฑ, ๋ฌธ์ ํ์์ ๊ฒํ ํด ์ต์ข ํ์ ํ๋ค.