์ด๋ฒˆ ํŽธ์€ **โ€œ์šด์˜ ๋กœ๊ทธ ํ…์ŠคํŠธ๋ฅผ ์ž…๋ ฅํ•˜๋ฉด, ์—์ด์ „ํŠธ๊ฐ€ ์žฅ์•  ์š”์•ฝ + ์‹ฌ๊ฐ๋„ + ์ฆ‰์‹œ ์กฐ์น˜์•ˆ์„ JSON์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•ธ์ฆˆ์˜จโ€**์ด๋‹ค.
HF Agents Course์˜ Hands-on ํ๋ฆ„(์ž‘๊ฒŒ ๋งŒ๋“ค๊ณ , ๊ฒ€์ฆ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋ฐ˜๋ณต)๊ณผ smolagents ์‹ค๋ฌด ํŒจํ„ด(CodeAgent + ๊ตฌ์กฐํ™” ์ถœ๋ ฅ)์„ ๊ทธ๋Œ€๋กœ ์žฌํ˜„ํ•œ๋‹ค.

  • ์ด์ „ ํŽธ: ๐Ÿค— 27. ๋ณธํŽธ 16
  • ๋‹ค์Œ ํŽธ ์˜ˆ๊ณ : ์‹ค์ŠตํŽธ 08-2 (๋‹ค์ค‘ ์„œ๋น„์Šค ๋กœ๊ทธ ๋ฐฐ์น˜ ์ฒ˜๋ฆฌ + ๋ฆฌํฌํŠธ ์ž๋™ ์ €์žฅ)
flowchart TD
  A[raw_log.txt ์ž…๋ ฅ] --> B[CodeAgent ์‹คํ–‰]
  B --> C[๋กœ๊ทธ ํ•ต์‹ฌ ์ด๋ฒคํŠธ ์ถ”์ถœ]
  C --> D[์‹ฌ๊ฐ๋„ ๋ถ„๋ฅ˜ sev0~sev3]
  D --> E[์กฐ์น˜์•ˆ + ๊ทผ๊ฑฐ JSON ์ƒ์„ฑ]
  E --> F[incident_summary.json ์ €์žฅ]
  F --> G{ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ ํ†ต๊ณผ?}
  G -- Yes --> H[์™„๋ฃŒ]
  G -- No --> I[ํ”„๋กฌํ”„ํŠธ/์ž…๋ ฅ ์ˆ˜์ • ํ›„ ์žฌ์‹คํ–‰]
  I --> B

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

๋‹จ์ผ ๋กœ๊ทธ ํŒŒ์ผ(raw_log.txt)์„ ๋„ฃ์–ด incident_summary.json์„ ์ƒ์„ฑํ•˜๊ณ , ๊ฒ€์ฆ ์Šคํฌ๋ฆฝํŠธ๊นŒ์ง€ PASSํ•œ๋‹ค.


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

  • ๋„๊ตฌ: ํ„ฐ๋ฏธ๋„
  • ์ž…๋ ฅ: Python 3.10+
  • ์‹คํ–‰๋ช…๋ น:
mkdir -p ~/hf-agents-lab28
cd ~/hf-agents-lab28
python3 -m venv .venv
source .venv/bin/activate
pip install -U "smolagents[toolkit]" litellm
  • ์„ฑ๊ณตํŒ์ •:
python -V
pip show smolagents | head -n 5
pip show litellm | head -n 5
  • Python ๋ฒ„์ „ ์ถœ๋ ฅ
  • smolagents, litellm ํŒจํ‚ค์ง€ ์ •๋ณด ํ™•์ธ

2) ๋ชจ๋ธ/API ์„ค์ •

  • ๋„๊ตฌ: ํ„ฐ๋ฏธ๋„
  • ์ž…๋ ฅ: 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 > raw_log.txt <<'LOG'
2026-04-18T08:55:11Z INFO api-gateway request_id=aa12 path=/checkout latency_ms=92 status=200
2026-04-18T08:55:12Z WARN payment-service request_id=aa12 retry=1 reason=upstream_timeout
2026-04-18T08:55:14Z ERROR payment-service request_id=aa12 error=DBConnectionRefused host=db-prod-1
2026-04-18T08:55:16Z ERROR payment-service request_id=aa13 error=DBConnectionRefused host=db-prod-1
2026-04-18T08:55:20Z WARN api-gateway request_id=aa14 path=/checkout latency_ms=3200 status=504
2026-04-18T08:55:25Z INFO alertmanager fired=true service=payment-service rule=high_error_rate
LOG
  • ์„ฑ๊ณตํŒ์ •:
wc -l raw_log.txt
  • 6 raw_log.txt ์ถœ๋ ฅ

