DEV Community

shashank ms
shashank ms

Posted on

Revolutionizing Architecture with LLMs

We're building an architectural programming agent that reads a plain-text client brief and returns a structured space program with area calculations, occupancy checks, and material suggestions. It runs entirely through Oxlo.ai's request-based API, so a 10-page brief costs the same flat fee as a one-liner. See https://oxlo.ai/pricing for details. If you are an architect or designer automating schematic workflows, this tool drops directly into your Python stack.

What you'll need

Step 1: Configure the Oxlo.ai client

One import and two lines. I set the base URL to Oxlo.ai and load the key from an environment variable so I do not commit secrets.

import os
import json
from openai import OpenAI

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key=os.getenv("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)

Step 2: Define the system prompt

The prompt is the contract. It tells the model to output strict JSON with rooms, net/gross areas, occupancy loads per IBC, and proposed materials. I keep it version controlled because changing one line shifts the square footage.

SYSTEM_PROMPT = """You are an architectural programming assistant.
A user will paste a client brief describing a building project.
Respond with a single valid JSON object. Do not wrap it in markdown.
Use this exact structure:
{
  "project_type": string,
  "total_gross_sf": number,
  "rooms": [
    {
      "name": string,
      "net_area_sf": number,
      "occupancy_load": number,
      "code_remark": string,
      "material_palette": [string]
    }
  ],
  "summary": string
}

Rules:
- Assume standard ceiling heights unless specified.
- Apply IBC occupancy load factors for business (1/150), assembly (1/15), or residential (1/200) based on context.
- Round areas to the nearest 10 sf.
- If the brief is ambiguous, note the assumption in the code_remark field.
"""

Step 3: Build the generation function

This function takes a brief string, sends it to Oxlo.ai, and parses the JSON response. I use Llama 3.3 70B because it follows structural instructions reliably at a flat per-request price.

BRIEF = """
We need a 4,500 sf community arts center in Portland.
It should include a 1,200 sf gallery, two 400 sf classrooms,
a 300 sf office, restrooms, and a 600 sf lobby with a small cafe.
"""

def generate_space_program(brief: str) -> dict:
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": brief},
        ],
        temperature=0.2,
        max_tokens=2048,
    )

    raw = response.choices[0].message.content.strip()
    # Grab the first '{' to the last '}' in case the model adds chatter
    start = raw.find("{")
    end = raw.rfind("}") + 1
    return json.loads(raw[start:end])

Step 4: Add code compliance

One pass gives us the program, but I want a second sanity check against energy and accessibility heuristics. I send the generated JSON back to the model with a tighter prompt. Because Oxlo.ai charges per request, not per token, this second pass still costs the same flat fee.

COMPLIANCE_PROMPT = """You are a code consultant. Review the provided space program JSON.
Return the same JSON with two added top-level keys:
- "energy_note": a short paragraph on envelope assumptions for the climate.
- "ada_alert": a list of any rooms that likely trigger accessibility requirements.
Do not change existing keys. Output only valid JSON."""

def add_compliance(program: dict) -> dict:
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": COMPLIANCE_PROMPT},
            {"role": "user", "content": json.dumps(program, indent=2)},
        ],
        temperature=0.1,
        max_tokens=2048,
    )
    raw = response.choices[0].message.content.strip()
    start = raw.find("{")
    end = raw.rfind("}") + 1
    return json.loads(raw[start:end])

Step 5: Render the report

I wrap the pipeline in a small CLI that prints a readable markdown summary. Architects can pipe this into a file or render it in a notebook.

def render_report(program: dict) -> str:
    lines = [
        f"# Space Program: {program['project_type']}",
        f"**Total Gross Area:** {program['total_gross_sf']:,} sf",
        "",
        "| Room | Net Area (sf) | Occupancy | Code Remark |",
        "|------|---------------|-----------|-------------|",
    ]
    for r in program["rooms"]:
        occ = r.get("occupancy_load", "N/A")
        lines.append(
            f"| {r['name']} | {r['net_area_sf']:,} | {occ} | {r['code_remark']} |"
        )

    lines.extend([
        "",
        f"**Energy Note:** {program.get('energy_note', 'N/A')}",
        "",
        f"**ADA Alerts:** {', '.join(program.get('ada_alert', []))}",
        "",
        f"**Summary:** {program['summary']}",
    ])
    return "\n".join(lines)

Run it

Call the pipeline from __main__ and print the report.

if __name__ == "__main__":
    draft = generate_space_program(BRIEF)
    final = add_compliance(draft)
    print(render_report(final))

Example output:

# Space Program: Community Arts Center
**Total Gross Area:** 4,520 sf

| Room | Net Area (sf) | Occupancy | Code Remark |
|------|---------------|-----------|-------------|
| Gallery | 1,200 | 80 | Assembly occupancy, IBC 303.1 |
| Classroom A | 400 | 27 | Educational, IBC 305.1 |
| Classroom B | 400 | 27 | Educational, IBC 305.1 |
| Office | 300 | 2 | Business occupancy, IBC 304.1 |
| Lobby / Cafe | 600 | 40 | Assembly / Mercantile mixed |
| Restrooms | 180 | 10 | Plumbing fixture count per IPC |
| Circulation | 440 | 0 | 10% gross added for corridors |

**Energy Note:** Portland Climate Zone 4C suggests a high-performance envelope with R-20 continuous insulation and triple-glazed north-facing gallery windows to mitigate thermal bridging.

**ADA Alerts:** Gallery, Classrooms, Lobby / Cafe, Restrooms

**Summary:** The program packs efficiently into a single-story slab on grade with shared plumbing walls between restrooms and classrooms. Consider clerestory daylighting for the gallery to reduce electrical loads.

Next steps

Connect the agent to a vector store of your local municipality's PDF zoning code and use Oxlo.ai's JSON mode to return cited chapter references instead of generic IBC assumptions. Alternatively, pipe the output into a Rhino or Blender Python script to generate rough massing blocks with the correct net areas extruded to default ceiling heights.

Top comments (0)