| | from typing import Dict, List, Any, Optional, Union
|
| | import pandas as pd
|
| | import smtplib
|
| | from email.mime.multipart import MIMEMultipart
|
| | from email.mime.text import MIMEText
|
| | from email.mime.image import MIMEImage
|
| | import base64
|
| | import io
|
| | from pathlib import Path
|
| | import json
|
| | import datetime
|
| | from llama_index.tools import FunctionTool
|
| |
|
| | class ExportTools:
|
| | """Tools for exporting data, generating reports, and sending emails."""
|
| |
|
| | def __init__(self, output_directory: str = "./exports"):
|
| | """Initialize with directory for saved exports."""
|
| | self.output_directory = Path(output_directory)
|
| | self.output_directory.mkdir(exist_ok=True, parents=True)
|
| | self.tools = self._create_tools()
|
| |
|
| | def _create_tools(self) -> List[FunctionTool]:
|
| | """Create LlamaIndex function tools for export operations."""
|
| | tools = [
|
| | FunctionTool.from_defaults(
|
| | name="generate_report",
|
| | description="Generate a report from conversation and results",
|
| | fn=self.generate_report
|
| | ),
|
| | FunctionTool.from_defaults(
|
| | name="save_results_to_csv",
|
| | description="Save query results to a CSV file",
|
| | fn=self.save_results_to_csv
|
| | ),
|
| | FunctionTool.from_defaults(
|
| | name="send_email",
|
| | description="Send results via email",
|
| | fn=self.send_email
|
| | )
|
| | ]
|
| | return tools
|
| |
|
| | def get_tools(self) -> List[FunctionTool]:
|
| | """Get all available export tools."""
|
| | return self.tools
|
| |
|
| | def generate_report(self, title: str, content: str,
|
| | images: List[str] = None) -> Dict[str, Any]:
|
| | """Generate HTML report from content and images."""
|
| | timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
| | filename = f"{title.replace(' ', '_')}_{timestamp}.html"
|
| | file_path = self.output_directory / filename
|
| |
|
| |
|
| | html = f"""
|
| | <!DOCTYPE html>
|
| | <html>
|
| | <head>
|
| | <title>{title}</title>
|
| | <style>
|
| | body {{ font-family: Arial, sans-serif; margin: 40px; line-height: 1.6; }}
|
| | h1 {{ color: #333366; }}
|
| | .report-container {{ max-width: 800px; margin: 0 auto; }}
|
| | .timestamp {{ color: #666; font-size: 0.8em; }}
|
| | img {{ max-width: 100%; height: auto; margin: 20px 0; }}
|
| | </style>
|
| | </head>
|
| | <body>
|
| | <div class="report-container">
|
| | <h1>{title}</h1>
|
| | <div class="timestamp">Generated on: {datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")}</div>
|
| | <div class="content">
|
| | {content.replace('\n', '<br>')}
|
| | </div>
|
| | """
|
| |
|
| |
|
| | if images and len(images) > 0:
|
| | html += "<div class='images'>"
|
| | for i, img_base64 in enumerate(images):
|
| | html += f"<img src='data:image/png;base64,{img_base64}' alt='Figure {i+1}'>"
|
| | html += "</div>"
|
| |
|
| | html += """
|
| | </div>
|
| | </body>
|
| | </html>
|
| | """
|
| |
|
| |
|
| | with open(file_path, "w", encoding="utf-8") as f:
|
| | f.write(html)
|
| |
|
| | return {
|
| | "success": True,
|
| | "report_path": str(file_path),
|
| | "title": title,
|
| | "timestamp": timestamp
|
| | }
|
| |
|
| | def save_results_to_csv(self, data: List[Dict[str, Any]],
|
| | filename: str = None) -> Dict[str, Any]:
|
| | """Save query results to a CSV file."""
|
| | if not data or len(data) == 0:
|
| | return {"success": False, "error": "No data provided"}
|
| |
|
| |
|
| | df = pd.DataFrame(data)
|
| |
|
| |
|
| | if not filename:
|
| | timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
| | filename = f"query_results_{timestamp}.csv"
|
| |
|
| |
|
| | if not filename.lower().endswith('.csv'):
|
| | filename += '.csv'
|
| |
|
| | file_path = self.output_directory / filename
|
| |
|
| |
|
| | df.to_csv(file_path, index=False)
|
| |
|
| | return {
|
| | "success": True,
|
| | "file_path": str(file_path),
|
| | "row_count": len(df),
|
| | "column_count": len(df.columns)
|
| | }
|
| |
|
| | def send_email(self, to_email: str, subject: str, body: str,
|
| | from_email: str = None, smtp_server: str = None,
|
| | smtp_port: int = 587, username: str = None,
|
| | password: str = None, images: List[str] = None) -> Dict[str, Any]:
|
| | """
|
| | Send email with results.
|
| | Note: In production, credentials should be securely managed.
|
| | For demo purposes, this will log the email content instead.
|
| | """
|
| |
|
| |
|
| |
|
| | email_content = {
|
| | "to": to_email,
|
| | "subject": subject,
|
| | "body": body[:100] + "..." if len(body) > 100 else body,
|
| | "images": f"{len(images) if images else 0} images would be attached",
|
| | "note": "Email sending is simulated for demo purposes"
|
| | }
|
| |
|
| |
|
| | print(f"SIMULATED EMAIL: {json.dumps(email_content, indent=2)}")
|
| |
|
| | return {
|
| | "success": True,
|
| | "to": to_email,
|
| | "subject": subject,
|
| | "simulated": True,
|
| | "timestamp": datetime.datetime.now().isoformat()
|
| | }
|
| |
|