from django.shortcuts import render from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import AllowAny from rest_framework.response import Response from rest_framework import status import sys import os import requests # Add the typesense directory to Python path typesense_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'extra', 'typesense') sys.path.append(typesense_path) from search_utility import SwaminiVatoSearch # Initialize the search utility with embeddings enabled book_searcher = SwaminiVatoSearch(use_embeddings=True) @api_view(['POST']) @permission_classes([AllowAny]) def search_books(request): """ API endpoint for semantic book search POST /api/llm/search-books/ Body: { "query": "What is the nature of God?", "scripture": "swamini_vato" (optional), "max_results": 5 (optional), "max_tokens": 2000 (optional) } Returns: { "query": "...", "context": "...", "sources": [...], "num_sources": 3, "total_chars": 1234 } """ try: query = request.data.get('query') if not query: return Response( {'error': 'Query parameter is required'}, status=status.HTTP_400_BAD_REQUEST ) # Get optional parameters scripture = request.data.get('scripture', 'swamini_vato') max_results = request.data.get('max_results', 5) max_tokens = request.data.get('max_tokens', 2000) # Perform search and get context for RAG context_data = book_searcher.get_context_for_rag( query=query, filters=None, # Can add chapter filters if needed max_tokens=max_tokens, num_results=max_results ) # Add query to response context_data['query'] = query context_data['scripture'] = scripture return Response(context_data, status=status.HTTP_200_OK) except Exception as e: return Response( {'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) @api_view(['GET']) @permission_classes([AllowAny]) def get_random_verse(request): """ API endpoint to get a random verse GET /api/llm/random-verse/ Returns: Random verse data """ try: verse = book_searcher.get_random_vat() if not verse: return Response( {'error': 'No verse found'}, status=status.HTTP_404_NOT_FOUND ) return Response(verse, status=status.HTTP_200_OK) except Exception as e: return Response( {'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) @api_view(['POST']) @permission_classes([AllowAny]) def serp_search(request): """ API endpoint for SERP (Search Engine Results Page) search POST /api/llm/serp-search/ Body: { "query": "search query", "engine": "google" (optional, default: google), "domain": "google.com" (optional, default: google.com), "gl": "US" (optional, default: US), "tbm": "" (optional, for image/news/video search), "lang": "en" (optional, default: en) } Returns: SERP results from Bright Data API """ try: query = request.data.get('query') if not query: return Response( {'error': 'Query parameter is required'}, status=status.HTTP_400_BAD_REQUEST ) # Get optional parameters with defaults engine = request.data.get('engine', 'google') domain = request.data.get('domain', 'google.com') gl = request.data.get('gl', 'US') tbm = request.data.get('tbm', '') lang = request.data.get('lang', 'en') # Set up headers headers = { 'accept': '*/*', 'accept-language': 'en-US,en;q=0.9,gu;q=0.8,ru;q=0.7,hi;q=0.6', 'priority': 'u=1, i', 'referer': 'https://brightdata.com/products/serp-api', 'sec-ch-ua': '"Chromium";v="140", "Not=A?Brand";v="24", "Google Chrome";v="140"', 'sec-ch-ua-mobile': '?0', 'sec-ch-ua-platform': '"Windows"', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-origin', 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36', } # Set up parameters params = { 'engine': engine, 'q': query, 'domain': domain, 'gl': gl, 'tbm': tbm, 'lang': lang, } # Make request to Bright Data SERP API response = requests.get( 'https://brightdata.com/web_api/serp_playground', params=params, headers=headers, timeout=30 # 30 second timeout ) # Check if request was successful if response.status_code != 200: return Response( { 'error': 'SERP API request failed', 'status_code': response.status_code, 'details': response.text }, status=status.HTTP_502_BAD_GATEWAY ) # Return the JSON response serp_data = response.json() return Response({ 'query': query, 'engine': engine, 'results': serp_data }, status=status.HTTP_200_OK) except requests.exceptions.Timeout: return Response( {'error': 'SERP API request timed out'}, status=status.HTTP_504_GATEWAY_TIMEOUT ) except requests.exceptions.RequestException as e: return Response( {'error': f'SERP API request failed: {str(e)}'}, status=status.HTTP_502_BAD_GATEWAY ) except Exception as e: return Response( {'error': str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR )