TanmaySah's picture
Update UI branding to JEV InvariantOne
459f388 verified
Raw History Blame Contribute Delete
13.3 kB
"""
JEV InvariantOne — Hugging Face Space Demo
Order-Equivariant Decision Model & Agent Routing
"""
from __future__ import annotations
import gradio as gr
from invariantone import InvariantOne
# ---------------------------------------------------------
# Load model once at application startup
# ---------------------------------------------------------
print("Loading InvariantOne-v1 checkpoint...")
model = InvariantOne.from_pretrained("invariantone-v1")
print(f"InvariantOne-v1 loaded successfully on device: {model.device}")
DEFAULT_COUNT = 4
MAX_OPTIONS = 6
def decide_action(
state: str,
question: str,
*options,
):
"""
Executes InvariantOne decision inference over active options.
"""
active_options = [opt.strip() for opt in options if opt and opt.strip()]
if len(active_options) < 2:
return (
"Error: Please provide at least 2 non-empty candidate options.",
"—",
"—",
{},
"**Validation Error:** InvariantOne requires at least 2 candidate actions (K ≥ 2).",
)
res = model.decide(
state=state.strip(),
question=question.strip(),
options=active_options,
)
selected_text = f"Option {res.choice_index + 1}: {res.choice}"
top_prob_text = f"{res.confidence * 100:.2f}%"
sorted_probs = sorted(res.probabilities, reverse=True)
margin_val = sorted_probs[0] - sorted_probs[1] if len(sorted_probs) > 1 else 0.0
margin_text = f"{margin_val * 100:.2f}% ({margin_val:.4f})"
# Format probability dictionary for gr.Label visualization
prob_dict = {
f"[{i+1}] {opt}": float(prob)
for i, (opt, prob) in enumerate(zip(active_options, res.probabilities))
}
# Markdown table breakdown
table_rows = []
for i, (opt, p) in enumerate(zip(active_options, res.probabilities)):
is_selected = " **Selected**" if i == res.choice_index else ""
table_rows.append(f"| Option {i+1} | {opt} | **{p*100:.2f}%** | `{p:.6f}` |{is_selected} |")
latency_sec = res.latency_ms / 1000.0
table_md = (
"### Candidate Evaluation Summary\n\n"
"| # | Candidate Action | Probability | Calibrated Score | Result |\n"
"| :-: | :--- | :-: | :-: | :-: |\n" + "\n".join(table_rows) + "\n\n"
f"*Inference Latency: {latency_sec:.1f} s | Device: `{model.device}` | Calibration Temperature: τ* = 1.0091*"
)
return selected_text, top_prob_text, margin_text, prob_dict, table_md
def add_option_field(count: int):
new_count = min(count + 1, MAX_OPTIONS)
updates = [gr.update(visible=(i < new_count)) for i in range(MAX_OPTIONS)]
return [new_count] + updates
def remove_option_field(count: int):
new_count = max(count - 1, 2)
updates = []
for i in range(MAX_OPTIONS):
if i >= new_count:
updates.append(gr.update(visible=False, value=""))
else:
updates.append(gr.update(visible=True))
return [new_count] + updates
# ---------------------------------------------------------
# Gradio Interface Definition
# ---------------------------------------------------------
custom_css = """
<style>
.main-header { text-align: center; margin-bottom: 1rem; }
.links-bar { text-align: center; font-size: 0.95rem; margin-bottom: 1.2rem; }
.links-bar a { margin: 0 0.75rem; font-weight: 600; text-decoration: none; color: #4f46e5; }
.links-bar a:hover { text-decoration: underline; }
.scope-box { background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 8px; padding: 1rem 1.25rem; margin-bottom: 1.5rem; }
.scope-title { font-size: 1.05rem; font-weight: 700; color: #0f172a; margin-bottom: 0.35rem; }
.scope-text { font-size: 0.92rem; color: #334155; line-height: 1.5; margin-bottom: 0.5rem; }
.scope-note { font-size: 0.86rem; color: #64748b; font-style: italic; }
.timing-note { font-size: 0.85rem; color: #64748b; font-style: italic; margin-top: 0.15rem; margin-bottom: 0.75rem; }
.cpu-note { font-size: 0.85rem; color: #64748b; margin-top: 0.4rem; text-align: center; }
</style>
"""
with gr.Blocks(title="JEV InvariantOne — Order-Equivariant Decision Model") as demo:
gr.HTML(custom_css)
gr.Markdown(
"""
# JEV InvariantOne — Order-Equivariant Decision Model
**Zero-Bias Action Selection & Decision Routing for AI Agents**
Give **JEV InvariantOne** the situation, governing rules or constraints, and candidate actions, and it selects among the candidates without candidate-order bias.
Candidate evaluations are **mathematically permutation-equivariant by construction in real arithmetic**, eliminating candidate-order and position sensitivity in LLM agent tool selection and decision pipelines.
"""
)
gr.Markdown(
"""
<div class="links-bar">
<a href="https://huggingface.co/TanmaySah/InvariantOne-v1" target="_blank">Model Card</a> |
<a href="https://github.com/tradertanmay/InvariantOne" target="_blank">GitHub</a>
</div>
"""
)
gr.HTML(
"""
<div class="scope-box">
<div class="scope-title">Where JEV InvariantOne is Useful</div>
<div class="scope-text">
JEV InvariantOne is designed for structured multi-candidate decision problems where actions must be selected under explicit rules, constraints, priorities, overrides, thresholds, or system state. Example applications include agent action selection, tool routing, operational control, policy/rule execution, safety constraints, and infrastructure workflow decisions.
</div>
<div class="scope-note">
JEV InvariantOne is a specialized decision model rather than a general-purpose question-answering or knowledge model. Provide the relevant rules and constraints in the context when they are necessary to determine the decision.
</div>
</div>
"""
)
with gr.Row():
with gr.Column(scale=1):
gr.Markdown("### 1. Situation, Rules & Question")
state_box = gr.Textbox(
label="State / Context",
lines=3,
value="Boiler steam pressure is 96 bar. The operating rule states: If steam pressure exceeds 90 bar, open the emergency relief valve; otherwise, maintain normal burner firing.",
placeholder="Describe current situation and relevant governing rules or constraints...",
)
question_box = gr.Textbox(
label="Decision Question",
lines=1,
value="What action should be taken?",
placeholder="What action should be taken?",
)
gr.Markdown("### 2. Candidate Actions (K ≥ 2)")
gr.Markdown(
"*Note on Candidate Options Count (K): The runtime supports arbitrary K ≥ 2; reported scientific benchmarks are primarily for K = 4.*",
elem_classes=["timing-note"],
)
option_boxes = []
default_options = [
"Open the emergency relief valve",
"Increase boiler burner firing",
"Maintain normal burner firing",
"Disable pressure telemetry sensors",
]
for i in range(MAX_OPTIONS):
val = default_options[i] if i < len(default_options) else ""
box = gr.Textbox(
label=f"Option {i+1}",
value=val,
visible=(i < DEFAULT_COUNT),
placeholder=f"Candidate option {i+1}...",
)
option_boxes.append(box)
option_count_state = gr.State(DEFAULT_COUNT)
with gr.Row():
add_btn = gr.Button("Add Option", size="sm")
remove_btn = gr.Button("Remove Option", size="sm")
add_btn.click(
fn=add_option_field,
inputs=[option_count_state],
outputs=[option_count_state] + option_boxes,
)
remove_btn.click(
fn=remove_option_field,
inputs=[option_count_state],
outputs=[option_count_state] + option_boxes,
)
decide_btn = gr.Button("Decide Action", variant="primary", size="lg")
gr.Markdown(
"<div class='cpu-note'>Running on Hugging Face free CPU. Inference may take approximately 45–60 seconds.</div>"
)
with gr.Column(scale=1):
gr.Markdown(
"""
### 3. Decision Output
*Expected inference time: approximately 45–60 seconds on free CPU.*
"""
)
selected_box = gr.Textbox(
label="Selected Decision (Argmax)",
interactive=False,
)
with gr.Row():
top_prob_box = gr.Textbox(
label="Top Candidate Probability",
interactive=False,
)
margin_box = gr.Textbox(
label="Decision Margin (Top 1 - Top 2)",
interactive=False,
)
prob_label = gr.Label(
label="Calibrated Probability Distribution (τ* = 1.0091)",
num_top_classes=MAX_OPTIONS,
)
breakdown_table = gr.Markdown()
decide_btn.click(
fn=decide_action,
inputs=[state_box, question_box] + option_boxes,
outputs=[selected_box, top_prob_box, margin_box, prob_label, breakdown_table],
)
# Pre-populate structured intended-use examples
gr.Examples(
examples=[
[
"Boiler steam pressure is 96 bar. The operating rule states: If steam pressure exceeds 90 bar, open the emergency relief valve; otherwise, maintain normal burner firing.",
"What action should be taken?",
"Open the emergency relief valve",
"Increase boiler burner firing",
"Maintain normal burner firing",
"Disable pressure telemetry sensors",
],
[
"Cluster failover policy: If primary database heartbeats fail for over 10 seconds AND replica replication lag is 0 seconds, promote the replica to active master. Telemetry: Primary heartbeat has failed for 25 seconds; replica replication lag is verified at 0 seconds.",
"What orchestrator action should be executed?",
"Promote the replica to active master",
"Demote the replica to read-only status",
"Restart the replica database service",
"Wait indefinitely for primary manual recovery",
],
[
"Operating precedence: Life-safety emergency shutdown takes strict precedence over maintenance routines and scheduled cycle completion. Current situation: Personnel have entered the robotic cell while an automated cycle is running.",
"Which action takes precedence?",
"Execute emergency safety shutdown of the robotic cell",
"Complete the current robotic cycle before stopping",
"Engage maintenance bypass switch",
"Increase robotic movement speed",
],
[
"Deployment policy: An Incident Commander P0 freeze directive overrides all automated scheduled pipelines. Telemetry: Scheduled release pipeline triggers while an active P0 incident freeze is in effect.",
"What action must the deployment pipeline take?",
"Halt deployment pipeline and honor the incident freeze",
"Bypass the incident freeze and deploy code to production",
"Delete the production release branch",
"Downgrade incident severity without approval",
],
[
"High-voltage safety constraint: Never close the busbar breaker while the earthing ground switch is closed. Status: Earthing ground switch is closed for maintenance; an operator requests busbar energization.",
"What action must the safety interlock enforce?",
"Block busbar breaker closing until earthing switch is verified open",
"Close busbar breaker immediately while earthed",
"Bypass electrical interlock and energize busbar",
"Disconnect electrical ground monitoring circuits",
],
[
"System lifecycle rule: A container in DRAINING state progresses to TERMINATE once active client connections reach zero. Current state: Container is DRAINING; active connection count is 0.",
"What is the appropriate state transition?",
"Terminate container process and release assigned resources",
"Route incoming client traffic back to draining container",
"Pause container indefinitely in system memory",
"Mark container as permanently active",
],
],
inputs=[state_box, question_box] + option_boxes[:4],
)
if __name__ == "__main__":
demo.launch()