DEV Community

shashank ms
shashank ms

Posted on

Building Manufacturing Tools with LLMs: A Step-by-Step Guide

We are building a manufacturing quality control agent that reads unstructured shift reports and extracts structured defect data, severity scores, and recommended actions. It helps floor managers spot patterns across production lines without manually parsing every handover log. We will run it on Oxlo.ai using the OpenAI-compatible endpoint so you can drop this into existing tooling.

What you'll need

I picked Llama 3.3 70B for this because it handles long, noisy shop-floor text reliably. If your reports contain technical Mandarin or Spanish notes, Qwen 3 32B is a strong alternative on Oxlo.ai.

Step 1: Connect to Oxlo.ai and test the endpoint

First, verify that your key and the base URL are working. I always run a quick health check before I build around a new endpoint.

from openai import OpenAI

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

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[
        {"role": "user", "content": "Reply with OK if you are online."},
    ],
)

print(response.choices[0].message.content)

Step 2: Define the manufacturing report format

Shift supervisors on my floor write freeform logs. I created a realistic example that mixes machine IDs, defect descriptions, and casual abbreviations. This is what the agent will consume.

SHIFT_REPORT = """
Shift: A-2
Date: 2024-05-14
Supervisor: M. Chen

Line 3 extruder temp spiked to 245C around 02:30. Three PP batches came out with
surface streaking. QC flagged lot #4481, #4482, #4483. We slowed feed rate to
80% and temp dropped back to 238C by 03:15. No more streaking after that.
Could be a bad heater cartridge or PID drift. Recommend maintenance check
before next shift.

Line 1 ran clean. No issues.
"""

Step 3: Write the system prompt

The system prompt is the contract. I keep it strict about the JSON keys and severity levels so downstream code never has to guess.

SYSTEM_PROMPT = """
You are a manufacturing quality control analyst. Read the shift report and
produce a JSON object with exactly these keys:

- line_id: string, the production line identifier
- defect_found: boolean
- defect_description: string, max 20 words
- severity: one of "critical", "major", "minor", "none"
- probable_cause: string, max 15 words
- recommended_action: string, max 20 words
- production_halt_recommended: boolean

Rules:
1. If no defect is mentioned, set severity to "none" and production_halt_recommended to false.
2. Temperature excursions that produce visible defects are "major".
3. Only recommend a halt for "critical" severity or repeated major defects.
4. Respond with only the JSON object, no markdown fences.
"""

Step 4: Build the defect classifier

Now I wrap the call in a function that accepts raw report text and returns the parsed string. I set temperature low because I want deterministic extraction, not creative writing.

import json

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

    raw = response.choices[0].message.content.strip()
    # Handle occasional markdown fences
    if raw.startswith("

```"):
        raw = raw.split("\n", 1)[1].rsplit("```

", 1)[0].strip()

    return json.loads(raw)

result = classify_defect(SHIFT_REPORT)
print(json.dumps(result, indent=2))

Step 5: Add structured output with JSON mode

To make the pipeline production-grade, I switch on JSON mode. This forces the model to emit valid JSON and eliminates the fence-stripping hack. I also add a second example to show how the agent handles a clean report.

import json

CLEAN_REPORT = """
Shift: B-1
Date: 2024-05-14
Supervisor: L. Rossi

All lines nominal. Throughput 104% of target. No maintenance calls.
"""

def classify_defect_strict(report_text: str) -> dict:
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        temperature=0.1,
        response_format={"type": "json_object"},
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": report_text},
        ],
    )

    return json.loads(response.choices[0].message.content)

for report in [SHIFT_REPORT, CLEAN_REPORT]:
    out = classify_defect_strict(report)
    print(out)

Step 6: Batch process a full week and flag critical issues

In practice I receive a folder of reports every Monday. This loop processes a list, counts severities, and surfaces anything that needs immediate attention. Because Oxlo.ai charges per request, not per token, processing a dozen long shift logs costs the same as a single short ping. That is useful when these reports run to multiple pages.

WEEKLY_REPORTS = [
    SHIFT_REPORT,
    CLEAN_REPORT,
    """
Shift: A-1
Date: 2024-05-15
Supervisor: J. Patel

Line 2 hydraulic press lost pressure twice. Two parts measured 0.3 mm out of
tolerance. We quarantined lot #4490. Press gauge reads erratic. Stop line until
maintenance clears it.
""",
]

def summarize_week(reports: list[str]) -> None:
    criticals = []

    for idx, report in enumerate(reports, 1):
        parsed = classify_defect_strict(report)
        print(f"Report {idx}: severity={parsed['severity']}, line={parsed['line_id']}")

        if parsed.get("production_halt_recommended"):
            criticals.append(parsed)

    print(f"\nTotal reports: {len(reports)}")
    print(f"Halts recommended: {len(criticals)}")
    for c in criticals:
        print(f"  - {c['line_id']}: {c['defect_description']}")

summarize_week(WEEKLY_REPORTS)

Run it

Save everything in qc_agent.py and run python qc_agent.py. Here is what I see when I execute the weekly summary:

Report 1: severity=major, line=Line 3
Report 2: severity=none, line=None
Report 3: severity=critical, line=Line 2

Total reports: 3
Halts recommended: 1
  - Line 2: Hydraulic press lost pressure, parts out of tolerance

The agent correctly flagged the extruder streaking as major, the clean shift as none, and the hydraulic press as critical with a halt recommendation. If you need deeper reasoning over maintenance history, swap the model to deepseek-v3.2 or kimi-k2.6 on Oxlo.ai without changing any other code.

Next steps

Feed the parsed JSON into a SQLite or TimescaleDB table so you can trend defect rates by line and station over time. You can also wire the production_halt_recommended flag into a Slack webhook or PagerDuty alert so supervisors get pinged within seconds of a report hitting the inbox.

Top comments (0)