Skip to content

CURENT/LLM_LTB

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

4 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

LLM-LTB: AI-Enabled Power System Large-scale Testbed

Update:

We are developing LLM for ANDES for transient stability modeling and simulation; LLM for AMS for scheduling modeling and simulation.

Conversational LangGraph agent that drives CURENT LTB AMS β€” DCOPF, RTED, ED, UC, ACOPF β€” through natural-language commands.

Built as a sibling to pv-curve-llm; same multi-agent architecture, swapped domain engine (AMS / cvxpy / ANDES instead of pandapower).


Table of Contents


Overview

LLM-AMS lets you ask things like

"Load case ieee14_uced, trip generator PV_1, then solve with SCS"

…and have the agent translate that into the exact AMS API calls you'd otherwise write by hand from examples/ex2.ipynb:

sp = ams.load(ams.get_case('ieee14/ieee14_uced.xlsx'), setup=True, no_output=True)
sp.StaticGen.set(src='u', idx='PV_1', attr='v', value=0)
sp.RTED.update()
sp.RTED.run(solver='SCS')

The agent uses a LangGraph state machine with a classifier β†’ router β†’ six route-specific nodes (Q&A, Discovery, Case I/O, Configure, Modify, Solve), plus a planner for compound queries like "change load PQ_1 to 3.2 then solve".

Technology stack

  • Agent framework: LangGraph + LangChain
  • LLMs: Ollama (default, local) or OpenAI
  • Power simulator: LTB AMS (ltbams) + ANDES + cvxpy
  • Solvers: open-source CLARABEL, OSQP, SCS, HiGHS, SCIP, SCIPY (commercial GUROBI / MOSEK / CPLEX / COPT auto-detected if installed)

Phase 1 Routes (1-6)

Route Node Maps to AMS API ex2 cell
1 – Q&A question_general concept Q&A: routines, constraints, cvxpy DCP (educational)
2 – Discovery question_parameter cvxpy.installed_solvers(), all_routines, list loads / gens / lines, constraint ON/OFF cell 64
3 – Case I/O case_io ams.load(ams.get_case(...)), case info cells 6, 50, 59
4 – Configure configure active routine, solver, routine.config.update(t=...), routine.disable([...]), routine.enable([...]) cells 69, 76, 81, 92
5 – Modify modify PQ.alter('p0', ...), StaticGen.set('u', ...), Line.alter('u', ...), Line.set('rate_a', ...) cells 19, 41, 52, 61
6 – Solve solve routine.run(solver=...) β†’ pg, plf, pd, obj + bar-chart plots cells 13, 23, 34, 45, 54, 66, 72, 78, 89, 96, 103

Routes 7-11 (multi-period temporal, ANDES co-sim, custom cvxpy formulations, exporting) are Phase 2 / 3.


Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  START  β”‚
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ CLASSIFIER β”‚  β†’ one of six message_type labels
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   ROUTER   β”‚  β†’ simple single-route OR planner for compound
β””β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜
     β”‚
     β”œβ”€β”€β–Ί QUESTION_GENERAL ────► END | ADVANCE_STEP
     β”œβ”€β”€β–Ί QUESTION_PARAMETER ──► END | ADVANCE_STEP
     β”œβ”€β”€β–Ί CASE_IO ─────────────► END | ADVANCE_STEP | ERROR_HANDLER
     β”œβ”€β”€β–Ί CONFIGURE ───────────► END | ADVANCE_STEP | ERROR_HANDLER
     β”œβ”€β”€β–Ί MODIFY ──────────────► END | ADVANCE_STEP | ERROR_HANDLER
     β”œβ”€β”€β–Ί SOLVE ───────────────► END | ADVANCE_STEP | ERROR_HANDLER
     └──► PLANNER ─────────────► STEP_CONTROLLER ──► (any of the 6) ──► ADVANCE_STEP ──► SUMMARY ──► END

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ ERROR_HANDLER  β”‚ ─────► ADVANCE_STEP | END
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Core components

  • State (agent/state/app_state.py): TypedDict LangGraph state holding messages, current Inputs, last results, plan / step counter, error info.
  • Inputs (agent/schemas/inputs.py): pydantic model β€” case_path, routine, solver, config_t, disabled_constraints, load_overrides, gen_off, line_off, line_rate_overrides.
  • AMSContext (agent/ams_engine/engine.py): thin object that owns one ams.System and exposes idempotent methods matching ex2's API (load_case, alter_load_p0, set_gen_status, set_line_status, set_config_t, disable_constraints, solve, …). Held by the SessionManager; bound into node closures (same pattern as retriever in pv-curve-llm).
  • Workflow (agent/workflows/workflow.py): compiled LangGraph StateGraph wiring all 13 nodes.
  • Plotting (agent/ams_engine/plotting.py): bar charts for pg, plf, pd saved under generated/.

