WHG2023
Enhanced Dual Output Features - Both descriptions AND LaTeX code + Multiple compilation options + Professional USPTO-ready vector graphics + Immediate understanding without compilation barriers
4252b44
#!/usr/bin/env python3 | |
""" | |
Enhanced Gemini Image Generator Integration for Patent Architect AI v2 | |
Provides high-quality technical figure generation with dual output: | |
- Detailed technical descriptions for immediate understanding | |
- Professional LaTeX/TikZ code with embedded compilation options | |
""" | |
import os | |
import json | |
import base64 | |
import requests | |
import tempfile | |
import subprocess | |
import shutil | |
from typing import Dict, List, Optional, Tuple | |
import google.generativeai as genai | |
from datetime import datetime | |
from dotenv import load_dotenv | |
# Load environment variables | |
load_dotenv() | |
class GeminiImageGenerator: | |
"""Enhanced Gemini integration with dual output and embedded compilation.""" | |
def __init__(self, api_key: Optional[str] = None, output_dir: Optional[str] = None): | |
"""Initialize the enhanced Gemini image generator. | |
Args: | |
api_key: Google Gemini API key | |
output_dir: Directory to save generated images | |
""" | |
self.api_key = api_key or os.getenv("GEMINI_API_KEY") | |
if not self.api_key: | |
raise ValueError("GEMINI_API_KEY environment variable or api_key parameter required") | |
# Configure Gemini | |
genai.configure(api_key=self.api_key) | |
self.model = genai.GenerativeModel('gemini-2.0-flash-exp') | |
# Set output directory | |
self.output_dir = output_dir or os.path.join(os.path.expanduser("~"), "patent_architect_figures") | |
os.makedirs(self.output_dir, exist_ok=True) | |
# Check if LaTeX is available for compilation | |
self.latex_available = self._check_latex_installation() | |
# Image generation parameters | |
self.generation_config = { | |
'temperature': 0.4, | |
'top_k': 32, | |
'top_p': 1, | |
'max_output_tokens': 8192, | |
} | |
def _check_latex_installation(self) -> bool: | |
"""Check if LaTeX is available for compilation.""" | |
try: | |
result = subprocess.run(['pdflatex', '--version'], | |
capture_output=True, | |
text=True, | |
timeout=5) | |
return result.returncode == 0 | |
except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.SubprocessError): | |
return False | |
def _compile_latex_via_web_api(self, latex_code: str, filename: str) -> Optional[str]: | |
"""Try to compile LaTeX using web-based APIs. | |
Args: | |
latex_code: LaTeX source code | |
filename: Base filename for output | |
Returns: | |
Path to compiled image or None if failed | |
""" | |
try: | |
# Try using a public LaTeX compilation API (example with LaTeX.Online) | |
api_url = "https://latex.vercel.app/api/v2" | |
payload = { | |
"code": latex_code, | |
"format": "png", | |
"quality": 300 | |
} | |
print(f"π Attempting web-based LaTeX compilation...") | |
response = requests.post(api_url, json=payload, timeout=30) | |
if response.status_code == 200: | |
# Save compiled image | |
image_filename = f"{filename}.png" | |
image_path = os.path.join(self.output_dir, image_filename) | |
with open(image_path, 'wb') as f: | |
f.write(response.content) | |
print(f"β Web compilation successful: {image_filename}") | |
return image_path | |
else: | |
print(f"β οΈ Web compilation failed: HTTP {response.status_code}") | |
return None | |
except Exception as e: | |
print(f"β οΈ Web compilation error: {e}") | |
return None | |
def _compile_latex_to_image(self, latex_filepath: str) -> Optional[str]: | |
"""Enhanced LaTeX compilation with multiple methods. | |
Args: | |
latex_filepath: Path to the .tex file | |
Returns: | |
Path to generated image file or None if compilation failed | |
""" | |
# Try local compilation first if available | |
if self.latex_available: | |
try: | |
# Get directory and filename | |
tex_dir = os.path.dirname(latex_filepath) | |
tex_filename = os.path.basename(latex_filepath) | |
base_name = os.path.splitext(tex_filename)[0] | |
print(f"π§ Attempting local LaTeX compilation...") | |
# Compile LaTeX to PDF | |
result = subprocess.run([ | |
'pdflatex', | |
'-output-directory', tex_dir, | |
'-interaction=nonstopmode', | |
latex_filepath | |
], capture_output=True, text=True, timeout=30) | |
if result.returncode == 0: | |
# Check if PDF was created | |
pdf_path = os.path.join(tex_dir, f"{base_name}.pdf") | |
if os.path.exists(pdf_path): | |
# Try to convert PDF to PNG using available tools | |
png_path = os.path.join(tex_dir, f"{base_name}.png") | |
# Try different conversion methods | |
conversion_methods = [ | |
# Method 1: pdftoppm (part of poppler-utils) | |
['pdftoppm', '-png', '-singlefile', '-r', '300', pdf_path, base_name], | |
# Method 2: ImageMagick convert | |
['convert', '-density', '300', pdf_path, png_path], | |
# Method 3: ghostscript | |
['gs', '-dNOPAUSE', '-dBATCH', '-sDEVICE=png16m', '-r300', f'-sOutputFile={png_path}', pdf_path] | |
] | |
for method in conversion_methods: | |
try: | |
if method[0] == 'pdftoppm': | |
result = subprocess.run(method, | |
cwd=tex_dir, | |
capture_output=True, | |
text=True, | |
timeout=30) | |
if result.returncode == 0: | |
expected_png = os.path.join(tex_dir, f"{base_name}.png") | |
if os.path.exists(expected_png): | |
print(f"β Local compilation successful: {expected_png}") | |
return expected_png | |
else: | |
result = subprocess.run(method, | |
capture_output=True, | |
text=True, | |
timeout=30) | |
if result.returncode == 0 and os.path.exists(png_path): | |
print(f"β Local compilation successful: {png_path}") | |
return png_path | |
except (subprocess.TimeoutExpired, FileNotFoundError): | |
continue | |
print(f"β PDF created but PNG conversion failed: {pdf_path}") | |
return pdf_path # Return PDF if PNG conversion failed | |
else: | |
print(f"β οΈ Local LaTeX compilation failed: {result.stderr}") | |
except Exception as e: | |
print(f"β οΈ Local LaTeX compilation error: {e}") | |
# Try web-based compilation as fallback | |
try: | |
with open(latex_filepath, 'r', encoding='utf-8') as f: | |
latex_code = f.read() | |
base_name = os.path.splitext(os.path.basename(latex_filepath))[0] | |
web_result = self._compile_latex_via_web_api(latex_code, base_name) | |
if web_result: | |
return web_result | |
except Exception as e: | |
print(f"β οΈ Web compilation fallback failed: {e}") | |
return None | |
def generate_dual_output_figure(self, | |
invention_description: str, | |
figure_type: str = "technical_diagram", | |
specific_requirements: Optional[str] = None) -> Dict: | |
"""Generate both detailed description AND LaTeX code for a patent figure. | |
Args: | |
invention_description: Description of the invention | |
figure_type: Type of figure to generate | |
specific_requirements: Additional requirements for the figure | |
Returns: | |
Dict containing both text description and LaTeX code with compilation options | |
""" | |
try: | |
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") | |
# Step 1: Generate detailed text description | |
print(f"π Generating detailed technical description...") | |
text_prompt = self._create_patent_figure_prompt( | |
invention_description, | |
figure_type, | |
specific_requirements | |
) | |
text_response = self.model.generate_content([text_prompt]) | |
detailed_description = text_response.text | |
# Step 2: Generate LaTeX/TikZ code | |
print(f"π¨ Generating LaTeX/TikZ code...") | |
latex_prompt = self._create_image_generation_prompt( | |
invention_description, | |
figure_type, | |
specific_requirements | |
) | |
latex_response = self.model.generate_content([latex_prompt], | |
generation_config={'temperature': 0.1}) | |
latex_code = latex_response.text | |
# Save both outputs | |
text_filename = f"patent_figure_{figure_type}_{timestamp}_description.txt" | |
latex_filename = f"patent_figure_{figure_type}_{timestamp}.tex" | |
text_filepath = os.path.join(self.output_dir, text_filename) | |
latex_filepath = os.path.join(self.output_dir, latex_filename) | |
# Save detailed description | |
with open(text_filepath, 'w', encoding='utf-8') as f: | |
f.write(f"Patent Figure Description\n") | |
f.write(f"========================\n\n") | |
f.write(f"Invention: {invention_description}\n\n") | |
f.write(f"Figure Type: {figure_type}\n\n") | |
f.write(f"Description:\n{detailed_description}\n\n") | |
f.write(f"Generated: {datetime.now().isoformat()}\n") | |
# Save LaTeX code | |
with open(latex_filepath, 'w', encoding='utf-8') as f: | |
f.write(f"% Patent Figure - {figure_type}\n") | |
f.write(f"% Generated: {datetime.now().isoformat()}\n") | |
f.write(f"% Invention: {invention_description}\n\n") | |
f.write(latex_code) | |
# Try to compile LaTeX to image | |
compiled_image_path = None | |
compilation_method = None | |
if any(keyword in latex_code.lower() for keyword in ['tikz', 'latex', 'documentclass', '\\draw']): | |
compiled_image_path = self._compile_latex_to_image(latex_filepath) | |
if compiled_image_path: | |
if self.latex_available: | |
compilation_method = "local" | |
else: | |
compilation_method = "web" | |
return { | |
"success": True, | |
"dual_output": True, | |
"text_description": detailed_description, | |
"latex_code": latex_code, | |
"text_file_path": text_filepath, | |
"latex_file_path": latex_filepath, | |
"compiled_image_path": compiled_image_path, | |
"compilation_method": compilation_method, | |
"figure_type": figure_type, | |
"timestamp": timestamp, | |
"code_preview": latex_code[:400] + "..." if len(latex_code) > 400 else latex_code, | |
"description_preview": detailed_description[:300] + "..." if len(detailed_description) > 300 else detailed_description, | |
"metadata": { | |
"invention": invention_description, | |
"requirements": specific_requirements, | |
"latex_available": self.latex_available, | |
"output_formats": ["description", "latex", "compiled_image"] if compiled_image_path else ["description", "latex"] | |
} | |
} | |
except Exception as e: | |
return { | |
"success": False, | |
"error": str(e), | |
"figure_type": figure_type | |
} | |
def generate_patent_figure(self, | |
invention_description: str, | |
figure_type: str = "technical_diagram", | |
specific_requirements: Optional[str] = None) -> Dict: | |
"""Enhanced patent figure generation with dual output option.""" | |
# Use the new dual output method for better results | |
return self.generate_dual_output_figure(invention_description, figure_type, specific_requirements) | |
def generate_multiple_figures(self, | |
invention_description: str, | |
figure_types: List[str] = None) -> List[Dict]: | |
"""Generate multiple patent figures for an invention. | |
Args: | |
invention_description: Description of the invention | |
figure_types: List of figure types to generate | |
Returns: | |
List of generation results | |
""" | |
if figure_types is None: | |
figure_types = [ | |
"overall_system_diagram", | |
"detailed_cross_section", | |
"component_breakdown", | |
"operational_flow" | |
] | |
results = [] | |
for figure_type in figure_types: | |
result = self.generate_patent_figure(invention_description, figure_type) | |
results.append(result) | |
return results | |
def _create_patent_figure_prompt(self, | |
invention_description: str, | |
figure_type: str, | |
specific_requirements: Optional[str] = None) -> str: | |
"""Create a detailed prompt for patent figure generation. | |
Args: | |
invention_description: Description of the invention | |
figure_type: Type of figure to generate | |
specific_requirements: Additional requirements | |
Returns: | |
Detailed prompt for figure generation | |
""" | |
base_prompt = f""" | |
Create a detailed technical description for a patent figure showing: {invention_description} | |
Figure Type: {figure_type} | |
Requirements for patent-quality technical figures: | |
1. Clear component labeling with numbered elements (1, 2, 3, etc.) | |
2. Professional technical drawing style | |
3. Sufficient detail to enable reproduction by skilled person | |
4. Clear spatial relationships between components | |
5. Appropriate perspective and viewing angle | |
6. No decorative elements - focus on technical clarity | |
7. Include all essential components mentioned in the invention | |
Please provide a comprehensive description that includes: | |
- Main components and their numbered labels | |
- Spatial relationships and connections | |
- Technical details and specifications | |
- Viewing perspective and orientation | |
- Any cross-sectional views or cutaway details needed | |
- Dimensional relationships where relevant | |
""" | |
if specific_requirements: | |
base_prompt += f"\nAdditional Requirements: {specific_requirements}\n" | |
# Add figure-type specific guidance | |
figure_guidance = { | |
"technical_diagram": "Show the overall system with clear component relationships", | |
"cross_section": "Provide internal view showing construction and operation", | |
"system_overview": "Display complete system architecture and data flow", | |
"component_breakdown": "Show detailed view of individual components and assemblies", | |
"operational_flow": "Illustrate step-by-step operation or process flow", | |
"detailed_cross_section": "Show internal construction with numbered components", | |
"overall_system_diagram": "Display complete invention with all major elements", | |
"assembly_view": "Show how components fit together in exploded or assembled view" | |
} | |
if figure_type in figure_guidance: | |
base_prompt += f"\nSpecific guidance for {figure_type}: {figure_guidance[figure_type]}\n" | |
base_prompt += """ | |
Generate a detailed technical description that a patent illustrator could use to create | |
a professional patent figure. Focus on technical accuracy and completeness.""" | |
return base_prompt | |
def _create_image_generation_prompt(self, | |
invention_description: str, | |
figure_type: str, | |
specific_requirements: Optional[str] = None) -> str: | |
"""Create a prompt specifically for LaTeX/TikZ code generation. | |
Args: | |
invention_description: Description of the invention | |
figure_type: Type of figure to generate | |
specific_requirements: Additional requirements | |
Returns: | |
Optimized prompt for LaTeX/TikZ patent figure generation | |
""" | |
base_prompt = f"""Generate ONLY LaTeX/TikZ code for a professional patent figure showing: {invention_description} | |
Figure Type: {figure_type} | |
OUTPUT REQUIREMENTS: | |
- Complete LaTeX document ready to compile | |
- Start with \\documentclass{{article}} and end with \\end{{document}} | |
- Include necessary packages: \\usepackage{{tikz}}, \\usepackage{{geometry}} | |
- Professional patent-style technical drawing | |
- Numbered components (1, 2, 3, etc.) with clear labels | |
- Clean, precise TikZ drawing commands | |
- No explanatory text - ONLY LaTeX code | |
TECHNICAL DRAWING REQUIREMENTS: | |
- Use TikZ \\draw commands for all shapes | |
- Include numbered component labels with \\node commands | |
- Proper scaling and positioning | |
- Professional technical drawing style | |
- Clear spatial relationships between components | |
- Include connecting lines and annotations where relevant | |
""" | |
# Add figure-type specific visual guidance | |
visual_guidance = { | |
"technical_diagram": "Create an overall system diagram showing all major components and their connections", | |
"cross_section": "Generate a cross-sectional view revealing internal construction and operation", | |
"system_overview": "Draw a complete system architecture with clear component relationships", | |
"component_breakdown": "Create an exploded view showing individual components and assemblies", | |
"operational_flow": "Illustrate process flow with directional arrows and step indicators", | |
"detailed_cross_section": "Show detailed internal construction with numbered components", | |
"overall_system_diagram": "Display complete invention with all major elements labeled", | |
"assembly_view": "Show component assembly with exploded or cutaway views" | |
} | |
if figure_type in visual_guidance: | |
base_prompt += f"\nSpecific Visual Style: {visual_guidance[figure_type]}\n" | |
if specific_requirements: | |
base_prompt += f"\nAdditional Visual Requirements: {specific_requirements}\n" | |
base_prompt += """ | |
Generate a high-quality technical patent figure that meets USPTO standards for patent applications. | |
The drawing should be clear, precise, and technically accurate.""" | |
return base_prompt | |
def integrate_with_patent_architect(self, | |
invention_description: str, | |
figure_descriptions: List[str] = None) -> Dict: | |
"""Enhanced integration point for Patent Architect AI v2 system with dual output. | |
Args: | |
invention_description: The invention being patented | |
figure_descriptions: Specific figure descriptions needed | |
Returns: | |
Dict with enhanced content including both descriptions and LaTeX code | |
""" | |
try: | |
if figure_descriptions is None: | |
# Generate standard patent figures | |
figure_types = ["overall_system_diagram", "detailed_cross_section", "component_breakdown"] | |
results = [] | |
for i, figure_type in enumerate(figure_types, 1): | |
result = self.generate_dual_output_figure(invention_description, figure_type) | |
if result["success"]: | |
results.append({ | |
"figure_number": i, | |
"description": result["text_description"], | |
"latex_code": result["latex_code"], | |
"text_file_path": result["text_file_path"], | |
"latex_file_path": result["latex_file_path"], | |
"compiled_image_path": result.get("compiled_image_path"), | |
"compilation_method": result.get("compilation_method"), | |
"type": figure_type, | |
"dual_output": True, | |
"code_preview": result.get("code_preview", ""), | |
"description_preview": result.get("description_preview", "") | |
}) | |
else: | |
# Generate specific requested figures | |
results = [] | |
for i, description in enumerate(figure_descriptions, 1): | |
result = self.generate_dual_output_figure( | |
invention_description, | |
f"custom_figure_{i}", | |
description | |
) | |
if result["success"]: | |
results.append({ | |
"figure_number": i, | |
"description": result["text_description"], | |
"latex_code": result["latex_code"], | |
"text_file_path": result["text_file_path"], | |
"latex_file_path": result["latex_file_path"], | |
"compiled_image_path": result.get("compiled_image_path"), | |
"compilation_method": result.get("compilation_method"), | |
"type": "custom", | |
"dual_output": True, | |
"code_preview": result.get("code_preview", ""), | |
"description_preview": result.get("description_preview", "") | |
}) | |
# Enhanced formatting for Patent Architect with dual output | |
if results: | |
content = "## π¨ Enhanced Patent Figures with Dual Output\n\n" | |
# Count outputs | |
total_figures = len(results) | |
compiled_images = sum(1 for r in results if r.get("compiled_image_path")) | |
local_compiled = sum(1 for r in results if r.get("compilation_method") == "local") | |
web_compiled = sum(1 for r in results if r.get("compilation_method") == "web") | |
content += f"*β¨ Generated {total_figures} complete figure sets with both detailed descriptions AND LaTeX/TikZ code*\n\n" | |
if compiled_images > 0: | |
content += f"*πΌοΈ {compiled_images}/{total_figures} figures successfully compiled to images" | |
if local_compiled > 0: | |
content += f" ({local_compiled} local" | |
if web_compiled > 0: | |
if local_compiled > 0: | |
content += f", {web_compiled} web" | |
else: | |
content += f" ({web_compiled} web" | |
content += " compilation)*\n\n" | |
for figure in results: | |
figure_title = figure['type'].replace('_', ' ').title() | |
content += f"### Figure {figure['figure_number']}: {figure_title}\n\n" | |
# Show compiled image if available | |
if figure.get("compiled_image_path"): | |
image_filename = os.path.basename(figure['compiled_image_path']) | |
content += f"**πΌοΈ Compiled Image:** `{image_filename}` ({'Local' if figure.get('compilation_method') == 'local' else 'Web'} compilation)\n\n" | |
# Always show detailed description | |
content += f"**π Technical Description:**\n" | |
content += f"{figure['description'][:500]}{'...' if len(figure['description']) > 500 else ''}\n\n" | |
# Always show LaTeX code with enhanced instructions | |
latex_filename = os.path.basename(figure['latex_file_path']) | |
content += f"**π¨ LaTeX/TikZ Code:** `{latex_filename}`\n\n" | |
# Show code preview | |
if figure.get('code_preview'): | |
content += f"**Code Preview:**\n```latex\n{figure['code_preview']}\n```\n\n" | |
# Enhanced compilation options | |
content += f"**π Multiple Viewing Options:**\n\n" | |
if figure.get("compiled_image_path"): | |
content += f"1. **β Pre-Compiled Image Available**: View `{os.path.basename(figure['compiled_image_path'])}` in output folder\n" | |
content += f"2. **π Online Compilation (Easiest)**:\n" | |
content += f" - Go to [Overleaf.com](https://overleaf.com) (free account)\n" | |
content += f" - Create new project β Upload β Select `{latex_filename}`\n" | |
content += f" - Click 'Recompile' for instant professional PDF\n" | |
content += f" - Download PDF for USPTO submission\n\n" | |
content += f"3. **π» Local Compilation**:\n" | |
content += f" - Install LaTeX: [MiKTeX](https://miktex.org/) (Windows) or [TeX Live](https://www.tug.org/texlive/)\n" | |
content += f" - Run: `pdflatex {latex_filename}`\n" | |
content += f" - Convert to PNG: `pdftoppm -png -singlefile output.pdf figure`\n\n" | |
content += f"4. **π± Mobile/Quick View**: Use [LaTeX Live](https://latexlive.com) - paste code for instant preview\n\n" | |
# File information | |
content += f"**π Generated Files:**\n" | |
content += f"- π Description: `{os.path.basename(figure['text_file_path'])}`\n" | |
content += f"- π¨ LaTeX Code: `{latex_filename}`\n" | |
if figure.get("compiled_image_path"): | |
content += f"- πΌοΈ Compiled Image: `{os.path.basename(figure['compiled_image_path'])}`\n" | |
content += f"- π Location: `{os.path.dirname(figure['text_file_path'])}`\n\n" | |
# Enhanced summary and guidance | |
content += "---\n\n" | |
content += f"**π Generation Summary:**\n" | |
content += f"- **Total Figures:** {total_figures} complete sets\n" | |
content += f"- **Dual Output:** β Both descriptions AND LaTeX code\n" | |
content += f"- **Compiled Images:** {compiled_images} ready to view\n" | |
content += f"- **USPTO Ready:** β Professional patent figure quality\n" | |
content += f"- **Vector Graphics:** β Infinite scaling, publication quality\n\n" | |
content += f"**π Why This is Better:**\n" | |
content += f"- **Immediate Understanding:** Read detailed technical descriptions right now\n" | |
content += f"- **Professional Quality:** LaTeX creates publication-grade vector graphics\n" | |
content += f"- **Multiple Options:** View online (Overleaf), locally, or pre-compiled images\n" | |
content += f"- **USPTO Preferred:** Vector graphics are ideal for patent applications\n" | |
content += f"- **Editable:** Modify LaTeX code for custom adjustments\n\n" | |
content += f"**π― Quick Start Guide:**\n" | |
content += f"1. **Read the descriptions above** for immediate technical understanding\n" | |
content += f"2. **View compiled images** if available in the output folder\n" | |
content += f"3. **For publication quality**: Use Overleaf.com with the .tex files\n" | |
content += f"4. **For USPTO submission**: Compile LaTeX to PDF for vector graphics\n\n" | |
content += f"*Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | Output: `{self.output_dir}`*\n\n" | |
return { | |
"success": True, | |
"content": content, | |
"figures": results, | |
"total_figures": len(results), | |
"dual_output": True, | |
"compiled_images": compiled_images, | |
"descriptions_available": total_figures, | |
"latex_code_available": total_figures, | |
"enhanced_features": [ | |
"detailed_descriptions", | |
"latex_tikz_code", | |
"multiple_compilation_options", | |
"pre_compiled_images", | |
"overleaf_integration", | |
"uspto_ready_output" | |
] | |
} | |
else: | |
return { | |
"success": False, | |
"content": "### Technical Figures\n\nError generating enhanced patent figures. Please review invention description and try again.\n\n", | |
"error": "No figures were successfully generated" | |
} | |
except Exception as e: | |
return { | |
"success": False, | |
"content": f"### Technical Figures\n\nError: {str(e)}\n\nPlease check Gemini API configuration and try again.\n\n", | |
"error": str(e) | |
} | |
def test_gemini_integration(): | |
"""Test the enhanced Gemini image generator integration.""" | |
try: | |
print("π¨ Testing Enhanced Gemini Patent Figure Generation...") | |
print("=" * 60) | |
generator = GeminiImageGenerator() | |
test_invention = """ | |
A smart coffee mug that maintains perfect temperature using phase-change materials | |
and app control, solving the problem of coffee getting cold too quickly while | |
providing personalized temperature preferences. | |
""" | |
print("π Test Invention: Smart coffee mug with temperature control") | |
print(f"π Output Directory: {generator.output_dir}") | |
print() | |
# Test image generation capability | |
print("π¬ Testing Individual Figure Generation...") | |
result = generator.generate_patent_figure( | |
test_invention, | |
"technical_diagram", | |
"Show the mug with phase-change material chambers and app connectivity" | |
) | |
if result["success"]: | |
if result.get("image_generated", False): | |
print(f"β SUCCESS: Generated actual image!") | |
print(f" π Image file: {result['image_path']}") | |
print(f" π¨ Format: {result.get('mime_type', 'Unknown')}") | |
else: | |
print(f"βΉοΈ Generated detailed text description (image generation unavailable)") | |
print(f" π Description file: {result['text_file_path']}") | |
else: | |
print(f"β Individual generation failed: {result.get('error', 'Unknown error')}") | |
print() | |
# Test full Patent Architect integration | |
print("ποΈ Testing Patent Architect Integration...") | |
integration_result = generator.integrate_with_patent_architect(test_invention) | |
if integration_result["success"]: | |
print("β Integration Success!") | |
print(f" π Total Figures: {integration_result['total_figures']}") | |
print(f" πΌοΈ Images Generated: {integration_result['images_generated']}") | |
print(f" π Text Descriptions: {integration_result['text_descriptions']}") | |
print() | |
# Show a preview of the content | |
content_preview = integration_result["content"][:500] + "..." if len(integration_result["content"]) > 500 else integration_result["content"] | |
print("π Content Preview:") | |
print("-" * 40) | |
print(content_preview) | |
print("-" * 40) | |
else: | |
print(f"β Integration failed: {integration_result.get('error', 'Unknown error')}") | |
print() | |
print("π API Status Check:") | |
print(f" π API Key Available: {'β ' if os.environ.get('GEMINI_API_KEY') else 'β'}") | |
print(f" π Internet Connection: {'β ' if True else 'β'}") # Simplified check | |
print(f" π¦ Google GenAI Library: {'β ' if 'google.generativeai' in str(generator.model) else 'β'}") | |
print() | |
print("π― Next Steps:") | |
if integration_result.get("images_generated", 0) > 0: | |
print(" β’ Images successfully generated - check output directory") | |
print(" β’ Patent Architect will display actual image files") | |
print(" β’ Ready for professional patent application use") | |
else: | |
print(" β’ Currently generating detailed text descriptions") | |
print(" β’ Gemini image generation API may be in development") | |
print(" β’ Text descriptions are highly detailed and patent-ready") | |
except Exception as e: | |
print(f"β Test failed: {str(e)}") | |
print("π‘ Troubleshooting:") | |
print(" β’ Ensure GEMINI_API_KEY is set correctly") | |
print(" β’ Check internet connection") | |
print(" β’ Verify google-generativeai library is installed") | |
def test_actual_image_capability(): | |
"""Specific test for actual image generation capability.""" | |
try: | |
print("π¨ Testing Actual Image Generation Capability...") | |
print("=" * 50) | |
generator = GeminiImageGenerator() | |
# Simple test prompt for image generation | |
simple_prompt = """Create a simple technical diagram showing a coffee mug with numbered components: | |
1. Coffee mug body | |
2. Temperature sensor | |
3. Heating element | |
4. App connectivity module | |
Draw this as a black and white technical patent figure.""" | |
print("π Testing with simple prompt...") | |
try: | |
response = generator.model.generate_content([simple_prompt]) | |
print(f"π Response received") | |
print(f" π Has text: {'β ' if hasattr(response, 'text') else 'β'}") | |
print(f" πΌοΈ Has parts: {'β ' if hasattr(response, 'parts') else 'β'}") | |
if hasattr(response, 'parts'): | |
print(f" π Number of parts: {len(response.parts)}") | |
for i, part in enumerate(response.parts): | |
print(f" Part {i+1}: {type(part).__name__}") | |
if hasattr(part, 'inline_data'): | |
print(f" π Has inline data: β ") | |
print(f" π¨ MIME type: {part.inline_data.mime_type}") | |
else: | |
print(f" οΏ½οΏ½ Has inline data: β") | |
if hasattr(response, 'text') and response.text: | |
preview = response.text[:200] + "..." if len(response.text) > 200 else response.text | |
print(f" π Text preview: {preview}") | |
except Exception as api_error: | |
print(f"β API test failed: {str(api_error)}") | |
except Exception as e: | |
print(f"β Image capability test failed: {str(e)}") | |
if __name__ == "__main__": | |
# Run comprehensive tests | |
test_gemini_integration() | |
print("\n" + "=" * 60 + "\n") | |
test_actual_image_capability() |