์ด๋ฒ ํธ์ **โ์์ฒญ์ ๋ฐ์ ๋๊ตฌ๋ฅผ ํธ์ถํ๊ณ , ๊ฒฐ๊ณผ๋ฅผ ๊ฒ์ฆํด PASS/RETRY๋ฅผ ๋ด๋ QA ๋ฏธ๋ ํ๋ก์ ํธโ**๋ฅผ ์ฌํํ๋ค.
ํต์ฌ์ CodeAgent + @tool + ํ์ง ๊ฒ์ดํธ๋ฅผ ๋ฌถ์ด, ๊ฒฐ๊ณผ๋ฅผ ์๋์ผ๋ก ๊ฒ์ฆ ๊ฐ๋ฅํ ํํ(JSON)๋ก ๋จ๊ธฐ๋ ๊ฒ์ด๋ค.
- ์ด์ ํธ: ๐ค 30. ๋ณธํธ 18
- ๋ค์ ํธ ์๊ณ : ์ค์ตํธ 09-2 (๋ค์ค ์ ๋ ฅ ๋ฐฐ์น ํ๊ฐ + ์คํจ ์ผ์ด์ค ๋ฆฌํฌํธ)
flowchart TD A[task.txt ์ ๋ ฅ] --> B[CodeAgent] B --> C[tool: normalize_request] C --> D[tool: make_answer] D --> E[tool: validate_answer] E --> F{valid?} F -- yes --> G[qa_result.json ์ ์ฅ] F -- no --> H[RETRY ์ฌ์ ๊ธฐ๋ก] H --> G
0) ์ค์ต ๋ชฉํ
task.txt๋ฅผ ์
๋ ฅํ๋ฉด qa_result.json์ ์๋ 4๊ฐ ํ๋๊ฐ ์์ฑ๋๋๋ก ๋ง๋ ๋ค.
request_normalizedanswervalid(true/false)reason
1) ํ๊ฒฝ ์ค๋น
- ๋๊ตฌ: ํฐ๋ฏธ๋
- ์ ๋ ฅ: Python 3.10+
- ์คํ๋ช ๋ น:
mkdir -p ~/hf-agents-lab31
cd ~/hf-agents-lab31
python3 -m venv .venv
source .venv/bin/activate
pip install -U "smolagents[toolkit]" litellm- ์ฑ๊ณตํ์ :
python -V
pip show smolagents | head -n 52) ๋ชจ๋ธ ์ค์
- ๋๊ตฌ: ํฐ๋ฏธ๋
- ์ ๋ ฅ: 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')))
PY3) ์ ๋ ฅ ๋ฐ์ดํฐ ์ค๋น
- ๋๊ตฌ: ํฐ๋ฏธ๋
- ์ ๋ ฅ: ์ฌ์ฉ์ ์์ฒญ ์ํ
- ์คํ๋ช ๋ น:
cat > task.txt <<'TXT'
๋ค์์ฃผ ์์์ผ ์ค์ 9์์ ์ ํ ๋ฐ๋ชจ ํ์ ์ก์์ค. ์ฐธ์์๋ minji@acme.ai, dev@acme.ai์ผ.
TXT- ์ฑ๊ณตํ์ :
cat task.txt4) ๋ฏธ๋ ํ๋ก์ ํธ ์ฝ๋ ์์ฑ
- ๋๊ตฌ: ์๋ํฐ/ํฐ๋ฏธ๋
- ์ ๋ ฅ: ์๋ ์ฝ๋
- ์คํ๋ช ๋ น:
cat > lab31_tool_validation_agent.py <<'PY'
from __future__ import annotations
import json
import os
from pathlib import Path
from smolagents import CodeAgent, LiteLLMModel, tool
INPUT_PATH = Path("task.txt")
OUTPUT_PATH = Path("qa_result.json")
@tool
def normalize_request(text: str) -> str:
"""์์ฒญ ๋ฌธ์ฅ์ ์คํ ๊ฐ๋ฅํ ํ ์ค ํฌ๋งท์ผ๋ก ์ ๊ทํํ๋ค."""
return " ".join(text.strip().split())
@tool
def make_answer(normalized: str) -> str:
"""์ ๊ทํ๋ ์์ฒญ ๊ธฐ๋ฐ์ ์คํ ์ ์ ๋ต๋ณ์ ๋ง๋ ๋ค."""
return f"ํ์ ์์ฑ ์์ฒญ ์ ์: {normalized}"
@tool
def validate_answer(answer: str) -> str:
"""๋ต๋ณ ์ต์ ํ์ง์ ๊ฒ์ฆํ๊ณ JSON ๋ฌธ์์ด์ ๋ฐํํ๋ค."""
valid = all(k in answer for k in ["ํ์", "์์ฒญ", "์ ์"])
reason = "PASS" if valid else "ํ์ ํค์๋ ๋๋ฝ"
return json.dumps({"valid": valid, "reason": reason}, ensure_ascii=False)
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 = INPUT_PATH.read_text(encoding="utf-8")
model = LiteLLMModel(model_id=os.getenv("MODEL_ID", "openai/gpt-4o-mini"))
agent = CodeAgent(
tools=[normalize_request, make_answer, validate_answer],
model=model,
max_steps=6,
additional_authorized_imports=["json"],
)
prompt = f"""
์๋ ์์ฒญ์ ์ฒ๋ฆฌํด ์ต์ข
JSON๋ง ๋ฐํํ๋ผ.
์์ฒญ:
{raw}
ํ์ ์ ์ฐจ:
1) normalize_request ํธ์ถ
2) make_answer ํธ์ถ
3) validate_answer ํธ์ถ
์ต์ข
์ถ๋ ฅ ์คํค๋ง:
{{
"request_normalized": "string",
"answer": "string",
"valid": true,
"reason": "string"
}}
์ฃผ์:
- 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}")
if __name__ == "__main__":
main()
PY- ์ฑ๊ณตํ์ :
CodeAgent,@tool,validate_answerํจ์ ์กด์ฌ
5) ์คํ
- ๋๊ตฌ: Python
- ์
๋ ฅ:
task.txt - ์คํ๋ช ๋ น:
python lab31_tool_validation_agent.py
cat qa_result.json- ์ฑ๊ณตํ์ :
saved: qa_result.json์ถ๋ ฅ- JSON์ 4๊ฐ ํ๋ ๋ชจ๋ ์กด์ฌ
6) ํ์ง ๊ฒ์ดํธ ๊ฒ์ฆ
- ๋๊ตฌ: Python
- ์
๋ ฅ:
qa_result.json - ์คํ๋ช ๋ น:
python - <<'PY'
import json
obj = json.load(open('qa_result.json', encoding='utf-8'))
for key in ['request_normalized', 'answer', 'valid', 'reason']:
assert key in obj, f'missing: {key}'
assert isinstance(obj['request_normalized'], str) and obj['request_normalized'].strip()
assert isinstance(obj['answer'], str) and obj['answer'].strip()
assert isinstance(obj['valid'], bool)
assert isinstance(obj['reason'], str)
print('PASS: ํ์ง ๊ฒ์ดํธ ํต๊ณผ')
PY- ์ฑ๊ณตํ์ :
PASS: ํ์ง ๊ฒ์ดํธ ํต๊ณผ
ํธ๋ฌ๋ธ์ํ (์ค์ 4์ )
AuthenticationError/ ํธ์ถ ์คํจ
- ์์ธ:
OPENAI_API_KEY๋ฏธ์ค์ ๋๋ ๋ชจ๋ธ ID ์คํ - ์กฐ์น:
python - <<'PY'
import os
print(bool(os.getenv('OPENAI_API_KEY')), os.getenv('MODEL_ID'))
PYModuleNotFoundError: smolagents
- ์์ธ: ๊ฐ์ํ๊ฒฝ ๋ฏธํ์ฑํ
- ์กฐ์น:
source .venv/bin/activate
pip install -U "smolagents[toolkit]" litellmjson.loadsํ์ฑ ์คํจ
- ์์ธ: ๋ชจ๋ธ์ด JSON ์ธ ์ค๋ช ๋ฌธ์ฅ ์ถ๋ ฅ
- ์กฐ์น: ํ๋กฌํํธ์
JSON ์ธ ํ ์คํธ ๊ธ์ง์ ์ง,strip_code_fence()์ ์ง
valid๊ฐ ๊ณ์ false
- ์์ธ:
make_answer์ถ๋ ฅ ํ์ ๋ณ๊ฒฝ์ผ๋ก ๊ฒ์ฆ ๊ท์น ๋ถ์ผ์น - ์กฐ์น:
validate_answerํค์๋ ๊ท์น๊ณผmake_answerํฌ๋งท์ ๊ฐ์ด ์์
์ฒดํฌ๋ฆฌ์คํธ
- ํ๊ฒฝ ๊ตฌ์ฑ ์๋ฃ
-
lab31_tool_validation_agent.py์คํ ์ฑ๊ณต -
qa_result.json์์ฑ ํ์ธ - ํ์ง ๊ฒ์ดํธ PASS
- ํธ๋ฌ๋ธ์ํ 3๊ฐ ์ด์ ์ ๊ฒ
์ฐธ๊ณ ๋งํฌ (์ฐ์ ์์)
- https://github.com/huggingface/agents-course
- https://huggingface.co/learn/agents-course
- https://huggingface.co/docs/smolagents
์์ฑํ AI ํ์ฉ ๊ณ ์ง
์ด ๋ฌธ์๋ ์์ฑํ AI๋ก ์ด์์ ์์ฑํ๊ณ , ์ฌ๋์ด ์ค์ต ์ฌํ์ฑ(๋๊ตฌ/์ ๋ ฅ/์คํ๋ช ๋ น/์ฑ๊ณตํ์ ), ์ค๋ฅ ๋์, ๋งํฌ ๋ฐ ๋ด๋ถ ์ฐ๊ฒฐ์ ๊ฒํ ํด ํ์ ํ๋ค.