पाठ 6 / 25
कोड में Tool Registry
Python functions को tools के रूप में register करें, उनके schemas बनाएँ और calls सुरक्षित रूप से भेजें।
सच्चाई का एक स्रोत
हर function के पास हाथ से schema लिखना बेमेल होने का न्योता है। छोटी registry हर function का signature पढ़कर schema बनाती है और function को नाम से सहेजती है। तब tool जोड़ना यानी एक function लिखना है।
Schema बनाने वाला decorator
यह जैसा दिखाया गया वैसा ही चला। जिस parameter का default नहीं है वह required बनता है; rate का default है इसलिए वैकल्पिक है। Decorator docstring को description की तरह पढ़ता है।
import inspect, json
TOOLS = {}
PY2JSON = {int: "integer", float: "number", str: "string", bool: "boolean"}
def tool(fn):
sig = inspect.signature(fn)
props = {n: {"type": PY2JSON[p.annotation]} for n, p in sig.parameters.items()}
required = [n for n, p in sig.parameters.items() if p.default is inspect._empty]
TOOLS[fn.__name__] = {"fn": fn, "schema": {
"name": fn.__name__,
"description": (fn.__doc__ or "").strip(),
"input_schema": {"type": "object", "properties": props, "required": required}}}
return fn
@tool
def get_balance(account_id: int) -> str:
"""Return the current balance of one account."""
return f"account {account_id}: 1500"
@tool
def convert(amount: float, rate: float = 1.0) -> str:
"""Convert an amount using a rate."""
return str(round(amount * rate, 2))
print(json.dumps(TOOLS["convert"]["schema"]["input_schema"]))
print(sorted(TOOLS))
Output:
{"type": "object", "properties": {"amount": {"type": "number"}, "rate": {"type": "number"}}, "required": ["amount"]}
['convert', 'get_balance']सुरक्षित dispatcher
Validation errors ऐसे tool results बनते हैं जिन्हें model पढ़कर ठीक कर सकता है। ये चार calls जैसे दिखाए वैसे, क्रम से चले।
def call_tool(name, args):
if name not in TOOLS:
return {"is_error": True, "content": f"Unknown tool '{name}'. Available: {sorted(TOOLS)}"}
schema = TOOLS[name]["schema"]["input_schema"]
missing = [r for r in schema["required"] if r not in args]
if missing:
return {"is_error": True, "content": f"Missing required argument(s): {missing}"}
extra = [a for a in args if a not in schema["properties"]]
if extra:
return {"is_error": True, "content": f"Unexpected argument(s): {extra}"}
try:
return {"is_error": False, "content": TOOLS[name]["fn"](**args)}
except Exception as exc:
return {"is_error": True, "content": f"{type(exc).__name__}: {exc}"}
print(call_tool("get_balance", {"account_id": 7}))
print(call_tool("get_balance", {}))
print(call_tool("get_balanse", {"account_id": 7}))
print(call_tool("convert", {"amount": 10, "rate": 0.5}))
Output:
{'is_error': False, 'content': 'account 7: 1500'}
{'is_error': True, 'content': "Missing required argument(s): ['account_id']"}
{'is_error': True, 'content': "Unknown tool 'get_balanse'. Available: ['convert', 'get_balance']"}
{'is_error': False, 'content': '5.0'}त्वरित जाँच: किसी call में ज़रूरी argument नहीं है। Dispatcher को क्या करना चाहिए?
- पूरा प्रोग्राम crash करे
- Tool हटा दे
- चुपचाप कोई मान अनुमान से भर दे
- छूटे argument का नाम बताने वाला error result लौटाए
Answer
छूटे argument का नाम बताने वाला error result लौटाए — साफ़ error model को अगली बारी में call सुधारने देता है।