본문 바로가기
C.W.K.
Stream
Lesson 04 of 04 · published

Tool calling 베스트 프랙티스

~18 min · tools, practices

Level 0Downloader
0 XP0/41 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

몸으로 익힌 룰

  1. 모든 tool call validate. 모델이 함수 이름 hallucinate, required 인자 누락, 잘못된 type 줄 수 있어. Dispatch를 try/except로 감싸고 crash 대신 error JSON 반환.
  2. Tool set은 작게. 5–10개가 sweet spot이야. 그 이상 넘어가면 모델이 산만해져서 엉뚱한 걸 골라. 더 필요하면 도메인별로 묶어두고 request마다 필요한 것만 골라 보내.
  3. Description은 docstring처럼 써. 첫 문장엔 뭘 하는지, 두 번째 문장엔 언제 쓸지 — 그리고 언제 쓰면 안 되는지.
  4. stream: false로 먼저 test. Streaming에 tool call까지 얹으면 parsing이 확 복잡해져. Non-streaming으로 loop을 제대로 세운 다음에 streaming을 올려.
  5. Registry를 써. {name: callable} dict가 거대한 if/else chain보다 나아. test하기 쉽고, 늘리기 쉽고, tool 하나만 갈아끼우기도 쉬워.

Ollama Python library 단축

v0.4부터 공식 library가 Python 함수를 tools로 바로 받아. Function signature랑 docstring에서 JSON Schema를 알아서 만들어주고. Prototyping 속도는 확실히 붙어. 다만 production에선 schema를 직접 써. description을 의식적으로 벼려야 하니까.

Code

Timeout 가진 방어적 dispatch·python
import asyncio, json, signal
from contextlib import contextmanager

class ToolError(Exception): ...

@contextmanager
def timeout(seconds: int):
    """POSIX SIGALRM 기반 timeout (single-thread만)."""
    def handler(_signum, _frame):
        raise TimeoutError(f"tool exceeded {seconds}s")
    old = signal.signal(signal.SIGALRM, handler)
    signal.alarm(seconds)
    try:
        yield
    finally:
        signal.alarm(0)
        signal.signal(signal.SIGALRM, old)

def dispatch(name: str, args: dict, registry: dict, timeout_s: int = 10) -> str:
    if name not in registry:
        return json.dumps({"error": f"Unknown tool: {name}"})
    try:
        with timeout(timeout_s):
            result = registry[name](**args)
        return result if isinstance(result, str) else json.dumps(result)
    except TypeError as e:
        return json.dumps({"error": f"Bad arguments: {e}"})
    except Exception as e:
        return json.dumps({"error": str(e)})
Ollama Python library — function-as-tool·python
from ollama import chat

def get_temperature(city: str) -> str:
    """Get the current temperature for a city. Returns string like '22C in Seoul'."""
    return f"22C in {city}"

# Library가 docstring + signature에서 JSON Schema 생성
response = chat(
    model="qwen2.5:7b",
    messages=[{"role": "user", "content": "Temperature in Paris?"}],
    tools=[get_temperature],
)
print(response.message.content)

External links

Exercise

Timeout, type-error → JSON, exception → JSON, unknown-name → JSON 다 되는 방어적 dispatcher 만들어. Stress test: 존재하지 않는 tool 이름, 잘못된 type, 무한 루프 요청하는 악의적-같은 메시지 보내. Loop 종료되고 실패 로깅되는지 확인.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.