mirror of
https://github.com/hanzoai/python-sdk.git
synced 2026-10-23 20:23:00 +00:00
76 lines
4.4 KiB
Python
76 lines
4.4 KiB
Python
"""One choice over 300, then 1,000 described labels: every label gets a probability, and a narrower re-ask keeps the order."""
|
|
|
|
from hanzo_kai import Choice, Kai, RetryPolicy
|
|
|
|
AREAS = {
|
|
"billing": ["invoice", "payment method", "refund", "subscription", "tax id",
|
|
"credit balance", "receipt", "usage report", "price plan", "discount code"],
|
|
"identity": ["password", "single sign-on", "two-factor code", "api key", "user role",
|
|
"team invite", "session", "audit log", "service account", "login alert"],
|
|
"storage": ["bucket", "file upload", "backup", "snapshot", "retention rule",
|
|
"public link", "folder", "quota", "encryption key", "object version"],
|
|
"compute": ["virtual machine", "container", "gpu node", "autoscaling rule", "cron job",
|
|
"machine image", "ssh key", "instance size", "startup script", "spot instance"],
|
|
"network": ["domain", "dns record", "tls certificate", "load balancer", "firewall rule",
|
|
"private network", "static ip", "cdn cache", "rate limit", "webhook url"],
|
|
"database": ["postgres cluster", "read replica", "connection pool", "schema migration", "slow query",
|
|
"index", "point-in-time restore", "user grant", "extension", "failover"],
|
|
"messaging": ["email template", "sms sender", "push notification", "queue", "topic",
|
|
"delivery log", "bounce list", "unsubscribe link", "sender domain", "message retry"],
|
|
"analytics": ["dashboard", "chart", "event stream", "funnel", "cohort",
|
|
"data export", "saved query", "alert rule", "metric", "scheduled report"],
|
|
"support": ["ticket", "live chat", "help article", "satisfaction survey", "escalation",
|
|
"sla", "canned reply", "agent seat", "call recording", "support hours"],
|
|
"compliance": ["data processing agreement", "gdpr request", "soc 2 report", "data residency", "access review",
|
|
"retention policy", "legal hold", "subprocessor list", "pen test report", "privacy policy"],
|
|
}
|
|
ACTIONS = {
|
|
"setup": "set up a new {o}",
|
|
"remove": "remove the {o}",
|
|
"change": "change the settings of the {o}",
|
|
"export": "export or download the {o}",
|
|
"error": "an error when using the {o}",
|
|
"access": "cannot access the {o}: permission denied",
|
|
"cost": "a question about the cost of the {o}",
|
|
"recover": "recover the {o} after it was deleted by mistake",
|
|
"limit": "raise the limit on the {o}",
|
|
"move": "move the {o} to another account",
|
|
}
|
|
TICKETS = [
|
|
("The download button for our March invoice shows 'Something went wrong' every time we click it.", "billing.invoice.error"),
|
|
("I deleted our assets-prod bucket by mistake an hour ago. Is there any way to get it back?", "storage.bucket.recover"),
|
|
("How much more would we pay per month if we added two GPU nodes?", "compute.gpu-node.cost"),
|
|
]
|
|
ASK = "Which support category does this ticket belong to?"
|
|
|
|
|
|
def taxonomy(areas: list[str]) -> dict[str, str]:
|
|
"""Every object of each area crossed with every action, as label: description."""
|
|
return {
|
|
f"{area}.{obj.replace(' ', '-')}.{action}": f"{text.format(o=obj)}, in {area}"
|
|
for area in areas
|
|
for obj in AREAS[area]
|
|
for action, text in ACTIONS.items()
|
|
}
|
|
|
|
|
|
with Kai(retry=RetryPolicy(max_retries=10), timeout=120) as kai:
|
|
for areas in (["billing", "identity", "storage"], list(AREAS)):
|
|
labels = taxonomy(areas)
|
|
for ticket, expected in TICKETS:
|
|
if expected not in labels:
|
|
continue
|
|
d = kai.decide(state={"ticket": ticket}, questions={"category": Choice(instructions=ASK, criteria=labels)})
|
|
a = d.choices["category"]
|
|
order = sorted(a.probabilities, key=a.probabilities.__getitem__, reverse=True)
|
|
print(
|
|
f"{len(labels)} labels, {len(a.probabilities)} probabilities, input_tokens {d.usage.input_tokens}\n"
|
|
f" answer {a.choice} p={a.answer_confidence} confidence={a.confidence}\n"
|
|
f" expected {expected} p={a.probabilities[expected]} rank {order.index(expected) + 1}"
|
|
)
|
|
if len(labels) == 1000:
|
|
top = {label: labels[label] for label in order[:20]}
|
|
again = kai.decide(state={"ticket": ticket}, questions={"category": Choice(instructions=ASK, criteria=top)})
|
|
b = again.choices["category"]
|
|
print(f" top 20 re-asked: {b.choice} p={b.answer_confidence}")
|