Skip to content

refactor: decompose LLMRails & LLMGenerationActions into modular components #1148

@Pouyanpi

Description

@Pouyanpi

Description

Currently we have two enormous classes, LLMRails (~2000 LOC) and LLMGenerationActions (~1200 LOC), that each do dozens of unrelated things (config loading, model init, DSL parsing, prompt templating, LLM calls, streaming logic, event translation, post-processing, etc.). This makes the code hard to understand, test, and extend.

Goal: break each of these “God classes” into a set of well-defined, single-responsibility modules. For example (this is just to show the idea and will change):

  • ConfigLoader (load & validate flows, ingest config.py overrides)
  • ModelFactory (instantiate LLM(s), set streaming flags)
  • KnowledgeBaseBuilder (async build of embeddings index)
  • EventTranslator (messages ⇄ events for v1/v2)
  • PromptRenderer (Jinja context & templating)
  • LLMClient (one entry‐point for llm_call → parse → clean)
  • RuntimeOrchestrator (invoke Colang runtime, handle sync/async, retries)
  • ResponseAssembler (assemble GenerationResponse or stream chunks)
  • RailsFacade (thin API layer wiring them together)

Acceptance criteria:

  • all existing behavior preserved (CI green, no regressions)
  • each new component has its own public interface and unit tests
  • no more classes > 500 LOC with mixed concerns (LOC does not really matter but SRP does)
  • global mutexes/threads/“if True or …” hacks eliminated

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions