Spaces:
Running
Running
Update main.py
Browse files
main.py
CHANGED
@@ -7,7 +7,6 @@ from pydantic import BaseModel
|
|
7 |
from transformers import pipeline
|
8 |
from io import StringIO
|
9 |
import os, csv, logging
|
10 |
-
from openai import OpenAI
|
11 |
from model import summarize_review, smart_summarize
|
12 |
from typing import Optional
|
13 |
|
@@ -40,71 +39,7 @@ def custom_swagger_ui():
|
|
40 |
|
41 |
@app.get("/", response_class=HTMLResponse)
|
42 |
def root():
|
43 |
-
return ""
|
44 |
-
<html>
|
45 |
-
<head>
|
46 |
-
<title>NeuroPulse AI</title>
|
47 |
-
<style>
|
48 |
-
body {
|
49 |
-
font-family: 'Segoe UI', sans-serif;
|
50 |
-
background: linear-gradient(135deg, #f0f4ff, #fef3c7);
|
51 |
-
margin: 0;
|
52 |
-
padding: 60px;
|
53 |
-
text-align: center;
|
54 |
-
color: #1f2937;
|
55 |
-
}
|
56 |
-
.container {
|
57 |
-
background: white;
|
58 |
-
padding: 40px;
|
59 |
-
border-radius: 16px;
|
60 |
-
max-width: 800px;
|
61 |
-
margin: auto;
|
62 |
-
box-shadow: 0 10px 30px rgba(0,0,0,0.08);
|
63 |
-
animation: fadeIn 1s ease-in-out;
|
64 |
-
}
|
65 |
-
@keyframes fadeIn {
|
66 |
-
from {opacity: 0; transform: translateY(20px);}
|
67 |
-
to {opacity: 1; transform: translateY(0);}
|
68 |
-
}
|
69 |
-
h1 {
|
70 |
-
font-size: 36px;
|
71 |
-
margin-bottom: 12px;
|
72 |
-
color: #4f46e5;
|
73 |
-
}
|
74 |
-
p {
|
75 |
-
font-size: 18px;
|
76 |
-
margin-bottom: 32px;
|
77 |
-
}
|
78 |
-
.btn {
|
79 |
-
display: inline-block;
|
80 |
-
margin: 8px;
|
81 |
-
padding: 14px 24px;
|
82 |
-
border-radius: 8px;
|
83 |
-
font-weight: 600;
|
84 |
-
color: white;
|
85 |
-
text-decoration: none;
|
86 |
-
background: linear-gradient(90deg, #4f46e5, #6366f1);
|
87 |
-
transition: all 0.3s ease;
|
88 |
-
}
|
89 |
-
.btn:hover {
|
90 |
-
transform: translateY(-2px);
|
91 |
-
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
92 |
-
}
|
93 |
-
.btn.red {
|
94 |
-
background: linear-gradient(90deg, #dc2626, #ef4444);
|
95 |
-
}
|
96 |
-
</style>
|
97 |
-
</head>
|
98 |
-
<body>
|
99 |
-
<div class="container">
|
100 |
-
<h1>🧠 Welcome to <strong>NeuroPulse AI</strong></h1>
|
101 |
-
<p>Smarter AI feedback analysis — Summarization, Sentiment, Emotion, Aspects, LLM Q&A, and Metadata Tags.</p>
|
102 |
-
<a class="btn" href="/docs">📘 Swagger UI</a>
|
103 |
-
<a class="btn red" href="/redoc">📕 ReDoc</a>
|
104 |
-
</div>
|
105 |
-
</body>
|
106 |
-
</html>
|
107 |
-
"""
|
108 |
|
109 |
class ReviewInput(BaseModel):
|
110 |
text: str
|
@@ -114,6 +49,9 @@ class ReviewInput(BaseModel):
|
|
114 |
follow_up: Optional[str] = None
|
115 |
product_category: Optional[str] = None
|
116 |
device: Optional[str] = None
|
|
|
|
|
|
|
117 |
|
118 |
class BulkReviewInput(BaseModel):
|
119 |
reviews: list[str]
|
@@ -123,14 +61,6 @@ class BulkReviewInput(BaseModel):
|
|
123 |
product_category: Optional[list[str]] = None
|
124 |
device: Optional[list[str]] = None
|
125 |
|
126 |
-
class ChatInput(BaseModel):
|
127 |
-
question: str
|
128 |
-
context: str
|
129 |
-
|
130 |
-
class TranslationInput(BaseModel):
|
131 |
-
text: str
|
132 |
-
target_lang: str = "fr"
|
133 |
-
|
134 |
VALID_API_KEY = "my-secret-key"
|
135 |
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
136 |
|
@@ -178,7 +108,7 @@ async def bulk(data: BulkReviewInput, x_api_key: str = Header(None)):
|
|
178 |
return {"results": results}
|
179 |
|
180 |
@app.post("/analyze/")
|
181 |
-
async def analyze(request: Request, data: ReviewInput, x_api_key: str = Header(None)
|
182 |
if x_api_key != VALID_API_KEY:
|
183 |
raise HTTPException(status_code=401, detail="Invalid or missing API key")
|
184 |
|
@@ -203,7 +133,11 @@ async def analyze(request: Request, data: ReviewInput, x_api_key: str = Header(N
|
|
203 |
"score": asp_result["score"]
|
204 |
})
|
205 |
|
206 |
-
follow_up_response =
|
|
|
|
|
|
|
|
|
207 |
|
208 |
return {
|
209 |
"summary": summary,
|
@@ -211,33 +145,12 @@ async def analyze(request: Request, data: ReviewInput, x_api_key: str = Header(N
|
|
211 |
"emotion": emotion,
|
212 |
"aspects": aspects_list,
|
213 |
"follow_up": follow_up_response,
|
|
|
214 |
"product_category": auto_fill(data.product_category),
|
215 |
"device": auto_fill(data.device, "Web"),
|
216 |
"industry": auto_fill(data.industry)
|
217 |
}
|
218 |
|
219 |
-
@app.post("/translate/")
|
220 |
-
async def translate(data: TranslationInput):
|
221 |
-
translator = pipeline("translation", model=f"Helsinki-NLP/opus-mt-en-{data.target_lang}")
|
222 |
-
return {"translated_text": translator(data.text)[0]["translation_text"]}
|
223 |
-
|
224 |
-
@app.post("/chat/")
|
225 |
-
async def chat(input: ChatInput, x_api_key: str = Header(None)):
|
226 |
-
if x_api_key != VALID_API_KEY:
|
227 |
-
raise HTTPException(status_code=401, detail="Invalid or missing API key")
|
228 |
-
return {"response": chat_llm(input.question, input.context)}
|
229 |
-
|
230 |
-
def chat_llm(question, context):
|
231 |
-
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
232 |
-
res = client.chat.completions.create(
|
233 |
-
model="gpt-3.5-turbo",
|
234 |
-
messages=[
|
235 |
-
{"role": "system", "content": "You are a helpful AI review analyst."},
|
236 |
-
{"role": "user", "content": f"Context: {context}\nQuestion: {question}"}
|
237 |
-
]
|
238 |
-
)
|
239 |
-
return res.choices[0].message.content.strip()
|
240 |
-
|
241 |
def custom_openapi():
|
242 |
if app.openapi_schema:
|
243 |
return app.openapi_schema
|
|
|
7 |
from transformers import pipeline
|
8 |
from io import StringIO
|
9 |
import os, csv, logging
|
|
|
10 |
from model import summarize_review, smart_summarize
|
11 |
from typing import Optional
|
12 |
|
|
|
39 |
|
40 |
@app.get("/", response_class=HTMLResponse)
|
41 |
def root():
|
42 |
+
return open("app/static/index.html").read()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
|
44 |
class ReviewInput(BaseModel):
|
45 |
text: str
|
|
|
49 |
follow_up: Optional[str] = None
|
50 |
product_category: Optional[str] = None
|
51 |
device: Optional[str] = None
|
52 |
+
intelligence: Optional[bool] = False
|
53 |
+
verbosity: Optional[str] = "detailed"
|
54 |
+
explain: Optional[bool] = False
|
55 |
|
56 |
class BulkReviewInput(BaseModel):
|
57 |
reviews: list[str]
|
|
|
61 |
product_category: Optional[list[str]] = None
|
62 |
device: Optional[list[str]] = None
|
63 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
64 |
VALID_API_KEY = "my-secret-key"
|
65 |
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
66 |
|
|
|
108 |
return {"results": results}
|
109 |
|
110 |
@app.post("/analyze/")
|
111 |
+
async def analyze(request: Request, data: ReviewInput, x_api_key: str = Header(None)):
|
112 |
if x_api_key != VALID_API_KEY:
|
113 |
raise HTTPException(status_code=401, detail="Invalid or missing API key")
|
114 |
|
|
|
133 |
"score": asp_result["score"]
|
134 |
})
|
135 |
|
136 |
+
follow_up_response = None
|
137 |
+
if data.follow_up and data.intelligence:
|
138 |
+
follow_up_response = f"[Mocked Detailed Answer in {data.verbosity} mode]"
|
139 |
+
|
140 |
+
explanation = "This summary was generated using transformer-based sequence modeling and contextual keyword expansion." if data.explain else None
|
141 |
|
142 |
return {
|
143 |
"summary": summary,
|
|
|
145 |
"emotion": emotion,
|
146 |
"aspects": aspects_list,
|
147 |
"follow_up": follow_up_response,
|
148 |
+
"explanation": explanation,
|
149 |
"product_category": auto_fill(data.product_category),
|
150 |
"device": auto_fill(data.device, "Web"),
|
151 |
"industry": auto_fill(data.industry)
|
152 |
}
|
153 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
def custom_openapi():
|
155 |
if app.openapi_schema:
|
156 |
return app.openapi_schema
|