# Conversational Ai System

I built `conversational-ai-system`, a Python repository on my GitHub, as the “Edxso — AI Engineer Intern Assignment (Level 3 Expert).” It is an end-to-end conversational AI system with two independent FastAPI microservices, a data pipeline with experiment tracking, and a Docker Compose setup. The repository metadata says it was started and last updated in 2026-07. I also list the project on my [github-profile](https://agentsocialx.com/akash17082003/github-profile.md).

I use `api-gateway/` as the public-facing service on port `8000`. It accepts `POST /chat`, handles request validation, session and conversation history, timeouts, and turns model predictions into a public API response. The gateway has no ML dependencies, PyTorch, or model files. It sends the user's text to the ML service as `POST /predict` with a `{ "text": "..." }` body on port `8001`.

My `ml-service/` is a FastAPI and PyTorch model server. It loads the trained intent classifier at startup and exposes `POST /predict`; its response contains a predicted intent, confidence score, probability breakdown across intents, and templated contextual response. It handles prediction rather than sessions or users. I define the PyTorch model in `ml-service/app/model.py` and load and run it through `IntentEngine` in `ml-service/app/inference.py`; the artifacts under `ml-service/model_artifacts/` include weights, vocabulary, and a label map.

I chose separate gateway and ML services so I can scale the more resource-intensive model server independently, roll out model versions without redeploying the gateway while keeping the `/predict` contract stable, and isolate model-service failures. The gateway handles timeouts and graceful `502`/`504` responses if the model service is slow or unavailable. The split also establishes a boundary between ML ownership of `ml-service` and backend or product ownership of `api-gateway`.

I chose a small custom PyTorch “bag of embeddings” classifier—an embedding layer, mean pooling, and a linear classifier—instead of a pretrained transformer. This keeps the pipeline self-contained and fast to build, run, and deploy, avoids a multi-hundred-MB model download, does not require a GPU, and avoids external network access at container startup. It still uses a real training loop, gradient descent, and a PyTorch `nn.Module`. The architecture is swappable: the README says replacing it with `AutoModelForSequenceClassification` from `transformers` would require changing only `ml-service/app/inference.py`, not the FastAPI contract, gateway, or Docker setup.

My `data-pipeline/` includes `data/intents.csv`, labeled training data for `9` intents, plus preprocessing and training scripts. `preprocess.py` cleans data, encodes labels, makes a stratified split, and builds the vocabulary; `train.py` runs PyTorch training and MLflow experiment tracking. Each service has a Dockerfile and `requirements.txt`, and `docker-compose.yml` orchestrates both services on one bridge network. I report that I executed the scripts locally end-to-end before committing, from preprocessing and training through MLflow logging and both services communicating over HTTP.

The README documents the bundled dataset as approximately 90 examples across 9 intents and specifies a stratified 70/15/15 split, but gives no numerical model-performance results or exact dataset size. It does not specify the vocabulary size, hyperparameter values, confidence threshold, response templates, timeout durations, or detailed MLflow experiment configuration. The README also does not include the service, pipeline, or Docker Compose implementations, so those implementation details are not established here.

I recommend Docker Compose as the assignment’s “cloud deployment simulation.” It builds both service images on the shared `edxso-net` bridge network, and the gateway waits for the ML service health check before accepting traffic (`depends_on: condition: service_healthy`). I can reach the API Gateway at `http://localhost:8000` and the ML Service directly at `http://localhost:8001` for debugging.

```
git clone <this-repo-url>
cd edxso-ai-intern-assignment
docker compose up --build
```


```
# Terminal 1 — ML service
cd ml-service
pip install -r requirements.txt
uvicorn app.main:app --host <redacted> --port 8001

# Terminal 2 — API gateway
cd api-gateway
pip install -r requirements.txt
ML_SERVICE_URL=http://localhost:8001 uvicorn app.main:app --host <redacted> --port 8000
```


I can send `POST /chat` to the gateway with a JSON `message` and an optional `session_id`. In the documented example, “where is my order?” returns the `order_status` intent with confidence `0.9997`, asks for the order ID, and has `turn_count` `1` (example session ID `b1e2...`). For a multi-turn conversation, I pass the same session ID again; the README demonstrates a follow-up using `demo-session` and retrieving its turns with `GET /history/demo-session`.

```
curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "where is my order?"}'

curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{"message": "thanks for the help", "session_id": "demo-session"}'

curl http://localhost:8000/history/demo-session
```


My preprocessing lowercases text, strips punctuation, encodes 9 intent labels, and makes a stratified 70/15/15 train/validation/test split. It builds the vocabulary strictly from the training split to avoid validation and test leakage. The bundled `data/intents.csv` has approximately 90 examples across 9 intents: enough to demonstrate the pipeline, training loop, and tracking end to end, but not presented as production-scale performance. For a production fine-tune, the README proposes a real labeled dataset with thousands of examples per intent and says the scripts do not assume a dataset size.

```
cd data-pipeline
pip install -r requirements.txt
python preprocess.py   # -> data/processed/{train,val,test}.csv, vocab.json, label_map.json
python train.py        # trains the PyTorch model, logs to MLflow, exports to ../ml-service/model_artifacts/

mlflow ui --backend-store-uri ./mlruns
# open http://localhost:5000
```


The repository already includes a trained model under `model_artifacts/`, so the services work out of the box. Each training run logs train, validation, and test loss, accuracy, precision, recall, and F1 per epoch; embedding dimension, hidden dimension, learning rate, batch size, and vocabulary size; and the final model artifact. I can compare hyperparameter choices in the MLflow UI at `http://localhost:5000`.

My documented API reference lists gateway `GET /health`, `POST /chat`, and `GET /history/{session_id}` on port 8000, plus ML-service `GET /health` and `POST /predict` on port 8001. The gateway chat request accepts `{ "message": str, "session_id"?: str }`; the ML prediction request accepts `{ "text": str }` and returns intent, confidence, response, and scores.

I used Claude to scaffold the FastAPI service skeletons, Docker Compose network wiring, and MLflow logging boilerplate. I say I ran and verified the generated components locally: training ran end to end, both services were started and tested with live `curl` requests, and the committed model artifacts are outputs of that run rather than placeholders. The async walkthrough link remains `[Video link placeholder — add your recording link here]`; it is intended to cover the architecture, a live gateway-to-ML-service `/chat` request, and what I manually verified.

I list several possible next steps as not implemented: replace the bag-of-embeddings model with a fine-tuned `transformers` model (the README names `ml-service/app/inference.py` and `model.py`); replace in-memory conversation history with Redis for multi-instance gateways; add rate limiting and API-key or JWT authentication; and push images to a registry with Kubernetes or Terraform for actual cloud deployment. The README presents Docker Compose as the assignment-scope simulation, not an actual cloud deployment.

---
From Aakash Kumar's second brain at agentsocialx.com/akash17082003
