viraj commited on
Commit
dacf14a
·
1 Parent(s): e5afeb9

Initial Commit

Browse files
.gitignore ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /env
2
+ __pycache__/
3
+ *.pyc
4
+ *.pyo
5
+ *.pyd
6
+ *.db
7
+ *.sqlite
8
+ .env
9
+ venv/
10
+ *.log
11
+ /venv
12
+ /.venv
13
+ .venv
14
+ backend/fine-tuned-model
FineTuning.ipynb ADDED
The diff for this file is too large to render. See raw diff
 
Makefile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Define variables for backend and frontend directories
2
+ BACKEND_DIR = backend
3
+ FRONTEND_DIR = frontend
4
+
5
+ start-backend:
6
+ cd $(BACKEND_DIR) && pip3 install -r requirements.txt && uvicorn app.main:app --host 0.0.0.0 --port 8000
7
+
8
+ start-frontend:
9
+ cd $(FRONTEND_DIR) && pip3 install -r requirements.txt && streamlit run app.py
10
+
11
+ up:
12
+ $(MAKE) start-backend &
13
+ $(MAKE) start-frontend
backend/.DS_Store ADDED
Binary file (6.15 kB). View file
 
backend/Dockerfile ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY app /app
9
+
10
+ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
backend/README.md ADDED
File without changes
backend/__init__.py ADDED
File without changes
backend/app/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ from .models import predict_sentiment
backend/app/api/__init__.py ADDED
File without changes
backend/app/api/v1/__init__.py ADDED
File without changes
backend/app/api/v1/config.py ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException
2
+ from .schemas import ConfigRequest
3
+ from transformers import AutoModelForQuestionAnswering, AutoTokenizer, pipeline, AutoModelForSequenceClassification
4
+ from app.models import predict_sentiment
5
+
6
+ router = APIRouter()
7
+
8
+ model_name = "fine-tuned-model"
9
+ tokenizer = AutoTokenizer.from_pretrained(model_name, use_safetensors=True)
10
+ model = AutoModelForSequenceClassification.from_pretrained(model_name)
11
+
12
+ @router.post("/")
13
+ def configure_model(config: ConfigRequest):
14
+ global model, tokenizer, qa_pipeline
15
+ try:
16
+ model = AutoModelForQuestionAnswering.from_pretrained(config.model_name)
17
+ tokenizer = AutoTokenizer.from_pretrained(config.model_name)
18
+ return {"message": f"Model loaded successfully: {config.model_name}"}
19
+ except Exception as e:
20
+ raise HTTPException(status_code=500, detail=str(e))
backend/app/api/v1/qa.py ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException
2
+ from .schemas import QARequest
3
+ from transformers import AutoModelForSequenceClassification
4
+ from transformers import AutoModelForQuestionAnswering, AutoTokenizer
5
+ from app.models import predict_sentiment
6
+
7
+ router = APIRouter()
8
+
9
+ model_name = "fine-tuned-model"
10
+ tokenizer = AutoTokenizer.from_pretrained(model_name, use_safetensors=True)
11
+ model = AutoModelForSequenceClassification.from_pretrained(model_name)
12
+
13
+ @router.post("/")
14
+ def get_answer(request: QARequest):
15
+ try:
16
+ sentiment, probs = predict_sentiment(request.command)
17
+ probs = [float(prob) for prob in probs]
18
+ print({"review": request.command, "sentiment": sentiment, "probs": probs})
19
+ return {"review": request.command, "sentiment": sentiment, "probs": probs}
20
+ except Exception as e:
21
+ raise HTTPException(status_code=500, detail=str(e))
backend/app/api/v1/schemas.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+ class QARequest(BaseModel):
4
+ command: str
5
+
6
+ class ConfigRequest(BaseModel):
7
+ model_name: str
backend/app/main.py ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from .api.v1 import qa, config
3
+
4
+ app = FastAPI()
5
+
6
+ # Include routers for the API
7
+ app.include_router(qa.router, prefix="/qa", tags=["qa"])
8
+ app.include_router(config.router, prefix="/config", tags=["config"])
9
+
10
+ if __name__ == "__main__":
11
+ import uvicorn
12
+ uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)
backend/app/models.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from transformers import AutoTokenizer, AutoModelForSequenceClassification
2
+ import torch
3
+ import os
4
+
5
+ model_name = "fine-tuned-model"
6
+ tokenizer = AutoTokenizer.from_pretrained(model_name, use_safetensors=True)
7
+ model = AutoModelForSequenceClassification.from_pretrained(model_name)
8
+
9
+ device = torch.device("cpu")
10
+
11
+ def predict_sentiment(review_text):
12
+ inputs = tokenizer(review_text, padding=True, truncation=True, return_tensors="pt").to(device)
13
+
14
+ with torch.no_grad():
15
+ outputs = model(**inputs)
16
+
17
+ logits = outputs.logits
18
+ predictions = torch.softmax(logits, dim=-1)
19
+
20
+ predicted_label = torch.argmax(predictions, dim=-1).item()
21
+ sentiment = "Positive" if predicted_label == 1 else "Negative"
22
+
23
+ return sentiment, predictions[0].cpu().numpy()
backend/app/schemas.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel
2
+
3
+ class QARequest(BaseModel):
4
+ command: str
5
+
6
+ class ConfigRequest(BaseModel):
7
+ model_name: str
backend/requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ fastapi==0.95.2
2
+ uvicorn==0.22.0
3
+ transformers==4.34.0
4
+ torch==2.3.1
5
+ pydantic==1.10.7
6
+ requests==2.31.0
backend/tests/__init__.py ADDED
File without changes
backend/tests/test_config.py ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+ from fastapi.testclient import TestClient
3
+ from backend.app.main import app
4
+
5
+ client = TestClient(app)
6
+
7
+ def test_configure_model():
8
+ response = client.post("/config/", json={"model_name": "distilbert-base-uncased-distilled-squad"})
9
+ assert response.status_code == 200
10
+ assert "message" in response.json()
backend/tests/test_qa.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pytest
2
+ from fastapi.testclient import TestClient
3
+ from backend.app.main import app
4
+
5
+ client = TestClient(app)
6
+
7
+ def test_get_answer():
8
+ response = client.post("/qa/", json={"context": "Hello world", "question": "What is this?"})
9
+ assert response.status_code == 200
10
+ assert "answer" in response.json()
11
+ assert "score" in response.json()
docker-compose.yml ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ version: '3.11'
2
+
3
+ services:
4
+ backend:
5
+ build:
6
+ context: ./backend
7
+ ports:
8
+ - "8000:8000"
9
+ volumes:
10
+ - ./backend:/app
11
+
12
+ frontend:
13
+ build:
14
+ context: ./frontend
15
+ ports:
16
+ - "8501:8501"
17
+ volumes:
18
+ - ./frontend:/app
19
+ environment:
20
+ - API_URL=http://0.0.0.0:8000
21
+ depends_on:
22
+ - backend
frontend/.streamlit/config.toml ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [theme]
2
+ base="dark"
3
+ primaryColor="#00b4ff"
4
+ backgroundColor="#000000"
frontend/Dockerfile ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.11-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+ RUN pip install --no-cache-dir -r requirements.txt
7
+
8
+ COPY app.py /app
9
+
10
+ CMD ["streamlit", "run", "app.py", "--server.port", "8501"]
frontend/README.md ADDED
File without changes
frontend/app.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import requests
3
+
4
+ API_URL = "http://localhost:8000"
5
+
6
+ st.title("BERT Fine Tuned Model on IMBD dataset")
7
+
8
+ st.header("try with reviews")
9
+ question = st.text_input("Review")
10
+
11
+ if st.button("Get Answer"):
12
+ if question:
13
+ print(f"{API_URL}/qa/")
14
+ response = requests.post(f"{API_URL}/qa/", json={"command": question})
15
+ if response.status_code == 200:
16
+ answer = response.json()
17
+ st.write(f"**Review**: {answer['review']}")
18
+ st.write(f"**Sentiment**: {answer['sentiment']}")
19
+ st.write(f"**Probs**: {answer['probs']}")
20
+ else:
21
+ st.error(f"Error: {response.json().get('detail', 'Unknown error')}")
22
+ else:
23
+ st.error("Please provide both context and question.")
frontend/requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ streamlit==1.37.0
2
+ pandas==2.2.2
3
+ requests==2.31.0
4
+
setup_template.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from pathlib import Path
3
+ import logging
4
+
5
+ logging.basicConfig(
6
+ level=logging.INFO,
7
+ format='[%(asctime)s]: %(message)s',
8
+ )
9
+
10
+ project_name = 'my_project'
11
+
12
+ list_of_files = [
13
+ # Backend
14
+ f"backend/app/__init__.py",
15
+ f"backend/app/main.py",
16
+ f"backend/app/models.py",
17
+ f"backend/app/schemas.py",
18
+ f"backend/app/api/__init__.py",
19
+ f"backend/app/api/v1/__init__.py",
20
+ f"backend/app/api/v1/qa.py",
21
+ f"backend/app/api/v1/config.py",
22
+ f"backend/tests/__init__.py",
23
+ f"backend/tests/test_qa.py",
24
+ f"backend/tests/test_config.py",
25
+ f"backend/Dockerfile",
26
+ f"backend/requirements.txt",
27
+ f"backend/README.md",
28
+
29
+ # Frontend
30
+ f"frontend/app.py",
31
+ f"frontend/Dockerfile",
32
+ f"frontend/requirements.txt",
33
+ f"frontend/README.md",
34
+
35
+ # Root
36
+ ".gitignore",
37
+ "README.md"
38
+ ]
39
+
40
+ for path in list_of_files:
41
+ file_path = Path(path)
42
+ filedir, filename = os.path.split(file_path)
43
+
44
+ if filedir != "":
45
+ os.makedirs(filedir, exist_ok=True)
46
+ logging.info(f"Created directory {filedir}")
47
+ if (not os.path.exists(file_path)) or (os.path.getsize(file_path) == 0):
48
+ with open(file_path, "w") as f:
49
+ pass
50
+ logging.info(f"Created file {filename}")
51
+ else:
52
+ logging.info(f"File {filename} already exists")