gouravbhadraDev commited on
Commit
6c0215b
·
verified ·
1 Parent(s): 3dd92d3

Upload 3 files

Browse files
Files changed (3) hide show
  1. Dockerfile +13 -0
  2. app.py +74 -0
  3. requirements.txt +7 -0
Dockerfile ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.10-slim
2
+
3
+ WORKDIR /app
4
+
5
+ COPY requirements.txt .
6
+
7
+ RUN pip install --no-cache-dir -r requirements.txt
8
+
9
+ COPY app.py .
10
+
11
+ EXPOSE 7860
12
+
13
+ CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, Query
2
+ from pydantic import BaseModel
3
+ import cloudscraper
4
+ from bs4 import BeautifulSoup
5
+ from transformers import AutoTokenizer, AutoModelForCausalLM
6
+ import torch
7
+ import re
8
+ import os
9
+ os.environ["TRANSFORMERS_CACHE"] = "/tmp/.cache"
10
+ os.environ["HF_HOME"] = "/tmp/.cache"
11
+ os.environ["HF_DATASETS_CACHE"] = "/tmp/.cache"
12
+
13
+ app = FastAPI()
14
+
15
+ class ThreadResponse(BaseModel):
16
+ question: str
17
+ replies: list[str]
18
+
19
+ def clean_text(text: str) -> str:
20
+ text = text.strip()
21
+ text = re.sub(r"\b\d+\s*likes?,?\s*\d*\s*replies?$", "", text, flags=re.IGNORECASE).strip()
22
+ return text
23
+
24
+ @app.get("/scrape", response_model=ThreadResponse)
25
+ def scrape(url: str = Query(...)):
26
+ scraper = cloudscraper.create_scraper()
27
+ response = scraper.get(url)
28
+
29
+ if response.status_code == 200:
30
+ soup = BeautifulSoup(response.content, 'html.parser')
31
+ comment_containers = soup.find_all('div', class_='post__content')
32
+
33
+ if comment_containers:
34
+ question = clean_text(comment_containers[0].get_text(strip=True, separator="\n"))
35
+ replies = [clean_text(comment.get_text(strip=True, separator="\n")) for comment in comment_containers[1:]]
36
+ return ThreadResponse(question=question, replies=replies)
37
+ return ThreadResponse(question="", replies=[])
38
+
39
+
40
+ MODEL_NAME = "sarvamai/sarvam-m"
41
+
42
+ # Load tokenizer and model once at startup, with device auto-mapping
43
+ tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
44
+ model = AutoModelForCausalLM.from_pretrained(MODEL_NAME, torch_dtype="auto", device_map="auto")
45
+ model.eval()
46
+
47
+ class PromptRequest(BaseModel):
48
+ prompt: str
49
+
50
+ @app.post("/generate")
51
+ async def generate_text(request: PromptRequest):
52
+ # Prepare chat-style input with thinking mode enabled
53
+ messages = [{"role": "user", "content": request.prompt}]
54
+ text = tokenizer.apply_chat_template(messages, tokenize=False, enable_thinking=True)
55
+
56
+ inputs = tokenizer([text], return_tensors="pt").to(model.device)
57
+ with torch.no_grad():
58
+ generated_ids = model.generate(**inputs, max_new_tokens=512, temperature=0.5)
59
+ output_ids = generated_ids[:, inputs.input_ids.shape[-1]:].tolist()[0]
60
+ output_text = tokenizer.decode(output_ids)
61
+
62
+ # Extract reasoning and content parts if thinking tags are present
63
+ if "</think>" in output_text:
64
+ reasoning_content = output_text.split("</think>")[0].strip()
65
+ content = output_text.split("</think>")[1].strip().rstrip("</s>")
66
+ else:
67
+ reasoning_content = ""
68
+ content = output_text.strip().rstrip("</s>")
69
+
70
+ return {
71
+ "reasoning_content": reasoning_content,
72
+ "generated_text": content
73
+ }
74
+
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn[standard]
3
+ cloudscraper
4
+ beautifulsoup4
5
+ pydantic
6
+ torch
7
+ transformers