4) ๋ฏธ๋‹ˆ ํ”„๋กœ์ ํŠธ ์ฝ”๋“œ ์ž‘์„ฑ

  • ๋„๊ตฌ: ์—๋””ํ„ฐ/ํ„ฐ๋ฏธ๋„
  • ์ž…๋ ฅ: ์•„๋ž˜ ์ฝ”๋“œ
  • ์‹คํ–‰๋ช…๋ น:
cat > lab28_incident_agent.py <<'PY'
from __future__ import annotations
 
import json
import os
from pathlib import Path
 
from smolagents import CodeAgent, LiteLLMModel
 
INPUT_PATH = Path("raw_log.txt")
OUTPUT_PATH = Path("incident_summary.json")
 
 
def strip_code_fence(text: str) -> str:
    t = text.strip()
    if t.startswith("```"):
        lines = t.splitlines()
        if lines and lines[0].startswith("```"):
            lines = lines[1:]
        if lines and lines[-1].startswith("```"):
            lines = lines[:-1]
        t = "\n".join(lines).strip()
    return t
 
 
def main() -> None:
    raw_log = INPUT_PATH.read_text(encoding="utf-8")
 
    model = LiteLLMModel(model_id=os.getenv("MODEL_ID", "openai/gpt-4o-mini"))
    agent = CodeAgent(
        model=model,
        tools=[],
        max_steps=6,
        additional_authorized_imports=["json", "re"],
    )
 
    prompt = f"""
๋„ˆ๋Š” SRE ๋ณด์กฐ ์—์ด์ „ํŠธ๋‹ค.
์•„๋ž˜ ์šด์˜ ๋กœ๊ทธ๋ฅผ ๋ถ„์„ํ•ด JSON๋งŒ ๋ฐ˜ํ™˜ํ•˜๋ผ.
 
[๋กœ๊ทธ]
{raw_log}
 
์ถœ๋ ฅ ์Šคํ‚ค๋งˆ(ํ‚ค ์ด๋ฆ„ ๊ณ ์ •):
{{
  "service": "string",
  "severity": "sev0|sev1|sev2|sev3",
  "summary": ["๋ฌธ์žฅ", "๋ฌธ์žฅ", "๋ฌธ์žฅ"],
  "probable_root_cause": "string",
  "immediate_actions": ["๋ฌธ์žฅ", "๋ฌธ์žฅ", "๋ฌธ์žฅ"],
  "evidence": [
    {{"line": "์›๋ฌธ ์ผ๋ถ€", "reason": "ํŒ๋‹จ ๊ทผ๊ฑฐ"}}
  ]
}}
 
๊ทœ์น™:
- summary๋Š” ์ •ํ™•ํžˆ 3๊ฐœ
- immediate_actions๋Š” ์ •ํ™•ํžˆ 3๊ฐœ
- evidence๋Š” ์ตœ์†Œ 2๊ฐœ
- JSON ์™ธ ํ…์ŠคํŠธ ๊ธˆ์ง€
"""
 
    result = agent.run(prompt)
    obj = json.loads(strip_code_fence(str(result)))
 
    OUTPUT_PATH.write_text(json.dumps(obj, ensure_ascii=False, indent=2), encoding="utf-8")
    print(f"saved: {OUTPUT_PATH}")
    print(json.dumps({
        "service": obj.get("service"),
        "severity": obj.get("severity"),
        "evidence_count": len(obj.get("evidence", [])),
    }, ensure_ascii=False))
 
 
if __name__ == "__main__":
    main()
PY
  • ์„ฑ๊ณตํŒ์ •:
    • lab28_incident_agent.py ์ƒ์„ฑ
    • ์ฝ”๋“œ์— CodeAgent, JSON ์Šคํ‚ค๋งˆ, strip_code_fence() ์กด์žฌ

5) ์‹คํ–‰ ๋ฐ ๊ฒฐ๊ณผ ์ €์žฅ

  • ๋„๊ตฌ: Python
  • ์ž…๋ ฅ: raw_log.txt
  • ์‹คํ–‰๋ช…๋ น:
python lab28_incident_agent.py
cat incident_summary.json
  • ์„ฑ๊ณตํŒ์ •:
    • saved: incident_summary.json ์ถœ๋ ฅ
    • JSON์— severity, summary(3๊ฐœ), immediate_actions(3๊ฐœ) ํ™•์ธ

6) ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ(์žฌํ˜„์„ฑ ๊ฒ€์ฆ)

  • ๋„๊ตฌ: Python
  • ์ž…๋ ฅ: incident_summary.json
  • ์‹คํ–‰๋ช…๋ น:
