A compact, production-ready multi-agent AI application for querying the ACLED conflict database in natural language.
Built with LangGraph, OpenAI GPT-4o-mini, FastAPI, and Streamlit as a portfolio project demonstrating state-of-the-art AI system design.
User Question (natural language)
│
▼
┌──────────────────────────────────────────────────────────┐
│ LangGraph StateGraph │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ QueryParser │───▶│ ACLEDApi │ │
│ │ Agent │ │ Agent │ │
│ │ │ │ │ │
│ │ NL → params │ │ OAuth2 GET │ │
│ └──────────────┘ │ + pagination │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ Analyst │ │
│ │ Agent │ │
│ │ │ │
│ │ Pandas agg. │ │
│ └──────┬───────┘ │
│ │ │
│ ┌──────▼───────┐ │
│ │ Synthesizer │ │
│ │ Agent │ │
│ │ │ │
│ │ LLM answer │ │
│ └──────────────┘ │
│ │
│ (any node failure → error node → user-friendly message) │
└──────────────────────────────────────────────────────────┘
│
▼
Answer + Data Table (Streamlit UI or REST API)
| Agent | File | Role |
|---|---|---|
| QueryParser | agents/query_parser.py |
Converts natural language to structured ACLED query parameters via LLM |
| ACLEDApi | agents/acled_api.py |
Authenticates via OAuth2, executes paginated GET requests |
| Analyst | agents/analyst.py |
Aggregates data with Pandas (counts, fatalities, timelines, breakdowns) |
| Synthesizer | agents/synthesizer.py |
Composes a concise, factual natural-language answer via LLM |
- Ask how many conflict events occurred in a country or region
- Query fatalities by country, event type, or time period
- Show trends over time (monthly / yearly aggregation)
- Get a breakdown by event type (Battles, Protests, Explosions, etc.)
- Get a general summary of a conflict situation
- Handle multi-country queries and date ranges
- Provide results as a natural-language answer + interactive data table
- Expose a REST API (
/chatendpoint) in addition to the UI
| Feature | Notes |
|---|---|
| 🗺 Interactive maps | ACLED events include lat/lon — could visualise with folium or pydeck |
| 📈 Charts & time-series plots | Matplotlib/Plotly integration in Streamlit |
| 💾 Conversation memory | Persist multi-turn context (LangGraph MemorySaver) |
| 🔁 Follow-up questions | Currently each question is independent |
| 🔍 Full-text search on notes | ACLED events contain free-text notes fields |
| 🌐 Multi-language input | Currently English only |
| 🔒 User authentication | No login/session management |
| ☁️ Cloud deployment | No Kubernetes / cloud infra yet |
- Python 3.12+
- A myACLED account (free) — register at https://acleddata.com/myacled
- An OpenAI API key — https://platform.openai.com/api-keys
- Docker (optional, for containerised run)
git clone https://github.com/fabs200/ACLED-Multi-Agent-Analytics-Chat.git
cd ACLED-Multi-Agent-Analytics-Chat
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txtCreate a .env file (do not commit it):
cp .env.example .env
# then edit .env with your credentialsRequired values in .env:
ACLED_EMAIL=your_email@example.com
ACLED_PASSWORD=your_acled_password
OPENAI_API_KEY=sk-...
python main.pyOpen http://localhost:8501 in your browser.
python main.py --api
# or
uvicorn app.api:app --reloadAPI docs available at http://localhost:8000/docs
# Build and start
docker compose up --build
# Open http://localhost:8501Note: make sure
.envexists before running Docker.
pytest tests/Run only unit tests:
pytest tests/unit/Run only integration tests:
pytest tests/integration/ACLED-Multi-Agent-Analytics-Chat/
├── main.py # Entrypoint — starts Streamlit or FastAPI
├── requirements.txt
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── app/
│ ├── app.py # Streamlit chat UI
│ └── api.py # FastAPI /chat endpoint
├── agents/
│ ├── orchestrator.py # LangGraph StateGraph
│ ├── query_parser.py # NL → query params (LLM)
│ ├── acled_api.py # ACLED API calls
│ ├── analyst.py # Pandas analytics
│ └── synthesizer.py # Answer synthesis (LLM)
├── tools/
│ ├── acled_client.py # OAuth2 client + pagination
│ └── data_utils.py # DataFrame helpers
├── config/
│ └── settings.py # Pydantic BaseSettings
├── logger/
│ └── logger.py # Centralised logging
└── tests/
├── unit/ # Unit tests (mocked)
└── integration/ # End-to-end pipeline tests (mocked)
This project uses the ACLED API under ACLED's terms of use. ACLED data covers political violence and protest events globally since 1997. Access is free after registration at myACLED.