Skip to content

feat: LLM chat backend with tool-use loop and AG-UI streaming#26

Draft
cdgaete wants to merge 7 commits into
PyPSA:mainfrom
open-energy-transition:dev-llm
Draft

feat: LLM chat backend with tool-use loop and AG-UI streaming#26
cdgaete wants to merge 7 commits into
PyPSA:mainfrom
open-energy-transition:dev-llm

Conversation

@cdgaete
Copy link
Copy Markdown

@cdgaete cdgaete commented May 15, 2026

Summary

Adds an LLM chat backend to pypsa-app with provider-agnostic configuration (OpenRouter, Ollama, or any OpenAI-compatible API).

What's included

  • llm/ package: LiteLLM client, chat service with multi-step tool-use loop, AG-UI SSE event streaming, system prompts
  • LLM tools: list_networks, get_network_detail, get_network_statistics
  • Chat API: POST /chat/stream (SSE), GET /chat/health
  • LLMSettings: provider-agnostic config via env vars (LLM_PROVIDER, LLM_API_KEY, LLM_API_BASE, LLM_MODEL)
  • Feature flag: CHAT_ENABLED wired through /version endpoint
  • Dependency: litellm>=1.83 added to pyproject.toml

Not included (future PRs)

  • Frontend chat UI
  • Conversation persistence
  • Stop/interrupt cleanup for partial messages

cdgaete and others added 5 commits May 12, 2026 18:38
Codebase-only snapshot of dev-llm-implementation, prepared per the two-PR
strategy in .claude/project/main-pr-strategy.md. Tests, lockfiles, and
AI-context files are excluded; they ship in a stacked follow-up PR.

This PR contains:
- Backend: pypsa_app.llm module (service-architecture refactor + tools:
  list_networks, get_network_detail, get_network_statistics), feature-flagged
  via CHAT_ENABLED; LLMSettings extracted from backend.settings; provider-
  agnostic client via LiteLLM with the openai/ prefix
- Frontend: Svelte chat panel built on AI Elements; modal UI with phase-
  tagged tool calls inside Reasoning; NetworkCard/NetworksTable/Statistics/
  ChatBar/Line/Pie/DataTable renderers; stick-to-bottom scroll, edit-and-
  resend, copy actions; Tailwind typography
- Infra: SPA static file serving, alembic advisory lock, /version exposes
  chat_enabled, compose + Dockerfile updates, sandcastle patch, seed data
- Docs: README + docs/configuration.md document the chat feature flag and
  LLM env vars

Excludes (per main-pr-strategy.md):
- Category A — never on main: .claude/, .sandcastle/, CLAUDE.md, AGENTS.md
- Category B — split into follow-up PR: tests/, **/*.test.{ts,js},
  vitest.config.*, uv.lock, package-lock.json, frontend/app/package-lock.json

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove files and references unrelated to the LLM chat MVP that
leaked into the codebase-promotion PR:

- delete seed.jsonl (private backlog dump)
- delete patches/@ai-hero+sandcastle+0.5.7.patch (sandcastle-only)
- delete root tsconfig.json (only typechecked .sandcastle/**)
- package.json: drop sandcastle scripts + @ai-hero/sandcastle,
  patch-package, tsx devDeps (all sandcastle-only)
- pyproject.toml: drop .sandcastle from ruff exclude

Frontend continues to use frontend/app/tsconfig.json and its
own package.json — root tooling was sandcastle-only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trim the M1 codebase promotion to only what the read-only chat MVP
actually consumes:

- Delete unused ai-elements subtrees: prompt-input/*, message/branching/*,
  message/attachments/*, MessageToolbar, MessageResponse. Verified zero
  consumers in src/lib/components/chat or src/routes.
- Rewrite message/index.ts to export only Message / MessageContent /
  MessageActions / MessageAction.
- Strip dead MessageBranchController / MessageAttachmentData from
  message-context.svelte.ts (only MessageRole is still consumed).
- Rewrite CHANGELOG [Unreleased] to describe what the MVP actually
  ships: LiteLLM-backed chat, OpenAI-compatible LLM_* env vars,
  three read-only tools, and the supporting backend changes. The
  previous text referenced the Anthropic SDK and ANTHROPIC_* env
  names that the code no longer uses.
- Patch README Quick Start to include LLM_PROVIDER and LLM_MODEL.

Verified end-to-end in the dev stack: chat FAB renders, list_networks
tool call and table render unchanged after the deletions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove three frontend artifacts not reached from the chat MVP path:
button-group/, aspect-ratio/, and the app-navigation test stub.
Tighten the CHANGELOG Added section to a concise summary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add llm/ package: LiteLLM client, chat service with tool-use loop,
  AG-UI SSE event streaming, system prompts
- Add LLM tools: list_networks, get_network_detail, get_network_statistics
- Add chat API routes (POST /chat/stream, GET /chat/health)
- Add LLMSettings with provider-agnostic config (OpenRouter, Ollama, etc.)
- Wire chat_enabled feature flag through version endpoint and schema
- Add litellm dependency to pyproject.toml
- Remove unused exception classes
@cdgaete cdgaete force-pushed the dev-llm branch 2 times, most recently from 89b5f84 to 375f07e Compare May 15, 2026 18:13
cdgaete added 2 commits May 15, 2026 14:17
- Fix PERF401: replace .append loop with .extend in service.py
- Apply ruff format to spa_static_files.py and tools/__init__.py
- Add trailing newline to compose/.env.example
- Default reasoning_effort to None (let provider decide)
- Remove unused exception classes
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant