BUILD 05 / OPEN SOURCE
LLM-Prompt-Router.
LLM-Prompt-Router
// an experiment in possibility
OPEN SOURCE / EXPERIMENT 05const idea = await
build("LLM-Prompt-Router");
ready for what's next
THE IDEA & THE BUILDFrom concept
From concept
to something real.
This project implements a Node.js service that routes user requests to specialized AI personas based on detected intent. Instead of using a single monolithic prompt for every request, the system first classifies the user's intent using an LLM, and then routes the request to an expert persona designed for that specific task.
THE QUICK TOUR
A closer look, in three steps.
Preview the project, understand the idea, then explore the product or source.
FROM THE REPOSITORY / README.mdOpen the source notes
# LLM-Powered Prompt Router for Intent Classification
## Overview
This project implements a **Node.js service that routes user requests to specialized AI personas based on detected intent**. Instead of using a single monolithic prompt for every request, the system first **classifies the user's intent using an LLM**, and then **routes the request to an expert persona designed for that specific task**.
This architecture improves response quality, reduces prompt complexity, and mirrors how production AI systems structure multi-purpose assistants.
The system is built using:
* Node.js
* Express.js
* LLM API (OpenAI-compatible providers such as Groq or Grok)
* Docker and Docker Compose for containerized deployment
The service exposes an API endpoint that receives a user message, determines the intent, routes it to the appropriate expert prompt, and returns the generated response.
---
# System Architecture
The system follows a **two-stage LLM pipeline**.
1. Intent Classification
2. Prompt Routing and Response Generation
### Processing Flow
User Request
→ Classifier LLM Call
→ Intent + Confidence Score
→ Prompt Router
→ Expert Persona Prompt
→ Response Generation LLM Call
→ Final Response to User
→ Log Entry Written
---
## Step 1: Intent Classification
The system first determines **what the user is asking for**.
A lightweight LLM prompt is used to classify the user's intent into one of the predefined labels:
* `code`
* `data`
* `writing`
* `career`
* `unclear`
The classifier returns **structured JSON output**:
```
{
"intent": "code",
"confidence": 0.92
}
```
This step is designed to be **fast and cost-efficient**, since it only performs classification.
---
## Step 2: Prompt Routing
After classification, the router selects the appropriate **expert system prompt**.
Each prompt represents a specialized AI persona.
Implemented personas include:
* **Code Expert** – Generates production-quality code and technical explanations.
* **Data Analyst** – Interprets data patterns and suggests statistical insights and visualizations.
* **Writing Coach** – Provides feedback on clarity, tone, and structure of written text.
* **Career Advisor** – Offers practical career advice and asks clarifying questions about goals.
The selected system prompt is combined with the **original user message** and sent to the LLM to generate the final response.
---
## Handling Unclear Intent
If the classifier returns:
```
intent: "unclear"
```
the system **does not route to any expert persona**.
Instead it asks the user for clarification:
```
Could you clarify if you need help with coding, data analysis, writing, or career advice?
```
This prevents incorrect routing and improves system reliability.
---
# Logging and Observability
Every processed request is recorded in:
```
route_log.jsonl
```
The system uses the **JSON Lines (JSONL)** format, where each line represents one request.
Example entry:
```
{
"request_id": "d9a7e2f5",
"timestamp": "2026-03-13T10:14:21Z",
"intent": "code",
"confidence": 0.97,
"user_message": "how to sort a list in python",
"final_response": "..."
}
```
This enables tracking and analysis of:
* routing decisions
* classifier accuracy
* user request patterns
---
# Project Structure
```
llm-prompt-router
│
├── Dockerfile
├── docker-compose.yml
├── package.json
├── package-lock.json
├── README.md
├── route_log.jsonl
├── .env.example
│
└── src
├── cli.js
├── config
│ └── configGrok.js
├── prompts
│ └── prompts.js
├── routes
│ └── router.js
├── server.js
├── services
│ └── classifier.service.js
└── utils
└── logger.js
```
### Key Components
**server.js**
Main Express server that exposes the `/chat` endpoint and orchestrates the classification and routing workflow.
**classifier.service.js**
Implements the `classify_intent()` function that calls the LLM and parses the returned JSON classification.
**router.js**
Implements `route_and_respond()` which maps the classified intent to the correct expert system prompt and generates the final response.
**prompts.js**
Contains the expert persona prompts used for generation.
**logger.js**
Writes structured request logs to `route_log.jsonl`.
**cli.js**
Optional CLI tool for testing the router directly from the terminal.
---
# Environment Variables
The project uses environment variables for API keys and configuration.
Create a `.env` file based on `.env.example`.
### Example `.env.example`
```
PORT=3000
LLM_API_KEY=your_llm_api_key_here
```
Copy the example file:
```
cp .env.example .env
```
Then update `.env` with your actual API key.
**Do not commit `.env` to the repository.**
---
# Running the Project Locally
Install dependencies:
```
npm install
```
Start the server:
```
npm start
```
The API will run at:
```
http://localhost:3000
```
---
# Running the Project with Docker
Docker allows the application to run in a consistent environment across systems.
### Build the Docker image
```
docker build -t llm-router .
```
### Run the container
```
docker run -p 3000:3000 --env-file .env llm-router
```
The service will be available at:
```
http://localhost:3000
```
---
# Running with Docker Compose
Docker Compose simplifies running the full application stack.
### docker-compose.yml
```
version: "3.8"
services:
llm-router:
build: .
container_name: llm-router
ports:
- "3000:3000"
env_file:
- .env
volumes:
- .:/app
```
### Start the application
```
docker compose up --build
```
### Stop the application
```
docker compose down
```
---
# Testing the API
Example request using curl:
```
curl -X POST http://localhost:3000/chat \
-H "Content-Type: application/json" \
-d '{"message":"how to sort a list in python"}'
```
---
# Viewing Logs
Logs are stored in:
```
route_log.jsonl
```
View logs:
```
cat route_log.jsonl
```
Stream logs in real time:
```
tail -f route_log.jsonl
```
If running inside Docker:
```
docker exec -it llm-router bash
cat route_log.jsonl
```
---
# Error Handling
The system includes safeguards to ensure stability.
* If the LLM returns malformed or invalid JSON during classification, the system safely defaults to:
```
{
"intent": "unclear",
"confidence": 0.0
}
```
* If the classifier cannot confidently determine the intent, the system asks the user for clarification rather than incorrectly routing the request.
These mechanisms ensure reliable operation even when external API responses are inconsistent.
---
## CLI Interface
The application also includes a **Command Line Interface (CLI)** that allows you to interact with the prompt router directly from the terminal without sending HTTP requests.
The CLI uses the same internal pipeline as the API, meaning it will:
1. Send your input message to the **intent classifier**.
2. Detect the **intent and confidence score**.
3. Route the request to the appropriate **expert persona prompt**.
4. Generate a response using the LLM.
5. Display the detected intent and response in the terminal.
### Running the CLI
Start the CLI with the following command:
```
npm run cli
```
After running the command, you can type messages directly into the terminal.
Example:
```
$ npm run cli
LLM Prompt Router CLI started.
Type your message and press Enter.
> how do i sort a list in python
Intent: code
Confidence: 0.97
Response:
<generated response>
```
### CLI Use Cases
The CLI is useful for:
* Quickly testing the **intent classification logic**
* Debugging the **prompt routing behavior**
* Verifying that different personas are being triggered correctly
* Testing the system without using HTTP clients like Postman or curl
The CLI interacts with the same core modules (`classifier.service.js`, `router.js`, and `logger.js`), ensuring consistent behavior between the CLI and the API server.
Continue on GitHub