Quillwright / quillwright /brain_tools.py
Aarya2004's picture
Deploy Quillwright (stub Docker Space): bespoke gr.Server app + sample data
76a2f92 verified
Raw
History Blame Contribute Delete
2.59 kB
"""The narrow tool surface the LLM brain may call.
The brain decides WHICH items to add and WHEN it's done; pricing and math stay
in the deterministic tools (Facts-from-Tools, ADR-0004). The brain never emits
numbers itself.
"""
from quillwright.catalog import Catalog
from quillwright.tools import compute, draft_line_item, lookup_price
# JSON-schema tool definitions handed to the model.
BRAIN_TOOLS = [
{
"type": "function",
"function": {
"name": "add_priced_item",
"description": (
"Add one line item to the estimate. Provide the item name and how many "
"units/hours (quantity); the catalog price is applied automatically. Call "
"once per distinct item observed or mentioned (parts and labor)."
),
"parameters": {
"type": "object",
"properties": {
"item": {"type": "string", "description": "item or labor name"},
"quantity": {
"type": "number",
"description": "how many units or hours (default 1)",
},
},
"required": ["item"],
},
},
},
{
"type": "function",
"function": {
"name": "finish",
"description": "Call when every observed/mentioned item has been added.",
"parameters": {"type": "object", "properties": {}},
},
},
]
def dispatch(name: str, args: dict, catalog: Catalog) -> dict:
"""Execute a brain tool call. Returns a status dict the loop interprets."""
if name == "finish":
return {"status": "done"}
if name == "add_priced_item":
item = (args or {}).get("item", "")
res = lookup_price(item, catalog)
if not res["found"]:
return {"status": "need_price", "item": item}
qty = _coerce_qty((args or {}).get("quantity"))
# Facts-from-Tools: compute owns the math; the model only supplies the count.
compute(f"{qty} * {res['rate']}")
line = draft_line_item(
res["description"], qty=qty, unit=res["unit"], rate=res["rate"], source="catalog"
)
return {"status": "added", "line_item": line}
return {"status": "error", "tool": name}
def _coerce_qty(value) -> float:
"""Quantity from possibly-noisy model output; fall back to 1 on anything invalid."""
try:
q = float(value)
return q if q > 0 else 1
except (TypeError, ValueError):
return 1