Installation

Prerequisites

  • Python β‰₯ 3.11 (tested on 3.12)
  • conda or any venv tool
  • Ollama for local LLM (optional if you use OpenAI)

Conda environment

conda create -n llm-ams python=3.12 -y
conda activate llm-ams
pip install -r requirements.txt

requirements.txt pulls in ltbams (which brings ANDES + cvxpy + kvxopt), LangChain stack, plus open-source solvers highspy + pyscipopt. cvxpy's bundled CLARABEL, OSQP, SCS, SCIPY are always available.

Ollama (default LLM)

ollama pull llama3.1:8b

Add a .env file (copy .env.example) if you want OpenAI:

OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-mini

Verify

python -c "import ams, cvxpy; print(ams.__version__, cvxpy.installed_solvers())"
# 1.3.0 ['CLARABEL', 'SCS', 'SCIP', 'SCIPY', 'HIGHS', 'OSQP']

Quick Start

conda activate llm-ams
cd LLM_AMS
python main.py

You will be asked three things in order (each has a default β€” just hit Enter):

  1. Provider: openai or ollama (default ollama)
  2. Routine: any AMS class name (RTED, DCOPF, ED, UC, …) (default RTED)
  3. Solver: shown filtered by your routine's compatibility (default first in list)

The agent then loads the ex2 default case 5bus/pjm5bus_demo.xlsx and you're at the prompt.


Usage Examples

1. Replay ex2.ipynb section "Change Load"

Message: Change load PQ_1 to 3.2 and PQ_2 to 3.2
  β†’ modify: load PQ_1 p0 β†’ 3.2 pu, load PQ_2 p0 β†’ 3.2 pu

Message: Solve
  β†’ solve: RTED with CLARABEL, obj = 0.846329
            pg = [0.20, 1.64, 0.60, 5.96, 2.00]   ← exact match with ex2

2. Replay ex2 section "Trip a Generator"

Message: Trip generator PV_1 then solve
  β†’ planner: 2 steps
  β†’ modify:  tripped generator PV_1
  β†’ solve:   pg = [-0.00, 0.50, 0.60, 2.97, 0.33]   ← matches ex2 cell 47

3. Replay ex2 section "Disable Constraints"

Message: Disable plflb and plfub
  β†’ configure: disabled plflb, disabled plfub

Message: Solve
  β†’ solve: line-flow limits ignored; plf swings to ex2 cell 74 values

4. Switch routine / solver / grid case

Message: Switch routine to DCOPF
Message: Use solver SCS
Message: Load case ieee14_uced
Message: Solve
  β†’ DCOPF on IEEE-14 with SCS, plots saved under generated/

5. Discovery

Message: What routines are available?
  β†’ list of 33 routines grouped by family

Message: Which solvers can I use for UC?
  β†’ ['SCIP', 'SCIPY']   ← only MIP-capable installed solvers

6. Pure Q&A

Message: What is RTED and how is it different from DCOPF?
  β†’ educational answer from the AMS concepts reference

Type quit (or q) to exit.


LangGraph Workflow

13 nodes wired in agent/workflows/workflow.py:

Category Nodes
Routing classifier, router
Planning planner, step_controller, advance_step, summary
Actions (Routes 1-6) question_general, question_parameter, case_io, configure, modify, solve
Recovery error_handler

Simple-query path: START β†’ classifier β†’ router β†’ <one route> β†’ END.

Multi-step path (planner-triggered by "then", "and then", "compare", or change-then-solve patterns):

START β†’ classifier β†’ router β†’ planner β†’
  step_controller β†’ <route node> β†’ advance_step β†’
    ... loop ...
  β†’ summary β†’ END

Recovery: any route node may attach error_info; the conditional edge routes to error_handler, which uses the LLM to explain the failure and resets retry state.


Configuration

Environment variables (.env)

# Default β€” local Ollama
OLLAMA_MODEL=llama3.1:8b
OLLAMA_BASE_URL=http://localhost:11434

# Optional β€” OpenAI
OPENAI_API_KEY=sk-...
OPENAI_MODEL=gpt-4o-mini

# Where to drop generated plots
AMS_OUTPUT_DIR=generated

Adding commercial solvers

