We are building a Physics Research Assistant that ingests a raw problem statement or paper excerpt, extracts governing equations, checks dimensional consistency, and proposes a concrete follow-up question. It is aimed at graduate students and working physicists who want to sanity-check derivations or explore new formulations without getting stuck in algebraic loops.
What you'll need
- Python 3.10 or newer
- The OpenAI SDK:
pip install openai - An Oxlo.ai API key from https://portal.oxlo.ai
Step 1: Connect to Oxlo.ai
First, we initialize the OpenAI SDK to point at Oxlo.ai and verify that our key is live. I use llama-3.3-70b here because it is a reliable general-purpose model for quick smoke tests.
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": "State the Schwarzschild radius of a black hole in LaTeX."}
]
)
print(response.choices[0].message.content)
Step 2: Write the system prompt
The system prompt is the only training the agent receives. I keep it strict so the model always returns the same sections, which makes downstream parsing trivial.
SYSTEM_PROMPT = """You are a physics research assistant. Analyze the user's problem or excerpt and return a JSON object with exactly these keys:
- domain: the physics subdomain, e.g., Fluid Dynamics or Quantum Mechanics.
- equations: a list of strings, each an equation in LaTeX with a short label.
- assumptions: a list of explicit physical or mathematical assumptions.
- dimensional_check: a sentence verifying SI base-unit consistency.
- follow_up: one concrete experimental or theoretical next step.
Be precise. If an equation is approximate, state its limiting condition."""
Step 3: Extract structured analysis with JSON mode
Oxlo.ai supports OpenAI-compatible JSON mode, so we can enforce valid output structure instead of parsing free text. I switch to kimi-k2.6 here because its reasoning capabilities handle multi-constraint physics problems cleanly.
import json
# client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
def analyze_problem(problem_text: str) -> dict:
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": problem_text},
],
response_format={"type": "json_object"},
temperature=0.2,
)
return json.loads(response.choices[0].message.content)
test_input = (
"A charged particle with charge q and mass m moves at speed v perpendicular "
"to a uniform magnetic field B. Derive the radius of its circular path."
)
result = analyze_problem(test_input)
print(json.dumps(result, indent=2))
Step 4: Verify dimensional consistency
Even capable models occasionally hallucinate units. We add a second pass that audits the equations explicitly. I use deepseek-v3.2 for this verifier because it is efficient at structured reasoning tasks.
import json
# client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
VERIFIER_PROMPT = """You are a dimensional-analysis auditor.
Given a physics domain and a list of equations, verify that the left-hand and right-hand sides carry identical SI base dimensions.
Return a JSON object with:
- validity: boolean, true only if every equation is dimensionally consistent.
- notes: a list of strings, one per equation, stating either 'Consistent' or describing the mismatch."""
def verify_dimensions(analysis: dict) -> dict:
payload = {
"domain": analysis.get("domain"),
"equations": analysis.get("equations"),
}
response = client.chat.completions.create(
model="deepseek-v3.2",
messages=[
{"role": "system", "content": VERIFIER_PROMPT},
{"role": "user", "content": json.dumps(payload)},
],
response_format={"type": "json_object"},
temperature=0.1,
)
return json.loads(response.choices[0].message.content)
audit = verify_dimensions(result)
print(json.dumps(audit, indent=2))
Step 5: Assemble the CLI agent
Now we wire the two stages into a single script that accepts a problem string, prints the analysis, and flags any dimensional errors.
from openai import OpenAI
import json
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
SYSTEM_PROMPT = """You are a physics research assistant. Analyze the user's problem or excerpt and return a JSON object with exactly these keys:
- domain: the physics subdomain, e.g., Fluid Dynamics or Quantum Mechanics.
- equations: a list of strings, each an equation in LaTeX with a short label.
- assumptions: a list of explicit physical or mathematical assumptions.
- dimensional_check: a sentence verifying SI base-unit consistency.
- follow_up: one concrete experimental or theoretical next step.
Be precise. If an equation is approximate, state its limiting condition."""
VERIFIER_PROMPT = """You are a dimensional-analysis auditor.
Given a physics domain and a list of equations, verify that the left-hand and right-hand sides carry identical SI base dimensions.
Return a JSON object with:
- validity: boolean, true only if every equation is dimensionally consistent.
- notes: a list of strings, one per equation, stating either 'Consistent' or describing the mismatch."""
def analyze_problem(problem_text: str) -> dict:
response = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": problem_text},
],
response_format={"type": "json_object"},
temperature=0.2,
)
return json.loads(response.choices[0].message.content)
def verify_dimensions(analysis: dict) -> dict:
payload = {
"domain": analysis.get("domain"),
"equations": analysis.get("equations"),
}
response = client.chat.completions.create(
model="deepseek-v3.2",
messages=[
{"role": "system", "content": VERIFIER_PROMPT},
{"role": "user", "content": json.dumps(payload)},
],
response_format={"type": "json_object"},
temperature=0.1,
)
return json.loads(response.choices[0].message.content)
def physics_research_agent(problem_text: str):
print("=== Physics Research Assistant ===\n")
analysis = analyze_problem(problem_text)
print(f"Domain: {analysis['domain']}\n")
print("Equations:")
for eq in analysis["equations"]:
print(f" - {eq}")
print()
print("Assumptions:")
for ass in analysis["assumptions"]:
print(f" - {ass}")
print()
audit = verify_dimensions(analysis)
print(f"Dimensional audit valid: {audit['validity']}")
for note in audit["notes"]:
print(f" - {note}")
print()
print(f"Follow-up: {analysis['follow_up']}")
if __name__ == "__main__":
sample = (
"A block of mass m slides down a frictionless incline at angle theta. "
"Find its acceleration."
)
physics_research_agent(sample)
Run it
Save the complete script as physics_agent.py, set your API key, and run it.
export OXLO_API_KEY="sk-oxlo.ai-..."
python physics_agent.py
Example output:
=== Physics Research Assistant ===
Domain: Classical Mechanics
Equations:
- $a = g \sin\theta$ (acceleration along incline)
- $N = mg \cos\theta$ (normal force)
Assumptions:
- Frictionless surface
- Constant gravitational acceleration $g$
- Point mass approximation
Dimensional audit valid: True
- Consistent: LHS [m/s^2], RHS [m/s^2]
- Consistent: LHS [kg m/s^2], RHS [kg m/s^2]
Follow-up: Measure the actual acceleration with a motion sensor and compare against theoretical prediction for varying angles.
Next steps
Because Oxlo.ai uses flat request-based pricing, adding extra verification loops or feeding in long paper excerpts does not inflate your cost the way token-based providers do. That makes this multi-pass agent architecture practical for daily research.
To extend the agent, wire in the arXiv API so the follow_up field cites real papers, or add a SymPy layer to solve the extracted equations symbolically instead of relying on the LLM alone.
Top comments (0)