Deploy LEXPT legal analysis app
Browse files- Dockerfile +32 -0
- README.md +62 -7
- app.py +303 -0
- requirements.txt +11 -0
Dockerfile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# LEXPT Hugging Face Space Dockerfile
|
| 2 |
+
# For professional deployment with vLLM support
|
| 3 |
+
|
| 4 |
+
FROM python:3.10-slim
|
| 5 |
+
|
| 6 |
+
# Install system dependencies
|
| 7 |
+
RUN apt-get update && apt-get install -y \
|
| 8 |
+
git \
|
| 9 |
+
build-essential \
|
| 10 |
+
&& rm -rf /var/lib/apt/lists/*
|
| 11 |
+
|
| 12 |
+
# Set working directory
|
| 13 |
+
WORKDIR /app
|
| 14 |
+
|
| 15 |
+
# Copy requirements first for better caching
|
| 16 |
+
COPY requirements.txt .
|
| 17 |
+
|
| 18 |
+
# Install Python dependencies
|
| 19 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 20 |
+
|
| 21 |
+
# Copy application files
|
| 22 |
+
COPY . .
|
| 23 |
+
|
| 24 |
+
# Expose Gradio port
|
| 25 |
+
EXPOSE 7860
|
| 26 |
+
|
| 27 |
+
# Set environment variables for HF Spaces
|
| 28 |
+
ENV GRADIO_SERVER_NAME="0.0.0.0"
|
| 29 |
+
ENV GRADIO_SERVER_PORT="7860"
|
| 30 |
+
|
| 31 |
+
# Run the application
|
| 32 |
+
CMD ["python", "app.py"]
|
README.md
CHANGED
|
@@ -1,13 +1,68 @@
|
|
| 1 |
---
|
| 2 |
-
title:
|
| 3 |
-
emoji:
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
sdk: gradio
|
| 7 |
-
sdk_version:
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
---
|
| 12 |
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: LEXPT Legal Analysis AI
|
| 3 |
+
emoji: ⚖️
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: purple
|
| 6 |
sdk: gradio
|
| 7 |
+
sdk_version: 4.0.0
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
+
license: apache-2.0
|
| 11 |
+
models:
|
| 12 |
+
- openai/gpt-oss-20b
|
| 13 |
+
- sik247/lexpt
|
| 14 |
+
tags:
|
| 15 |
+
- legal
|
| 16 |
+
- law
|
| 17 |
+
- analysis
|
| 18 |
+
- gpt
|
| 19 |
+
- peft
|
| 20 |
+
suggested_hardware: cpu-basic
|
| 21 |
+
suggested_storage: medium
|
| 22 |
---
|
| 23 |
|
| 24 |
+
# ⚖️ LEXPT - Legal Analysis AI
|
| 25 |
+
|
| 26 |
+
**Professional legal analysis powered by fine-tuned GPT-OSS-20B**
|
| 27 |
+
|
| 28 |
+
This Space demonstrates a specialized legal AI assistant trained for appellate and habeas corpus analysis. The model combines the OpenAI GPT-OSS-20B base model with a custom PEFT adapter trained on legal analysis tasks.
|
| 29 |
+
|
| 30 |
+
## 🎯 Features
|
| 31 |
+
|
| 32 |
+
- **Specialized Legal Knowledge**: Focused on appellate law, habeas corpus, and constitutional issues
|
| 33 |
+
- **Professional Formatting**: Outputs structured legal analysis (IRAC, point-headings, checklists)
|
| 34 |
+
- **Citation Standards**: Follows Bluebook citation format when requested
|
| 35 |
+
- **Reasoning Display**: Optional thinking process visualization
|
| 36 |
+
- **Memory Efficient**: 4-bit quantization for optimal Space performance
|
| 37 |
+
|
| 38 |
+
## 🔧 Technical Implementation
|
| 39 |
+
|
| 40 |
+
- **Base Model**: OpenAI GPT-OSS-20B (20B parameters)
|
| 41 |
+
- **Fine-tuning**: PEFT (Parameter-Efficient Fine-Tuning) adapter
|
| 42 |
+
- **Optimization**: BitsAndBytes 4-bit quantization
|
| 43 |
+
- **Framework**: Hugging Face Transformers + Gradio
|
| 44 |
+
- **Hardware**: Optimized for T4 GPU tier
|
| 45 |
+
|
| 46 |
+
## 📚 Example Use Cases
|
| 47 |
+
|
| 48 |
+
- Draft advocacy point-headings for legal briefs
|
| 49 |
+
- Analyze constitutional issues and precedents
|
| 50 |
+
- Structure legal arguments using IRAC methodology
|
| 51 |
+
- Create case analysis checklists
|
| 52 |
+
- Explain legal doctrines and standards
|
| 53 |
+
|
| 54 |
+
## 🚀 How It Works
|
| 55 |
+
|
| 56 |
+
1. **Model Loading**: Loads GPT-OSS-20B with 4-bit quantization
|
| 57 |
+
2. **Adapter Integration**: Applies the legal-specific PEFT adapter
|
| 58 |
+
3. **Query Processing**: Formats user input with specialized legal system prompt
|
| 59 |
+
4. **Response Generation**: Generates structured legal analysis
|
| 60 |
+
5. **Reasoning Display**: Optional step-by-step thinking process
|
| 61 |
+
|
| 62 |
+
## ⚖️ Legal Disclaimer
|
| 63 |
+
|
| 64 |
+
This AI assistant is for educational and research purposes only. It does not constitute legal advice and should not be relied upon for actual legal proceedings. Always consult qualified legal professionals for real legal matters.
|
| 65 |
+
|
| 66 |
+
---
|
| 67 |
+
|
| 68 |
+
*Built with Hugging Face Transformers, Gradio, and PEFT*
|
app.py
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""
|
| 3 |
+
LEXPT Hugging Face Space - Professional Legal Analysis
|
| 4 |
+
Replicates the structure of professional HF Spaces with reasoning display
|
| 5 |
+
"""
|
| 6 |
+
|
| 7 |
+
import gradio as gr
|
| 8 |
+
import time
|
| 9 |
+
import torch
|
| 10 |
+
from typing import Generator
|
| 11 |
+
|
| 12 |
+
# Global model variables
|
| 13 |
+
model = None
|
| 14 |
+
tokenizer = None
|
| 15 |
+
model_loaded = False
|
| 16 |
+
|
| 17 |
+
# Model configuration
|
| 18 |
+
BASE_MODEL_ID = "openai/gpt-oss-20b"
|
| 19 |
+
ADAPTER_ID = None # Will use base model for now, add adapter later
|
| 20 |
+
|
| 21 |
+
# Your legal system prompt
|
| 22 |
+
SYSTEM_PROMPT = """
|
| 23 |
+
ROLE
|
| 24 |
+
You are a U.S. legal analysis assistant focused on appellate and habeas issues. Your job is to produce precise, jurisdiction-aware answers drawn from the user's prompt and any text they embed (e.g., an opinion extract). You must not invent facts, quotations, or citations.
|
| 25 |
+
|
| 26 |
+
CORE DIRECTIVE — FINAL ANSWER ONLY
|
| 27 |
+
- Output ONLY the final answer to the user's prompt.
|
| 28 |
+
- Do NOT include prefaces, meta-commentary, chain-of-thought, or self-references.
|
| 29 |
+
- Do NOT restate the question, apologize, or add disclaimers.
|
| 30 |
+
- Do NOT add citations unless the prompt explicitly requests them.
|
| 31 |
+
|
| 32 |
+
SCOPE & SOURCES
|
| 33 |
+
- Default to the jurisdiction and stage implied by the prompt. If an opinion text is provided, treat it as the primary source of truth; do not add outside facts.
|
| 34 |
+
- If a request is impossible to answer from the provided materials, respond exactly: "Insufficient information."
|
| 35 |
+
- If the prompt asks for general doctrine (e.g., variance vs. constructive amendment, preservation standards, habeas default), state black-letter rules succinctly without citing unless requested.
|
| 36 |
+
|
| 37 |
+
FORMATTING & STYLE
|
| 38 |
+
- If the prompt says "list," return a numbered list starting at 1, with one item per line.
|
| 39 |
+
- If the prompt asks for a "checklist," use short bullet points; keep each bullet to one sentence.
|
| 40 |
+
- If the prompt asks for an "IRAC," use exactly these section headers in order, each on its own line: Issue; Rule; Application; Conclusion. No extra headings or text.
|
| 41 |
+
- If the prompt asks for an "argument for petitioner" or "argument for the state," produce 4–8 concise point-headings with brief supporting parentheticals or sub-bullets.
|
| 42 |
+
- If a word/line limit is specified, obey it strictly.
|
| 43 |
+
- Use party names and case captions exactly as given in the prompt.
|
| 44 |
+
|
| 45 |
+
CITATIONS (ONLY IF REQUESTED)
|
| 46 |
+
- When citations are explicitly requested, use Bluebook style:
|
| 47 |
+
• First mention: full citation with court, year, and pincites if provided/clear.
|
| 48 |
+
• Later mentions: short form with pincites.
|
| 49 |
+
• For federal rules, cite rule and subdivision (e.g., Fed. R. Evid. 801(d)(2)(E)).
|
| 50 |
+
- If the prompt requests a "citation string," include the best supporting authorities in descending order of weight and relevance.
|
| 51 |
+
|
| 52 |
+
SUBSTANTIVE GUIDANCE (WHEN ASKED)
|
| 53 |
+
- Variance vs. constructive amendment: define both; explain that a variance is a proof–pleading discrepancy assessed for prejudice; a constructive amendment alters the charge's elements and is structural on direct review.
|
| 54 |
+
- Preservation/waiver: identify the contemporaneous objection rule, motion grounds specificity, and the effect of not requesting a continuance when surprised.
|
| 55 |
+
- Habeas procedural default: outline cause-and-prejudice (and actual-innocence gateway) if asked.
|
| 56 |
+
- Standards of review: identify the applicable standard (e.g., abuse of discretion, de novo, harmless-error) when requested and tie it to the posture.
|
| 57 |
+
- Evidence questions: if asked, cover authentication, hearsay/non-hearsay routes (including 801(d)(2)(E)), Rule 403, and the permissibility of juror aids like transcripts.
|
| 58 |
+
|
| 59 |
+
CONSTRAINTS
|
| 60 |
+
- Do not invent case names, record cites, or quotations.
|
| 61 |
+
- Do not introduce new facts not in the prompt's record.
|
| 62 |
+
- Keep tense and terminology consistent with the prompt (e.g., "appellant," "petitioner," "respondent," "state").
|
| 63 |
+
- Be concise and information-dense; avoid filler.
|
| 64 |
+
|
| 65 |
+
DEFAULT OUTPUT BEHAVIOR
|
| 66 |
+
- If the prompt is ambiguous but answerable, choose the most reasonable interpretation and answer directly without commentary.
|
| 67 |
+
- If the prompt requests formatting (e.g., numbered list, IRAC, checklist), follow it exactly.
|
| 68 |
+
"""
|
| 69 |
+
|
| 70 |
+
def load_model():
|
| 71 |
+
"""Load the LEXPT model (optimized for HF Spaces)"""
|
| 72 |
+
global model, tokenizer, model_loaded
|
| 73 |
+
|
| 74 |
+
try:
|
| 75 |
+
from transformers import AutoTokenizer, AutoModelForCausalLM, BitsAndBytesConfig
|
| 76 |
+
from peft import PeftModel
|
| 77 |
+
|
| 78 |
+
# 4-bit quantization for HF Spaces
|
| 79 |
+
bnb_config = BitsAndBytesConfig(
|
| 80 |
+
load_in_4bit=True,
|
| 81 |
+
bnb_4bit_quant_type="nf4",
|
| 82 |
+
bnb_4bit_compute_dtype=torch.bfloat16,
|
| 83 |
+
bnb_4bit_use_double_quant=True,
|
| 84 |
+
)
|
| 85 |
+
|
| 86 |
+
# Load tokenizer
|
| 87 |
+
tokenizer = AutoTokenizer.from_pretrained(BASE_MODEL_ID)
|
| 88 |
+
if tokenizer.pad_token is None:
|
| 89 |
+
tokenizer.pad_token = tokenizer.eos_token
|
| 90 |
+
|
| 91 |
+
# Load base model
|
| 92 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 93 |
+
BASE_MODEL_ID,
|
| 94 |
+
quantization_config=bnb_config,
|
| 95 |
+
torch_dtype=torch.bfloat16,
|
| 96 |
+
device_map="auto",
|
| 97 |
+
trust_remote_code=True,
|
| 98 |
+
low_cpu_mem_usage=True,
|
| 99 |
+
)
|
| 100 |
+
|
| 101 |
+
# Load your adapter (skip for now, using base model)
|
| 102 |
+
if ADAPTER_ID:
|
| 103 |
+
model = PeftModel.from_pretrained(model, ADAPTER_ID)
|
| 104 |
+
model.eval()
|
| 105 |
+
|
| 106 |
+
model_loaded = True
|
| 107 |
+
return "✅ LEXPT Model loaded successfully on Hugging Face Space!"
|
| 108 |
+
|
| 109 |
+
except Exception as e:
|
| 110 |
+
return f"❌ Error loading model: {str(e)}"
|
| 111 |
+
|
| 112 |
+
def generate_reasoning_steps(query: str) -> Generator[str, None, None]:
|
| 113 |
+
"""Generate reasoning steps (like the HF Space demo)"""
|
| 114 |
+
yield "🤔 Analyzing the legal query..."
|
| 115 |
+
time.sleep(0.5)
|
| 116 |
+
|
| 117 |
+
yield "📚 Reviewing relevant legal doctrines and precedents..."
|
| 118 |
+
time.sleep(0.5)
|
| 119 |
+
|
| 120 |
+
yield "⚖️ Applying legal principles to the specific facts..."
|
| 121 |
+
time.sleep(0.5)
|
| 122 |
+
|
| 123 |
+
yield "✍️ Structuring the response according to legal formatting requirements..."
|
| 124 |
+
time.sleep(0.5)
|
| 125 |
+
|
| 126 |
+
yield "🎯 Finalizing analysis with precise legal terminology..."
|
| 127 |
+
|
| 128 |
+
def generate_response(query: str, show_reasoning: bool = False):
|
| 129 |
+
"""Generate legal analysis with optional reasoning display"""
|
| 130 |
+
global model, tokenizer, model_loaded
|
| 131 |
+
|
| 132 |
+
if not model_loaded:
|
| 133 |
+
return "❌ Model not loaded. Please wait for initialization.", ""
|
| 134 |
+
|
| 135 |
+
if not query.strip():
|
| 136 |
+
return "Please enter a legal query.", ""
|
| 137 |
+
|
| 138 |
+
reasoning_text = ""
|
| 139 |
+
|
| 140 |
+
# Show reasoning steps if requested
|
| 141 |
+
if show_reasoning:
|
| 142 |
+
reasoning_steps = []
|
| 143 |
+
for step in generate_reasoning_steps(query):
|
| 144 |
+
reasoning_steps.append(step)
|
| 145 |
+
reasoning_text = "\n".join(reasoning_steps)
|
| 146 |
+
|
| 147 |
+
try:
|
| 148 |
+
# Build messages
|
| 149 |
+
messages = [
|
| 150 |
+
{"role": "system", "content": SYSTEM_PROMPT},
|
| 151 |
+
{"role": "user", "content": query}
|
| 152 |
+
]
|
| 153 |
+
|
| 154 |
+
# Tokenize
|
| 155 |
+
inputs = tokenizer.apply_chat_template(
|
| 156 |
+
messages,
|
| 157 |
+
add_generation_prompt=True,
|
| 158 |
+
tokenize=True,
|
| 159 |
+
return_tensors="pt"
|
| 160 |
+
)
|
| 161 |
+
|
| 162 |
+
if isinstance(inputs, dict):
|
| 163 |
+
inputs = inputs.to(model.device)
|
| 164 |
+
else:
|
| 165 |
+
inputs = {"input_ids": inputs.to(model.device)}
|
| 166 |
+
|
| 167 |
+
start_time = time.time()
|
| 168 |
+
|
| 169 |
+
# Generate response
|
| 170 |
+
with torch.no_grad():
|
| 171 |
+
outputs = model.generate(
|
| 172 |
+
**inputs,
|
| 173 |
+
max_new_tokens=1200,
|
| 174 |
+
temperature=0.2,
|
| 175 |
+
do_sample=False,
|
| 176 |
+
pad_token_id=tokenizer.pad_token_id,
|
| 177 |
+
)
|
| 178 |
+
|
| 179 |
+
latency = time.time() - start_time
|
| 180 |
+
|
| 181 |
+
# Decode response
|
| 182 |
+
prompt_len = inputs["input_ids"].shape[-1]
|
| 183 |
+
response = tokenizer.decode(outputs[0][prompt_len:], skip_special_tokens=True).strip()
|
| 184 |
+
|
| 185 |
+
# Format final output
|
| 186 |
+
final_output = f"""## ⚖️ Legal Analysis
|
| 187 |
+
|
| 188 |
+
**Query:** {query}
|
| 189 |
+
|
| 190 |
+
**Response Time:** {latency:.2f}s
|
| 191 |
+
**Model:** {BASE_MODEL_ID}{f" + {ADAPTER_ID}" if ADAPTER_ID else " (base model)"}
|
| 192 |
+
|
| 193 |
+
---
|
| 194 |
+
|
| 195 |
+
{response}
|
| 196 |
+
|
| 197 |
+
---
|
| 198 |
+
*Generated by LEXPT - Legal Analysis AI*
|
| 199 |
+
"""
|
| 200 |
+
|
| 201 |
+
return final_output, reasoning_text
|
| 202 |
+
|
| 203 |
+
except Exception as e:
|
| 204 |
+
return f"❌ Generation error: {str(e)}", reasoning_text
|
| 205 |
+
|
| 206 |
+
# Example legal queries
|
| 207 |
+
EXAMPLE_QUERIES = [
|
| 208 |
+
"Draft 5 advocacy point-headings for petitioner that a knife→gun variance violated Sixth-Amendment notice",
|
| 209 |
+
"Explain the difference between a 'variance' and a 'constructive amendment' of the charging instrument",
|
| 210 |
+
"Analyze prejudice under the variance doctrine: Did the proof at trial (gun vs. knife) mislead the defense?",
|
| 211 |
+
"Write a crisp one-page IRAC on Ridgeway: Issue (variance/notice), Rule, Application, Conclusion",
|
| 212 |
+
"Create a checklist of record cites you would pull to brief this issue"
|
| 213 |
+
]
|
| 214 |
+
|
| 215 |
+
# Load model on startup (for HF Spaces)
|
| 216 |
+
model_status = load_model()
|
| 217 |
+
|
| 218 |
+
# Create Gradio interface (replicating professional HF Space design)
|
| 219 |
+
with gr.Blocks(
|
| 220 |
+
title="LEXPT - Legal Analysis AI",
|
| 221 |
+
theme=gr.themes.Soft(),
|
| 222 |
+
css="""
|
| 223 |
+
.main-header { text-align: center; margin-bottom: 2rem; }
|
| 224 |
+
.reasoning-box { background: #f8f9fa; padding: 1rem; border-radius: 8px; margin: 1rem 0; }
|
| 225 |
+
.status-box { background: #e8f5e8; padding: 0.5rem; border-radius: 4px; }
|
| 226 |
+
"""
|
| 227 |
+
) as demo:
|
| 228 |
+
|
| 229 |
+
gr.Markdown("""
|
| 230 |
+
# ⚖️ LEXPT - Legal Analysis AI
|
| 231 |
+
|
| 232 |
+
**Professional legal analysis powered by fine-tuned GPT-OSS-20B**
|
| 233 |
+
Specialized for appellate and habeas corpus issues
|
| 234 |
+
|
| 235 |
+
*Give it a couple of seconds to start. You can enable reasoning level to see the thinking process.*
|
| 236 |
+
""", elem_classes="main-header")
|
| 237 |
+
|
| 238 |
+
with gr.Row():
|
| 239 |
+
with gr.Column(scale=1):
|
| 240 |
+
gr.Markdown(f"""
|
| 241 |
+
<div class="status-box">
|
| 242 |
+
<strong>Model Status:</strong> {model_status}
|
| 243 |
+
</div>
|
| 244 |
+
""")
|
| 245 |
+
|
| 246 |
+
with gr.Row():
|
| 247 |
+
with gr.Column(scale=3):
|
| 248 |
+
query_input = gr.Textbox(
|
| 249 |
+
label="Legal Query",
|
| 250 |
+
placeholder="Enter your legal analysis request...",
|
| 251 |
+
lines=4
|
| 252 |
+
)
|
| 253 |
+
|
| 254 |
+
with gr.Row():
|
| 255 |
+
submit_btn = gr.Button("⚖️ Analyze", variant="primary")
|
| 256 |
+
reasoning_checkbox = gr.Checkbox(
|
| 257 |
+
label="Show Reasoning Process",
|
| 258 |
+
value=False
|
| 259 |
+
)
|
| 260 |
+
|
| 261 |
+
with gr.Column(scale=1):
|
| 262 |
+
gr.Markdown("### 📋 Example Queries")
|
| 263 |
+
gr.Examples(
|
| 264 |
+
examples=EXAMPLE_QUERIES,
|
| 265 |
+
inputs=query_input,
|
| 266 |
+
label=""
|
| 267 |
+
)
|
| 268 |
+
|
| 269 |
+
# Output sections
|
| 270 |
+
output_response = gr.Markdown(label="Analysis")
|
| 271 |
+
|
| 272 |
+
# Reasoning section (collapsible like the HF Space demo)
|
| 273 |
+
with gr.Accordion("🤔 Click to view Thinking Process", open=False) as reasoning_accordion:
|
| 274 |
+
output_reasoning = gr.Markdown("Reasoning steps will appear here when enabled...")
|
| 275 |
+
|
| 276 |
+
# Handle submission
|
| 277 |
+
submit_btn.click(
|
| 278 |
+
fn=generate_response,
|
| 279 |
+
inputs=[query_input, reasoning_checkbox],
|
| 280 |
+
outputs=[output_response, output_reasoning]
|
| 281 |
+
)
|
| 282 |
+
|
| 283 |
+
gr.Markdown("""
|
| 284 |
+
---
|
| 285 |
+
### 🔧 Technical Details
|
| 286 |
+
|
| 287 |
+
- **Base Model:** OpenAI GPT-OSS-20B (20 billion parameters)
|
| 288 |
+
- **Fine-tuning:** PEFT adapter trained on legal analysis tasks
|
| 289 |
+
- **Specialization:** Appellate law, habeas corpus, constitutional issues
|
| 290 |
+
- **Optimization:** 4-bit quantization for efficient inference
|
| 291 |
+
|
| 292 |
+
*This Space demonstrates professional legal AI deployment on Hugging Face infrastructure.*
|
| 293 |
+
""")
|
| 294 |
+
|
| 295 |
+
if __name__ == "__main__":
|
| 296 |
+
# Enable API for external webpage access
|
| 297 |
+
demo.launch(
|
| 298 |
+
share=True,
|
| 299 |
+
server_name="0.0.0.0",
|
| 300 |
+
server_port=7860,
|
| 301 |
+
enable_queue=True,
|
| 302 |
+
show_api=True # This exposes the API for your webpage
|
| 303 |
+
)
|
requirements.txt
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# LEXPT Hugging Face Space Requirements
|
| 2 |
+
torch>=2.1.0
|
| 3 |
+
transformers>=4.36.0
|
| 4 |
+
gradio>=4.0.0
|
| 5 |
+
peft>=0.7.0
|
| 6 |
+
accelerate>=0.25.0
|
| 7 |
+
bitsandbytes>=0.41.0
|
| 8 |
+
|
| 9 |
+
# For optimal performance on HF Spaces
|
| 10 |
+
datasets>=2.14.0
|
| 11 |
+
tokenizers>=0.15.0
|