This document provides a comprehensive overview of the "Evolve on Click" project, specifically focusing on the controller_microservice_v2. It is intended as a guide for AI agents and developers to understand the project's architecture, conventions, and operational procedures.
This project is the central backend controller for the Evolve on Click (EvOC) v2 platform, a system designed to provide a Jupyter-style notebook interface for working with Evolutionary Algorithms (EAs).
The controller_microservice_v2 is a Go-based microservice that acts as the brain of the operation. It handles API requests from the frontend, manages the lifecycle of notebooks and coding problems, and communicates with a Jupyter Kernel Gateway to execute code written by users.
The broader architecture, as defined in docker-compose.yaml and design documents, includes:
controller_microservice_v2: The main Go service.jupyter_gateway: Manages code execution kernels.python_runner: The Docker environment where Python code (using libraries likedeap) is executed.cockroachdb: A distributed SQL database for storing all metadata related to users, problems, notebooks, and evolution runs.minio: An S3-compatible object store for large files like plots and graphs.- AI Pipeline: A separate, asynchronous service (communicating via a message queue) responsible for the "code evolution" feature.
The project uses a Makefile for standardized development and operational commands.
-
Start the entire stack (recommended for development):
make docker-up
-
Run the Go service locally (requires other services to be running):
make run
-
Build the Go binary:
make build
-
Run tests:
make test -
Stop and clean up Docker containers:
make clean
The project follows a set of clear conventions to ensure code quality and maintainability, as outlined in ARCHITECTURE.md.
-
Layered Architecture: Code is strictly separated into layers:
routes(API definition) ->controllers(HTTP handling) ->modules(Business Logic) ->repository(Data Access). -
API Design:
- The API is versioned under
/api/v1/. - It follows RESTful principles.
- Routing is handled by the standard library's
http.ServeMuxwith explicitMETHOD /pathpatterns (e.g.,POST /api/v1/kernels).
- The API is versioned under
-
Database Interaction:
- The database schema is defined in
db/schema.sql. - The Repository Pattern is the standard for all database operations. Business logic in the
moduleslayer should not contain raw SQL queries; it must call methods on a repository interface.
- The database schema is defined in
-
Logging:
zerologis used for structured logging.- The use of
fmt.Print*orlog.Print*is forbidden and blocked by a pre-commit hook. - The logger instance is injected as a dependency from
main.go.
-
Configuration:
- All configuration (DB URLs, tokens, etc.) is managed via environment variables.
- There should be no hardcoded configuration values. The
.envfile is used for local development.
-
Tooling:
Makefileprovides standard commands for building, running, and testing.
-
The user has successfully started both the
auth_microserviceand thecontroller_microservice_v2. I have implemented a gRPC authentication middleware in the controller that communicates with the auth service. ThePOST /api/v1/sessionsroute is now protected by this middleware. The user will begin testing this new authentication flow next. -
I have refactored the notebook object structure in the frontend to align with the backend's
controller_microservice_v2andllm_microserviceexpectations. This involved renamingtypetocell_type,contenttosource, and addingexecution_countto code cells. I updateduseNotebookCells.js,useNotebook.js,useNotebookFetch.js,notebook-mapper.js, anduseNotebookExecution.jsto ensure consistency across the application. -
I have improved the "modify" and "fix" functionality for individual cells and the chat window. This includes:
- Modifying
useNotebookLLM.jsto return the full API response. - Updating
useNotebook.jsto correctly process API responses, handle conditional in-cell messages (only for single cell modifications), and manage chat messages. - Enhancing
ChatWindow.jsto display LLM responses, includingchanges_made, and visually distinguish user and bot messages. - Adding in-cell messages that appear for 5 seconds after a cell is modified or fixed.
- Correcting the indexing logic in
useNotebook.jsforcells_modifiedto use the cell's index instead of its ID.
- Modifying
-
I have also updated the UI of the notebook page to match the theme of the rest of the application. This included:
- Changing the background to a light gray gradient.
- Applying the
Geist Monofont to the entire notebook layout. - Updating buttons in
CodeCellControls,ChatWindow,KernelControls, andActionsToolbarModernto use a teal color scheme. - Updating the code cell containers to have rounded corners and borders consistent with other card components.
- Improving the output area with a teal theme, better error display, and a "Clear" button.
- Implementing a confirmation popup for deleting cells, and resizing it for better fit.
-
I have also implemented a new "Add Cell" functionality with a single plus icon at the top and bottom centers of each cell. Clicking this plus icon opens a small popup menu allowing the user to select between adding a "Code" or "Markdown" cell at that specific index. This functionality has been implemented in both
CodeCell.jsandMarkdownCell.js, and theAddCellMenuhas been refactored into a separate reusable component. -
I have implemented a new, more engaging loading screen for the notebook page (
NotebookLoadingScreen.js) that displays cycling text and icons. I also fixed a critical bug where the semanticcell_namewas being lost during API data mapping, which involved correcting logic inuseNotebookFetch.js,notebook-mapper.js, anduseNotebook.js. Finally, I improved the cell controls UI by adding a manual close button to in-cell messages and ensuring that loading spinners and disabled states are correctly applied during LLM operations. -
I have implemented a new delta-based autosave system to efficiently persist notebook changes. This includes a new
useAutosave.jshook that tracks changes (new, modified, deleted, and reordered cells) and sends them to aPATCH /api/v1/notebooks/{id}/cellsendpoint every 5 minutes. The UI now includes a status indicator (Saving...,Last saved at...). I also re-integrated the manual save button to use this same efficient delta-based logic.
This service is responsible for the AI-powered generation, modification, and fixing of DEAP (Distributed Evolutionary Algorithms in Python) code notebooks.
The evocv2_llm_microservice is a Python-based service using FastAPI. It exposes a REST API to create and manage 12-cell Jupyter notebooks for evolutionary algorithms. It uses a Large Language Model (LLM) via the Groq API to understand specifications and natural language instructions.
- Architecture:
- FastAPI: Serves the REST API.
- LangGraph: Orchestrates the workflow for generating, modifying, and fixing notebooks, including validation and retry loops.
- Instructor & Pydantic: Ensures structured, validated JSON output from the LLM.
- Groq: Provides fast LLM inference.
- Mem0: An optional memory layer to persist session history and user preferences.
- Key Features:
- Generate: Creates a complete, 12-cell DEAP notebook from a flexible JSON specification in a single LLM call.
- Modify: Updates an existing notebook based on natural language instructions.
- Fix: Attempts to automatically repair a broken notebook using an error traceback.
- Session Management: Maintains the state of notebooks across API calls.
The service is designed to be run with Docker.
-
Prerequisites:
- Docker and Docker Compose
- A Groq API key, which should be placed in a
.envfile.
-
Set up environment variables:
cp .env.example .env # Edit .env and add your GROQ_API_KEY -
Build and run with Docker Compose:
docker-compose up --build
-
Run locally (without Docker):
- Create a Python virtual environment and activate it.
- Install dependencies:
pip install -r requirements.txt - Run the server:
uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload
-
Verify it's running:
- Access the health check endpoint:
curl http://localhost:8000/health - Or view the OpenAPI docs:
http://localhost:8000/docs
- Access the health check endpoint:
POST /v1/generate: Creates a new notebook.POST /v1/sessions/{session_id}/modify: Modifies an existing notebook.POST /v1/sessions/{session_id}/fix: Fixes a broken notebook.GET /v1/sessions/{session_id}: Retrieves session details.GET /v1/sessions: Lists all active sessions.
To ensure user work is saved efficiently without overwhelming the backend, the notebook implements a timed, delta-based autosave system.
- Change Tracking: The frontend (
useAutosave.jshook) constantly monitors the notebook for changes. It tracks:- New cells being added.
- Existing cells being modified (source code changes).
- Cells being deleted.
- The order of cells being changed.
- Dirty Flag: Any change marks the notebook as "dirty," indicating it has unsaved changes.
- Timed Autosave: A timer runs every 5 minutes. If the notebook is "dirty," it automatically triggers a save.
- Manual Save: A manual save button is also available, which triggers the same save logic immediately.
- Delta-Based Payload: Instead of sending the entire notebook, the save logic calculates a "delta" containing only what has changed. This delta is sent to the backend.
- Endpoint:
PATCH /api/v1/notebooks/{id}/cells - Method:
PATCH - Payload Structure:
All fields are optional. Only fields with actual changes are sent.
{ "updated_order": ["id-1", "id-3", "id-2"], "cells_to_upsert": { "id-3": { "cell_type": "code", "source": "print('modified')" }, "id-4": { "cell_type": "markdown", "source": "## New Cell" } }, "cells_to_delete": ["id-5"] }
This approach minimizes network traffic and backend load, providing an efficient and reliable persistence layer.