Final Year Project β AI Microservice Β· Part of the Insafdaar legal case management platform.
FastAPI microservice that generates, iterates, and exports legal documents for Pakistani courts using Gemini AI.
This microservice generates complete legal documents for Pakistani courts β plaints, written statements, affidavits, appeals, contracts, notices, petitions, and injunctions β from case data using Gemini 2.5 Flash via Vertex AI.
It powers the AI Document Drafting feature inside the main Insafdaar webapp. Advocates can generate full drafts, regenerate specific sections with custom instructions, and export the final result as a formatted DOCX file β all without leaving the case dashboard.
Express Backend (via internal API)
β
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DRAFTING SERVICE (:8001) β
β β
β βββββββββββββ ENV=local ββββββββββββββββββββββββββββ β
β β Direct asyncpg to PostgreSQL for case data β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β βββββββββ ENV=production ββββββββββββββββββββββββββββ β
β β HTTP proxy to Express /internal/draft/* endpoints β β
β β with X-Internal-Key auth β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββ β
β β
β ββββββββββββββββββ GENERATION PIPELINE ββββββββββββββββ β
β β β β
β β 1. Case Context (SQL join or Express proxy) β β
β β - client_cases, users, client_profiles, β β
β β advocate_profiles tables β β
β β β β
β β 2. Intake Analysis (case_intake_sessions) β β
β β - JSONB analysis: parties, locations, β β
β β dates, amounts, issue summary β β
β β - Full transcript from voice interview β β
β β β β
β β 3. Case & Client Documents β β
β β - Filtered by document type relevance β β
β β - Truncated by token budget per doc type β β
β β β β
β β 4. Prefilled Fields from analysis entities β β
β β β β
β β 5. Balanced Case Context (type-specific fields) β β
β β β β
β β 6. RAG Legal References (Phase 2 β stub) β β
β β β β
β β 7. Gemini 2.5 Flash (temperature=0.2) β β
β β - Document-type-specific prompt instructions β β
β β - JSON output with sections + headings + body β β
β β - Multi-layer repair on malformed JSON β β
β β β β
β β 8. DOCX Export (python-docx) β β
β β - A4, Times New Roman 12pt, justified β β
β ββββββββββββββββββββββββββββββββββββββββββββββββββββββ β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
API Reference
All endpoints are under the /draft prefix.
Initialise a drafting session β detect document type, prefilled fields, and missing documents.
Request:
{
"case_id": 44,
"advocate_id": 12
}Response:
{
"case_id": 44,
"current_stage": "case_active",
"document_type": "Plaint",
"client_name": "Abuzar Khan",
"language": "English",
"prefilled_fields": {
"plaintiff": "Abuzar Khan",
"defendant": "To be specified",
"advocate": "Ali Ahmed",
"advocate_email": "ali@example.com",
"advocate_phone": "+92-300-1234567",
"advocate_bar_council_id": "KHC-1234",
"jurisdiction": "Civil Judge, Lahore",
"nature_of_dispute": "Property boundary dispute",
"relief_sought": "Declaration and permanent injunction",
"key_facts": "Locations: Lahore | Dates: 2022"
},
"missing_documents": ["CNIC_FRONT", "FIR_COPY"]
}Generate a full legal document draft using Gemini.
Request:
{
"case_id": 44,
"advocate_id": 12,
"document_type": "Plaint",
"advocate_notes": "Emphasize the property boundary dispute.",
"language": "English"
}Response:
{
"document_type": "Plaint",
"draft": {
"title": "IN THE COURT OF CIVIL JUDGE, LAHORE",
"sections": [
{ "id": "sec_1", "heading": "Parties to the Suit", "content": "..." },
{ "id": "sec_2", "heading": "Facts of the Case", "content": "..." },
{ "id": "sec_3", "heading": "Cause of Action", "content": "..." },
{ "id": "sec_4", "heading": "Relief Sought", "content": "..." },
{ "id": "sec_5", "heading": "Verification", "content": "..." }
]
},
"legal_references_used": [],
"generation_id": "gen_abc123def456"
}Regenerate a single section with specific instructions (e.g., "make this more concise", "focus on X").
Request:
{
"case_id": 44,
"advocate_id": 12,
"generation_id": "gen_abc123def456",
"section_id": "sec_2",
"instruction": "Make this more concise, focus on 2022 events only.",
"document_type": "Plaint",
"language": "English",
"current_draft": {
"title": "...",
"sections": [
{ "id": "sec_1", "heading": "...", "content": "..." },
{ "id": "sec_2", "heading": "Facts of the Case", "content": "..." }
]
}
}Response:
{
"section_id": "sec_2",
"heading": "Facts of the Case",
"content": "... revised content ..."
}Persist the current draft to the database.
Request:
{
"case_id": 44,
"document_type": "Plaint",
"generation_id": "gen_abc123def456",
"advocate_id": 12,
"draft": { "title": "...", "sections": [...] }
}Response: { "generation_id": "gen_abc123def456", "saved": true }
Export the final draft as a formatted DOCX file.
Request:
{
"case_id": 44,
"document_type": "Plaint",
"final_draft": { "title": "...", "sections": [...] },
"format": "docx"
}Response: Binary DOCX file stream (Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document)
Response: {"status": "ok", "env": "local", "service": "drafting-assistant"}
The service generates 9 document types, each with stage-triggered defaults and required sections:
| Document Type | Trigger Stage | Required Sections |
|---|---|---|
| Plaint | case_active, filing |
Parties, Jurisdiction, Facts, Cause of Action, Relief Sought, Verification |
| Written Statement | response_stage |
Preliminary Objections, Para-wise Reply, Affirmative Defenses, Prayer |
| Objection Response | maintainability |
(same as Written Statement) |
| Affidavit | evidence_stage |
Deponent Details, Statement of Facts, Verification, Attestation |
| Appeal | appeal |
Parties, Impugned Order, Grounds of Appeal, Prayer |
| Client-Lawyer Contract | pre_acceptance |
Parties, Recitals, Scope, Fee Structure, Payment, Obligations, Confidentiality, Conflict, Term, Liability, Dispute Resolution, Governing Law, Signature Blocks |
| Notice | (manual) | Addressee, Subject, Authority, Facts, Breach, Demand, Consequences, Signature |
| Misc. Petition | (manual) | Cause Title, Background Facts, Grounds, Interim Relief, Prayer, Verification |
| Stay/Injunction | (manual) | Cause Title, Facts, Grounds for Interim Relief, Urgency & Irreparable Loss, Balance of Convenience, Prayer |
Each document type has configurable limits to stay within token budgets:
| Document Type | Max Docs | Max Chars/Doc | Max Total Chars |
|---|---|---|---|
| Client-Lawyer Contract | 5 | 1,100 | 4,500 |
| Affidavit | 5 | 1,200 | 4,800 |
| Notice | 5 | 1,200 | 4,800 |
| Misc. Petition | 6 | 1,300 | 5,600 |
| Stay/Injunction | 6 | 1,400 | 6,000 |
| All others | 6 | 1,400 | 6,200 |
When /draft/generate is called, the service assembles a rich context for Gemini:
-
Case Context β Joined data from
client_cases,users,client_profiles,advocate_profiles. Includes case title, stage, legal domain, parties, verification status. -
Intake Analysis β The latest voice interview's structured analysis (JSONB) and transcript. Extracted by
build_prefilled_fields(): plaintiff/defendant names, advocate details, jurisdiction, nature of dispute, relief sought, key facts (dates, locations, amounts). -
Verified Documents β
case_documentsandclient_documentswithstatus = 'approved'and non-emptyextracted_text. Filtered by relevance to target document type, capped by per-type token budgets. -
Balanced Case Context β A compact, type-specific summary. Contracts include payment terms and contact details; other documents include nature of dispute and key facts.
-
Legal References β Optional RAG assistant citations (Phase 2 β currently stubbed).
-
Prompt Construction β The base prompt (
prompts/base.py) combines:- System role ("legal drafting assistant for Pakistani civil courts")
- Document-specific instructions from
prompts/{type}.py - All context layers above
- Advocate's custom notes
- Strict JSON output specification
- Writing rules (use only relevant context, no invented facts, "To be specified" for gaps)
-
Gemini Invocation β
temperature=0.2for consistent output. If JSON parsing fails, a second repair call withtemperature=0.0attempts to fix it. If that also fails, a fallback payload is returned. -
DOCX Export β
python-docxgenerates A4, Times New Roman 12pt, justified alignment, with title as Heading 1 and sections as Heading 2.
| Component | Technology |
|---|---|
| Framework | FastAPI + Uvicorn |
| AI Model | Gemini 2.5 Flash via Vertex AI (temperature=0.2) |
| Database | asyncpg (PostgreSQL connection pool) |
| Export | python-docx (A4, Times New Roman 12pt) |
| Config | pydantic-settings + python-dotenv |
| Deployment | Google Cloud Run (GitHub-connected auto-deploy) |
| Language | Python 3.11 |
- Python 3.11+
- PostgreSQL (local mode only)
- Vertex AI access in your GCP project
# Clone
git clone https://github.com/abuzarai/drafting-assistant.git
cd drafting-assistant
# Virtual environment
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
# Environment
cp .env.example .env
# Edit .env with your values| Variable | Required | Default | Description |
|---|---|---|---|
ENV |
Yes | local |
Runtime mode: local or production |
GCP_PROJECT_ID |
Yes | β | GCP project for Vertex AI Gemini |
GOOGLE_VERTEX_LOCATION |
No | us-central1 |
Vertex AI region |
GOOGLE_APPLICATION_CREDENTIALS |
Yes | β | Path to GCP service account key |
DB_HOST |
Local only | localhost |
PostgreSQL host |
DB_PORT |
Local only | 5432 |
PostgreSQL port |
DB_DATABASE |
Local only | insafdaar_db |
PostgreSQL database |
DB_USER |
Local only | postgres |
PostgreSQL user |
DB_PASSWORD |
Local only | β | PostgreSQL password |
EXPRESS_INTERNAL_URL |
Prod only | β | Express backend internal URL |
INTERNAL_API_KEY |
Prod only | β | Shared secret for internal auth |
RAG_API_URL |
No | β | Legal RAG Assistant URL (Phase 2) |
PORT |
No | 8001 |
Service port |
CORS_ORIGINS |
No | http://localhost:3000 |
Comma-separated CORS origins |
python -m uvicorn main:app --host 0.0.0.0 --port 8001 --reloadHealth check: curl http://localhost:8001/health
pytest tests/test_draft_api.py -vdocker build -t drafting-assistant .
docker run --rm -p 8080:8080 --env-file .env drafting-assistant- Platform: Google Cloud Run (GitHub-connected auto build/deploy)
- Mode:
ENV=production(proxies DB queries to Express backend; no direct PostgreSQL connection) - Internal API: Express exposes
/internal/draft/*endpoints with shared secret auth - Auto-deploy: Pushes to
maintrigger a Cloud Run rebuild and deploy
drafting-assistant/
βββ main.py # FastAPI entrypoint, CORS, health
βββ config.py # Pydantic settings (all env vars)
βββ db/
β βββ connection.py # asyncpg pool setup + draft_sessions table
βββ models/
β βββ schemas.py # Pydantic request/response models
βββ routes/
β βββ draft.py # 5 endpoints: init, generate, regenerate, save, export
βββ services/
β βββ gemini_service.py # Gemini invocation, JSON parsing, repair fallback
β βββ context_service.py # Case context, intake analysis, document assembly
β βββ draft_store.py # Draft persistence (extended schema)
β βββ export_service.py # DOCX generation (python-docx)
β βββ rag_service.py # RAG client (Phase 2 stub)
βββ prompts/
β βββ base.py # System prompt builder + JSON output spec
β βββ plaint.py # Plaint document instructions
β βββ written_statement.py # Written Statement & Objection Response
β βββ affidavit.py # Affidavit instructions
β βββ appeal.py # Appeal instructions
β βββ contract.py # Client-Lawyer Contract (15 sections)
β βββ notice.py # Legal Notice instructions
β βββ misc_petition.py # Misc. Petition instructions
β βββ stay_injunction.py # Stay/Injunction instructions
βββ tests/
β βββ test_draft_api.py # FastAPI TestClient test suite
βββ Dockerfile # Cloud Run build
βββ requirements.txt # Python dependencies
Licensed under the Apache License 2.0.