[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FJHBPYPQZ2KVCMH32Z7E97":3,"skill-same:01M6FJHBPYPQZ2KVCMH32Z7E97":58},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":17,"publishedAt":25,"linkOnly":26,"markdownContent":27,"markdownBody":28,"frontMatter":29,"refName":31,"commitSha":32,"skillDirectory":33,"forksCount":34,"repositoryHtmlUrl":35,"repositoryHomepageUrl":6,"ownerHtmlUrl":36,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":37,"install":38,"resources":51},"01M6FJHBPYPQZ2KVCMH32Z7E97","bim-classification-ai",null,"Classify BIM elements using AI and standard classification systems. Map elements to UniFormat, MasterFormat, OmniClass, and CWICR codes.","kbarbel640-del\u002Fskills","kbarbel640-del","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F255315490?v=4","01M6CJPPQGCCESXMG3K7BBGQ5J","01M6CJPPX2PB2BCZERFVM2C2B3",1,"MIT","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fbim-classification-ai\u002FSKILL.md",[],[18,19,20,21,22,23,24],"classification","bim classification ai","map","elements","classify","systems","codes","2026-11-10 10:12:30",false,"---\r\nslug: \"bim-classification-ai\"\r\ndisplay_name: \"BIM Classification AI\"\r\ndescription: \"Classify BIM elements using AI and standard classification systems. Map elements to UniFormat, MasterFormat, OmniClass, and CWICR codes.\"\r\n---\r\n\r\n# BIM Classification AI\r\n\r\n## Business Case\r\n\r\n### Problem Statement\r\nBIM models often lack proper classification:\r\n- Elements without classification codes\r\n- Inconsistent naming conventions\r\n- Manual classification is tedious\r\n- Difficult to map to cost databases\r\n\r\n### Solution\r\nAI-powered classification system that analyzes BIM element properties and suggests appropriate classification codes from multiple standards.\r\n\r\n### Business Value\r\n- **Automation** - Reduce manual classification effort\r\n- **Consistency** - Standardized classification across projects\r\n- **Integration** - Enable cost estimation and QTO\r\n- **Quality** - Improved data quality in BIM models\r\n\r\n## Technical Implementation\r\n\r\n```python\r\nimport pandas as pd\r\nfrom typing import Dict, Any, List, Optional, Tuple\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\nimport re\r\n\r\n\r\nclass ClassificationSystem(Enum):\r\n    \"\"\"Classification standards.\"\"\"\r\n    UNIFORMAT = \"uniformat\"\r\n    MASTERFORMAT = \"masterformat\"\r\n    OMNICLASS = \"omniclass\"\r\n    UNICLASS = \"uniclass\"\r\n    CWICR = \"cwicr\"\r\n\r\n\r\n@dataclass\r\nclass ClassificationCode:\r\n    \"\"\"Classification code with metadata.\"\"\"\r\n    code: str\r\n    title: str\r\n    system: ClassificationSystem\r\n    level: int\r\n    parent_code: Optional[str] = None\r\n    keywords: List[str] = field(default_factory=list)\r\n\r\n\r\n@dataclass\r\nclass ClassificationResult:\r\n    \"\"\"Result of classification attempt.\"\"\"\r\n    element_id: str\r\n    element_name: str\r\n    element_category: str\r\n    suggested_codes: List[Tuple[ClassificationCode, float]]  # (code, confidence)\r\n    selected_code: Optional[ClassificationCode] = None\r\n    manual_override: bool = False\r\n\r\n\r\nclass ClassificationDatabase:\r\n    \"\"\"Classification codes database.\"\"\"\r\n\r\n    def __init__(self):\r\n        self.codes: Dict[ClassificationSystem, List[ClassificationCode]] = {\r\n            system: [] for system in ClassificationSystem\r\n        }\r\n        self._load_standard_codes()\r\n\r\n    def _load_standard_codes(self):\r\n        \"\"\"Load standard classification codes.\"\"\"\r\n        # UniFormat II codes\r\n        uniformat_codes = [\r\n            (\"A\", \"Substructure\", 1, None, [\"foundation\", \"basement\", \"excavation\"]),\r\n            (\"A10\", \"Foundations\", 2, \"A\", [\"footing\", \"pile\", \"foundation\"]),\r\n            (\"A1010\", \"Standard Foundations\", 3, \"A10\", [\"spread footing\", \"strip footing\"]),\r\n            (\"A1020\", \"Special Foundations\", 3, \"A10\", [\"pile\", \"caisson\", \"mat foundation\"]),\r\n            (\"B\", \"Shell\", 1, None, [\"superstructure\", \"exterior\", \"roof\"]),\r\n            (\"B10\", \"Superstructure\", 2, \"B\", [\"floor\", \"roof\", \"structure\"]),\r\n            (\"B1010\", \"Floor Construction\", 3, \"B10\", [\"slab\", \"deck\", \"floor\"]),\r\n            (\"B1020\", \"Roof Construction\", 3, \"B10\", [\"roof\", \"deck\", \"truss\"]),\r\n            (\"B20\", \"Exterior Enclosure\", 2, \"B\", [\"wall\", \"window\", \"door\"]),\r\n            (\"B2010\", \"Exterior Walls\", 3, \"B20\", [\"curtain wall\", \"masonry\", \"cladding\"]),\r\n            (\"B2020\", \"Exterior Windows\", 3, \"B20\", [\"window\", \"glazing\", \"storefront\"]),\r\n            (\"B30\", \"Roofing\", 2, \"B\", [\"roof\", \"membrane\", \"insulation\"]),\r\n            (\"C\", \"Interiors\", 1, None, [\"partition\", \"ceiling\", \"floor finish\"]),\r\n            (\"C10\", \"Interior Construction\", 2, \"C\", [\"partition\", \"door\", \"glazing\"]),\r\n            (\"C20\", \"Stairs\", 2, \"C\", [\"stair\", \"railing\", \"ladder\"]),\r\n            (\"C30\", \"Interior Finishes\", 2, \"C\", [\"finish\", \"paint\", \"flooring\"]),\r\n            (\"D\", \"Services\", 1, None, [\"mechanical\", \"electrical\", \"plumbing\"]),\r\n            (\"D10\", \"Conveying\", 2, \"D\", [\"elevator\", \"escalator\", \"lift\"]),\r\n            (\"D20\", \"Plumbing\", 2, \"D\", [\"pipe\", \"fixture\", \"drain\"]),\r\n            (\"D30\", \"HVAC\", 2, \"D\", [\"duct\", \"hvac\", \"air handling\"]),\r\n            (\"D40\", \"Fire Protection\", 2, \"D\", [\"sprinkler\", \"fire\", \"suppression\"]),\r\n            (\"D50\", \"Electrical\", 2, \"D\", [\"electrical\", \"power\", \"lighting\"]),\r\n        ]\r\n\r\n        for code, title, level, parent, keywords in uniformat_codes:\r\n            self.codes[ClassificationSystem.UNIFORMAT].append(\r\n                ClassificationCode(code, title, ClassificationSystem.UNIFORMAT, level, parent, keywords)\r\n            )\r\n\r\n        # MasterFormat codes (simplified)\r\n        masterformat_codes = [\r\n            (\"03\", \"Concrete\", 1, None, [\"concrete\", \"formwork\", \"reinforcing\"]),\r\n            (\"03 30 00\", \"Cast-in-Place Concrete\", 2, \"03\", [\"concrete\", \"pour\", \"slab\"]),\r\n            (\"03 41 00\", \"Precast Structural Concrete\", 2, \"03\", [\"precast\", \"concrete\", \"panel\"]),\r\n            (\"04\", \"Masonry\", 1, None, [\"brick\", \"block\", \"stone\"]),\r\n            (\"05\", \"Metals\", 1, None, [\"steel\", \"metal\", \"aluminum\"]),\r\n            (\"05 12 00\", \"Structural Steel Framing\", 2, \"05\", [\"beam\", \"column\", \"steel\"]),\r\n            (\"06\", \"Wood, Plastics, Composites\", 1, None, [\"wood\", \"timber\", \"lumber\"]),\r\n            (\"07\", \"Thermal and Moisture Protection\", 1, None, [\"insulation\", \"roofing\", \"waterproofing\"]),\r\n            (\"08\", \"Openings\", 1, None, [\"door\", \"window\", \"glazing\"]),\r\n            (\"09\", \"Finishes\", 1, None, [\"drywall\", \"paint\", \"flooring\"]),\r\n            (\"21\", \"Fire Suppression\", 1, None, [\"sprinkler\", \"fire\", \"suppression\"]),\r\n            (\"22\", \"Plumbing\", 1, None, [\"pipe\", \"fixture\", \"plumbing\"]),\r\n            (\"23\", \"HVAC\", 1, None, [\"hvac\", \"duct\", \"mechanical\"]),\r\n            (\"26\", \"Electrical\", 1, None, [\"electrical\", \"power\", \"lighting\"]),\r\n        ]\r\n\r\n        for code, title, level, parent, keywords in masterformat_codes:\r\n            self.codes[ClassificationSystem.MASTERFORMAT].append(\r\n                ClassificationCode(code, title, ClassificationSystem.MASTERFORMAT, level, parent, keywords)\r\n            )\r\n\r\n    def search(self, query: str, system: ClassificationSystem = None) -> List[ClassificationCode]:\r\n        \"\"\"Search classification codes by keyword.\"\"\"\r\n        results = []\r\n        query_lower = query.lower()\r\n\r\n        systems = [system] if system else list(ClassificationSystem)\r\n\r\n        for sys in systems:\r\n            for code in self.codes.get(sys, []):\r\n                # Check title\r\n                if query_lower in code.title.lower():\r\n                    results.append(code)\r\n                    continue\r\n                # Check keywords\r\n                if any(query_lower in kw.lower() for kw in code.keywords):\r\n                    results.append(code)\r\n\r\n        return results\r\n\r\n\r\nclass BIMClassificationAI:\r\n    \"\"\"AI-powered BIM element classification.\"\"\"\r\n\r\n    def __init__(self, classification_db: ClassificationDatabase = None):\r\n        self.db = classification_db or ClassificationDatabase()\r\n        self.category_mappings = self._load_category_mappings()\r\n        self.results: List[ClassificationResult] = []\r\n\r\n    def _load_category_mappings(self) -> Dict[str, List[str]]:\r\n        \"\"\"Load Revit\u002FIFC category to classification mappings.\"\"\"\r\n        return {\r\n            # Structural\r\n            \"Structural Columns\": [\"B10\", \"05 12 00\", \"column\", \"structural\"],\r\n            \"Structural Framing\": [\"B10\", \"05 12 00\", \"beam\", \"framing\"],\r\n            \"Structural Foundations\": [\"A10\", \"03 30 00\", \"foundation\", \"footing\"],\r\n            \"Floors\": [\"B1010\", \"03 30 00\", \"floor\", \"slab\"],\r\n            # Architectural\r\n            \"Walls\": [\"B20\", \"04\", \"wall\", \"partition\"],\r\n            \"Curtain Walls\": [\"B2010\", \"08 44 00\", \"curtain wall\", \"glazing\"],\r\n            \"Windows\": [\"B2020\", \"08 50 00\", \"window\", \"glazing\"],\r\n            \"Doors\": [\"C10\", \"08 10 00\", \"door\", \"opening\"],\r\n            \"Roofs\": [\"B30\", \"07 50 00\", \"roof\", \"roofing\"],\r\n            \"Ceilings\": [\"C30\", \"09 51 00\", \"ceiling\", \"finish\"],\r\n            \"Stairs\": [\"C20\", \"05 51 00\", \"stair\", \"railing\"],\r\n            # MEP\r\n            \"Ducts\": [\"D30\", \"23 31 00\", \"duct\", \"hvac\"],\r\n            \"Pipes\": [\"D20\", \"22 11 00\", \"pipe\", \"plumbing\"],\r\n            \"Electrical Equipment\": [\"D50\", \"26 20 00\", \"electrical\", \"panel\"],\r\n            \"Lighting Fixtures\": [\"D50\", \"26 51 00\", \"light\", \"fixture\"],\r\n            \"Sprinklers\": [\"D40\", \"21 13 00\", \"sprinkler\", \"fire protection\"],\r\n            \"Mechanical Equipment\": [\"D30\", \"23 70 00\", \"ahu\", \"hvac equipment\"],\r\n        }\r\n\r\n    def classify_element(self,\r\n                        element_id: str,\r\n                        element_name: str,\r\n                        category: str,\r\n                        properties: Dict[str, Any] = None,\r\n                        target_systems: List[ClassificationSystem] = None) -> ClassificationResult:\r\n        \"\"\"Classify a single BIM element.\"\"\"\r\n\r\n        target_systems = target_systems or [ClassificationSystem.UNIFORMAT, ClassificationSystem.MASTERFORMAT]\r\n        suggestions = []\r\n\r\n        # Get keywords from category mapping\r\n        keywords = self.category_mappings.get(category, [])\r\n\r\n        # Add keywords from element name\r\n        name_words = re.findall(r'\\w+', element_name.lower())\r\n        keywords.extend(name_words)\r\n\r\n        # Add keywords from properties\r\n        if properties:\r\n            for key, value in properties.items():\r\n                if isinstance(value, str):\r\n                    keywords.extend(re.findall(r'\\w+', value.lower()))\r\n\r\n        # Search classification codes\r\n        for system in target_systems:\r\n            for keyword in keywords:\r\n                matches = self.db.search(keyword, system)\r\n                for match in matches:\r\n                    confidence = self._calculate_confidence(match, keywords, category)\r\n                    suggestions.append((match, confidence))\r\n\r\n        # Remove duplicates and sort by confidence\r\n        seen = set()\r\n        unique_suggestions = []\r\n        for code, conf in sorted(suggestions, key=lambda x: x[1], reverse=True):\r\n            if code.code not in seen:\r\n                seen.add(code.code)\r\n                unique_suggestions.append((code, conf))\r\n\r\n        result = ClassificationResult(\r\n            element_id=element_id,\r\n            element_name=element_name,\r\n            element_category=category,\r\n            suggested_codes=unique_suggestions[:5],\r\n            selected_code=unique_suggestions[0][0] if unique_suggestions else None\r\n        )\r\n\r\n        self.results.append(result)\r\n        return result\r\n\r\n    def _calculate_confidence(self, code: ClassificationCode,\r\n                             keywords: List[str], category: str) -> float:\r\n        \"\"\"Calculate classification confidence score.\"\"\"\r\n        score = 0.0\r\n\r\n        # Direct category match\r\n        if category in self.category_mappings:\r\n            if code.code in self.category_mappings[category]:\r\n                score += 0.5\r\n\r\n        # Keyword matches\r\n        keyword_matches = sum(1 for kw in keywords if kw.lower() in\r\n                            [k.lower() for k in code.keywords])\r\n        score += min(keyword_matches * 0.1, 0.3)\r\n\r\n        # Title match\r\n        title_words = code.title.lower().split()\r\n        title_matches = sum(1 for kw in keywords if kw.lower() in title_words)\r\n        score += min(title_matches * 0.1, 0.2)\r\n\r\n        return min(score, 1.0)\r\n\r\n    def classify_batch(self, elements_df: pd.DataFrame,\r\n                      id_column: str = 'element_id',\r\n                      name_column: str = 'name',\r\n                      category_column: str = 'category') -> pd.DataFrame:\r\n        \"\"\"Classify multiple elements from DataFrame.\"\"\"\r\n\r\n        results = []\r\n        for _, row in elements_df.iterrows():\r\n            result = self.classify_element(\r\n                element_id=str(row[id_column]),\r\n                element_name=str(row[name_column]),\r\n                category=str(row[category_column]),\r\n                properties=row.to_dict()\r\n            )\r\n\r\n            results.append({\r\n                'element_id': result.element_id,\r\n                'element_name': result.element_name,\r\n                'category': result.element_category,\r\n                'uniformat_code': next((c.code for c, _ in result.suggested_codes\r\n                                       if c.system == ClassificationSystem.UNIFORMAT), None),\r\n                'masterformat_code': next((c.code for c, _ in result.suggested_codes\r\n                                          if c.system == ClassificationSystem.MASTERFORMAT), None),\r\n                'confidence': result.suggested_codes[0][1] if result.suggested_codes else 0\r\n            })\r\n\r\n        return pd.DataFrame(results)\r\n\r\n    def get_summary(self) -> Dict[str, Any]:\r\n        \"\"\"Get classification summary.\"\"\"\r\n        total = len(self.results)\r\n        classified = sum(1 for r in self.results if r.selected_code)\r\n        high_confidence = sum(1 for r in self.results\r\n                            if r.suggested_codes and r.suggested_codes[0][1] > 0.7)\r\n\r\n        return {\r\n            'total_elements': total,\r\n            'classified': classified,\r\n            'classification_rate': round(classified \u002F total * 100, 1) if total > 0 else 0,\r\n            'high_confidence': high_confidence,\r\n            'high_confidence_rate': round(high_confidence \u002F total * 100, 1) if total > 0 else 0\r\n        }\r\n\r\n    def export_results(self) -> pd.DataFrame:\r\n        \"\"\"Export classification results to DataFrame.\"\"\"\r\n        data = []\r\n        for result in self.results:\r\n            row = {\r\n                'element_id': result.element_id,\r\n                'element_name': result.element_name,\r\n                'category': result.element_category,\r\n                'selected_code': result.selected_code.code if result.selected_code else None,\r\n                'selected_title': result.selected_code.title if result.selected_code else None,\r\n                'selected_system': result.selected_code.system.value if result.selected_code else None,\r\n                'manual_override': result.manual_override\r\n            }\r\n\r\n            # Add top suggestions\r\n            for i, (code, conf) in enumerate(result.suggested_codes[:3]):\r\n                row[f'suggestion_{i+1}_code'] = code.code\r\n                row[f'suggestion_{i+1}_confidence'] = round(conf, 2)\r\n\r\n            data.append(row)\r\n\r\n        return pd.DataFrame(data)\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\n# Initialize classifier\r\nclassifier = BIMClassificationAI()\r\n\r\n# Classify single element\r\nresult = classifier.classify_element(\r\n    element_id=\"12345\",\r\n    element_name=\"Concrete Floor Slab Level 2\",\r\n    category=\"Floors\",\r\n    properties={'material': 'Concrete', 'thickness': '200mm'}\r\n)\r\n\r\nprint(f\"Suggested: {result.selected_code.code} - {result.selected_code.title}\")\r\nprint(f\"Confidence: {result.suggested_codes[0][1]:.1%}\")\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### 1. Batch Classification\r\n```python\r\n# Load BIM elements\r\nelements = pd.read_excel(\"bim_elements.xlsx\")\r\n\r\n# Classify all\r\nclassified = classifier.classify_batch(elements)\r\nclassified.to_excel(\"classified_elements.xlsx\")\r\n```\r\n\r\n### 2. Map to CWICR\r\n```python\r\n# Get UniFormat code for cost mapping\r\nuniformat = result.selected_code.code\r\ncwicr_code = map_uniformat_to_cwicr(uniformat)\r\n```\r\n\r\n### 3. Quality Check\r\n```python\r\nsummary = classifier.get_summary()\r\nprint(f\"Classification rate: {summary['classification_rate']}%\")\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 2.5 - Data Standards\r\n- **Reference**: UniFormat II, CSI MasterFormat\r\n","# BIM Classification AI\r\n\r\n## Business Case\r\n\r\n### Problem Statement\r\nBIM models often lack proper classification:\r\n- Elements without classification codes\r\n- Inconsistent naming conventions\r\n- Manual classification is tedious\r\n- Difficult to map to cost databases\r\n\r\n### Solution\r\nAI-powered classification system that analyzes BIM element properties and suggests appropriate classification codes from multiple standards.\r\n\r\n### Business Value\r\n- **Automation** - Reduce manual classification effort\r\n- **Consistency** - Standardized classification across projects\r\n- **Integration** - Enable cost estimation and QTO\r\n- **Quality** - Improved data quality in BIM models\r\n\r\n## Technical Implementation\r\n\r\n```python\r\nimport pandas as pd\r\nfrom typing import Dict, Any, List, Optional, Tuple\r\nfrom dataclasses import dataclass, field\r\nfrom enum import Enum\r\nimport re\r\n\r\n\r\nclass ClassificationSystem(Enum):\r\n    \"\"\"Classification standards.\"\"\"\r\n    UNIFORMAT = \"uniformat\"\r\n    MASTERFORMAT = \"masterformat\"\r\n    OMNICLASS = \"omniclass\"\r\n    UNICLASS = \"uniclass\"\r\n    CWICR = \"cwicr\"\r\n\r\n\r\n@dataclass\r\nclass ClassificationCode:\r\n    \"\"\"Classification code with metadata.\"\"\"\r\n    code: str\r\n    title: str\r\n    system: ClassificationSystem\r\n    level: int\r\n    parent_code: Optional[str] = None\r\n    keywords: List[str] = field(default_factory=list)\r\n\r\n\r\n@dataclass\r\nclass ClassificationResult:\r\n    \"\"\"Result of classification attempt.\"\"\"\r\n    element_id: str\r\n    element_name: str\r\n    element_category: str\r\n    suggested_codes: List[Tuple[ClassificationCode, float]]  # (code, confidence)\r\n    selected_code: Optional[ClassificationCode] = None\r\n    manual_override: bool = False\r\n\r\n\r\nclass ClassificationDatabase:\r\n    \"\"\"Classification codes database.\"\"\"\r\n\r\n    def __init__(self):\r\n        self.codes: Dict[ClassificationSystem, List[ClassificationCode]] = {\r\n            system: [] for system in ClassificationSystem\r\n        }\r\n        self._load_standard_codes()\r\n\r\n    def _load_standard_codes(self):\r\n        \"\"\"Load standard classification codes.\"\"\"\r\n        # UniFormat II codes\r\n        uniformat_codes = [\r\n            (\"A\", \"Substructure\", 1, None, [\"foundation\", \"basement\", \"excavation\"]),\r\n            (\"A10\", \"Foundations\", 2, \"A\", [\"footing\", \"pile\", \"foundation\"]),\r\n            (\"A1010\", \"Standard Foundations\", 3, \"A10\", [\"spread footing\", \"strip footing\"]),\r\n            (\"A1020\", \"Special Foundations\", 3, \"A10\", [\"pile\", \"caisson\", \"mat foundation\"]),\r\n            (\"B\", \"Shell\", 1, None, [\"superstructure\", \"exterior\", \"roof\"]),\r\n            (\"B10\", \"Superstructure\", 2, \"B\", [\"floor\", \"roof\", \"structure\"]),\r\n            (\"B1010\", \"Floor Construction\", 3, \"B10\", [\"slab\", \"deck\", \"floor\"]),\r\n            (\"B1020\", \"Roof Construction\", 3, \"B10\", [\"roof\", \"deck\", \"truss\"]),\r\n            (\"B20\", \"Exterior Enclosure\", 2, \"B\", [\"wall\", \"window\", \"door\"]),\r\n            (\"B2010\", \"Exterior Walls\", 3, \"B20\", [\"curtain wall\", \"masonry\", \"cladding\"]),\r\n            (\"B2020\", \"Exterior Windows\", 3, \"B20\", [\"window\", \"glazing\", \"storefront\"]),\r\n            (\"B30\", \"Roofing\", 2, \"B\", [\"roof\", \"membrane\", \"insulation\"]),\r\n            (\"C\", \"Interiors\", 1, None, [\"partition\", \"ceiling\", \"floor finish\"]),\r\n            (\"C10\", \"Interior Construction\", 2, \"C\", [\"partition\", \"door\", \"glazing\"]),\r\n            (\"C20\", \"Stairs\", 2, \"C\", [\"stair\", \"railing\", \"ladder\"]),\r\n            (\"C30\", \"Interior Finishes\", 2, \"C\", [\"finish\", \"paint\", \"flooring\"]),\r\n            (\"D\", \"Services\", 1, None, [\"mechanical\", \"electrical\", \"plumbing\"]),\r\n            (\"D10\", \"Conveying\", 2, \"D\", [\"elevator\", \"escalator\", \"lift\"]),\r\n            (\"D20\", \"Plumbing\", 2, \"D\", [\"pipe\", \"fixture\", \"drain\"]),\r\n            (\"D30\", \"HVAC\", 2, \"D\", [\"duct\", \"hvac\", \"air handling\"]),\r\n            (\"D40\", \"Fire Protection\", 2, \"D\", [\"sprinkler\", \"fire\", \"suppression\"]),\r\n            (\"D50\", \"Electrical\", 2, \"D\", [\"electrical\", \"power\", \"lighting\"]),\r\n        ]\r\n\r\n        for code, title, level, parent, keywords in uniformat_codes:\r\n            self.codes[ClassificationSystem.UNIFORMAT].append(\r\n                ClassificationCode(code, title, ClassificationSystem.UNIFORMAT, level, parent, keywords)\r\n            )\r\n\r\n        # MasterFormat codes (simplified)\r\n        masterformat_codes = [\r\n            (\"03\", \"Concrete\", 1, None, [\"concrete\", \"formwork\", \"reinforcing\"]),\r\n            (\"03 30 00\", \"Cast-in-Place Concrete\", 2, \"03\", [\"concrete\", \"pour\", \"slab\"]),\r\n            (\"03 41 00\", \"Precast Structural Concrete\", 2, \"03\", [\"precast\", \"concrete\", \"panel\"]),\r\n            (\"04\", \"Masonry\", 1, None, [\"brick\", \"block\", \"stone\"]),\r\n            (\"05\", \"Metals\", 1, None, [\"steel\", \"metal\", \"aluminum\"]),\r\n            (\"05 12 00\", \"Structural Steel Framing\", 2, \"05\", [\"beam\", \"column\", \"steel\"]),\r\n            (\"06\", \"Wood, Plastics, Composites\", 1, None, [\"wood\", \"timber\", \"lumber\"]),\r\n            (\"07\", \"Thermal and Moisture Protection\", 1, None, [\"insulation\", \"roofing\", \"waterproofing\"]),\r\n            (\"08\", \"Openings\", 1, None, [\"door\", \"window\", \"glazing\"]),\r\n            (\"09\", \"Finishes\", 1, None, [\"drywall\", \"paint\", \"flooring\"]),\r\n            (\"21\", \"Fire Suppression\", 1, None, [\"sprinkler\", \"fire\", \"suppression\"]),\r\n            (\"22\", \"Plumbing\", 1, None, [\"pipe\", \"fixture\", \"plumbing\"]),\r\n            (\"23\", \"HVAC\", 1, None, [\"hvac\", \"duct\", \"mechanical\"]),\r\n            (\"26\", \"Electrical\", 1, None, [\"electrical\", \"power\", \"lighting\"]),\r\n        ]\r\n\r\n        for code, title, level, parent, keywords in masterformat_codes:\r\n            self.codes[ClassificationSystem.MASTERFORMAT].append(\r\n                ClassificationCode(code, title, ClassificationSystem.MASTERFORMAT, level, parent, keywords)\r\n            )\r\n\r\n    def search(self, query: str, system: ClassificationSystem = None) -> List[ClassificationCode]:\r\n        \"\"\"Search classification codes by keyword.\"\"\"\r\n        results = []\r\n        query_lower = query.lower()\r\n\r\n        systems = [system] if system else list(ClassificationSystem)\r\n\r\n        for sys in systems:\r\n            for code in self.codes.get(sys, []):\r\n                # Check title\r\n                if query_lower in code.title.lower():\r\n                    results.append(code)\r\n                    continue\r\n                # Check keywords\r\n                if any(query_lower in kw.lower() for kw in code.keywords):\r\n                    results.append(code)\r\n\r\n        return results\r\n\r\n\r\nclass BIMClassificationAI:\r\n    \"\"\"AI-powered BIM element classification.\"\"\"\r\n\r\n    def __init__(self, classification_db: ClassificationDatabase = None):\r\n        self.db = classification_db or ClassificationDatabase()\r\n        self.category_mappings = self._load_category_mappings()\r\n        self.results: List[ClassificationResult] = []\r\n\r\n    def _load_category_mappings(self) -> Dict[str, List[str]]:\r\n        \"\"\"Load Revit\u002FIFC category to classification mappings.\"\"\"\r\n        return {\r\n            # Structural\r\n            \"Structural Columns\": [\"B10\", \"05 12 00\", \"column\", \"structural\"],\r\n            \"Structural Framing\": [\"B10\", \"05 12 00\", \"beam\", \"framing\"],\r\n            \"Structural Foundations\": [\"A10\", \"03 30 00\", \"foundation\", \"footing\"],\r\n            \"Floors\": [\"B1010\", \"03 30 00\", \"floor\", \"slab\"],\r\n            # Architectural\r\n            \"Walls\": [\"B20\", \"04\", \"wall\", \"partition\"],\r\n            \"Curtain Walls\": [\"B2010\", \"08 44 00\", \"curtain wall\", \"glazing\"],\r\n            \"Windows\": [\"B2020\", \"08 50 00\", \"window\", \"glazing\"],\r\n            \"Doors\": [\"C10\", \"08 10 00\", \"door\", \"opening\"],\r\n            \"Roofs\": [\"B30\", \"07 50 00\", \"roof\", \"roofing\"],\r\n            \"Ceilings\": [\"C30\", \"09 51 00\", \"ceiling\", \"finish\"],\r\n            \"Stairs\": [\"C20\", \"05 51 00\", \"stair\", \"railing\"],\r\n            # MEP\r\n            \"Ducts\": [\"D30\", \"23 31 00\", \"duct\", \"hvac\"],\r\n            \"Pipes\": [\"D20\", \"22 11 00\", \"pipe\", \"plumbing\"],\r\n            \"Electrical Equipment\": [\"D50\", \"26 20 00\", \"electrical\", \"panel\"],\r\n            \"Lighting Fixtures\": [\"D50\", \"26 51 00\", \"light\", \"fixture\"],\r\n            \"Sprinklers\": [\"D40\", \"21 13 00\", \"sprinkler\", \"fire protection\"],\r\n            \"Mechanical Equipment\": [\"D30\", \"23 70 00\", \"ahu\", \"hvac equipment\"],\r\n        }\r\n\r\n    def classify_element(self,\r\n                        element_id: str,\r\n                        element_name: str,\r\n                        category: str,\r\n                        properties: Dict[str, Any] = None,\r\n                        target_systems: List[ClassificationSystem] = None) -> ClassificationResult:\r\n        \"\"\"Classify a single BIM element.\"\"\"\r\n\r\n        target_systems = target_systems or [ClassificationSystem.UNIFORMAT, ClassificationSystem.MASTERFORMAT]\r\n        suggestions = []\r\n\r\n        # Get keywords from category mapping\r\n        keywords = self.category_mappings.get(category, [])\r\n\r\n        # Add keywords from element name\r\n        name_words = re.findall(r'\\w+', element_name.lower())\r\n        keywords.extend(name_words)\r\n\r\n        # Add keywords from properties\r\n        if properties:\r\n            for key, value in properties.items():\r\n                if isinstance(value, str):\r\n                    keywords.extend(re.findall(r'\\w+', value.lower()))\r\n\r\n        # Search classification codes\r\n        for system in target_systems:\r\n            for keyword in keywords:\r\n                matches = self.db.search(keyword, system)\r\n                for match in matches:\r\n                    confidence = self._calculate_confidence(match, keywords, category)\r\n                    suggestions.append((match, confidence))\r\n\r\n        # Remove duplicates and sort by confidence\r\n        seen = set()\r\n        unique_suggestions = []\r\n        for code, conf in sorted(suggestions, key=lambda x: x[1], reverse=True):\r\n            if code.code not in seen:\r\n                seen.add(code.code)\r\n                unique_suggestions.append((code, conf))\r\n\r\n        result = ClassificationResult(\r\n            element_id=element_id,\r\n            element_name=element_name,\r\n            element_category=category,\r\n            suggested_codes=unique_suggestions[:5],\r\n            selected_code=unique_suggestions[0][0] if unique_suggestions else None\r\n        )\r\n\r\n        self.results.append(result)\r\n        return result\r\n\r\n    def _calculate_confidence(self, code: ClassificationCode,\r\n                             keywords: List[str], category: str) -> float:\r\n        \"\"\"Calculate classification confidence score.\"\"\"\r\n        score = 0.0\r\n\r\n        # Direct category match\r\n        if category in self.category_mappings:\r\n            if code.code in self.category_mappings[category]:\r\n                score += 0.5\r\n\r\n        # Keyword matches\r\n        keyword_matches = sum(1 for kw in keywords if kw.lower() in\r\n                            [k.lower() for k in code.keywords])\r\n        score += min(keyword_matches * 0.1, 0.3)\r\n\r\n        # Title match\r\n        title_words = code.title.lower().split()\r\n        title_matches = sum(1 for kw in keywords if kw.lower() in title_words)\r\n        score += min(title_matches * 0.1, 0.2)\r\n\r\n        return min(score, 1.0)\r\n\r\n    def classify_batch(self, elements_df: pd.DataFrame,\r\n                      id_column: str = 'element_id',\r\n                      name_column: str = 'name',\r\n                      category_column: str = 'category') -> pd.DataFrame:\r\n        \"\"\"Classify multiple elements from DataFrame.\"\"\"\r\n\r\n        results = []\r\n        for _, row in elements_df.iterrows():\r\n            result = self.classify_element(\r\n                element_id=str(row[id_column]),\r\n                element_name=str(row[name_column]),\r\n                category=str(row[category_column]),\r\n                properties=row.to_dict()\r\n            )\r\n\r\n            results.append({\r\n                'element_id': result.element_id,\r\n                'element_name': result.element_name,\r\n                'category': result.element_category,\r\n                'uniformat_code': next((c.code for c, _ in result.suggested_codes\r\n                                       if c.system == ClassificationSystem.UNIFORMAT), None),\r\n                'masterformat_code': next((c.code for c, _ in result.suggested_codes\r\n                                          if c.system == ClassificationSystem.MASTERFORMAT), None),\r\n                'confidence': result.suggested_codes[0][1] if result.suggested_codes else 0\r\n            })\r\n\r\n        return pd.DataFrame(results)\r\n\r\n    def get_summary(self) -> Dict[str, Any]:\r\n        \"\"\"Get classification summary.\"\"\"\r\n        total = len(self.results)\r\n        classified = sum(1 for r in self.results if r.selected_code)\r\n        high_confidence = sum(1 for r in self.results\r\n                            if r.suggested_codes and r.suggested_codes[0][1] > 0.7)\r\n\r\n        return {\r\n            'total_elements': total,\r\n            'classified': classified,\r\n            'classification_rate': round(classified \u002F total * 100, 1) if total > 0 else 0,\r\n            'high_confidence': high_confidence,\r\n            'high_confidence_rate': round(high_confidence \u002F total * 100, 1) if total > 0 else 0\r\n        }\r\n\r\n    def export_results(self) -> pd.DataFrame:\r\n        \"\"\"Export classification results to DataFrame.\"\"\"\r\n        data = []\r\n        for result in self.results:\r\n            row = {\r\n                'element_id': result.element_id,\r\n                'element_name': result.element_name,\r\n                'category': result.element_category,\r\n                'selected_code': result.selected_code.code if result.selected_code else None,\r\n                'selected_title': result.selected_code.title if result.selected_code else None,\r\n                'selected_system': result.selected_code.system.value if result.selected_code else None,\r\n                'manual_override': result.manual_override\r\n            }\r\n\r\n            # Add top suggestions\r\n            for i, (code, conf) in enumerate(result.suggested_codes[:3]):\r\n                row[f'suggestion_{i+1}_code'] = code.code\r\n                row[f'suggestion_{i+1}_confidence'] = round(conf, 2)\r\n\r\n            data.append(row)\r\n\r\n        return pd.DataFrame(data)\r\n```\r\n\r\n## Quick Start\r\n\r\n```python\r\n# Initialize classifier\r\nclassifier = BIMClassificationAI()\r\n\r\n# Classify single element\r\nresult = classifier.classify_element(\r\n    element_id=\"12345\",\r\n    element_name=\"Concrete Floor Slab Level 2\",\r\n    category=\"Floors\",\r\n    properties={'material': 'Concrete', 'thickness': '200mm'}\r\n)\r\n\r\nprint(f\"Suggested: {result.selected_code.code} - {result.selected_code.title}\")\r\nprint(f\"Confidence: {result.suggested_codes[0][1]:.1%}\")\r\n```\r\n\r\n## Common Use Cases\r\n\r\n### 1. Batch Classification\r\n```python\r\n# Load BIM elements\r\nelements = pd.read_excel(\"bim_elements.xlsx\")\r\n\r\n# Classify all\r\nclassified = classifier.classify_batch(elements)\r\nclassified.to_excel(\"classified_elements.xlsx\")\r\n```\r\n\r\n### 2. Map to CWICR\r\n```python\r\n# Get UniFormat code for cost mapping\r\nuniformat = result.selected_code.code\r\ncwicr_code = map_uniformat_to_cwicr(uniformat)\r\n```\r\n\r\n### 3. Quality Check\r\n```python\r\nsummary = classifier.get_summary()\r\nprint(f\"Classification rate: {summary['classification_rate']}%\")\r\n```\r\n\r\n## Resources\r\n- **DDC Book**: Chapter 2.5 - Data Standards\r\n- **Reference**: UniFormat II, CSI MasterFormat\r\n",{"slug":5,"description":7,"display_name":30},"BIM Classification AI","main","e7e336ac628c3e3bd771aff1aaa469c93778f94a","skills\u002Fdatadrivenconstruction\u002Fbim-classification-ai",0,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del","2026-08-23 22:39:37",{"source":8,"skillName":5,"commands":39,"prompt":49,"zipAvailable":50},[40,43,46],{"tool":41,"command":42},"npx","npx skills add kbarbel640-del\u002Fskills --skill bim-classification-ai",{"tool":44,"command":45},"bunx","bunx skills add kbarbel640-del\u002Fskills --skill bim-classification-ai",{"tool":47,"command":48},"pnpm","pnpm dlx skills add kbarbel640-del\u002Fskills --skill bim-classification-ai","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fbim-classification-ai\u002FSKILL.md",true,[52],{"path":53,"resourceType":54,"resourceTypeDesc":55,"sizeBytes":56,"sourceHtmlUrl":57},"_meta.json","REFERENCE","参考文档",310,"https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fdatadrivenconstruction\u002Fbim-classification-ai\u002F_meta.json",[59,90,119,140,146,166],{"skillNo":60,"name":61,"nameZh":6,"description":62,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":63,"categories":64,"keywords":70,"publishedAt":25},"01M6G8J55967D6281ACMKAKTEQ","crowd-prompting","A marketplace where AI agents improve prompts, system instructions, tool descriptions, and other text-based content with domain expertise from real-world operations — and earn tokens for valuable contributions.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzzadrian\u002Fcrowd-prompting\u002FSKILL.md",[65],{"categoryNo":66,"categoryName":67,"taxonomyType":68,"taxonomyTypeDesc":69},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89],"crowd prompting","prompting","api","with","tokens","domain","world","prompts","operations","instructions","text","tool","system","improve","productivity","marketplace","https","content","ai agents",{"skillNo":91,"name":92,"nameZh":6,"description":93,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":94,"categories":95,"keywords":101,"publishedAt":25},"01M6G8J0PKPAYVET6BWE8W4C26","dilemm-ai","Compete in DilemmAI, the prisoner's dilemma AI arena at dilemm.ai. Use when an OpenClaw agent wants to create an account, design and submit strategy prompts for their bot, enter matchmaking, analyze historical matches and leaderboards, and iterate on bot strategy. Requires headless browser automation (no API available yet).","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzyori\u002Fdilemm-ai\u002FSKILL.md",[96],{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[102,73,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,78,118],"dilemm ai","arena","analyze","browser","openclaw agent","create","automation","browser automation","bot","openclaw","design","strategy","headless","compete","submit","matchmaking","use",{"skillNo":120,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":123,"categories":124,"keywords":128,"publishedAt":25},"01M6G8HWAF3K9SW7NP3Z83CPJ6","arxiv-paper-reviews","Interact with arXiv Crawler API to fetch papers, read reviews, and submit comments. Use when working with arXiv papers, fetching paper lists by date\u002Fcategory\u002Finterest, viewing paper details with comments, or submitting paper reviews via API at http:\u002F\u002F150.158.152.82:8000.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Fweak-accept\u002FSKILL.md",[125],{"categoryNo":126,"categoryName":127,"taxonomyType":99,"taxonomyTypeDesc":100},"01JBSEEDCAT000000000000021","资料检索与研究",[129,130,131,132,133,134,135,74,136,116,118,137,73,138,139],"arxiv paper reviews","reviews","arxiv","paper","crawler","papers","comments","fetch","read","http","via",{"skillNo":141,"name":121,"nameZh":6,"description":122,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":142,"categories":143,"keywords":145,"publishedAt":25},"01M6G8HQJ7N7WMY6YV7D7SSJ16","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzxrys\u002Farxiv-paper-reviews\u002FSKILL.md",[144],{"categoryNo":126,"categoryName":127,"taxonomyType":99,"taxonomyTypeDesc":100},[132,131,130,129,139,134,135,74,133,116,118,136,137,73,138],{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":152,"publishedAt":25},"01M6G8HM95Y64JNVFC2HN4E2BG","git-summary","Get a quick summary of the current Git repository including status, recent commits, branches, and contributors.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fzweack\u002Fgit-summary\u002FSKILL.md",[],[153,154,155,156,157,158,159,160,161,162,163,164,165],"git","summary","git summary","commits","repository","win32","status","linux","contributors","true","quick","get","branches",{"skillNo":167,"name":168,"nameZh":6,"description":169,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":170,"categories":171,"keywords":176,"publishedAt":25},"01M6G8HGEGF05CNEJCGVYFSC4R","agent-constitution","Interact with AgentConstitution governance contracts on Base Sepolia. Check compliance, read rules, log actions, query governance state.","https:\u002F\u002Fgithub.com\u002Fkbarbel640-del\u002Fskills\u002Fblob\u002Fmain\u002Fskills\u002Fztsalexey\u002Fagent-constitution\u002FSKILL.md",[172,173],{"categoryNo":97,"categoryName":98,"taxonomyType":99,"taxonomyTypeDesc":100},{"categoryNo":174,"categoryName":175,"taxonomyType":68,"taxonomyTypeDesc":69},"01JBSEEDCAT000000000000037","律师与法务",[177,178,179,180,74,181,182,31,183,137,184,185,186,187,188,87,189,190,191],"agent constitution","constitution","contracts","tree","query","base","log","check","Rules","projects","compliance","actions","state","governance","github"]