Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Semantic search in DDC CWICR construction database using vector embeddings. Find similar work items and resources for cost estimation.
.claude/skills/datadrivenconstruction-semantic-search-cwicr/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 26% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 33% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 33% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 24% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 18% | 0% |
Construction cost estimation requires finding relevant work items from large databases. Traditional keyword search fails when:
DDC CWICR provides pre-computed embeddings (BAAI/bge-m3, 1024 dimensions) enabling multilingual semantic search across 8 national bases (78,228 positions) plus the 30-market global base in 26 languages, with 48 PPP-repriced market catalogs per national base.
| National base | Region id | Positions | |---|---|---| | Turkey (Birim Fiyat) | TR_NATIONAL | 22,704 | | China (Beijing Dinge + Bole) | ZH_CHINA | 11,312 | | Brazil (SINAPI) | BR_NATIONAL | 9,723 | | Spain (BCCA Andalucía) | ES_ANDALUCIA | 6,453 | | Italy (Prezzario Toscana) | IT_TOSCANA | 5,836 | | Vietnam (Dinh Muc) | VN_NATIONAL | 4,299 | | Indonesia (AHSP) | ID_NATIONAL | 2,784 | | Greece (GGDE) | GR_NATIONAL | 2,647 |
Each base ships the 95-column CWICR master schema (rate_code, rate_original_name, rate_final_name, rate_unit, total_cost_per_position, classification hierarchy collection/department/section/subsection/category, resource_* component lines with is_material/is_machine/is_labor flags) plus 26 language editions and 48 markets/*.csv catalogs.
Latest data release: v0.4.0 (see releases).
bashpip install qdrant-client pandas sentence-transformers
The vector store uses BAAI/bge-m3 (1024-dim dense + sparse + colbert in one forward pass, MIT license, 100+ languages). Production collections are named cwicr_{LANG}_v3 (e.g. cwicr_tr_v3, cwicr_zh_v3). An ONNX-int8 variant (gpahal/bge-m3-onnx-int8, ~700 MB) is used on VPS-sized hosts.
pythonimport pandas as pd from qdrant_client import QdrantClient from sentence_transformers import SentenceTransformer class CWICRSemanticSearch: def __init__(self, host="localhost", port=6333, lang="en"): self.client = QdrantClient(host=host, port=port) self.collection = f"cwicr_{lang}_v3" self.model = SentenceTransformer("BAAI/bge-m3") def search_work_items(self, query, limit=10): vec = self.model.encode(query).tolist() hits = self.client.search( collection_name=self.collection, query_vector=vec, limit=limit, ) return pd.DataFrame([{**h.payload, "score": h.score} for h in hits]) def search_by_category(self, query, category, limit=10): vec = self.model.encode(query).tolist() hits = self.client.search( collection_name=self.collection, query_vector=vec, query_filter={"must": [{"key": "category", "match": {"value": category}}]}, limit=limit, ) return pd.DataFrame([{**h.payload, "score": h.score} for h in hits])
The platform's costs module already exposes semantic matching:
POST /api/v1/costs/suggest-for-element — rank cost items for a BIM element body./qdrant-search — multilingual candidate retrieval for a query.GET /api/v1/costs/?q=...) works without Qdrant.Key fields the payload carries:
| Field | Type | Description | |-------|------|-------------| | rate_code | string | Unique work item code (e.g. 15.115.1008) | | rate_original_name | string | Source-language description | | rate_final_name | string | Display/translated description | | rate_unit | string | m², m³, m, kg, Ad, Sa… | | total_cost_per_position | float | Total unit price | | total_resource_cost_per_position | float | Resource sum (before markup) | | collection_name / department_name / section_name / subsection_name | string | Classification hierarchy | | category_type | string | Normalized category (e.g. CONSTRUCTION WORK) | | resource_name / resource_quantity / resource_price_per_unit_current / resource_cost | mixed | Component lines | | is_material / is_machine / is_labor | bool | Component nature flags |
pythonsearch = CWICRSemanticSearch(lang="tr") # Natural language query results = search.search_work_items("tuğla duvar örülmesi") print(results[["rate_code", "rate_original_name", "total_cost_per_position", "score"]])
python# Find work items for foundation work foundation = search.search_work_items("reinforced concrete foundation", limit=20) # Estimate with quantities (BIM takeoff) quantities = {"15.115.1008": 150.0} # m³ total = sum(quantities[c] * row["total_cost_per_position"] for _, row in foundation.iterrows() if row["rate_code"] in quantities) print(f"Estimated: {total:,.2f} TRY")
rate_original_name holds the source wording; translations live in rate_final_name| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-20 | pass→pass | 10,961 | 2,430 | -78% | 1 | 1 | 0% | 1,695 | 2,266 | +34% | 0 | 0 | — |
case-01 | fail→pass | 15,789 | 24,562 | +56% | 1 | 1 | 0% | 3,415 | 4,310 | +26% | 0 | 0 | — |
case-02 | fail→pass | 15,796 | 10,356 | -34% | 1 | 1 | 0% | 3,077 | 4,107 | +33% | 0 | 0 | — |
case-03 | fail→pass | 17,182 | 13,564 | -21% | 1 | 1 | 0% | 3,644 | 4,830 | +33% | 0 | 0 | — |
case-04 | fail→pass | 11,371 | 4,741 | -58% | 1 | 1 | 0% | 2,198 | 2,728 | +24% | 0 | 0 | — |
case-09 | fail→pass | 11,225 | 1,872 | -83% | 1 | 1 | 0% | 1,879 | 2,220 | +18% | 0 | 0 | — |
case-05 | fail→pass | 9,856 | 1,937 | -80% | 1 | 1 | 0% | 1,605 | 2,274 | +42% | 0 | 0 | — |
case-06 | fail→pass | 7,728 | 2,248 | -71% | 1 | 1 | 0% | 1,247 | 2,292 | +84% | 0 | 0 | — |
case-07 | fail→pass | 9,436 | 2,135 | -77% | 1 | 1 | 0% | 1,608 | 2,257 | +40% | 0 | 0 | — |
case-08 | fail→pass | 24,279 | 2,214 | -91% | 1 | 1 | 0% | 1,869 | 2,257 | +21% | 0 | 0 | — |
case-10 | fail→pass | 19,175 | 2,219 | -88% | 1 | 1 | 0% | 3,306 | 2,280 | -31% | 0 | 0 | — |
case-11 | fail→pass | 23,008 | 2,796 | -88% | 1 | 1 | 0% | 3,896 | 2,401 | -38% | 0 | 0 | — |
case-12 | fail→pass | 11,019 | 1,893 | -83% | 1 | 1 | 0% | 1,849 | 2,171 | +17% | 0 | 0 | — |
case-13 | fail→pass | 25,450 | 1,527 | -94% | 1 | 1 | 0% | 4,181 | 2,136 | -49% | 0 | 0 | — |
case-14 | fail→pass | 45,142 | 1,664 | -96% | 1 | 1 | 0% | 8,021 | 2,139 | -73% | 0 | 0 | — |
case-19 | fail→pass | 10,042 | 2,165 | -78% | 1 | 1 | 0% | 1,831 | 2,243 | +23% | 0 | 0 | — |
case-15 | pass→pass | 15,780 | 13,832 | -12% | 1 | 1 | 0% | 2,446 | 4,482 | +83% | 0 | 0 | — |
case-16 | pass→pass | 22,851 | 3,023 | -87% | 1 | 1 | 0% | 2,180 | 2,506 | +15% | 0 | 0 | — |
case-17 | pass→pass | 3,107 | 2,305 | -26% | 1 | 1 | 0% | 552 | 2,264 | +310% | 0 | 0 | — |
case-18 | pass→pass | 8,889 | 1,876 | -79% | 1 | 1 | 0% | 1,572 | 2,238 | +42% | 0 | 0 | — |
case-21 | fail→pass | 15,163 | 1,879 | -88% | 1 | 1 | 0% | 2,225 | 2,248 | +1% | 0 | 0 | — |
case-22 | pass→pass | 16,236 | 18,203 | +12% | 1 | 1 | 0% | 3,285 | 5,622 | +71% | 0 | 0 | — |
case-23 | pass→pass | 14,998 | 13,254 | -12% | 1 | 1 | 0% | 2,933 | 4,516 | +54% | 0 | 0 | — |
case-24 | pass→pass | 14,453 | 13,824 | -4% | 1 | 1 | 0% | 2,943 | 4,803 | +63% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted. The headline lift of +67 percentage points is the difference between those two pass rates over the 24 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/22/2026 | +59% |
Other measured skills in the registry, with their headline benchmark lift.