Spaces:
Sleeping
Sleeping
Sai809701 commited on
Commit Β·
a2464d3
1
Parent(s): 17205ab
fix model loader error
Browse files- Dockerfile +4 -3
- main.py +68 -23
- model_loader.py +0 -19
Dockerfile
CHANGED
|
@@ -13,8 +13,9 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
|
| 13 |
# Copy the rest of the application code
|
| 14 |
COPY . /code/app
|
| 15 |
|
| 16 |
-
#
|
| 17 |
-
|
| 18 |
|
| 19 |
# Run uvicorn when the container launches
|
| 20 |
-
|
|
|
|
|
|
| 13 |
# Copy the rest of the application code
|
| 14 |
COPY . /code/app
|
| 15 |
|
| 16 |
+
# Set the working directory to where your app is
|
| 17 |
+
WORKDIR /code/app
|
| 18 |
|
| 19 |
# Run uvicorn when the container launches
|
| 20 |
+
# This now correctly points to the 'app' instance in your 'main.py' file
|
| 21 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
main.py
CHANGED
|
@@ -1,49 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from fastapi import FastAPI
|
| 2 |
from pydantic import BaseModel
|
| 3 |
from pymongo import MongoClient
|
| 4 |
-
from model_loader import ModelLoader
|
| 5 |
import torch
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
|
| 7 |
# Initialize FastAPI app
|
| 8 |
app = FastAPI(title="AI Legal Aid Chatbot")
|
| 9 |
|
| 10 |
-
#
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
# MongoDB Atlas connection
|
| 16 |
-
client = MongoClient("mongodb+srv://saisunil22ecs:9m2ajd0GxVn43Fbu@majorproject.g0g1as0.mongodb.net/?retryWrites=true&w=majority&appName=MajorProject")
|
| 17 |
-
db = client["legal_chatbot_db"]
|
| 18 |
-
collection = db["datasets"]
|
| 19 |
-
# Request schema
|
| 20 |
class QueryRequest(BaseModel):
|
| 21 |
question: str
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
@app.get("/")
|
| 24 |
async def root():
|
|
|
|
| 25 |
return {"message": "AI Legal Aid Chatbot is running β
"}
|
| 26 |
|
| 27 |
-
@app.post("/chat")
|
| 28 |
async def chat(req: QueryRequest):
|
| 29 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
inputs = tokenizer(req.question, return_tensors="pt", truncation=True, padding=True)
|
| 31 |
with torch.no_grad():
|
| 32 |
outputs = model(**inputs)
|
| 33 |
predicted_label_id = torch.argmax(outputs.logits, dim=1).item()
|
| 34 |
|
| 35 |
-
|
| 36 |
|
| 37 |
-
# Step 2:
|
| 38 |
-
|
|
|
|
|
|
|
| 39 |
if doc and "Answer" in doc:
|
| 40 |
answer = doc["Answer"]
|
| 41 |
else:
|
| 42 |
-
answer = "
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
return {
|
| 46 |
-
"question": req.question,
|
| 47 |
-
"predicted_intent": label,
|
| 48 |
-
"answer": answer
|
| 49 |
-
}
|
|
|
|
| 1 |
+
# main.py
|
| 2 |
+
|
| 3 |
+
import os
|
| 4 |
from fastapi import FastAPI
|
| 5 |
from pydantic import BaseModel
|
| 6 |
from pymongo import MongoClient
|
|
|
|
| 7 |
import torch
|
| 8 |
+
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 9 |
+
from sentence_transformers import SentenceTransformer
|
| 10 |
+
|
| 11 |
+
# --- 1. Configuration and Initialization ---
|
| 12 |
|
| 13 |
# Initialize FastAPI app
|
| 14 |
app = FastAPI(title="AI Legal Aid Chatbot")
|
| 15 |
|
| 16 |
+
# It's good practice to load environment variables for sensitive data
|
| 17 |
+
# For this example, we'll use the hardcoded connection string from your original file.
|
| 18 |
+
MONGO_URI = "mongodb+srv://saisunil22ecs:9m2ajd0GxVn43Fbu@majorproject.g0g1as0.mongodb.net/?retryWrites=true&w=majority&appName=MajorProject"
|
| 19 |
+
DB_NAME = "legal_chatbot_db"
|
| 20 |
+
COLLECTION_NAME = "datasets"
|
| 21 |
+
MODEL_PATH = "./final_bert_model_pdf" # Make sure this folder is uploaded
|
| 22 |
+
|
| 23 |
+
# --- 2. Load Models and Database Connection (Consolidated from model_loader.py) ---
|
| 24 |
+
|
| 25 |
+
def load_all_resources():
|
| 26 |
+
"""
|
| 27 |
+
A single function to load all necessary models and connect to the database.
|
| 28 |
+
This runs once when the API starts up.
|
| 29 |
+
"""
|
| 30 |
+
try:
|
| 31 |
+
print("π Loading classifier model and tokenizer...")
|
| 32 |
+
tokenizer = AutoTokenizer.from_pretrained(MODEL_PATH)
|
| 33 |
+
model = AutoModelForSequenceClassification.from_pretrained(MODEL_PATH)
|
| 34 |
+
print("β
Classifier loaded successfully!")
|
| 35 |
+
|
| 36 |
+
print("π Connecting to MongoDB Atlas...")
|
| 37 |
+
client = MongoClient(MONGO_URI)
|
| 38 |
+
db = client[DB_NAME]
|
| 39 |
+
collection = db[COLLECTION_NAME]
|
| 40 |
+
# Test connection
|
| 41 |
+
db.command('ping')
|
| 42 |
+
print("β
MongoDB connection successful!")
|
| 43 |
+
|
| 44 |
+
return tokenizer, model, collection
|
| 45 |
+
except Exception as e:
|
| 46 |
+
print(f"β Critical Error during startup: {e}")
|
| 47 |
+
return None, None, None
|
| 48 |
+
|
| 49 |
+
# Load everything into global variables
|
| 50 |
+
tokenizer, model, collection = load_all_resources()
|
| 51 |
+
|
| 52 |
+
# --- 3. Define API Request and Response Schemas ---
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
class QueryRequest(BaseModel):
|
| 55 |
question: str
|
| 56 |
|
| 57 |
+
# You can add a response model for better documentation and validation
|
| 58 |
+
class ChatResponse(BaseModel):
|
| 59 |
+
predicted_intent: str
|
| 60 |
+
answer: str
|
| 61 |
+
|
| 62 |
+
# --- 4. Create API Endpoints ---
|
| 63 |
+
|
| 64 |
@app.get("/")
|
| 65 |
async def root():
|
| 66 |
+
"""A simple endpoint to check if the API is running."""
|
| 67 |
return {"message": "AI Legal Aid Chatbot is running β
"}
|
| 68 |
|
| 69 |
+
@app.post("/chat", response_model=ChatResponse)
|
| 70 |
async def chat(req: QueryRequest):
|
| 71 |
+
"""
|
| 72 |
+
Main chat endpoint to get a legal answer for a given question.
|
| 73 |
+
"""
|
| 74 |
+
if not model or not tokenizer or not collection:
|
| 75 |
+
return {"predicted_intent": "Error", "answer": "Server is not ready. Resources could not be loaded."}
|
| 76 |
+
|
| 77 |
+
# Step 1: Predict the intent using the fine-tuned model
|
| 78 |
inputs = tokenizer(req.question, return_tensors="pt", truncation=True, padding=True)
|
| 79 |
with torch.no_grad():
|
| 80 |
outputs = model(**inputs)
|
| 81 |
predicted_label_id = torch.argmax(outputs.logits, dim=1).item()
|
| 82 |
|
| 83 |
+
predicted_intent = model.config.id2label[predicted_label_id]
|
| 84 |
|
| 85 |
+
# Step 2: Retrieve the answer from your MongoDB knowledge base
|
| 86 |
+
# This uses a simple find_one, but can be replaced with your vector search logic
|
| 87 |
+
doc = collection.find_one({"Intent": predicted_intent})
|
| 88 |
+
|
| 89 |
if doc and "Answer" in doc:
|
| 90 |
answer = doc["Answer"]
|
| 91 |
else:
|
| 92 |
+
answer = "I have identified the intent, but could not find a specific answer in the knowledge base."
|
| 93 |
+
|
| 94 |
+
return {"predicted_intent": predicted_intent, "answer": answer}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
model_loader.py
DELETED
|
@@ -1,19 +0,0 @@
|
|
| 1 |
-
from transformers import AutoTokenizer, AutoModelForSequenceClassification
|
| 2 |
-
from sentence_transformers import SentenceTransformer
|
| 3 |
-
import numpy as np
|
| 4 |
-
|
| 5 |
-
class ModelLoader:
|
| 6 |
-
def __init__(self, model_path="./final_bert_model_pdf"):
|
| 7 |
-
print(f"π Loading classifier from {model_path} ...")
|
| 8 |
-
self.tokenizer = AutoTokenizer.from_pretrained(model_path)
|
| 9 |
-
self.model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
| 10 |
-
print("β
Classifier model & tokenizer loaded successfully!")
|
| 11 |
-
|
| 12 |
-
print("π Loading embedding model (all-MiniLM-L6-v2) ...")
|
| 13 |
-
self.embedding_model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
|
| 14 |
-
print("β
Embedding model loaded successfully!")
|
| 15 |
-
|
| 16 |
-
def embed(self, text: str) -> list:
|
| 17 |
-
"""Convert text into a vector embedding (list of floats)."""
|
| 18 |
-
embedding = self.embedding_model.encode(text)
|
| 19 |
-
return embedding.tolist() # MongoDB needs list, not numpy array
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|