guide / CLAUDE.md
anmol-iisc's picture
UI enhancements, letter text redundant text removed
d230384
|
Raw
History Blame Contribute Delete
10.6 kB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Workflow gate (READ FIRST)

Before changing anything, read SPEC.md β€” it defines the mandatory process: sanity tests (tests/test_sanity.py) must pass before any commit (enforced by the git pre-commit hook installed via bash scripts/install-hooks.sh), and the How To Guide tab in ui/app.py must be updated on any user-facing UI change.

Project

G.U.I.D.E. (Grievance Utility for Information Extraction, Drafting and Enrichment) β€” a privacy-first consumer complaint assistant for Indian consumers. Users describe their complaint in plain language; the system redacts PII locally, drafts a formal letter, and routes to the correct Indian regulatory authority.

Startup

1. Configure environment

Create a .env file in the project root with the following keys (all three are required):

cp .env.example .env

Then edit .env and fill in:

ANTHROPIC_API_KEY=sk-ant-...      # Claude API β€” powers the managed agent
HF_TOKEN=hf_...                   # HuggingFace token β€” needed to download model checkpoints from sarav95/guide-models
LANGCHAIN_API_KEY=ls__...         # LangSmith API key β€” used for tracing / observability

The .env file is git-ignored and must never be committed.

2. Install dependencies

pip install -r requirements.txt
python -m spacy download en_core_web_lg

3. Run

# Run everything (auto-downloads models from HF if missing, then starts both servers)
python start.py

# Access
#   API docs  β†’  http://localhost:8000/docs
#   UI        β†’  http://localhost:7860

start.py flags

Flag Effect
(none) Auto-download missing checkpoints from HF, auto-train any still missing, then serve
--download-models Force download all checkpoints from sarav95/guide-models on HuggingFace
--no-train Skip training; start servers immediately (models must exist)
--train Force re-train all three models even if checkpoints exist
--train-only Train then exit β€” no servers started
--cfpb_csv PATH Override default CFPB CSV path (data/raw/complaints.csv)

--no-train and --train are mutually exclusive. --train-only can be combined with --train.

Model checkpoints are stored in models/ (git-ignored). They are hosted on HuggingFace at sarav95/guide-models and auto-downloaded on first run when the directory is missing.

Train individual models

# EvidenceNER β€” synthetic data generated in-memory, no download required
python -m src.ner.train --output_dir models/evidence_ner

# NextActionPredictor β€” synthetic data, <30 s on CPU
python -m src.next_action.train --output_path models/next_action/model.pt

# DomainClassifier β€” needs CFPB CSV first (one-time Kaggle download)
python -m src.classifier.train \
    --cfpb_csv data/raw/complaints.csv \
    --output_dir models/domain_classifier

Without a DomainClassifier checkpoint the system falls back to keyword heuristics (confidence=0.0 sentinel). Without a NextActionPredictor checkpoint it falls back to DOMAIN_ACTION_PRIORS rule mapping. Both fallbacks keep the pipeline fully functional.

Architecture

Layer 1 β€” Privacy (runs first, locally, on every message)

src/privacy/redactor.py β€” Microsoft Presidio (presidio-analyzer + presidio-anonymizer) with spaCy en_core_web_lg. Detects and replaces PII with <ENTITY_TYPE> placeholders before any text leaves the process. Fails open: on any error the original text is returned unchanged so the pipeline is never blocked.

Entity types redacted: PERSON, PHONE_NUMBER, EMAIL_ADDRESS, CREDIT_CARD, IBAN_CODE, US_BANK_NUMBER, IN_AADHAAR, IN_PAN, IN_VEHICLE_REGISTRATION.

Layer 2 β€” Deep Learning Models

Module Architecture Checkpoint Fallback
src/classifier/ DistilBERT + linear head, 6 classes models/domain_classifier/ keyword heuristics
src/ner/ DistilBERT token classifier, BIO tags, 6 entity types models/evidence_ner/ (none β€” required)
src/next_action/ MLP 12β†’64β†’64β†’6 models/next_action/model.pt DOMAIN_ACTION_PRIORS
src/document_processor/ Tesseract OCR + ViT patch-variance scoring HuggingFace google/vit-base-patch16-224 OCR-only

6 domain classes: ecommerce Β· telecom Β· banking Β· cibil Β· insurance Β· general

6 NER entity types: ORG Β· AMOUNT Β· DATE Β· REF_ID Β· ACCOUNT Β· PERSON

6 escalation actions: company_support Β· nch Β· trai Β· rbi_ombudsman Β· irdai Β· legal

Document processing path: PDF (pdfplumber) β†’ EvidenceNER; image (pytesseract + Pillow greyscale/threshold/deskew) β†’ EvidenceNER + DocumentViT. Both paths merge entities by (text.lower(), label) key, keeping the higher-confidence span.

Layer 3 β€” Claude Managed Agent

src/agent/ β€” one GUIDEAgent instance per session; model is env-driven via GUIDE_MODEL (default claude-sonnet-4-6). Agent loop: stream response β†’ on stop_reason == "tool_use" dispatch all tool_use blocks via execute_tool() β†’ append tool_result messages β†’ repeat until end_turn. Loop capped at 12 rounds.

