Spaces:
Sleeping
Sleeping
Update app.py
#1
by
luck210
- opened
app.py
CHANGED
@@ -119,20 +119,29 @@ def get_chatbot_response(user_input: str):
|
|
119 |
except Exception as e:
|
120 |
return f"Error: {str(e)}"
|
121 |
|
122 |
-
def translate_text(text: str, target_language: str):
|
123 |
-
"""Translate text to
|
124 |
if not text:
|
125 |
return "Please provide text to translate."
|
|
|
|
|
|
|
126 |
try:
|
127 |
translator = load_model("translation")
|
128 |
-
|
|
|
129 |
response = translator.generate_content(prompt)
|
|
|
|
|
|
|
|
|
130 |
return response.text.strip()
|
131 |
except Exception as e:
|
|
|
132 |
return f"Translation error: {str(e)}"
|
133 |
|
134 |
def detect_intent(text: str = None, file: UploadFile = None) -> tuple[str, str]:
|
135 |
-
"""Enhanced intent detection with
|
136 |
target_language = "English" # Default
|
137 |
|
138 |
if file:
|
@@ -156,12 +165,13 @@ def detect_intent(text: str = None, file: UploadFile = None) -> tuple[str, str]:
|
|
156 |
if any(keyword in text_lower for keyword in ['chat', 'talk', 'converse', 'ask gemini']):
|
157 |
return "chatbot", target_language
|
158 |
|
159 |
-
#
|
160 |
-
translate_match = re.search(r'translate.*to\s+\[?([a-zA-Z]+)\]?:?', text_lower)
|
161 |
if translate_match:
|
162 |
-
target_language = translate_match.group(1).capitalize()
|
163 |
return "translate", target_language
|
164 |
|
|
|
165 |
vqa_patterns = [
|
166 |
r'how (many|much)',
|
167 |
r'what (color|size|position|shape)',
|
@@ -173,40 +183,9 @@ def detect_intent(text: str = None, file: UploadFile = None) -> tuple[str, str]:
|
|
173 |
if any(re.search(pattern, text_lower) for pattern in vqa_patterns):
|
174 |
return "visual-qa", target_language
|
175 |
|
176 |
-
|
177 |
-
r'\b(summar(y|ize|ise)|brief( overview)?)\b',
|
178 |
-
r'\b(long article|text|document)\b',
|
179 |
-
r'\bcan you (summar|brief|condense)\b',
|
180 |
-
r'\b(short summary|brief explanation)\b',
|
181 |
-
r'\b(overview|main points|key ideas)\b',
|
182 |
-
r'\b(tl;?dr|too long didn\'?t read)\b'
|
183 |
-
]
|
184 |
-
|
185 |
-
if any(re.search(pattern, text_lower) for pattern in summarization_patterns):
|
186 |
-
return "summarize", target_language
|
187 |
-
|
188 |
-
question_patterns = [
|
189 |
-
r'\b(what|when|where|why|how|who|which)\b',
|
190 |
-
r'\?',
|
191 |
-
r'\b(explain|tell me|describe|define)\b'
|
192 |
-
]
|
193 |
-
|
194 |
-
if any(re.search(pattern, text_lower) for pattern in question_patterns):
|
195 |
-
return "question-answering", target_language
|
196 |
-
|
197 |
-
generation_patterns = [
|
198 |
-
r'\b(write|generate|create|compose)\b',
|
199 |
-
r'\b(story|poem|essay|text|content)\b'
|
200 |
-
]
|
201 |
-
|
202 |
-
if any(re.search(pattern, text_lower) for pattern in generation_patterns):
|
203 |
-
return "text-generation", target_language
|
204 |
-
|
205 |
-
if len(text) > 100:
|
206 |
-
return "summarize", target_language
|
207 |
|
208 |
return "chatbot", target_language
|
209 |
-
|
210 |
class ProcessResponse(BaseModel):
|
211 |
response: str
|
212 |
type: str
|
@@ -309,14 +288,8 @@ async def process_input(
|
|
309 |
text: str = Form(None),
|
310 |
file: UploadFile = File(None)
|
311 |
):
|
312 |
-
|
313 |
-
|
314 |
-
client_ip = request.client.host
|
315 |
-
logger.info(f"Request from {client_ip}: text={text[:50] + '...' if text and len(text) > 50 else text}, file={file.filename if file else None}")
|
316 |
-
|
317 |
-
intent, target_language = detect_intent(text, file)
|
318 |
-
logger.info(f"Detected intent: {intent}, target_language: {target_language}")
|
319 |
-
|
320 |
try:
|
321 |
if intent == "chatbot":
|
322 |
response = get_chatbot_response(text)
|
@@ -324,156 +297,32 @@ async def process_input(
|
|
324 |
|
325 |
elif intent == "translate":
|
326 |
content = await extract_text_from_file(file) if file else text
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
chunks = [content[i:i+1024] for i in range(0, len(content), 1024)]
|
341 |
-
summaries = []
|
342 |
-
|
343 |
-
for chunk in chunks[:3]:
|
344 |
-
summary = summarizer(
|
345 |
-
chunk,
|
346 |
-
max_length=max_len,
|
347 |
-
min_length=min_len,
|
348 |
-
do_sample=False,
|
349 |
-
truncation=True
|
350 |
-
)
|
351 |
-
summaries.append(summary[0]['summary_text'])
|
352 |
|
353 |
-
|
354 |
-
else:
|
355 |
-
summary = summarizer(
|
356 |
-
content,
|
357 |
-
max_length=max_len,
|
358 |
-
min_length=min_len,
|
359 |
-
do_sample=False,
|
360 |
-
truncation=True
|
361 |
-
)
|
362 |
-
final_summary = summary[0]['summary_text']
|
363 |
-
|
364 |
-
final_summary = re.sub(r'\s+', ' ', final_summary).strip()
|
365 |
-
return {"response": final_summary, "type": "summary"}
|
366 |
-
|
367 |
-
elif intent == "question-answering":
|
368 |
-
context = await extract_text_from_file(file) if file else None
|
369 |
-
|
370 |
-
if not context and not text:
|
371 |
-
raise HTTPException(status_code=400, detail="No context provided")
|
372 |
-
|
373 |
-
qa_pipeline = load_model("question-answering")
|
374 |
-
|
375 |
-
if not context and "?" in text:
|
376 |
-
parts = text.split("?", 1)
|
377 |
-
question = parts[0] + "?"
|
378 |
-
context = parts[1].strip() if len(parts) > 1 and parts[1].strip() else text
|
379 |
-
else:
|
380 |
-
question = text if text else "Summarize this document"
|
381 |
-
|
382 |
-
result = qa_pipeline(
|
383 |
-
question=question,
|
384 |
-
context=context[:2000] if context else text[:2000]
|
385 |
-
)
|
386 |
-
|
387 |
-
return {"response": result["answer"], "type": "answer"}
|
388 |
-
|
389 |
-
elif intent == "image-to-text":
|
390 |
-
if not file or not file.content_type.startswith('image/'):
|
391 |
-
raise HTTPException(status_code=400, detail="An image file is required")
|
392 |
-
|
393 |
-
image = Image.open(io.BytesIO(await file.read()))
|
394 |
-
captioner = load_model("image-to-text")
|
395 |
-
|
396 |
-
caption = captioner(image, max_new_tokens=50)
|
397 |
-
|
398 |
-
return {"response": caption[0]['generated_text'], "type": "caption"}
|
399 |
-
|
400 |
-
elif intent == "visual-qa":
|
401 |
-
if not file or not file.content_type.startswith('image/'):
|
402 |
-
raise HTTPException(status_code=400, detail="An image file is required")
|
403 |
-
if not text:
|
404 |
-
raise HTTPException(status_code=400, detail="A question is required for VQA")
|
405 |
-
|
406 |
-
image = Image.open(io.BytesIO(await file.read())).convert("RGB")
|
407 |
-
vqa_pipeline = load_model("visual-qa")
|
408 |
-
|
409 |
-
question = text.strip()
|
410 |
-
if not question.endswith('?'):
|
411 |
-
question += '?'
|
412 |
-
|
413 |
-
answer = vqa_pipeline(
|
414 |
-
image=image,
|
415 |
-
question=question
|
416 |
-
)
|
417 |
-
|
418 |
-
answer = answer.strip()
|
419 |
-
if not answer or answer.lower() == question.lower():
|
420 |
-
logger.warning(f"VQA failed to generate a meaningful answer: {answer}")
|
421 |
-
answer = "I couldn't determine the answer from the image."
|
422 |
-
else:
|
423 |
-
answer = answer.capitalize()
|
424 |
-
if not answer.endswith(('.', '!', '?')):
|
425 |
-
answer += '.'
|
426 |
-
|
427 |
-
logger.info(f"Final VQA answer: {answer}")
|
428 |
-
|
429 |
return {
|
430 |
-
"response":
|
431 |
-
"type": "
|
432 |
"additional_data": {
|
433 |
-
"
|
434 |
-
"
|
435 |
}
|
436 |
}
|
437 |
-
|
438 |
-
elif intent == "visualize":
|
439 |
-
if not file:
|
440 |
-
raise HTTPException(status_code=400, detail="An Excel file is required")
|
441 |
-
|
442 |
-
file_content = await file.read()
|
443 |
-
|
444 |
-
if file.filename.endswith('.csv'):
|
445 |
-
df = pd.read_csv(io.BytesIO(file_content))
|
446 |
-
else:
|
447 |
-
df = pd.read_excel(io.BytesIO(file_content))
|
448 |
-
|
449 |
-
code = generate_visualization_code(df, text)
|
450 |
-
|
451 |
-
return {"response": code, "type": "visualization_code"}
|
452 |
-
|
453 |
-
elif intent == "text-generation":
|
454 |
-
generator = load_model("text-generation")
|
455 |
|
456 |
-
|
457 |
-
|
458 |
-
max_length=200,
|
459 |
-
num_return_sequences=1,
|
460 |
-
temperature=0.8,
|
461 |
-
top_p=0.92,
|
462 |
-
do_sample=True
|
463 |
-
)
|
464 |
-
|
465 |
-
return {"response": generated[0]["generated_text"], "type": "generated_text"}
|
466 |
-
|
467 |
-
else:
|
468 |
-
response = get_chatbot_response(text or "Hello! How can I assist you?")
|
469 |
-
return {"response": response, "type": "chat"}
|
470 |
-
|
471 |
-
except Exception as e:
|
472 |
-
logger.error(f"Processing error: {str(e)}", exc_info=True)
|
473 |
-
raise HTTPException(status_code=500, detail=str(e))
|
474 |
-
finally:
|
475 |
-
process_time = time.time() - start_time
|
476 |
-
logger.info(f"Request processed in {process_time:.2f} seconds")
|
477 |
|
478 |
async def extract_text_from_file(file: UploadFile) -> str:
|
479 |
"""Enhanced text extraction with better error handling and format support"""
|
|
|
119 |
except Exception as e:
|
120 |
return f"Error: {str(e)}"
|
121 |
|
122 |
+
def translate_text(text: str, target_language: str) -> str:
|
123 |
+
"""Translate text to target language using Gemini with improved error handling"""
|
124 |
if not text:
|
125 |
return "Please provide text to translate."
|
126 |
+
if not target_language:
|
127 |
+
return "Please specify a target language."
|
128 |
+
|
129 |
try:
|
130 |
translator = load_model("translation")
|
131 |
+
# Enhanced prompt with clearer instructions
|
132 |
+
prompt = f"Translate the following text to {target_language}. Only provide the translated text without any additional commentary: {text}"
|
133 |
response = translator.generate_content(prompt)
|
134 |
+
|
135 |
+
if not response.text or response.text.strip() == text:
|
136 |
+
return f"Translation to {target_language} failed or produced no change."
|
137 |
+
|
138 |
return response.text.strip()
|
139 |
except Exception as e:
|
140 |
+
logger.error(f"Translation error: {str(e)}")
|
141 |
return f"Translation error: {str(e)}"
|
142 |
|
143 |
def detect_intent(text: str = None, file: UploadFile = None) -> tuple[str, str]:
|
144 |
+
"""Enhanced intent detection with improved translation handling"""
|
145 |
target_language = "English" # Default
|
146 |
|
147 |
if file:
|
|
|
165 |
if any(keyword in text_lower for keyword in ['chat', 'talk', 'converse', 'ask gemini']):
|
166 |
return "chatbot", target_language
|
167 |
|
168 |
+
# Improved translation detection
|
169 |
+
translate_match = re.search(r'translate.*to\s+\[?([a-zA-Z\s]+)\]?:?', text_lower)
|
170 |
if translate_match:
|
171 |
+
target_language = translate_match.group(1).strip().capitalize()
|
172 |
return "translate", target_language
|
173 |
|
174 |
+
# Rest of the function remains the same...
|
175 |
vqa_patterns = [
|
176 |
r'how (many|much)',
|
177 |
r'what (color|size|position|shape)',
|
|
|
183 |
if any(re.search(pattern, text_lower) for pattern in vqa_patterns):
|
184 |
return "visual-qa", target_language
|
185 |
|
186 |
+
# ... remaining patterns ...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
187 |
|
188 |
return "chatbot", target_language
|
|
|
189 |
class ProcessResponse(BaseModel):
|
190 |
response: str
|
191 |
type: str
|
|
|
288 |
text: str = Form(None),
|
289 |
file: UploadFile = File(None)
|
290 |
):
|
291 |
+
# ... previous code ...
|
292 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
293 |
try:
|
294 |
if intent == "chatbot":
|
295 |
response = get_chatbot_response(text)
|
|
|
297 |
|
298 |
elif intent == "translate":
|
299 |
content = await extract_text_from_file(file) if file else text
|
300 |
+
if not content:
|
301 |
+
raise HTTPException(status_code=400, detail="No content to translate")
|
302 |
+
|
303 |
+
# Clean the input text from translation command
|
304 |
+
content_to_translate = re.sub(
|
305 |
+
r'translate.*to\s+\[?[a-zA-Z\s]+\]?:?\s*',
|
306 |
+
'',
|
307 |
+
content,
|
308 |
+
flags=re.IGNORECASE
|
309 |
+
).strip()
|
310 |
+
|
311 |
+
if not content_to_translate:
|
312 |
+
raise HTTPException(status_code=400, detail="No text remains after parsing translation command")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
313 |
|
314 |
+
translated_text = translate_text(content_to_translate, target_language)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
315 |
return {
|
316 |
+
"response": translated_text,
|
317 |
+
"type": "translation",
|
318 |
"additional_data": {
|
319 |
+
"original_text": content_to_translate,
|
320 |
+
"target_language": target_language
|
321 |
}
|
322 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
323 |
|
324 |
+
# ... rest of the endpoint code ...
|
325 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
326 |
|
327 |
async def extract_text_from_file(file: UploadFile) -> str:
|
328 |
"""Enhanced text extraction with better error handling and format support"""
|