MCPcopy Create free account
hub / github.com/PierreGode/Ragnar / classify_device_ai

Function classify_device_ai

device_classifier.py:703–800  ·  view source on GitHub ↗

Classify a device using rule-based logic first, then GPT-5 Nano if confidence is below threshold. Args: vendor: MAC OUI vendor string ports: list of port strings or ints hostname: device hostname (mDNS, DHCP, NetBIOS) mac: full MAC address ai_service:

(vendor, ports, hostname, mac, ai_service=None,
                       gateway_ip=None, device_ip=None)

Source from the content-addressed store, hash-verified

701# AI-enhanced classification via GPT-5.4 Nano (optional)
702# ---------------------------------------------------------------------------
703def classify_device_ai(vendor, ports, hostname, mac, ai_service=None,
704 gateway_ip=None, device_ip=None):
705 """Classify a device using rule-based logic first, then GPT-5.4 Nano if
706 confidence is below threshold.
707
708 Args:
709 vendor: MAC OUI vendor string
710 ports: list of port strings or ints
711 hostname: device hostname (mDNS, DHCP, NetBIOS)
712 mac: full MAC address
713 ai_service: an AIService instance (or None to skip AI)
714 gateway_ip: default gateway IP
715 device_ip: this device IP
716
717 Returns:
718 dict with keys: device_type, label, confidence, ai_enhanced (bool)
719 """
720 # Step 1: rule-based classification
721 result = classify_device(vendor, ports, gateway_ip=gateway_ip, device_ip=device_ip)
722 result["ai_enhanced"] = False
723
724 # Step 2: hostname-based refinement
725 # Strong hostname hints override even high-confidence vendor matches because
726 # hostnames are user-visible names that are very specific (e.g. "RE200" is
727 # always a TP-Link extender even though TP-Link vendor → router).
728 if hostname:
729 hostname_lower = hostname.lower()
730 # Priority hostname hints — these ALWAYS override (even at confidence 0.8+)
731 # because the hostname is more specific than a broad vendor match.
732 _STRONG_HOSTNAME_HINTS = {
733 "re200": "extender", "re300": "extender", "re450": "extender",
734 "re505x": "extender", "re605x": "extender", "re650": "extender",
735 "range-ext": "extender", "repeater": "extender", "ty_wr": "extender",
736 "raspberry": "sbc", "raspberrypi": "sbc", "pi-hole": "sbc",
737 "nest-audio": "speaker", "nest-mini": "speaker", "nest-hub": "speaker",
738 "google-home": "speaker", "homepod": "speaker",
739 "bosch-wat": "appliance", "bosch-wt": "appliance",
740 "appletv": "smart_tv", "edvinsappletv": "smart_tv",
741 "apple-tv": "smart_tv",
742 "homepod": "speaker", "apple-homepod": "speaker",
743 "macbook": "laptop", "imac": "workstation", "mac-mini": "workstation",
744 "mac-pro": "workstation", "mac-studio": "workstation",
745 "iphone": "phone", "ipad": "tablet",
746 "apple-watch": "wearable", "applewatch": "wearable",
747 # ASUS router hostnames (product lines that are always routers)
748 "rt-ax": "router", "rt-ac": "router", "rt-n": "router",
749 "gt-ax": "router", "gt-ac": "router",
750 "zenwifi": "router", "asus router": "router",
751 # Ragnar devices
752 "ragnar": "ragnar",
753 }
754 for hint, dtype in _STRONG_HOSTNAME_HINTS.items():
755 if hint in hostname_lower:
756 result["device_type"] = dtype
757 result["label"] = DEVICE_TYPE_LABELS.get(dtype, "Unknown")
758 result["confidence"] = 0.85 # hostname is strong signal
759 return result # short circuit — hostname is definitive
760

Callers 1

get_network_topologyFunction · 0.90

Calls 4

classify_deviceFunction · 0.85
_ask_ai_classifyFunction · 0.85
itemsMethod · 0.45
getMethod · 0.45

Tested by

no test coverage detected