viskav commited on
Commit
8391e3e
Β·
verified Β·
1 Parent(s): c7a85a9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -56
app.py CHANGED
@@ -2,29 +2,36 @@ from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from pydantic import BaseModel, Field
4
  from llama_cpp import Llama
 
5
  import re
6
 
7
- # ==================== MODEL CONFIG ====================
8
  MODEL_REPO = "bartowski/Phi-3.5-mini-instruct-GGUF"
9
  MODEL_FILE = "Phi-3.5-mini-instruct-Q4_K_M.gguf"
10
 
11
- print("πŸš€ Loading Phi-3.5 Mini (Fast Summarizer)...")
12
- llm = Llama.from_pretrained(
13
- repo_id=MODEL_REPO,
14
- filename=MODEL_FILE,
15
- n_threads=4,
16
- n_ctx=2048, # Enough for summarization
17
- n_batch=256,
18
- n_gpu_layers=0,
19
- verbose=False,
20
- )
21
- print("βœ… Model loaded")
 
 
 
 
 
 
 
22
 
23
- # ==================== FASTAPI ====================
24
  app = FastAPI(
25
  title="AI Summarizer",
26
  description="Fast & Accurate AI Text Summarizer",
27
- version="1.0"
 
28
  )
29
 
30
  app.add_middleware(
@@ -34,70 +41,54 @@ app.add_middleware(
34
  allow_headers=["*"],
35
  )
36
 
37
- # ==================== REQUEST ====================
38
  class SummarizeRequest(BaseModel):
39
  text: str = Field(..., min_length=1, max_length=2000)
40
- length: str = "short" # short | medium | long
41
 
42
- # ==================== PROMPTS ====================
43
  LENGTH_INSTRUCTIONS = {
44
  "short": "Summarize in 2–3 concise sentences.",
45
  "medium": "Summarize in 4–5 clear sentences.",
46
  "long": "Summarize in a detailed paragraph.",
47
  }
48
 
49
- # ==================== CLEAN OUTPUT ====================
50
  def clean_output(text: str) -> str:
51
  text = re.sub(r"<\|.*?\|>", "", text)
52
  text = re.sub(r"\s+", " ", text)
53
  return text.strip()
54
 
55
- # ==================== ENDPOINT ====================
56
  @app.post("/api/summarize")
57
  async def summarize(req: SummarizeRequest):
58
- text = req.text.strip()
59
- if not text:
60
- raise HTTPException(status_code=400, detail="Text cannot be empty")
61
 
 
62
  length_instruction = LENGTH_INSTRUCTIONS.get(req.length, LENGTH_INSTRUCTIONS["short"])
63
 
64
- prompt = (
65
- f"<|user|>\n"
66
- f"You are an expert text summarizer.\n"
67
- f"{length_instruction}\n\n"
68
- f"Text:\n{text}\n"
69
- f"<|end|>\n"
70
- f"<|assistant|>\n"
 
 
 
 
 
 
 
 
 
 
 
 
71
  )
72
 
73
- try:
74
- output = llm(
75
- prompt,
76
- max_tokens=140 if req.length == "short" else 220,
77
- temperature=0.3, # Low = factual
78
- top_p=0.9,
79
- top_k=40,
80
- repeat_penalty=1.05,
81
- stop=["<|end|>", "<|user|>"],
82
- echo=False,
83
- )
84
-
85
- summary = clean_output(output["choices"][0]["text"])
86
-
87
- if not summary:
88
- raise RuntimeError("Empty summary")
89
-
90
- return {
91
- "original_length": len(text),
92
- "summary": summary,
93
- "length": req.length,
94
- "success": True
95
- }
96
-
97
- except Exception as e:
98
- print("❌ Summarization error:", e)
99
- raise HTTPException(status_code=500, detail="Summarization failed")
100
 
101
  @app.get("/")
102
  def health():
103
  return {"status": "ok", "model": MODEL_FILE}
 
 
2
  from fastapi.middleware.cors import CORSMiddleware
3
  from pydantic import BaseModel, Field
4
  from llama_cpp import Llama
5
+ from contextlib import asynccontextmanager
6
  import re
7
 
 
8
  MODEL_REPO = "bartowski/Phi-3.5-mini-instruct-GGUF"
9
  MODEL_FILE = "Phi-3.5-mini-instruct-Q4_K_M.gguf"
10
 
11
+ llm = None # global reference
12
+
13
+ @asynccontextmanager
14
+ async def lifespan(app: FastAPI):
15
+ global llm
16
+ print("πŸš€ Loading Phi-3.5 Mini (Fast Summarizer)...")
17
+ llm = Llama.from_pretrained(
18
+ repo_id=MODEL_REPO,
19
+ filename=MODEL_FILE,
20
+ n_threads=4,
21
+ n_ctx=2048,
22
+ n_batch=256,
23
+ n_gpu_layers=0,
24
+ verbose=False,
25
+ )
26
+ print("βœ… Model loaded")
27
+ yield
28
+ print("πŸ›‘ Shutting down...")
29
 
 
30
  app = FastAPI(
31
  title="AI Summarizer",
32
  description="Fast & Accurate AI Text Summarizer",
33
+ version="1.0",
34
+ lifespan=lifespan
35
  )
36
 
37
  app.add_middleware(
 
41
  allow_headers=["*"],
42
  )
43
 
 
44
  class SummarizeRequest(BaseModel):
45
  text: str = Field(..., min_length=1, max_length=2000)
46
+ length: str = "short"
47
 
 
48
  LENGTH_INSTRUCTIONS = {
49
  "short": "Summarize in 2–3 concise sentences.",
50
  "medium": "Summarize in 4–5 clear sentences.",
51
  "long": "Summarize in a detailed paragraph.",
52
  }
53
 
 
54
  def clean_output(text: str) -> str:
55
  text = re.sub(r"<\|.*?\|>", "", text)
56
  text = re.sub(r"\s+", " ", text)
57
  return text.strip()
58
 
 
59
  @app.post("/api/summarize")
60
  async def summarize(req: SummarizeRequest):
61
+ if llm is None:
62
+ raise HTTPException(status_code=503, detail="Model not loaded")
 
63
 
64
+ text = req.text.strip()
65
  length_instruction = LENGTH_INSTRUCTIONS.get(req.length, LENGTH_INSTRUCTIONS["short"])
66
 
67
+ prompt = f"""
68
+ <|user|>
69
+ You are an expert text summarizer.
70
+ {length_instruction}
71
+
72
+ Text:
73
+ {text}
74
+ <|end|>
75
+ <|assistant|>
76
+ """
77
+
78
+ output = llm(
79
+ prompt,
80
+ max_tokens=140 if req.length == "short" else 220,
81
+ temperature=0.3,
82
+ top_p=0.9,
83
+ top_k=40,
84
+ repeat_penalty=1.05,
85
+ stop=["<|end|>", "<|user|>"],
86
  )
87
 
88
+ summary = clean_output(output["choices"][0]["text"])
89
+ return {"summary": summary, "success": True}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
 
91
  @app.get("/")
92
  def health():
93
  return {"status": "ok", "model": MODEL_FILE}
94
+