pycsamt.agents.hybrid_agent#

pycsamt.agents.hybrid_agent#

HybridInversionAgent wraps HybridInverter1D, HybridInverter2D, and HybridInverter3D.

Two-stage workflow:

Stage 1 — pre-trained supervised AI inverter (EMInverter1D / EMInverter2D / GCNInverter3D) is applied to produce a physically plausible initial model in milliseconds.

Stage 2 — physics-informed gradient descent (same Wait 1954 loss as PINNInverter) refines the Stage-1 model. Convergence is faster and more reliable than starting from a random initialisation.

Classes

HybridInversionAgent(*[, dim, max_iter, ...])

Two-stage AI + physics MT inversion.

class pycsamt.agents.hybrid_agent.HybridInversionAgent(*, dim=1, max_iter=200, smoothness_weight=0.005, lateral_weight=0.005, graph_weight=0.005, radius=5000.0, lr=0.005, solver='mt1d', comp='xy', n_freqs=32, api_key=None, model=None, llm_provider='claude')[source]#

Bases: BaseAgent

Two-stage AI + physics MT inversion.

Stage 1 applies a pre-trained supervised AI inverter to obtain a starting model. Stage 2 refines it with physics-informed Adam gradient descent.

Parameters:
  • dim ({1, 2, 3}) – Dimensionality. Default 1.

  • max_iter (int) – Physics refinement iterations (Stage 2). Default 200.

  • smoothness_weight (float) – Vertical regularisation weight. Default 0.005.

  • lateral_weight (float) – Lateral smoothness weight (2-D only). Default 0.005.

  • graph_weight (float) – Graph-Laplacian weight (3-D only). Default 0.005.

  • radius (float) – Edge radius in metres for 3-D graph. Default 5000.0.

  • lr (float) – Adam learning rate for Stage 2. Default 5e-3.

  • solver ({"mt1d", "csamt1d"}) – Physics solver. Default "mt1d".

  • comp (str) – Impedance component (1-D only). Default "xy".

  • n_freqs (int) – Frequency-grid size fed to the 1-D AI inverter. Default 32.

  • api_key (str | None) – LLM configuration (optional).

  • model (str | None) – LLM configuration (optional).

  • llm_provider (str) – LLM configuration (optional).

  • keys (Input)

  • ----------

  • data (sites / path observed)

  • object (ai_inverter fitted AI inverter) – or path to checkpoint

  • ai_inverter (checkpoint alias for)

  • directory (output_dir optional save)

  • dim

  • max_iter

:param : :param smoothness_weight: :param : :param lateral_weight: :param : :param graph_weight: :type graph_weight: optional overrides :param Output data keys: :param —————-: :param inverter fitted HybridInverterXD: :param section ndarray (n_layers: Stage-2 log10-rho section :param n_stations): Stage-2 log10-rho section :param stage1_section ndarray — Stage-1 section: :param models list of LayeredModel (1-D): :param stage1_models list of LayeredModel (1-D): :param n_stations int: :param rms_per_station dict {station: :type rms_per_station dict {station: float} :param rms_global float (Stage-2): :param rms_stage1 float (Stage-1 for comparison): :param convergence_df pandas.DataFrame or None: :param residuals_df pandas.DataFrame or None: :param figures dict: :param figure_paths dict:

Examples

>>> from pycsamt.ai.inversion import EMInverter1D
>>> ai = EMInverter1D.load("checkpoint.npz")
>>> agent = HybridInversionAgent(
...     dim=1, max_iter=100
... )
>>> res = agent.execute({
...     "path":        "/data/L22PLT",
...     "ai_inverter": ai,
... })
>>> res["rms_global"]
0.14
SYSTEM_PROMPT: str = 'You are an expert in hybrid AI + physics-informed\ninversion for MT/CSAMT geophysics.\nGiven a hybrid inversion result write 4-5 sentences:\n1. Compare Stage-1 (AI) and Stage-2 (physics) RMS.\n2. Describe how much the physics step improved the fit.\n3. State the recovered resistivity structure.\n4. Flag stations where Stage-2 failed to improve on\n   Stage-1 or where residuals remain high.\n5. Recommend whether to retrain the AI component,\n   run more physics iterations, or proceed to 2-D.\nReply in plain scientific English.\n'#

Override in subclasses to give the LLM its domain expertise.

execute(input_data)[source]#

Run this agent on input_data and return an AgentResult.

Subclasses must implement this method. The contract:

  • Reset self._last_cost = 0.0 at the top.

  • Record wall-clock time with t0 = time.time().

  • Return AgentResult(elapsed_seconds=time.time()-t0, cost_estimate_usd=self._last_cost, ...).

Parameters:

input_data (dict[str, Any])

Return type:

AgentResult