A university project exploring how large language models and retrieval-augmented generation (RAG) can automate ESG (Environmental, Social, Governance) reporting for companies. Given a company's basic profile, the system produces a structured ESG report grounded in the official GRI (Global Reporting Initiative) standards.
ESG reporting is a complex, expert-driven process where companies disclose their environmental, social, and governance impact against established frameworks like the GRI Standards. This tool automates that process end-to-end:
- Sector classification — classifies the company into its GRI sector (Oil & Gas, Coal, Agriculture/Aquaculture, or general)
- Topic selection — retrieves the relevant GRI disclosure topics for that sector using vector similarity search
- Disclosure generation — for each topic, generates concrete disclosure requirements grounded in the GRI documents
- Action recommendations — produces actionable improvement steps tailored to the company's profile
- ESG rating — assigns an overall rating with a short justification
The output is a structured JSON report covering environmental, social, and governance categories, each with GRI-aligned topics, disclosures, and recommended actions.
| Layer | Technology |
|---|---|
| API | FastAPI (Python) |
| LLM | OpenAI GPT-3.5-turbo-16k via LangChain |
| Vector DB (cloud) | Pinecone — consolidated GRI standards index |
| Vector DB (local) | ChromaDB — per-sector and per-disclosure-category indexes |
| Embeddings | OpenAI text-embedding-ada-002 |
| Auth | JWT (email/password) + Google OAuth2 |
| Database | SQLite via SQLAlchemy |
Multi-index RAG pipeline: The GRI standard is published as a family of separate documents — a consolidated universal standard plus individual sector supplements (GRI 11 Oil & Gas, GRI 12 Coal, GRI 13 Agriculture/Aquaculture) plus category-specific disclosure guides for environmental, social, and governance topics. Stuffing all of these into one index would hurt retrieval precision: a query about oil-sector water usage would pull in irrelevant coal governance chunks, polluting the context window passed to the LLM.
To avoid this, each document group lives in its own Chroma index (local, fast, no network call), and a Pinecone index holds the consolidated GRI standards for broad cross-cutting queries like ratings and general compliance. The pipeline routes each step to the right index: sector classification hits the sector index, disclosure expansion hits the disclosure-category index (env/soc/gov), and final rating/action generation hits the consolidated Pinecone index where broader context helps.
Multi-step LLM chain: Rather than a single prompt, the pipeline runs a sequence of LangChain RetrievalQA chains — sector detection → topic grouping → description enrichment → disclosure expansion → action generation → rating. Each step's output feeds into the next, with JSON parsing and validation between steps.
In-memory caching: ESG reports are cached in-memory keyed by a hash of the company input, so repeated requests for the same company profile are served instantly without re-running the LLM pipeline.
Prerequisites: Python 3.10+, an OpenAI API key, a Pinecone account.
# 1. Install dependencies
pip install -r requirements.txt
# 2. Set up environment
cp .env-template .env
# Add your OPENAI_API_KEY and PINECONE_API_KEY to .env
# 3. Start the dev server
make dev-run
# → http://localhost:8000The API docs are available at http://localhost:8000/docs (Swagger UI).
| Method | Path | Description |
|---|---|---|
POST |
/langchain/esg_report |
Generate a full ESG report for a company |
POST |
/langchain/chat |
General ESG Q&A chat |
POST |
/auth/signup |
Register with email/password |
POST |
/auth/login |
Login, returns JWT |
POST |
/auth/signup-google |
Register via Google OAuth |
Example request:
POST /langchain/esg_report
{
"legal_name": "Shell LLC",
"ownership": "Stock Company",
"legal_form": "LLC",
"location": "USA",
"sector": "Energy",
"activities": "We refine oil to gasoline",
"products": "Gasoline",
"markets": "We operate globally",
"supply_chain": "We do everything ourselves",
"num_employees": "10000"
}pytest tests/make build # build image
make push # push to ghcr.io/nkster1/esg-pilot-backend