์ด๋ฒˆ ํŽธ์€ **โ€œ์›น์—์„œ ๊ทผ๊ฑฐ๋ฅผ ์ฐพ๊ณ , 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')))
PY
  • OPENAI_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๊ฐœ ์ด์ƒ)

  1. 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
  • ์กฐ์น˜: ํ‚ค ์žฌ์„ค์ • ํ›„ ๋™์ผ ๋ช…๋ น ์žฌ์‹คํ–‰
  1. ImportError: DuckDuckGoSearchTool
  • ์›์ธ: smolagents ๊ตฌ๋ฒ„์ „ ๋˜๋Š” ํŒจํ‚ค์ง€ ๋ถˆ์ผ์น˜
  • ์กฐ์น˜:
pip install -U smolagents duckduckgo-search
python - <<'PY'
from smolagents import DuckDuckGoSearchTool
print('ok')
PY
  1. JSON ํŒŒ์‹ฑ ์‹คํŒจ (json.loads ์—๋Ÿฌ)
  • ์›์ธ: ๋ชจ๋ธ์ด ์„ค๋ช… ๋ฌธ์žฅ์„ ์„ž์–ด ์ถœ๋ ฅ
  • ์กฐ์น˜:
    • ํ”„๋กฌํ”„ํŠธ์— JSON ๋ฌธ์ž์—ด 1๊ฐœ๋งŒ ๊ทœ์น™ ์œ ์ง€
    • ํ•„์š” ์‹œ ์ฝ”๋“œ์—์„œ ์ฝ”๋“œ๋ธ”๋ก/์žก๋ฌธ ์ œ๊ฑฐ ํ›„ ํŒŒ์‹ฑ
  1. ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ์—์„œ URL ๊ฒ€์ฆ ์‹คํŒจ
  • ์›์ธ: sources.url์ด ๋นˆ ๊ฐ’ ๋˜๋Š” ๋น„์ •์ƒ ๋ฌธ์ž์—ด
  • ์กฐ์น˜:
    • ํ”„๋กฌํ”„ํŠธ์— URL์€ ์‹ค์ œ ์›น ์ฃผ์†Œ ๊ทœ์น™ ๊ฐ•ํ™”
    • sources ์ตœ์†Œ ๊ฐœ์ˆ˜์™€ ํ˜•์‹์„ assert๋กœ ๊ณ ์ •

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

  • CodeAgent + DuckDuckGoSearchTool ์‹คํ–‰ ์„ฑ๊ณต
  • briefing_result.json ์ €์žฅ ์™„๋ฃŒ
  • 5์ค„ ์š”์•ฝ + ์ถœ์ฒ˜ 3๊ฐœ ์ด์ƒ ์ถฉ์กฑ
  • ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ ์Šคํฌ๋ฆฝํŠธ PASS
  • ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… 3๊ฐœ ์ด์ƒ ์žฌํ˜„/์ •๋ฆฌ

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

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

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

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