# GUROBI (license required)
pip install gurobipy

# MOSEK (license required)
pip install mosek

Both are auto-detected via cvxpy.installed_solvers() and will appear in the solver-selection prompt for compatible routines (UC, ACOPF, large-scale DCOPF).

Adding cases

Drop any AMS-readable file (.xlsx, .json, .raw, MATPOWER .m) into AMS's cases/ folder, or pass an absolute path:

Message: Load case /Users/me/my_grid.xlsx

Custom banner

The startup banner is an ASCII-art string in agent/utils/display.py (constant _BANNER_LINES, ANSI-Shadow font). Edit those lines to change the wordmark.


Project Structure

LLM_AMS/
β”œβ”€β”€ main.py                       # entry point
β”œβ”€β”€ cli.py                        # terminal interface (provider β†’ routine β†’ solver prompts)
β”œβ”€β”€ requirements.txt
β”œβ”€β”€ .env.example
β”‚
β”œβ”€β”€ agent/
β”‚   β”œβ”€β”€ core.py                   # LLM + AMSContext + graph factory
β”‚   β”œβ”€β”€ session.py                # SessionManager (bootstraps default case, streams turns)
β”‚   β”œβ”€β”€ prompts.py                # all system / user prompts
β”‚   β”‚
β”‚   β”œβ”€β”€ workflows/
β”‚   β”‚   └── workflow.py           # compiled LangGraph
β”‚   β”‚
β”‚   β”œβ”€β”€ nodes/                    # 13 nodes
β”‚   β”‚   β”œβ”€β”€ classify.py
β”‚   β”‚   β”œβ”€β”€ route.py
β”‚   β”‚   β”œβ”€β”€ planner.py
β”‚   β”‚   β”œβ”€β”€ step_controller.py
β”‚   β”‚   β”œβ”€β”€ advance_step.py
β”‚   β”‚   β”œβ”€β”€ summary.py
β”‚   β”‚   β”œβ”€β”€ error_handler.py
β”‚   β”‚   β”œβ”€β”€ question_general.py   # Route 1
β”‚   β”‚   β”œβ”€β”€ question_parameter.py # Route 2
β”‚   β”‚   β”œβ”€β”€ case_io.py            # Route 3
β”‚   β”‚   β”œβ”€β”€ configure.py          # Route 4
β”‚   β”‚   β”œβ”€β”€ modify.py             # Route 5
β”‚   β”‚   └── solve.py              # Route 6
β”‚   β”‚
β”‚   β”œβ”€β”€ state/
β”‚   β”‚   └── app_state.py          # TypedDict
β”‚   β”‚
β”‚   β”œβ”€β”€ schemas/                  # pydantic structured-output schemas
β”‚   β”‚   β”œβ”€β”€ inputs.py
β”‚   β”‚   β”œβ”€β”€ classifier.py
β”‚   β”‚   β”œβ”€β”€ parameter.py
β”‚   β”‚   β”œβ”€β”€ planner.py
β”‚   β”‚   └── response.py
β”‚   β”‚
β”‚   β”œβ”€β”€ ams_engine/               # the AMS-side "engine" (mirrors pv_curve/)
β”‚   β”‚   β”œβ”€β”€ engine.py             # AMSContext: live ams.System wrapper
β”‚   β”‚   β”œβ”€β”€ routines.py           # routine ↔ solver compatibility
β”‚   β”‚   └── plotting.py           # pg / plf / pd bar charts
β”‚   β”‚
β”‚   └── utils/
β”‚       β”œβ”€β”€ common_utils.py
β”‚       β”œβ”€β”€ context.py
β”‚       └── display.py            # rich banner / parameter table / streaming
β”‚
└── generated/                    # output plots (gitignored)

Roadmap (Phase 2 & 3)

Phase 1 ships Routes 1-6 (single-period DCOPF / RTED workflows from ex1-ex4). The following routes from the design table are deferred:

Phase Route Function
2 7 – Temporal multi-period ED / UC schedule, time-series plots
2 8 – Scenario snapshot + compare two solve results (matches pv-curve Route 8)
3 9 – ANDES ss.to_andes(...) co-simulation (AMS's unique feature)
3 10 – Custom Formulation runtime cvxpy extension (ex8)
3 11 – Export dump case to xlsx / JSON / MATPOWER

License

This project follows the licenses of its dependencies:

  • LangChain / LangGraph: MIT
  • LTB AMS: GPL-3.0
  • cvxpy: Apache-2.0
  • ANDES: GPL-3.0

Acknowledgments

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages