Architecture¶
Style is a largely stateless web application with clearly separated layers for the user interface, profile and document processing, and LLM connection. The application is delivered as a container and is prepared for operation behind a reverse proxy. The business logic is distributed across four modules, each encapsulating a clearly delimited area of responsibility.
At a glance¶
- Web application based on Gradio with four functionally separated tabs.
- Four core modules: LLM client, document processor, profile manager, export handler.
- LLM connection via OpenAI-compatible REST API.
- Profiles stored as JSON files on the file system; the profile library is loaded at startup.
- Largely stateless workspaces; only refinement maintains a session-bound state.
- Containerized via Docker; configurable via environment variables, with reverse proxy support.
Architecture description¶
Components and layers¶
The application is divided into a presentation layer (Gradio UI with the four tabs Transform, Analyze Style, Refinement, Style Overview), an application logic layer (four functional modules), and an integration layer to the LLM API. Profiles, texts, and prompts are kept as files on the file system.
flowchart TB
User([User]) --> UI[Gradio interface]
UI --> T1[Transform]
UI --> T2[Analyze style]
UI --> T3[Refinement]
UI --> T4[Style overview]
T1 --> DocProc
T1 --> ProfMgr
T1 --> LLM
T1 --> Export
T2 --> DocProc
T2 --> ProfMgr
T2 --> LLM
T2 --> Export
T3 --> ProfMgr
T3 --> LLM
T3 --> Export
T4 --> ProfMgr
subgraph Modules
DocProc[Document Processor]
ProfMgr[Profile Manager]
LLM[LLM Client]
Export[Export Handler]
end
LLM <-->|OpenAI-compatible| LocalLLM[Local LLM]
DocProc <--> Files[(Texts: TXT/MD/DOCX)]
ProfMgr <--> Profiles[(Profile library)]
LLM --> Prompts[(Prompt templates)]
Export --> Outputs[(Export files)]
Workflow¶
A typical workflow follows a consistent pattern across all four tabs. Inputs (profile and/or text) are received via the Gradio interface. The Document Processor loads files — TXT directly, Markdown directly, DOCX via python-docx while preserving headings, lists, and tables — and converts them into a uniform Markdown representation. The Profile Manager reads all JSON profiles from the profiles/ directory at startup and offers them to the UI as a selection; uploaded profiles are loaded ad hoc. From a loaded profile, either the stored transformation prompt is extracted or — if it is missing or too extensive — a compact prompt is generated from the structured profile data.
The prepared inputs are then combined by the LLM Client with one of the three prompt templates (style_analysis.txt, style_transformation.txt, diff_analysis.txt) and passed to the model via the OpenAI-compatible chat completions endpoint. Before each call, the client measures the token requirement using tiktoken (encoding cl100k_base) against a configurable limit and aborts with a message if the limit is exceeded.
In the Refinement workspace, a session-bound state is additionally used: an optionally loaded base profile and up to five sequentially analyzed before-and-after pairs are kept in an in-memory state and merged into a refined profile on export.
The Export Handler finally produces the output files — texts as TXT, Markdown, or DOCX, profiles as JSON, single prompt as TXT, or as a complete ZIP package (profile parameters, prompt, example sentences).
LLM usage¶
LLM usage is intentionally kept flat: one model call per user action, with no agentic loops, no retrieval, no embedder, and no reranker. Structural quality instead emerges from the explicit profile schema and the three fixed prompt templates. The multi-stage character lies in the workflow between the tabs (analysis → profile → transformation → refinement), not within a single call. Three tasks are modeled as separate templates:
style_analysis.txt— extraction of the four dimensions linguistics, lexis, pragmatics, structure, as well as representative example sentences.style_transformation.txt— application of a style profile to a text, content-preserving, optionally with additional feedback.diff_analysis.txt— extraction of systematic change patterns from a before-and-after pair, optionally against an existing base profile.
Configuration and deployment¶
The application is delivered in a Docker container (Python 3.11-slim as base, executed as a non-root user). Configuration is performed via environment variables — in particular OPENAI_BASE_URL, OPENAI_API_KEY, and MODEL_NAME for the LLM connection, and GRADIO_SERVER_NAME, GRADIO_SERVER_PORT, and GRADIO_ROOT_PATH for the web server. GRADIO_ROOT_PATH allows operation behind a reverse proxy under a sub-path. A healthcheck verifies the availability of the Gradio interface.
Robustness¶
- The token requirement is calculated before every LLM call and checked against a configurable limit.
- Profiles with a missing or overly long transformation prompt are compensated through fallback generation from the structured data.
- Unrecognized or unsupported file formats are rejected before processing with a clear error message.
Technology overview¶
- Language and runtime: Python 3.11.
- Web framework: Gradio (≥ 5.47).
- LLM connection: OpenAI Python SDK against OpenAI-compatible endpoints (e.g., LM Studio, Ollama with OpenAI adapter).
- Tokenization: tiktoken (encoding
cl100k_base). - Document processing: python-docx, markdown.
- Configuration: python-dotenv, environment variables.
- Deployment: Docker, Docker Compose; healthcheck and reverse proxy support via
GRADIO_ROOT_PATH.