Initial commit: Conflict Checker
Cross-discipline design-contradiction checker for construction drawing sets. Standalone tool broken out from Iron_Bid; a pipeline stage may later fold back into Iron_Bid. Pipeline: PDF->images -> per-sheet assertion extraction -> deterministic clustering by location -> per-cluster reasoning -> report. Includes CLI (cli/run_check.py) and web UI (backend/main.py). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# Conflict Checker
|
||||
|
||||
Cross-discipline **design contradiction** detector for construction drawing sets.
|
||||
Built for architects to back-check a set (Arch / Struct / Mech / Elec / Plumb / FP / …)
|
||||
**before** it goes out to a GC for bid. It flags information that *disagrees between
|
||||
disciplines* — e.g. the RCP ceiling height vs the mechanical duct elevation, a door
|
||||
schedule count vs the floor plan, a column that lands in a corridor.
|
||||
|
||||
> This is **not** the IronBid scope-ownership conflict checker (who-owns-what for bidding).
|
||||
> That stays in IronBid; this tool is a separate, design-QA pipeline.
|
||||
|
||||
## How it works (hybrid extract-then-compare)
|
||||
|
||||
```
|
||||
PDF -> page images -> per-sheet grounded facts -> cluster by location -> reason -> report
|
||||
Stage 0 Stage 1 (vision) Stage 2 (no LLM) Stage 3 Stage 4
|
||||
```
|
||||
|
||||
1. **Stage 0** `pdf_processor` — PDF pages to base64 JPEGs (100 DPI, 2400px cap).
|
||||
2. **Stage 1** `extractor` — one vision call per sheet extracts discrete, **grounded**
|
||||
assertions (each carries verbatim `source_text` and a `location_key`). A grounding
|
||||
guard drops any assertion whose number isn't in its own source text.
|
||||
3. **Stage 2** `clusterer` — deterministic: groups assertions that refer to the same
|
||||
grid / room / tag across **≥2 disciplines** (or a schedule-vs-plan within one). This
|
||||
keeps Stage 3 calls small and few.
|
||||
4. **Stage 3** `conflict_checker` — one reasoning call per cluster (with the relevant
|
||||
sheet images) decides whether the disciplines genuinely contradict, and classifies it.
|
||||
5. **Stage 4** `report` — `conflicts.json` + a readable `report.md`.
|
||||
|
||||
The model is **`google/gemini-2.5-pro`** via OpenRouter (configurable). **All prompt
|
||||
tuning lives in `backend/prompts.py`** — the system prompts, the attribute vocabulary,
|
||||
and the conflict taxonomy.
|
||||
|
||||
## Setup
|
||||
|
||||
```bash
|
||||
python3 -m venv .venv && . .venv/bin/activate
|
||||
pip install -r requirements.txt # needs system poppler-utils for pdf2image
|
||||
cp backend/.env.example backend/.env # then set AI_API_KEY to your OpenRouter key
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
CLI (the fast tuning loop — also dumps `assertions.json` / `clusters.json` for inspection):
|
||||
|
||||
```bash
|
||||
python cli/run_check.py samples/your_set.pdf --out out/your_set
|
||||
# -> out/your_set/report.md + conflicts.json
|
||||
```
|
||||
|
||||
Web UI (upload + view):
|
||||
|
||||
```bash
|
||||
uvicorn backend.main:app --reload # open http://127.0.0.1:8000
|
||||
```
|
||||
|
||||
## Conflict categories
|
||||
|
||||
`dimensional_disagreement`, `elevation_disagreement`, `location_mismatch`,
|
||||
`missing_element`, `schedule_vs_plan_mismatch`, `tag_or_reference_inconsistency`,
|
||||
`spatial_clash`, `note_or_spec_contradiction`.
|
||||
|
||||
## Tuning
|
||||
|
||||
- Edit prompts/vocab/taxonomy in `backend/prompts.py`.
|
||||
- Inspect `out/<set>/assertions.json` to see what Stage 1 extracted, and
|
||||
`out/<set>/clusters.json` to see what got compared. Most false negatives are a
|
||||
clustering/extraction miss; most false positives are a Stage-3 prompt issue.
|
||||
- Build a golden set: hand-verify `conflicts.json` for a known set and diff future runs.
|
||||
|
||||
## Known limitations (v1)
|
||||
|
||||
- A location appearing in only **one** discipline never forms a cluster, so pure
|
||||
"missing element" gaps aren't caught deterministically (Stage 3 still catches missing
|
||||
counterparts when the location is co-located).
|
||||
- Stage 3 currently sends **full pages**, not crops. If accuracy/cost needs it, add
|
||||
crop-by-grid later.
|
||||
Reference in New Issue
Block a user