FinMK / backend /chatbot /views.py
Kumar
Refactor: Exclude PDF and CSV files from Git to fix HF push error
24e6f5b
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, permissions
from .rag_service import generate_chat_response
from finance.utils_mongo import get_user_db_id
import tempfile
import os
import pdfplumber
class ChatView(APIView):
permission_classes = [permissions.IsAuthenticated]
def post(self, request):
query = request.data.get('message', '')
provider = request.data.get('provider')
is_voice = request.data.get('is_voice', False)
attached_file = request.FILES.get('file')
# 1. Process PDF Attachment (Text Extraction)
if attached_file and attached_file.name.lower().endswith('.pdf'):
try:
with pdfplumber.open(attached_file) as pdf:
pdf_text = ""
for page in pdf.pages:
pdf_text += (page.extract_text() or "") + "\n"
if pdf_text:
query = f"[ATTACHED PDF CONTENT: {attached_file.name}]\n{pdf_text}\n\nUSER QUESTION: {query}"
except Exception as e:
print(f"PDF extraction error: {e}")
# 2. Process Image Attachment (Temporary Save for Vision)
image_path = None
if attached_file and any(attached_file.name.lower().endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.webp']):
try:
suffix = os.path.splitext(attached_file.name)[1]
with tempfile.NamedTemporaryFile(delete=False, suffix=suffix) as tmp:
for chunk in attached_file.chunks():
tmp.write(chunk)
image_path = tmp.name
except Exception as e:
print(f"Image save error: {e}")
if not query and not image_path:
return Response({"error": "Message or attachment is required"}, status=status.HTTP_400_BAD_REQUEST)
mongo_user_id = get_user_db_id(request.user)
auth_header = request.headers.get('Authorization', '')
access_token = auth_header.replace('Bearer ', '').strip() if auth_header.startswith('Bearer ') else None
if is_voice:
from finance.ai_helper import generate_voice_response
result = generate_voice_response(query, provider=provider)
else:
result = generate_chat_response(
mongo_user_id,
query,
provider=provider,
access_token=access_token,
image_path=image_path
)
# Cleanup temporary image file
if image_path and os.path.exists(image_path):
try:
os.remove(image_path)
except:
pass
# Save to MongoDB (Embedded in User)
try:
from expense_tracker.utils import MongoDBClient
from datetime import datetime
from bson import ObjectId
db = MongoDBClient.get_client()
chat_log = {
'_id': ObjectId(),
'query': query,
'response': result.get('response'),
'context_used': result.get('context_used'),
'timestamp': datetime.now()
}
db.users.update_one(
{'_id': mongo_user_id},
{'$push': {'chat_history': chat_log}}
)
except Exception as e:
pass # Silently fail if chat log saving fails
return Response(result)
def get(self, request):
"""Retrieve chat history for the user"""
try:
from expense_tracker.utils import MongoDBClient
from bson import ObjectId
db = MongoDBClient.get_client()
db = MongoDBClient.get_client()
mongo_user_id = get_user_db_id(request.user)
user = db.users.find_one({'_id': mongo_user_id}, {'chat_history': 1})
history = []
if user and 'chat_history' in user:
# Return last 50 entries
raw_history = user['chat_history'][-50:]
for h in raw_history:
# Format for frontend with ID for deletion
history.append({
'id': str(h.get('_id', '')),
'sender': 'user',
'text': h.get('query'),
'timestamp': h.get('timestamp')
})
history.append({
'id': str(h.get('_id', '')),
'sender': 'bot',
'text': h.get('response'),
'timestamp': h.get('timestamp')
})
return Response(history)
except Exception as e:
return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
def delete(self, request, msg_id=None):
"""Delete a specific chat entry from history"""
if not msg_id:
return Response({"error": "Message ID required"}, status=status.HTTP_400_BAD_REQUEST)
try:
from expense_tracker.utils import MongoDBClient
from bson import ObjectId
db = MongoDBClient.get_client()
db = MongoDBClient.get_client()
mongo_user_id = get_user_db_id(request.user)
if msg_id == 'all':
result = db.users.update_one(
{'_id': mongo_user_id},
{'$set': {'chat_history': []}}
)
if result.modified_count > 0:
return Response({"message": "All chat history cleared"}, status=status.HTTP_200_OK)
return Response({"message": "No chat history to clear"}, status=status.HTTP_200_OK)
result = db.users.update_one(
{'_id': mongo_user_id},
{'$pull': {'chat_history': {'_id': ObjectId(msg_id)}}}
)
if result.modified_count > 0:
return Response({"message": "Chat deleted successfully"}, status=status.HTTP_200_OK)
else:
return Response({"error": "Chat not found"}, status=status.HTTP_404_NOT_FOUND)
except Exception as e:
return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)