| import os |
| from google import genai |
| from PIL import Image |
| import io |
| import puremagic |
| from pypdf import PdfReader |
| import fitz |
| from datetime import datetime |
|
|
| class FraudAnalyzer: |
| def __init__(self, api_key): |
| self.client = genai.Client(api_key=api_key) |
| |
| self.model_flash = 'gemini-3-flash-preview' |
| |
| self.model_nano = 'nano-banana-pro-preview' |
|
|
| def analyze_document(self, file_path): |
| """Perform visual and structural analysis + data extraction.""" |
| file_ext = os.path.splitext(file_path)[1].lower() |
| metadata = self._extract_metadata(file_path) |
| |
| current_datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
| visual_prompt = f"Today is {current_datetime}. Examine this image for visual manipulations: clones, font mismatches, edges around text, or retouching. Be extremely critical." |
| extraction_prompt = f""" |
| Today is {current_datetime}. Extract all text data from the following analysis and metadata. |
| Return a structured analysis in JSON format with: |
| - label: A short descriptive name for the document. |
| - amount: Any monetary amount found (default 0 or null). |
| - fraud_score: An integer score from 0 to 100 indicating fraud probability (0 = clean, 100 = definitely fraud). |
| - detailed_analysis: Your full reasoning. |
| - extracted_fields: Key names, dates, and ID numbers. |
| """ |
|
|
| image_input = None |
| text_content = "" |
|
|
| if file_ext in ['.png', '.jpg', '.jpeg']: |
| image_input = Image.open(file_path) |
| elif file_ext == '.pdf': |
| |
| reader = PdfReader(file_path) |
| for page in reader.pages: |
| text_content += page.extract_text() |
| |
| |
| try: |
| doc = fitz.open(file_path) |
| page = doc.load_page(0) |
| pix = page.get_pixmap() |
| img_data = pix.tobytes("png") |
| image_input = Image.open(io.BytesIO(img_data)) |
| doc.close() |
| except Exception as e: |
| print(f"Error converting PDF to image: {e}") |
|
|
| if image_input: |
| |
| visual_resp = self.client.models.generate_content( |
| model=self.model_nano, |
| contents=[visual_prompt, image_input] |
| ) |
| |
| |
| content_to_flash = [ |
| extraction_prompt, |
| f"Visual Analysis Report (from Nano Banana): {visual_resp.text}", |
| f"Metadata: {metadata}" |
| ] |
| if text_content: |
| content_to_flash.append(f"Extracted Text: {text_content}") |
| content_to_flash.append(image_input) |
| |
| combined_resp = self.client.models.generate_content( |
| model=self.model_flash, |
| contents=content_to_flash |
| ) |
| |
| return { |
| "llm_analysis": f"Visual Report (Nano Banana):\n{visual_resp.text}\n\nFinal Reasoning (Flash):\n{combined_resp.text}", |
| "metadata": metadata |
| } |
| else: |
| |
| combined_resp = self.client.models.generate_content( |
| model=self.model_flash, |
| contents=[extraction_prompt, f"Metadata: {metadata}", f"Text: {text_content}"] |
| ) |
| return { |
| "llm_analysis": f"Reasoning (Flash):\n{combined_resp.text}", |
| "metadata": metadata |
| } |
|
|
| def _extract_metadata(self, file_path): |
| """Extract file system and internal metadata.""" |
| try: |
| file_mime = puremagic.from_file(file_path, mime=True) |
| except Exception: |
| file_mime = "application/octet-stream" |
| |
| stats = os.stat(file_path) |
| metadata = { |
| "mime_type": file_mime, |
| "size_bytes": stats.st_size, |
| "modified_time": stats.st_mtime |
| } |
| |
| if "image" in file_mime: |
| try: |
| img = Image.open(file_path) |
| exif = img._getexif() |
| if exif: |
| metadata["exif"] = {str(k): str(v) for k, v in exif.items()} |
| except Exception: |
| pass |
| |
| return metadata |
|
|