Spaces:
Paused
Paused
Upload 7 files
Browse files- Dockerfile +34 -0
- app.py +17 -0
- config.js +15 -0
- index.js +74 -0
- model.py +32 -0
- package.json +14 -0
- requirements.txt +4 -0
Dockerfile
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM mcr.microsoft.com/devcontainers/javascript-node:0-18-bullseye
|
| 2 |
+
|
| 3 |
+
RUN apt-get update && apt-get install -y \
|
| 4 |
+
chromium chromium-driver \
|
| 5 |
+
fonts-liberation libappindicator3-1 \
|
| 6 |
+
libasound2 libatk-bridge2.0-0 libatk1.0-0 libcups2 libdbus-1-3 \
|
| 7 |
+
libgdk-pixbuf2.0-0 libnspr4 libnss3 libx11-xcb1 libxcomposite1 \
|
| 8 |
+
libxdamage1 libxrandr2 xdg-utils libu2f-udev libvulkan1 \
|
| 9 |
+
libxcb-dri3-0 libxshmfence1 libxss1 libgbm1 \
|
| 10 |
+
python3 python3-pip \
|
| 11 |
+
--no-install-recommends && \
|
| 12 |
+
apt-get clean && rm -rf /var/lib/apt/lists/*
|
| 13 |
+
|
| 14 |
+
# Set working directory
|
| 15 |
+
WORKDIR /workspace
|
| 16 |
+
|
| 17 |
+
# Copy package files and install
|
| 18 |
+
COPY package*.json ./
|
| 19 |
+
RUN npm install
|
| 20 |
+
|
| 21 |
+
# Copy Python app and install Python deps
|
| 22 |
+
COPY requirements.txt .
|
| 23 |
+
RUN pip install -r requirements.txt
|
| 24 |
+
|
| 25 |
+
# Copy rest of the files
|
| 26 |
+
COPY . .
|
| 27 |
+
|
| 28 |
+
# Make Chromium usable by Puppeteer
|
| 29 |
+
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
|
| 30 |
+
|
| 31 |
+
# Hugging Face exposes port 7860 or 3000
|
| 32 |
+
EXPOSE 7860
|
| 33 |
+
# Run both wa-automate and FastAPI
|
| 34 |
+
CMD uvicorn app:app --host 0.0.0.0 --port 7860
|
app.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, Body
|
| 2 |
+
from model import AdsMod
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
MODEL_PRETRAINED_PATH = "venishpatidar/wa-ad-mod"
|
| 6 |
+
|
| 7 |
+
app = FastAPI()
|
| 8 |
+
model = AdsMod(MODEL_PRETRAINED_PATH)
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
@app.get("/")
|
| 12 |
+
def greet_json()->None:
|
| 13 |
+
return "Hello from Ad-Mod"
|
| 14 |
+
|
| 15 |
+
@app.post("/classify")
|
| 16 |
+
def classify_text(input:str=Body(...))->None:
|
| 17 |
+
return model.predict(input)
|
config.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
module.exports = {
|
| 2 |
+
LAUNCH_CONFIG:{
|
| 3 |
+
qrTimeout: 0, // infinite time for QR
|
| 4 |
+
authTimeout: 60, // seconds
|
| 5 |
+
headless: true,
|
| 6 |
+
useChrome: false,
|
| 7 |
+
killProcessOnBrowserClose: true,
|
| 8 |
+
deleteSessionDataOnLogout: false,
|
| 9 |
+
cacheEnabled: false,
|
| 10 |
+
sessionId: 'hr',
|
| 11 |
+
skipSessionSave:true,
|
| 12 |
+
autoRefresh:true
|
| 13 |
+
},
|
| 14 |
+
LLM_URL:"http://127.0.0.1:7860/classify"
|
| 15 |
+
};
|
index.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
const { create } = require('@open-wa/wa-automate');
|
| 2 |
+
const { LAUNCH_CONFIG, LLM_URL } = require('./config')
|
| 3 |
+
|
| 4 |
+
// Only process message having length more then 46
|
| 5 |
+
const WORD_LEN_TRSH = 46;
|
| 6 |
+
const STATUS_KEYWORD = "Hi :status"
|
| 7 |
+
const CLEAR_INTERVAL = 12 * 60 * 1000; // 12 hours in milliseconds
|
| 8 |
+
|
| 9 |
+
function start(client) {
|
| 10 |
+
client.onMessage(async message => {
|
| 11 |
+
const messageId = message.id;
|
| 12 |
+
const from = message.from // If from group from contains group id else author id
|
| 13 |
+
const text = message.body
|
| 14 |
+
const author = message.author // Author and from can be different in case of group;
|
| 15 |
+
const message_type = message.type
|
| 16 |
+
|
| 17 |
+
if (text===STATUS_KEYWORD){
|
| 18 |
+
await client.sendText(from, 'Hello 👋, my system is online and running smoothly.');
|
| 19 |
+
}
|
| 20 |
+
// Calling the LLM api to analyze the text
|
| 21 |
+
if(message_type==="chat" && text.length>=WORD_LEN_TRSH){
|
| 22 |
+
|
| 23 |
+
let msg = await fetch(
|
| 24 |
+
LLM_URL,{
|
| 25 |
+
method:"POST",
|
| 26 |
+
body: JSON.stringify({ input: text })
|
| 27 |
+
})
|
| 28 |
+
let response = await msg.json()
|
| 29 |
+
|
| 30 |
+
// await client.sendText(from, response===0?"Safe":"Ad");
|
| 31 |
+
|
| 32 |
+
if(response){
|
| 33 |
+
try{
|
| 34 |
+
await client.deleteMessage(messageId);
|
| 35 |
+
// For debugging purpose
|
| 36 |
+
// await client.sendText(from, 'Chat deleted successfully.');
|
| 37 |
+
|
| 38 |
+
/* Commenting this as cant send message to a user until its in contact*/
|
| 39 |
+
// Sending the sender that you have sent Ad message in wrong group
|
| 40 |
+
// await client.sendText(author, 'Please donot send Ads to the support group.');
|
| 41 |
+
|
| 42 |
+
}
|
| 43 |
+
catch (error) {
|
| 44 |
+
console.error('[X] Log: Failed to delete chat error:', error);
|
| 45 |
+
}
|
| 46 |
+
}
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
else{
|
| 50 |
+
// Handle for not message type == chat
|
| 51 |
+
}
|
| 52 |
+
}); // End of Client.onMeassage
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
// Clears all the chat after CLEAR_INTERVAL time period
|
| 57 |
+
// setTimeout(async () => {
|
| 58 |
+
// try {
|
| 59 |
+
// const success = await client.clearAllChats();
|
| 60 |
+
// if (success) {
|
| 61 |
+
// console.log('[+] All chats cleared.');
|
| 62 |
+
// }
|
| 63 |
+
// else {
|
| 64 |
+
// console.log('[X] Failed to clear chats.');
|
| 65 |
+
// }
|
| 66 |
+
// }
|
| 67 |
+
// catch (error) {
|
| 68 |
+
// console.error('[X] Failed to clear chats:', error);
|
| 69 |
+
// }
|
| 70 |
+
// }, CLEAR_INTERVAL);
|
| 71 |
+
}
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
create(LAUNCH_CONFIG).then(start);
|
model.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from transformers import AutoConfig, AutoModelForSequenceClassification, AutoTokenizer
|
| 2 |
+
import torch
|
| 3 |
+
|
| 4 |
+
class AdsMod:
|
| 5 |
+
"""
|
| 6 |
+
Model init method
|
| 7 |
+
base model used = bloom-560m
|
| 8 |
+
model_path: takes the path of saved model weights
|
| 9 |
+
"""
|
| 10 |
+
def __init__(self,model_path:str="./") -> None:
|
| 11 |
+
self.model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
| 12 |
+
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
| 13 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 14 |
+
self.tokenize = lambda input: tokenizer(input, truncation=True, padding="max_length", max_length=256,return_tensors="pt").to(device)
|
| 15 |
+
self.model.to(device)
|
| 16 |
+
|
| 17 |
+
"""
|
| 18 |
+
predict
|
| 19 |
+
takes text as input and classifies the text
|
| 20 |
+
returns 0 or 1
|
| 21 |
+
"""
|
| 22 |
+
def predict(self,text:str) -> int:
|
| 23 |
+
input = self.tokenize(text)
|
| 24 |
+
with torch.no_grad():
|
| 25 |
+
output = self.model(**input)
|
| 26 |
+
predicted_class = torch.argmax(output.logits, dim=1).item()
|
| 27 |
+
return predicted_class
|
| 28 |
+
|
| 29 |
+
if __name__=="__main__":
|
| 30 |
+
model = AdsMod('venishpatidar/wa-ad-mod')
|
| 31 |
+
text = "Hi I am text classifier, will help you in deleteing housing ads message"
|
| 32 |
+
print("Ad" if model.predict(text) else "Safe")
|
package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
{
|
| 2 |
+
"name": "wa-automate",
|
| 3 |
+
"version": "1.0.0",
|
| 4 |
+
"description": "",
|
| 5 |
+
"main": "index.js",
|
| 6 |
+
"scripts": {
|
| 7 |
+
"test": "echo \"Error: no test specified\" && exit 1"
|
| 8 |
+
},
|
| 9 |
+
"dependencies": {
|
| 10 |
+
"@open-wa/wa-automate": "^4.76.0"
|
| 11 |
+
},
|
| 12 |
+
"author": "venish",
|
| 13 |
+
"license": "ISC"
|
| 14 |
+
}
|
requirements.txt
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
fastapi
|
| 2 |
+
uvicorn
|
| 3 |
+
transformers
|
| 4 |
+
torch
|