Initial competition release of IRIS Maintenance Copilot, an evidence-grounded industrial maintenance assistant built with InterSystems IRIS.
VECTOR_COSINE%iFind.Index.BasicThe application is intended as maintenance decision support and does not replace qualified inspection or a definitive technical diagnosis.
An evidence-grounded industrial maintenance assistant built with Python and
InterSystems IRIS.
IRIS Maintenance Copilot lets a technician describe a machine symptom in
natural language and receive a structured maintenance assessment supported by
retrieved evidence. The current synthetic knowledge base covers electric
motors, bearings, alignment, centrifugal pumps, mechanical seals, industrial
fans, vibration, temperature rise, cavitation, and rotor or blade imbalance.
The application is decision support, not a definitive diagnostic system. It
distinguishes possible causes from confirmed failures, exposes evidence IDs,
and states when the available information is insufficient.
InterSystems IRIS is the operational and retrieval data platform for the
project. It performs concrete responsibilities in one database:
Equipment and MaintenanceEvent records;DocumentChunk rows;VECTOR(FLOAT, 384) column;VECTOR_COSINE inside IRIS;%iFind.Index.Basic index;Python generates embeddings, performs Reciprocal Rank Fusion (RRF), selects a
small evidence set, calls the configured LLM, and validates its structured
output. Vector similarity and lexical matching are not calculated by scanning
documents in Python.
Maintenance query
|
v
SentenceTransformer query embedding
|
v
+---------------------------------------+
| InterSystems IRIS |
| |
| VECTOR_COSINE semantic retrieval |
| iFind lexical retrieval and ranking |
+---------------------------------------+
| |
+---------+----------+
v
Reciprocal Rank Fusion (Python)
|
v
Evidence selection
|
v
OpenAI-compatible LLM provider
|
v
JSON and grounding validation
|
v
Cited maintenance assessment
sentence-transformers/all-MiniLM-L6-v2.k = 60.The generation layer is deliberately constrained:
E1;In live adversarial validation, the fictional code ZX-991 was not present in
the knowledge base. The system did not invent a meaning, likely cause, or
technical check, marked evidence coverage as low, and stated that the code was
absent from the supplied evidence.
intersystems_irispython==5.4.0sentence-transformers==6.0.1sentence-transformers/all-MiniLM-L6-v2 (384 dimensions)VECTOR, VECTOR_COSINE, and iFindMAINTENANCEall-MiniLM-L6-v2This repository does not include Docker Compose or automate IRIS namespace
creation. Prepare the IRIS instance and namespace before running the project
commands.
The following PowerShell workflow is the configuration validated on Windows.
Run it from the repository root:
py -3.13 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt
On another operating system, create and activate a Python 3.13 virtual
environment using the platform-equivalent commands, then run the same
python -m pip install -r requirements.txt command.
The validated development instance used:
localhost1972MAINTENANCE_SYSTEMThese are local development defaults, not embedded credentials. The password
has no default. For a fresh IRIS installation, create or select the
MAINTENANCE namespace through the IRIS Management Portal before running the
initializer.
Once connection variables are configured, create the SQL tables and iFind
index with:
python -m src.init_db
The initializer checks INFORMATION_SCHEMA before creating objects and is safe
to run repeatedly.
The application reads process environment variables directly. It does not load
a .env file.
| Variable | Required | Default |
|---|---|---|
IRIS_HOST |
No | localhost |
IRIS_PORT |
No | 1972 |
IRIS_NAMESPACE |
No | MAINTENANCE |
IRIS_USERNAME |
No | _SYSTEM |
IRIS_PASSWORD |
Yes | None |
PowerShell example using a masked password prompt:
$env:IRIS_HOST = "localhost" $env:IRIS_PORT = "1972" $env:IRIS_NAMESPACE = "MAINTENANCE" $env:IRIS_USERNAME = "_SYSTEM"
$irisSecret = Read-Host "IRIS password" -AsSecureString $env:IRIS_PASSWORD = [System.Net.NetworkCredential]::new("", $irisSecret).Password
| Variable | Required for generation | Default |
|---|---|---|
LLM_BASE_URL |
Yes | None |
LLM_API_KEY |
Yes | None |
LLM_MODEL |
Yes | None |
The live-validated Gemini-compatible configuration used this non-secret base
URL and model name:
$env:LLM_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai" $env:LLM_MODEL = "gemini-3.8-flash"
$llmSecret = Read-Host "LLM API key" -AsSecureString $env:LLM_API_KEY = [System.Net.NetworkCredential]::new("", $llmSecret).Password
Never place passwords or API keys in source files. Clear session credentials
when finished:
Remove-Item Env:IRIS_PASSWORD -ErrorAction SilentlyContinue
Remove-Item Env:LLM_API_KEY -ErrorAction SilentlyContinue
With IRIS running and the connection variables set, run these commands in
order:
# Create Equipment, MaintenanceEvent, DocumentChunk, and the iFind index. python -m src.init_dbInsert 3 synthetic equipment records and 5 synthetic maintenance events.
python -m src.seed_data
Generate real embeddings and insert 12 synthetic knowledge chunks.
python -m src.ingest_knowledge
All three operations are repeat-safe. The first knowledge-ingestion run may
download the embedding model and therefore take longer.
Generation requires both IRIS and LLM environment variables:
python -m src.rag_cli "High vibration at the drive-end bearing of the main conveyor motor"
Without a query argument, the CLI uses that motor-vibration example by default:
python -m src.rag_cli
The output includes the observed issue, assessment, possible causes,
recommended checks, evidence coverage, evidence IDs and titles, limitations,
and a safety note.
These commands require installed Python dependencies but no live IRIS or LLM
credentials:
python -m compileall -q src
python -m src.validate_rag --components-only
python -m src.validate_llm_provider
They cover context construction, unsupported identifier detection, JSON and
citation rejection rules, retry bounds, non-retryable HTTP failures, and
credential redaction. Controlled fixtures are not live LLM results.
These require IRIS_PASSWORD and a reachable initialized database:
# Structured tables and live Equipment/MaintenanceEvent JOIN. python -m src.validate_dataNative IRIS VECTOR_COSINE retrieval.
python -m src.validate_vector_search
IRIS semantic + iFind lexical retrieval followed by Python RRF.
python -m src.validate_hybrid_search
The initial connection can also be smoke-tested against the validated local
defaults with python scripts/test_iris_connection.py; that script prompts for
the password directly.
This requires both IRIS and LLM credentials and exercises all four validated
queries, including fictional code ZX-991:
python -m src.validate_rag
Transient HTTP 429, 500, 502, 503, and 504 responses are retried up
to three attempts with bounded exponential backoff.
The following summarizes live-observed behavior without reproducing full model
responses:
E1/E2/E3, used medium coverage, and disclosed missingZX-991 code: did not infer a meaning or produce unsupportedEach knowledge chunk is embedded by all-MiniLM-L6-v2 into 384 floating-point
values. Python serializes the embedding for TO_VECTOR(?, FLOAT, 384), and IRIS
stores it as VECTOR(FLOAT, 384). At query time, IRIS calculates and orders
VECTOR_COSINE similarity.
In parallel, the DocumentChunkContentIdx %iFind.Index.Basic index performs
word-level retrieval over chunk content. Query terms are normalized into a
small deterministic OR expression, and IRIS returns a lexical TF-IDF ranking.
Python fuses the two ranked lists using Reciprocal Rank Fusion:
RRF_score(document) = sum(1 / (k + rank_i(document)))
The default is k = 60. RRF uses rank positions rather than adding raw cosine
and lexical scores because the two score scales are not directly comparable.
All bundled equipment records, maintenance events, and knowledge chunks are
synthetic and general. They do not reproduce proprietary manufacturer manuals,
service bulletins, or real customer operational data.
AI agents were intentionally used to help develop and review the project as
part of the competition methodology. The chronological record is maintained in
https://github.com/raphapaulin/iris-maintenance-copilot/blob/main/AI_LOG.md, including what was requested, what was actually tested,
and where AI suggestions required correction.
Examples include:
section initially generated as a column name was rejected because SECTIONdocument_section and revalidated;iris-maintenance-copilot/
|-- src/
| |-- init_db.py # Repeat-safe SQL tables and iFind index
| |-- seed_data.py # Synthetic operational data
| |-- knowledge_base.py # Synthetic maintenance guidance
| |-- ingest_knowledge.py # Embedding generation and vector ingestion
| |-- semantic_search.py # IRIS VECTOR_COSINE retrieval
| |-- lexical_search.py # IRIS iFind lexical retrieval
| |-- hybrid_search.py # Python Reciprocal Rank Fusion
| |-- evidence_context.py # Evidence selection and context formatting
| |-- llm_provider.py # OpenAI-compatible HTTP provider and retry
| |-- rag_service.py # Grounded generation and output validation
| |-- rag_cli.py # User-facing CLI demo
| |-- validate_*.py # Controlled and live validation entry points
| `-- iris_connection.py # Environment-based IRIS connection
|-- scripts/
| `-- test_iris_connection.py # Original local connection smoke test
|-- https://github.com/raphapaulin/iris-maintenance-copilot/blob/main/AI_LOG.md # AI-assisted development record
|-- ARTICLE_NOTES_PT.md # Portuguese article source material
|-- SUBMISSION.md # Open Exchange submission source material
|-- requirements.txt
|-- https://github.com/raphapaulin/iris-maintenance-copilot/blob/main/LICENSE
`-- README.md
This project is licensed under the MIT License. See https://github.com/raphapaulin/iris-maintenance-copilot/blob/main/LICENSE.