7 tools: classify_domain Β· extract_entities Β· process_document Β· draft_complaint Β· recommend_action Β· store_memory Β· get_memory

draft_complaint is handled internally by Claude (returns {"status": "proceed"} from Python); the actual letter is generated as text in the next assistant turn.

HITL gate (mandatory): Claude must present a numbered entity summary and receive [USER CONFIRMED]: {...} (injected by POST /api/session/{id}/validate-entities) before calling draft_complaint(). This is enforced in the system prompt (Rule 4 + Rule 5) and in GUIDEAgent.confirm_entities().

Layer 4 β€” FastAPI + Gradio

FastAPI (src/api/) β€” singleton startup order in lifespan(): Presidio β†’ DomainClassifier β†’ EvidenceNER β†’ NextActionPredictor β†’ (DocumentProcessor lazy). All blocking model calls and CMA calls use run_in_threadpool.

Gradio (ui/app.py) β€” tabs: Chat (πŸ”’ privacy badge + side-by-side redaction reveal showing original-vs-sent text) Β· Verify Entities (HITL editable fields + Confirm button) Β· Complaint Draft (copy + .txt/PDF download via reportlab) Β· Escalation Guide Β· Privacy Audit (timestamped outbound/local event log with verified "0 raw identifiers transmitted" guarantee) Β· About.

Privacy reveal & audit: POST /message returns original_text, redacted_text, and redactions (per-span RedactionSpans) so the UI renders a side-by-side reveal β€” these are returned ONLY to the same user's browser, never forwarded externally. Each /message and /upload appends an entry to Session.audit; GET /session/{id}/audit serves the trail. The audit's leak_check re-verifies that no original PII value survives into the transmitted text.

Critical Files

File Role
start.py Single entry point β€” training + server launch + [API]/[UI] log prefixing
src/privacy/redactor.py PIIRedactor singleton; init_redactor() / get_redactor()
src/agent/prompts.py SYSTEM_PROMPT β€” all 7 CMA rules including HITL gate
src/agent/tools.py TOOL_DEFINITIONS (JSON Schema) + execute_tool() dispatcher
src/agent/memory.py SessionMemory β€” per-session key-value store
src/agent/agent.py GUIDEAgent β€” streaming agent loop, send_message(), confirm_entities(), add_document()
src/api/main.py FastAPI app, lifespan() startup order, _component_status dict
src/api/routes.py All HTTP endpoints; Presidio redaction wired into POST /message
src/api/sessions.py Session registry (session_id β†’ Session(agent, history))
src/next_action/priors.py DOMAIN_ACTION_PRIORS + ACTION_METADATA (URLs) β€” training source of truth
ui/app.py Gradio Blocks app (build_app()), all event handlers, API client helpers
.env ANTHROPIC_API_KEY, HF_TOKEN, LANGCHAIN_API_KEY β€” never committed (in .gitignore)

Key Invariants

  • PII never reaches Anthropic. Presidio runs in-process before every POST /message. The Gradio UI sends raw text to FastAPI; FastAPI redacts before calling GUIDEAgent.send_message(). The agent only ever sees <ENTITY_TYPE> placeholders.
  • HITL gate is mandatory before drafting. draft_complaint() must not be called until [USER CONFIRMED] arrives. This is encoded in both the system prompt (Rules 4-5) and the route handler separation (/message vs /validate-entities).
  • All model inference is blocking I/O. Every call to a DL model or the Anthropic API uses run_in_threadpool to avoid blocking the FastAPI async event loop.
  • Fallbacks keep the pipeline alive. DomainClassifier β†’ keyword fallback. NextActionPredictor β†’ DOMAIN_ACTION_PRIORS. Both degrade gracefully with no code changes required.
  • add_document() queues, not processes. The document path is held in _pending_documents and prepended as [Document uploaded: <path>] on the next send_message() call, triggering Rule 3 of the system prompt.

Model Checkpoint Paths

models/
  evidence_ner/          ← HuggingFace format (config.json + pytorch_model.bin)
  domain_classifier/     ← HuggingFace format
  next_action/
    model.pt             ← PyTorch state_dict + metadata dict

start.py detects checkpoints by checking for config.json (HuggingFace) or file existence (.pt). The --train flag bypasses these checks and retrains unconditionally.

Environment Variables

Variable Default Purpose
ANTHROPIC_API_KEY (required) Anthropic API key β€” powers the Claude managed agent
HF_TOKEN (required) HuggingFace token β€” authenticates snapshot_download from sarav95/guide-models
LANGCHAIN_API_KEY (required) LangSmith API key β€” tracing and observability
GUIDE_MODEL claude-sonnet-4-6 Claude model for the CMA. Use an Anthropic ID (e.g. claude-opus-4-8, claude-haiku-4-5-20251001) or a gateway/Bedrock ID when LITELLM_PROXY_URL is set
LITELLM_PROXY_URL (unset) If set, route Anthropic calls through a LiteLLM gateway instead of the direct API
API_PORT 8000 FastAPI port
GRADIO_PORT 7860 Gradio port
LOG_LEVEL info Uvicorn log level