Skip to content

theChefEngineer/Graph-risk

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

RiskGraph

A multi-tenant credit risk analysis platform for SMEs, built on a GraphRAG pipeline (Neo4j + LangChain4j) with a Spring Boot backend and an Angular 17 frontend.

Upload a financial PDF → entities are extracted by an LLM → a relationship graph is materialized in Neo4j → ask natural-language questions and get a risk score backed by both graph evidence and computed financial ratios.


Tech stack

Layer Stack
Backend Java 21, Spring Boot 3.3, Spring Data Neo4j, Spring Security OAuth2 RS, Lombok
AI LangChain4j 0.31 + OpenAI GPT-4o (entity extraction & GraphRAG)
PDF parsing Apache PDFBox 3.0
Graph DB Neo4j 5 (APOC plugin)
Auth Keycloak 24 (realm-per-organization, PKCE public client)
Frontend Angular 17 standalone components + signals, Tailwind, ng2-charts, ngx-graph
DevOps Docker Compose (local), per-service Dockerfile

Prerequisites

You only need Docker and Docker Compose installed locally.

docker --version          # Docker 20+ recommended
docker compose version    # v2+

(For development outside containers, you'd also want Java 21, Maven 3.9+, and Node 20+.)


Quick start (Docker Compose)

From the repository root:

# 1. Configure environment
cp .env.example .env
# Then edit .env and set OPENAI_API_KEY=sk-...
# (without it, uploads still work but entity extraction returns empty results)

# 2. Bring up the infrastructure (Neo4j, Postgres, Keycloak)
docker compose up -d neo4j postgres keycloak

# 3. Build and start the application services
docker compose up -d --build backend frontend

# 4. Watch logs (optional)
docker compose logs -f backend frontend

First boot takes 1–3 minutes (Keycloak needs to import the realm, the backend waits for Neo4j health). Subsequent boots are seconds.

Endpoints once it's up

Service URL
Frontend (the app) http://localhost:4200
Backend health http://localhost:8080/actuator/health
Keycloak admin console http://localhost:8180/admin
Keycloak realm http://localhost:8180/realms/riskgraph
Neo4j browser http://localhost:7474

Logging in

As an app user

  1. Open http://localhost:4200 — the app redirects to Keycloak.
  2. Sign in with the seeded user:
    • Username: admin@riskgraph.com
    • Password: admin123
  3. You'll land on the dashboard with ADMIN, ANALYST, and VIEWER realm roles.

As Keycloak admin (manage users / realms)

  • URL: http://localhost:8180/admin
  • Username: admin
  • Password: admin
  • Switch the top-left realm dropdown from masterriskgraph to manage app users.

Neo4j browser

  • URL: http://localhost:7474
  • Connect to bolt://localhost:7687
  • User: neo4jPassword: riskgraph123 (matches .env.example)

Trying the pipeline

Sample PDFs are pre-generated under sample-pdfs/:

File Profile Expected risk level
01-acme-industries.pdf Healthy SME (manufacturing) LOW – MEDIUM
02-northstar-logistics.pdf Distressed SME (logistics) HIGH – CRITICAL
03-pixelwave-tech.pdf Mid-market SaaS MEDIUM

Workflow in the UI:

  1. Go to Upload, set a company name and sector, drop in one of the PDFs.
  2. Wait ~10–20 s for status to flip from PROCESSINGDONE.
  3. From the dashboard, click into the company → run Analyze with a question like "What is the credit risk over the next 12 months?"
  4. Open Graph view to see the extracted suppliers, owners, and documents as nodes connected to the company.

To regenerate or extend the sample PDFs:

cd sample-pdfs
pip install reportlab
python3 generate.py

Configuration

All secrets and host overrides live in .env:

Variable Default Notes
NEO4J_URI bolt://neo4j:7687 Service-name DNS inside compose
NEO4J_USER neo4j
NEO4J_PASSWORD riskgraph123 Used both by Neo4j and the backend
KEYCLOAK_URL http://keycloak:8180 Inside compose; backend uses this
OPENAI_API_KEY (empty) Required for real entity extraction

Project layout

riskgraph/
├── docker-compose.yml
├── .env.example
├── keycloak/
│   └── realm-export.json          # imported on first Keycloak boot
├── backend/
│   ├── pom.xml
│   ├── Dockerfile                 # multi-stage: maven build + JRE runtime
│   └── src/main/java/com/riskgraph/
│       ├── RiskGraphApplication.java
│       ├── config/                # Security, Neo4j, LangChain4j wiring
│       ├── domain/                # @Node entities + @RelationshipProperties
│       ├── repository/            # Spring Data Neo4j repos
│       ├── security/              # TenantContext + TenantFilter
│       ├── service/               # Ingestion, Extraction, GraphBuilder, GraphRAG, Scoring
│       ├── controller/            # REST endpoints
│       └── dto/
└── frontend/
    ├── package.json
    ├── Dockerfile                 # node build → nginx
    ├── nginx.conf                 # serves SPA, proxies /api/ to backend
    └── src/app/
        ├── app.config.ts
        ├── app.routes.ts
        ├── core/
        │   ├── auth/keycloak.service.ts
        │   ├── interceptors/auth.interceptor.ts
        │   ├── guards/auth.guard.ts
        │   ├── services/api.service.ts
        │   └── models/api.models.ts
        ├── features/
        │   ├── dashboard/
        │   ├── upload/
        │   ├── analysis/
        │   └── graph-view/
        └── shared/components/     # sidebar, header, risk-badge

REST API summary

Method Path Roles Purpose
POST /api/documents/upload ADMIN, ANALYST Upload a PDF (multipart)
GET /api/documents/{id}/status ADMIN, ANALYST, VIEWER Polling for ingestion status
GET /api/documents ADMIN, ANALYST, VIEWER List documents (current tenant)
POST /api/analysis/query ADMIN, ANALYST GraphRAG risk analysis
GET /api/analysis/{companyId}/score ADMIN, ANALYST, VIEWER Latest computed risk score
GET /api/companies ADMIN, ANALYST, VIEWER List companies (current tenant)
GET /api/companies/{id} ADMIN, ANALYST, VIEWER Company details
GET /api/companies/{id}/graph ADMIN, ANALYST, VIEWER Nodes + edges for visualization
GET /api/companies/dashboard/summary ADMIN, ANALYST, VIEWER KPI cards + charts data

All endpoints require a valid Keycloak JWT and are filtered by the organization claim in the token (multi-tenant isolation).


Stop / reset

docker compose down                # stop, keep data
docker compose down -v             # stop and wipe Neo4j + Postgres volumes

Troubleshooting

Frontend redirects to Keycloak then errors out. Make sure Keycloak finished importing the realm: curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8180/realms/riskgraph should return 200. On the first boot it takes 30–60 s.

POST /api/analysis/query returns 500 or a low-confidence fallback answer. You probably haven't set OPENAI_API_KEY in .env. The backend logs GraphRAG LLM call failed and returns a fallback response instead of crashing.

Backend can't connect to Neo4j on first boot. The compose health check waits for Neo4j to be healthy before starting the backend. If you used docker compose up backend before Neo4j was ready, restart with docker compose restart backend.

Port already in use. Default ports are 4200 (frontend), 8080 (backend), 8180 (Keycloak), 7474/7687 (Neo4j). Either stop the conflicting service or override the host port in docker-compose.yml.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors