File size: 6,512 Bytes
24e6f5b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | 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)
|