python - <<'PY'
import json
 
obj = json.load(open('incident_summary.json', encoding='utf-8'))
 
assert obj.get('severity') in {'sev0','sev1','sev2','sev3'}, 'invalid severity'
assert isinstance(obj.get('summary'), list) and len(obj['summary']) == 3, 'summary must be 3'
assert isinstance(obj.get('immediate_actions'), list) and len(obj['immediate_actions']) == 3, 'immediate_actions must be 3'
assert isinstance(obj.get('evidence'), list) and len(obj['evidence']) >= 2, 'evidence must be >=2'
for ev in obj['evidence']:
    assert 'line' in ev and 'reason' in ev, 'evidence item must include line/reason'
 
print('PASS: ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ ํ†ต๊ณผ')
PY
  • ์„ฑ๊ณตํŒ์ •:
    • PASS: ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ ํ†ต๊ณผ

ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… (์‹ค์ „ 5์„ )

  1. AuthenticationError / ๋ชจ๋ธ ํ˜ธ์ถœ ์‹คํŒจ
  • ์›์ธ: API ํ‚ค ๋ฏธ์„ค์ •, ๋ชจ๋ธ ID ์˜คํƒ€
  • ์ ๊ฒ€:
python - <<'PY'
import os
print('OPENAI_API_KEY set =', bool(os.getenv('OPENAI_API_KEY')))
print('MODEL_ID =', os.getenv('MODEL_ID'))
PY
  • ์กฐ์น˜: ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์žฌ์„ค์ • ํ›„ ์žฌ์‹คํ–‰
  1. ModuleNotFoundError: smolagents
  • ์›์ธ: ๊ฐ€์ƒํ™˜๊ฒฝ ๋ฏธํ™œ์„ฑํ™” ๋˜๋Š” ์„ค์น˜ ๋ˆ„๋ฝ
  • ์กฐ์น˜:
source .venv/bin/activate
pip install -U "smolagents[toolkit]" litellm
  1. json.loads ํŒŒ์‹ฑ ์‹คํŒจ
  • ์›์ธ: ๋ชจ๋ธ์ด JSON ์™ธ ์„ค๋ช… ๋ฌธ์žฅ์„ ์„ž์–ด ์ถœ๋ ฅ
  • ์กฐ์น˜:
    • ํ”„๋กฌํ”„ํŠธ์— JSON ์™ธ ํ…์ŠคํŠธ ๊ธˆ์ง€ ์œ ์ง€
    • strip_code_fence() ์œ ์ง€
    • ํ•„์š” ์‹œ max_steps๋ฅผ ์ค„์—ฌ ์‚ฐ๋งŒํ•œ ์‘๋‹ต ๋ฐฉ์ง€
  1. ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ์—์„œ summary/immediate_actions ๊ฐœ์ˆ˜ ๋ถˆ์ผ์น˜
  • ์›์ธ: ์Šคํ‚ค๋งˆ ๊ฐ•์ œ ๊ทœ์น™์ด ์•ฝํ•จ
  • ์กฐ์น˜:
    • ํ”„๋กฌํ”„ํŠธ ๊ทœ์น™์— ์ •ํ™•ํžˆ 3๊ฐœ๋ฅผ ๋ช…์‹œ
    • ์‹คํŒจ ์‹œ ๋™์ผ ์ž…๋ ฅ์œผ๋กœ ์žฌ์‹คํ–‰ํ•˜์—ฌ ์ผ๊ด€์„ฑ ํ™•์ธ
  1. severity ๊ณผ๋Œ€/๊ณผ์†Œ ๋ถ„๋ฅ˜
  • ์›์ธ: ๋กœ๊ทธ ์ˆ˜๊ฐ€ ์ ์–ด ๋งฅ๋ฝ ๋ถ€์กฑ
  • ์กฐ์น˜:
    • ๋กœ๊ทธ 20~50์ค„๋กœ ํ™•์žฅํ•ด ์žฌ์‹คํ–‰
    • ๊ฒฝ๊ณ /์˜ค๋ฅ˜/์žฅ์•  ์•Œ๋ฆผ ๋ผ์ธ์„ ๋ฐ˜๋“œ์‹œ ํฌํ•จ

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

  • raw_log.txt ์ค€๋น„
  • lab28_incident_agent.py ์‹คํ–‰ ์„ฑ๊ณต
  • incident_summary.json ์ €์žฅ
  • ํ’ˆ์งˆ ๊ฒŒ์ดํŠธ PASS
  • ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ํ•ญ๋ชฉ ์ตœ์†Œ 3๊ฐœ ์žฌํ˜„/์ ๊ฒ€

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

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

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

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