WHG2023 commited on
Commit ·
137c880
1
Parent(s): 4252b44
feat: Implement full agentic workflow with dual image generation
Browse filesThis commit introduces a true, stateful agentic negotiation process orchestrated by a Chief Strategist Agent. Key features include Segmind Ideogram API integration for conceptual images, real-time LaTeX compilation for viewable technical figures, and a complete, strategy-aligned patent draft generation.
- app.py +168 -733
- real_ai_agents_implementation.py +282 -513
- requirements.txt +7 -6
app.py
CHANGED
|
@@ -2,670 +2,179 @@ import gradio as gr
|
|
| 2 |
import os
|
| 3 |
import requests
|
| 4 |
import json
|
| 5 |
-
from typing import Dict, List
|
| 6 |
from dotenv import load_dotenv
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
|
| 8 |
# Load environment variables from .env file
|
| 9 |
load_dotenv()
|
| 10 |
|
| 11 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
try:
|
| 13 |
from gemini_image_generator import GeminiImageGenerator
|
| 14 |
GEMINI_IMAGE_AVAILABLE = True
|
| 15 |
except ImportError:
|
| 16 |
GEMINI_IMAGE_AVAILABLE = False
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
#
|
| 31 |
-
|
| 32 |
-
from nebius_image_generator import integrate_with_patent_architect
|
| 33 |
-
NEBIUS_AVAILABLE = True
|
| 34 |
-
except ImportError:
|
| 35 |
-
NEBIUS_AVAILABLE = False
|
| 36 |
-
|
| 37 |
-
# Configuration for HuggingFace Spaces - no environment variables needed
|
| 38 |
-
|
| 39 |
-
# --- Configuration ---
|
| 40 |
-
# Using the clean Groq-only backend (reliable, no proxy issues)
|
| 41 |
-
MODAL_BACKEND_URL = "https://gebhardt-wolfh--patent-architect-groq-fastapi-app.modal.run"
|
| 42 |
-
# Alternative backends:
|
| 43 |
-
# - Nebius with images (experimental): "https://gebhardt-wolfh--patent-architect-nebius-clean-fastapi-app.modal.run"
|
| 44 |
-
# - Clean backend: "https://gebhardt-wolfh--patent-architect-clean-fastapi-app.modal.run"
|
| 45 |
-
|
| 46 |
-
# --- Enhanced Agent Personalities for Strategy Demo ---
|
| 47 |
-
AGENT_PERSONALITIES = {
|
| 48 |
-
"Technical Analysis Agent": {
|
| 49 |
-
"personality": "Technical Deep-Dive Specialist",
|
| 50 |
-
"thinking_style": "Analyzing technical mechanisms and specifications",
|
| 51 |
-
"catchphrase": "Understanding the physics behind the innovation",
|
| 52 |
-
"bias": "Demand detailed technical explanations and identify knowledge gaps",
|
| 53 |
-
"negotiation_weight": 0.20,
|
| 54 |
-
"expertise": "Technical feasibility, mechanism analysis, specification requirements"
|
| 55 |
-
},
|
| 56 |
-
"Prior Art Agent": {
|
| 57 |
-
"personality": "Patent Detective",
|
| 58 |
-
"thinking_style": "Comprehensive patent landscape analysis",
|
| 59 |
-
"catchphrase": "Finding every relevant patent and publication",
|
| 60 |
-
"bias": "Exhaustive prior art search across multiple technology domains",
|
| 61 |
-
"negotiation_weight": 0.25,
|
| 62 |
-
"expertise": "Patent databases, academic literature, international filings"
|
| 63 |
-
},
|
| 64 |
-
"Invention Summary Agent": {
|
| 65 |
-
"personality": "Technical Writer",
|
| 66 |
-
"thinking_style": "Creating precise technical narratives",
|
| 67 |
-
"catchphrase": "Crafting clear and compelling technical stories",
|
| 68 |
-
"bias": "Maximize technical clarity while highlighting true innovation",
|
| 69 |
-
"negotiation_weight": 0.15,
|
| 70 |
-
"expertise": "Technical writing, invention disclosure, differentiation"
|
| 71 |
-
},
|
| 72 |
-
"Figure Drafter Agent": {
|
| 73 |
-
"personality": "Technical Illustrator",
|
| 74 |
-
"thinking_style": "Designing patent drawings and diagrams",
|
| 75 |
-
"catchphrase": "Visual documentation of technical concepts",
|
| 76 |
-
"bias": "Ensure complete visual documentation of invention",
|
| 77 |
-
"negotiation_weight": 0.15,
|
| 78 |
-
"expertise": "Technical drawings, patent figures, visual communication"
|
| 79 |
-
},
|
| 80 |
-
"Claims Strategy Agent": {
|
| 81 |
-
"personality": "Patent Attorney",
|
| 82 |
-
"thinking_style": "Strategic patent claim optimization",
|
| 83 |
-
"catchphrase": "Crafting bulletproof patent claims",
|
| 84 |
-
"bias": "Balance broad protection with technical accuracy and grantability",
|
| 85 |
-
"negotiation_weight": 0.25,
|
| 86 |
-
"expertise": "Claim drafting, patent law, prosecution strategy"
|
| 87 |
-
}
|
| 88 |
-
}
|
| 89 |
-
|
| 90 |
-
# Enhanced IP Opportunity Categories with more specificity
|
| 91 |
-
IP_OPPORTUNITIES = [
|
| 92 |
-
{"type": "Core Technology Patent", "description": "Main invention with detailed technical claims"},
|
| 93 |
-
{"type": "Method Patents", "description": "Process and algorithmic innovations"},
|
| 94 |
-
{"type": "System Integration Patents", "description": "Combination with other technologies"},
|
| 95 |
-
{"type": "Application-Specific Patents", "description": "Industry-specific implementations"},
|
| 96 |
-
{"type": "Improvement Patents", "description": "Enhanced versions and optimizations"},
|
| 97 |
-
{"type": "Defensive Patents", "description": "Block competitor strategies"}
|
| 98 |
-
]
|
| 99 |
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
# If we have real AI results, use them for enhanced analysis
|
| 104 |
-
if real_ai_results and real_ai_results.get("available"):
|
| 105 |
-
markdown = f"### 🤖 Real AI Agent Analysis\n\n"
|
| 106 |
-
|
| 107 |
-
results = real_ai_results["results"]
|
| 108 |
-
readiness_score = real_ai_results["readiness_score"]
|
| 109 |
-
assessment = real_ai_results["assessment"]
|
| 110 |
-
|
| 111 |
-
# Technical Completeness
|
| 112 |
-
tech_analysis = real_ai_results.get("technical_analysis", {})
|
| 113 |
-
tech_score = tech_analysis.get("completeness_score", 0) * 100
|
| 114 |
-
risk_level = tech_analysis.get("prosecution_risk", "Unknown")
|
| 115 |
-
missing_elements = tech_analysis.get("missing_elements", [])
|
| 116 |
-
|
| 117 |
-
markdown += f"**🔬 Technical Completeness Agent:** {tech_score:.1f}%\n"
|
| 118 |
-
markdown += f"📊 Prosecution Risk: **{risk_level}**\n"
|
| 119 |
-
if missing_elements:
|
| 120 |
-
markdown += f"⚠️ Missing Critical Elements: {len(missing_elements)}\n"
|
| 121 |
-
for element in missing_elements[:2]: # Show first 2
|
| 122 |
-
markdown += f" • **{element.get('element_type', 'Unknown')}**: {element.get('suggestion', 'Needs improvement')}\n"
|
| 123 |
-
markdown += "\n"
|
| 124 |
-
|
| 125 |
-
# Prior Art Analysis
|
| 126 |
-
prior_art = real_ai_results.get("prior_art_analysis", {})
|
| 127 |
-
risk_assessment = prior_art.get("risk_assessment", {})
|
| 128 |
-
competitors = prior_art.get("key_competitors", [])
|
| 129 |
-
|
| 130 |
-
markdown += f"**🔍 Prior Art Landscape Agent:**\n"
|
| 131 |
-
markdown += f"📊 Risk Level: **{risk_assessment.get('overall_risk', 'Medium')}**\n"
|
| 132 |
-
if competitors:
|
| 133 |
-
markdown += f"🏢 Key Competitors: {len(competitors)}\n"
|
| 134 |
-
for comp in competitors[:2]: # Show first 2
|
| 135 |
-
markdown += f" • **{comp.get('company', 'Unknown')}**: {comp.get('patent_count', 0)} patents\n"
|
| 136 |
-
markdown += "\n"
|
| 137 |
-
|
| 138 |
-
# Claim Architecture
|
| 139 |
-
claim_analysis = real_ai_results.get("claim_analysis", {})
|
| 140 |
-
claim_strength = claim_analysis.get("claim_strength", {})
|
| 141 |
-
overall_strength = claim_strength.get("overall_strength", 0) * 100
|
| 142 |
-
|
| 143 |
-
markdown += f"**⚖️ Claim Architecture Agent:** {overall_strength:.1f}%\n"
|
| 144 |
-
markdown += f"📊 Grantability: **{claim_strength.get('grantability', 'Unknown')}**\n\n"
|
| 145 |
-
|
| 146 |
-
# Overall Assessment
|
| 147 |
-
markdown += f"**🎯 OVERALL READINESS ASSESSMENT:**\n"
|
| 148 |
-
markdown += f"**Score:** {readiness_score*100:.1f}% - **{assessment}**\n\n"
|
| 149 |
|
| 150 |
-
#
|
| 151 |
-
|
| 152 |
-
costs = results.get("estimated_costs", "Unknown")
|
| 153 |
-
markdown += f"**📈 Business Planning:**\n"
|
| 154 |
-
markdown += f"• **Timeline:** {timeline}\n"
|
| 155 |
-
markdown += f"• **Estimated Costs:** {costs}\n\n"
|
| 156 |
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
# Fallback to original negotiation display
|
| 167 |
-
total_weight = sum(AGENT_PERSONALITIES[agent["name"]]["negotiation_weight"] for agent in agent_responses if agent["name"] in AGENT_PERSONALITIES)
|
| 168 |
-
|
| 169 |
-
negotiations = []
|
| 170 |
-
for agent in agent_responses:
|
| 171 |
-
if agent["name"] in AGENT_PERSONALITIES:
|
| 172 |
-
personality = AGENT_PERSONALITIES[agent["name"]]
|
| 173 |
-
weight = personality["negotiation_weight"]
|
| 174 |
-
influence = (weight / total_weight) * 100 if total_weight > 0 else 0
|
| 175 |
-
|
| 176 |
-
# Enhanced negotiation points with technical depth
|
| 177 |
-
agent_type = agent["name"].split()[0].lower()
|
| 178 |
-
if agent_type == "technical":
|
| 179 |
-
position = f"Technical gaps identified: Missing mechanism details, frequency analysis specs, signal processing algorithms"
|
| 180 |
-
concern_level = "High"
|
| 181 |
-
elif agent_type == "prior":
|
| 182 |
-
num_patents = agent.get("num_patents", 1)
|
| 183 |
-
if num_patents < 10:
|
| 184 |
-
position = f"Shallow search: Only {num_patents} patents found. Missing ultrasonic sensors, acoustic emission, vibration analysis domains"
|
| 185 |
-
concern_level = "High"
|
| 186 |
-
else:
|
| 187 |
-
position = f"Comprehensive analysis: {num_patents} patents analyzed across multiple domains"
|
| 188 |
-
concern_level = "Low"
|
| 189 |
-
elif agent_type == "invention":
|
| 190 |
-
position = f"Technical clarity: Low - needs specific mechanism explanation, frequency ranges, sensor specifications"
|
| 191 |
-
concern_level = "Medium"
|
| 192 |
-
elif agent_type == "figure":
|
| 193 |
-
position = f"Visual documentation: Incomplete - needs actual technical drawings with numbered components"
|
| 194 |
-
concern_level = "Medium"
|
| 195 |
-
elif agent_type == "claims":
|
| 196 |
-
position = f"Claims analysis: Too broad, likely not novel - need specific technical limitations"
|
| 197 |
-
concern_level = "High"
|
| 198 |
-
else:
|
| 199 |
-
position = personality['bias']
|
| 200 |
-
concern_level = "Medium"
|
| 201 |
|
| 202 |
-
|
| 203 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 204 |
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
"concern_level": concern_level,
|
| 210 |
-
"status_color": status_color,
|
| 211 |
-
"status": "Reviewing" if len(agent_responses) <= 3 else "Complete"
|
| 212 |
-
})
|
| 213 |
-
|
| 214 |
-
# Build markdown display with detailed feedback
|
| 215 |
-
markdown = f"### Multi-Agent Technical Review (Step {len(agent_responses)}/5)\n\n"
|
| 216 |
-
|
| 217 |
-
for neg in negotiations:
|
| 218 |
-
status_text = "(Active Review)" if neg["status"] == "Reviewing" else "(Complete)"
|
| 219 |
-
markdown += f"**{neg['name']}** {status_text} - {neg['influence']:.0f}% influence {neg['status_color']}\n"
|
| 220 |
-
markdown += f"Assessment: {neg['position']}\n"
|
| 221 |
-
markdown += f"Concern Level: {neg['concern_level']}\n\n"
|
| 222 |
-
|
| 223 |
-
# Calculate realistic consensus based on technical concerns
|
| 224 |
-
high_concerns = sum(1 for neg in negotiations if neg['concern_level'] == 'High')
|
| 225 |
-
medium_concerns = sum(1 for neg in negotiations if neg['concern_level'] == 'Medium')
|
| 226 |
-
|
| 227 |
-
if high_concerns >= 2:
|
| 228 |
-
consensus_level = 45
|
| 229 |
-
patentability_score = 4.5
|
| 230 |
-
outcome = "Major technical gaps identified. Invention needs significant development before patent filing."
|
| 231 |
-
elif high_concerns == 1 and medium_concerns >= 1:
|
| 232 |
-
consensus_level = 65
|
| 233 |
-
patentability_score = 6.5
|
| 234 |
-
outcome = "Technical issues identified. Requires expert review and refinement."
|
| 235 |
-
elif medium_concerns >= 2:
|
| 236 |
-
consensus_level = 75
|
| 237 |
-
patentability_score = 7.5
|
| 238 |
-
outcome = "Good foundation with areas for improvement. Recommend technical enhancement."
|
| 239 |
-
else:
|
| 240 |
-
consensus_level = 85
|
| 241 |
-
patentability_score = 8.5
|
| 242 |
-
outcome = "Strong technical foundation. Ready for expert patent attorney review."
|
| 243 |
-
|
| 244 |
-
markdown += f"**Technical Consensus:** {consensus_level}% - **Realistic Patentability Score: {patentability_score:.1f}/10**\n\n"
|
| 245 |
-
markdown += f"**Outcome:** {outcome}\n\n"
|
| 246 |
-
|
| 247 |
-
# Add specific recommendations based on critique
|
| 248 |
-
markdown += "**Expert Recommendations:**\n"
|
| 249 |
-
if high_concerns >= 1:
|
| 250 |
-
markdown += "• Conduct deeper technical development before patent filing\n"
|
| 251 |
-
markdown += "• Engage patent attorney for comprehensive prior art search\n"
|
| 252 |
-
markdown += "• Define specific technical mechanism and parameters\n"
|
| 253 |
-
markdown += "• Identify true novel contribution vs. existing art\n"
|
| 254 |
-
else:
|
| 255 |
-
markdown += "• Ready for professional patent attorney review\n"
|
| 256 |
-
markdown += "• Consider filing provisional patent for priority\n"
|
| 257 |
-
|
| 258 |
return markdown
|
| 259 |
|
| 260 |
-
def
|
| 261 |
-
"""Generates IP opportunity cards from backend data."""
|
| 262 |
-
if not opportunities:
|
| 263 |
-
return ""
|
| 264 |
-
|
| 265 |
-
html = """
|
| 266 |
-
<div style="background: #f8f9fa; border-radius: 10px; padding: 20px; margin: 20px 0;">
|
| 267 |
-
<h4 style="color: #333; margin-bottom: 15px;">Discovered IP Opportunities</h4>
|
| 268 |
-
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 15px;">
|
| 269 |
"""
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
score = opp.get("score", 75)
|
| 273 |
-
color = "#28a745" if score >= 85 else "#ffc107" if score >= 75 else "#17a2b8"
|
| 274 |
-
|
| 275 |
-
opp_info = next((o for o in IP_OPPORTUNITIES if o["type"] == opp.get("type")), IP_OPPORTUNITIES[0])
|
| 276 |
-
|
| 277 |
-
html += f"""
|
| 278 |
-
<div style="background: white; border: 2px solid {color}; border-radius: 8px; padding: 15px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
|
| 279 |
-
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px;">
|
| 280 |
-
<h6 style="color: #333; margin: 0; font-size: 1.1em;">{opp.get('type', 'Opportunity')}</h6>
|
| 281 |
-
<span style="background: {color}; color: white; padding: 3px 8px; border-radius: 12px; font-size: 0.8em; font-weight: bold;">
|
| 282 |
-
{score}/100
|
| 283 |
-
</span>
|
| 284 |
-
</div>
|
| 285 |
-
<p style="color: #666; font-size: 0.9em; margin: 5px 0;">{opp.get('description', '')}</p>
|
| 286 |
-
<p style="color: #28a745; font-weight: bold; font-size: 0.8em; margin: 5px 0;">
|
| 287 |
-
Market: {opp.get('market_size', 'N/A')}
|
| 288 |
-
</p>
|
| 289 |
-
</div>
|
| 290 |
-
"""
|
| 291 |
-
|
| 292 |
-
html += """
|
| 293 |
-
</div>
|
| 294 |
-
</div>
|
| 295 |
"""
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
try:
|
| 304 |
-
# Initialize the coordinator
|
| 305 |
-
coordinator = InterAgentCoordinator()
|
| 306 |
-
|
| 307 |
-
# Run comprehensive analysis
|
| 308 |
-
results = coordinator.orchestrate_patent_development(invention_disclosure)
|
| 309 |
-
|
| 310 |
-
return {
|
| 311 |
-
"available": True,
|
| 312 |
-
"results": results,
|
| 313 |
-
"readiness_score": results.get("overall_readiness_score", 0),
|
| 314 |
-
"assessment": results.get("readiness_assessment", "Unknown"),
|
| 315 |
-
"technical_analysis": results.get("technical_completeness", {}),
|
| 316 |
-
"prior_art_analysis": results.get("prior_art_landscape", {}),
|
| 317 |
-
"claim_analysis": results.get("claim_architecture", {})
|
| 318 |
-
}
|
| 319 |
-
except Exception as e:
|
| 320 |
-
return {"available": False, "error": str(e)}
|
| 321 |
|
| 322 |
-
|
| 323 |
-
"""Enhanced patent section formatting with technical analysis and image generation."""
|
| 324 |
-
|
| 325 |
-
# Enhanced Figure Drafter Agent with Gemini and Nebius integration
|
| 326 |
-
if agent_name == "Figure Drafter Agent":
|
| 327 |
-
try:
|
| 328 |
-
# Try Gemini first (preferred for high-quality patent figures)
|
| 329 |
-
if GEMINI_IMAGE_AVAILABLE and os.environ.get("GEMINI_API_KEY"):
|
| 330 |
-
try:
|
| 331 |
-
print("🎨 Activating Gemini 2.0 Flash for patent figure generation...")
|
| 332 |
-
generator = GeminiImageGenerator()
|
| 333 |
-
|
| 334 |
-
# Extract invention description from content or use a default
|
| 335 |
-
# Look for invention context in the content
|
| 336 |
-
if "SUMMARY OF THE INVENTION" in content:
|
| 337 |
-
# Extract from summary section
|
| 338 |
-
start = content.find("SUMMARY OF THE INVENTION") + len("SUMMARY OF THE INVENTION")
|
| 339 |
-
end = content.find("'. This would include", start) if "'. This would include" in content[start:] else len(content)
|
| 340 |
-
invention_context = content[start:end].strip()[:800]
|
| 341 |
-
# Clean up the context
|
| 342 |
-
invention_context = invention_context.replace("The present invention relates to", "").replace("The present invention provides", "").strip()
|
| 343 |
-
else:
|
| 344 |
-
# Fallback: extract a reasonable description from the available content
|
| 345 |
-
invention_context = "Passive acoustic liquid level detection system with machine learning analysis"
|
| 346 |
-
|
| 347 |
-
print(f"🔍 Extracted invention context: {invention_context[:100]}...")
|
| 348 |
-
|
| 349 |
-
gemini_result = generator.integrate_with_patent_architect(invention_context)
|
| 350 |
-
|
| 351 |
-
if gemini_result.get("success"):
|
| 352 |
-
# COMPLETELY REPLACE the backend content with Gemini-generated content
|
| 353 |
-
content = gemini_result["content"]
|
| 354 |
-
|
| 355 |
-
# Check if we have dual output (descriptions + LaTeX)
|
| 356 |
-
if gemini_result.get("dual_output"):
|
| 357 |
-
# Enhanced dual output available
|
| 358 |
-
descriptions_available = gemini_result.get("descriptions_available", 0)
|
| 359 |
-
latex_available = gemini_result.get("latex_code_available", 0)
|
| 360 |
-
compiled_images = gemini_result.get("compiled_images", 0)
|
| 361 |
-
|
| 362 |
-
content += f"\n\n*🚀 Enhanced Dual Output: {descriptions_available} technical descriptions + {latex_available} LaTeX/TikZ code sets generated*\n\n"
|
| 363 |
-
|
| 364 |
-
if compiled_images > 0:
|
| 365 |
-
content += f"*🖼️ {compiled_images} figures successfully compiled to images - View immediately in output folder*\n\n"
|
| 366 |
-
|
| 367 |
-
content += f"*💡 Best Experience: Read descriptions above, then use LaTeX code with Overleaf.com for professional figures*\n\n"
|
| 368 |
-
|
| 369 |
-
# Update thought to reflect dual output
|
| 370 |
-
thought = f"Generated comprehensive dual output with {descriptions_available} detailed technical descriptions AND {latex_available} professional LaTeX/TikZ code sets. Users can read descriptions immediately and compile LaTeX for USPTO-ready vector graphics."
|
| 371 |
-
|
| 372 |
-
elif gemini_result.get("images_generated", 0) > 0:
|
| 373 |
-
if gemini_result.get("latex_generated", 0) > 0:
|
| 374 |
-
content += "\n\n*🎨 Generated LaTeX/TikZ code using Google Gemini 2.0 Flash - Compile with pdflatex to create professional patent figures*\n\n"
|
| 375 |
-
content += f"*💡 To view images: Compile the .tex files in `{os.path.expanduser('~')}/patent_architect_figures/`*\n\n"
|
| 376 |
-
thought = "Generated professional LaTeX/TikZ code for patent figures using Google Gemini 2.0 Flash. Code can be compiled to create high-quality technical drawings with numbered components and USPTO-ready formatting."
|
| 377 |
-
else:
|
| 378 |
-
content += "\n\n*🎨 Generated visual patent figures using Google Gemini 2.0 Flash - Professional images ready for USPTO submission*\n\n"
|
| 379 |
-
thought = "Generated high-quality patent figures using Google Gemini 2.0 Flash with professional technical drawings, numbered components, and USPTO-ready formatting."
|
| 380 |
-
else:
|
| 381 |
-
content += "\n\n*📝 Generated detailed patent figure descriptions using Google Gemini 2.0 Flash - Professional technical specifications*\n\n"
|
| 382 |
-
thought = "Generated detailed technical specifications for patent figures using Google Gemini 2.0 Flash with professional patent formatting."
|
| 383 |
-
|
| 384 |
-
print("✅ Gemini image generation successful - Backend content replaced")
|
| 385 |
-
|
| 386 |
-
else:
|
| 387 |
-
print(f"❌ Gemini generation failed: {gemini_result.get('error', 'Unknown error')}")
|
| 388 |
-
|
| 389 |
-
except Exception as e:
|
| 390 |
-
print(f"❌ Gemini integration error: {e}")
|
| 391 |
-
|
| 392 |
-
# Fallback to Nebius if Gemini failed or unavailable
|
| 393 |
-
elif NEBIUS_AVAILABLE and not image_urls:
|
| 394 |
-
try:
|
| 395 |
-
if "figure" in content.lower() or "drawing" in content.lower():
|
| 396 |
-
figure_descriptions = [
|
| 397 |
-
"Cross-sectional view showing main components",
|
| 398 |
-
"System diagram showing connections"
|
| 399 |
-
]
|
| 400 |
-
|
| 401 |
-
from dotenv import load_dotenv
|
| 402 |
-
load_dotenv()
|
| 403 |
-
|
| 404 |
-
if os.environ.get("NEBIUS_API_KEY"):
|
| 405 |
-
nebius_result = integrate_with_patent_architect(
|
| 406 |
-
invention_description="Technical invention with numbered components",
|
| 407 |
-
figure_descriptions=figure_descriptions
|
| 408 |
-
)
|
| 409 |
-
|
| 410 |
-
if nebius_result.get("success"):
|
| 411 |
-
content = nebius_result["content"]
|
| 412 |
-
image_urls = nebius_result.get("image_urls", [])
|
| 413 |
-
content += "\n\n*🖼️ Generated using Nebius AI - Enhanced with visual diagrams*\n\n"
|
| 414 |
-
print("✅ Nebius image generation successful")
|
| 415 |
-
|
| 416 |
-
except Exception as e:
|
| 417 |
-
print(f"❌ Nebius integration error: {e}")
|
| 418 |
-
|
| 419 |
-
# If no image generation available, enhance the text-based content
|
| 420 |
-
else:
|
| 421 |
-
# Check if this is Groq's "no image generation" content
|
| 422 |
-
if "image generation is not available with groq" in content.lower() or "since image generation is not available" in content.lower():
|
| 423 |
-
# Replace Groq's limitation message with enhancement message
|
| 424 |
-
content = content.replace(
|
| 425 |
-
"Generated detailed text descriptions for patent figures since image generation is not available with Groq.",
|
| 426 |
-
"Enhanced patent figure descriptions with detailed technical specifications."
|
| 427 |
-
)
|
| 428 |
-
content = content.replace(
|
| 429 |
-
"Since image generation is not available with Groq, here are detailed descriptions",
|
| 430 |
-
"Enhanced technical figure descriptions with professional patent formatting"
|
| 431 |
-
)
|
| 432 |
-
content += f"\n\n*💡 To enable professional image generation: Set GEMINI_API_KEY environment variable and get API key from https://makersuite.google.com/app/apikey*\n\n"
|
| 433 |
-
|
| 434 |
-
# Add critique-based improvements to figure descriptions
|
| 435 |
-
content += "\n\n### 🎯 Figure Enhancement Recommendations:\n"
|
| 436 |
-
content += "• **Missing Elements:** Numbered components, dimension lines, material callouts\n"
|
| 437 |
-
content += "• **Technical Precision:** Frequency response curves, signal processing flow\n"
|
| 438 |
-
content += "• **Patent Standards:** USPTO figure requirements compliance\n"
|
| 439 |
-
content += "• **Professional Quality:** Vector graphics suitable for patent submission\n\n"
|
| 440 |
-
|
| 441 |
-
print("✅ Enhanced Groq content with detailed recommendations")
|
| 442 |
-
|
| 443 |
-
except Exception as e:
|
| 444 |
-
print(f"❌ Figure generation error: {e}")
|
| 445 |
-
content += f"\n\n*⚠️ Image generation unavailable. Please check API configuration.*\n\n"
|
| 446 |
-
|
| 447 |
-
# Enhanced Prior Art Agent feedback
|
| 448 |
-
elif agent_name == "Prior Art Agent":
|
| 449 |
-
# Count sources and provide detailed analysis
|
| 450 |
-
num_sources = len(sources) if sources else 0
|
| 451 |
-
|
| 452 |
-
if num_sources < 10:
|
| 453 |
-
content += f"\n\n### ⚠️ Prior Art Search Limitations:\n"
|
| 454 |
-
content += f"• **Sources Found:** Only {num_sources} patents/publications\n"
|
| 455 |
-
content += f"• **Missing Domains:** Ultrasonic sensors, acoustic emission monitoring, vibration analysis\n"
|
| 456 |
-
content += f"• **Incomplete Coverage:** International patents, academic literature, industry standards\n"
|
| 457 |
-
content += f"• **Recommendation:** Comprehensive search required before filing\n\n"
|
| 458 |
-
|
| 459 |
-
content += f"### 🔍 Suggested Additional Search Terms:\n"
|
| 460 |
-
content += f"• Ultrasonic level detection patents\n"
|
| 461 |
-
content += f"• Acoustic emission sensors\n"
|
| 462 |
-
content += f"• Passive vibration monitoring\n"
|
| 463 |
-
content += f"• Machine learning signal processing\n"
|
| 464 |
-
content += f"• Non-invasive liquid measurement\n\n"
|
| 465 |
-
|
| 466 |
-
# Enhanced Claims Strategy Agent feedback
|
| 467 |
-
elif agent_name == "Claims Drafter Agent": # Fixed: Backend sends "Claims Drafter Agent"
|
| 468 |
-
# Analyze claims for common issues
|
| 469 |
-
if "acoustic sensor" in content.lower() and "passive" in content.lower():
|
| 470 |
-
content += f"\n\n### ⚠️ Claims Analysis - Critical Issues:\n"
|
| 471 |
-
content += f"• **Overly Broad:** Claims 1 likely lacks novelty (passive acoustic sensors exist)\n"
|
| 472 |
-
content += f"• **Missing Specificity:** No technical limitations on frequency analysis method\n"
|
| 473 |
-
content += f"• **Weak Differentiation:** Doesn't capture unique ML training approach\n"
|
| 474 |
-
content += f"• **Patent Risk:** Current claims may be rejected for obviousness\n\n"
|
| 475 |
-
|
| 476 |
-
content += f"### 🎯 Recommended Claim Improvements:\n"
|
| 477 |
-
content += f"• Focus on specific frequency change detection method\n"
|
| 478 |
-
content += f"• Add ML model architecture and training claims\n"
|
| 479 |
-
content += f"• Include anomaly detection for bubbles/splashes\n"
|
| 480 |
-
content += f"• Define technical parameters (frequency ranges, sensitivity)\n\n"
|
| 481 |
-
|
| 482 |
-
# Format agent response with enhanced personality
|
| 483 |
-
if agent_name in AGENT_PERSONALITIES:
|
| 484 |
-
personality = AGENT_PERSONALITIES[agent_name]
|
| 485 |
-
|
| 486 |
-
formatted = f"### {agent_name}\n\n"
|
| 487 |
-
|
| 488 |
-
# Add thinking process if available
|
| 489 |
-
if thought:
|
| 490 |
-
formatted += f"**Agent Analysis:**\n{thought}\n\n"
|
| 491 |
-
|
| 492 |
-
formatted += content
|
| 493 |
-
|
| 494 |
-
# Add enhanced strategy note with expertise
|
| 495 |
-
formatted += f"\n\n*Strategy: {personality['bias']}*\n"
|
| 496 |
-
formatted += f"*Expertise: {personality.get('expertise', 'General patent analysis')}*\n\n"
|
| 497 |
-
|
| 498 |
-
else:
|
| 499 |
-
# Fallback for unknown agents
|
| 500 |
-
formatted = f"### {agent_name}\n\n"
|
| 501 |
-
if thought:
|
| 502 |
-
formatted += f"**Analysis:** {thought}\n\n"
|
| 503 |
-
formatted += content
|
| 504 |
-
|
| 505 |
-
# Add sources if available with enhanced formatting
|
| 506 |
-
if sources and len(sources) > 0:
|
| 507 |
-
formatted += "\n\n**📚 Prior Art Sources:**\n"
|
| 508 |
-
for i, source in enumerate(sources, 1):
|
| 509 |
-
if source.get('url'):
|
| 510 |
-
formatted += f"{i}. [{source.get('title', 'Patent Source')}]({source.get('url')})\n"
|
| 511 |
-
|
| 512 |
-
# Add search quality assessment
|
| 513 |
-
if len(sources) < 10:
|
| 514 |
-
formatted += f"\n*⚠️ Limited search results ({len(sources)} sources). Comprehensive search recommended.*\n"
|
| 515 |
-
|
| 516 |
-
return formatted
|
| 517 |
|
| 518 |
-
def run_patent_architect_in_ui(invention_disclosure):
|
| 519 |
-
"""Enhanced UI function with agent personalities and IP discovery."""
|
| 520 |
if not invention_disclosure:
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
"opportunities": gr.HTML.update(value="<h3>IP Opportunities</h3><p>Enter invention to discover patent opportunities</p>"),
|
| 524 |
-
"negotiation": gr.Markdown.update(value="### Agent Negotiation\n\nAgents will negotiate optimal strategy"),
|
| 525 |
-
"prior_art": gr.Markdown.update(value="### Prior Art Analysis\n\n*This section will show the analysis of existing patents and technologies related to your invention.*"),
|
| 526 |
-
"summary": gr.Markdown.update(value="### Invention Summary\n\n*This section will contain the professional Background of the Invention and Summary of the Invention sections.*"),
|
| 527 |
-
"figures": gr.Markdown.update(value="### Technical Figures\n\n*This section will display the generated patent-style technical drawings with numbered components.*"),
|
| 528 |
-
"claims": gr.Markdown.update(value="### Patent Claims\n\n*This section will contain the numbered patent claims that legally define the scope of your invention.*"),
|
| 529 |
-
"status": "Enhanced Patent Architect v2 - Ready for rigorous technical analysis",
|
| 530 |
-
}
|
| 531 |
-
yield list(outputs.values())
|
| 532 |
return
|
| 533 |
|
| 534 |
-
if not
|
| 535 |
-
|
| 536 |
-
|
|
|
|
| 537 |
return
|
| 538 |
-
|
| 539 |
-
# Initialize all sections with clean interface
|
| 540 |
-
opportunities_html = create_ip_opportunity_cards([])
|
| 541 |
-
|
| 542 |
-
# Run real AI analysis if available
|
| 543 |
-
real_ai_results = None
|
| 544 |
-
if REAL_AI_AGENTS_AVAILABLE:
|
| 545 |
-
status = "🤖 Running Real AI Agent Analysis..."
|
| 546 |
-
yield opportunities_html, "### Real AI Analysis\n\nRunning comprehensive technical analysis...", "### Prior Art Analysis\n\n*Waiting for technical analysis...*", "### Invention Summary\n\n*Waiting for analysis...*", "### Technical Figures\n\n*Waiting for analysis...*", "### Patent Claims\n\n*Waiting for analysis...*", status
|
| 547 |
|
| 548 |
-
|
| 549 |
-
|
| 550 |
-
if real_ai_results.get("available"):
|
| 551 |
-
status = f"✅ Real AI Analysis Complete - Readiness: {real_ai_results['readiness_score']*100:.1f}%"
|
| 552 |
-
else:
|
| 553 |
-
status = f"⚠️ Real AI Analysis Failed: {real_ai_results.get('error', 'Unknown error')}"
|
| 554 |
|
| 555 |
-
|
| 556 |
-
|
| 557 |
-
|
| 558 |
-
|
| 559 |
-
|
| 560 |
-
|
| 561 |
-
|
| 562 |
-
yield opportunities_html, negotiation_display, prior_art_section, summary_section, figures_section, claims_section, status
|
| 563 |
-
|
| 564 |
-
try:
|
| 565 |
-
print(f"Connecting to Patent Architect backend: {MODAL_BACKEND_URL}")
|
| 566 |
|
| 567 |
-
#
|
| 568 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 569 |
|
| 570 |
-
|
| 571 |
-
f"{
|
| 572 |
-
json={"invention_disclosure": invention_disclosure},
|
| 573 |
-
timeout=1800, # 30 minute timeout for full patent generation
|
| 574 |
-
stream=True
|
| 575 |
-
) as response:
|
| 576 |
-
response.raise_for_status()
|
| 577 |
|
| 578 |
-
|
| 579 |
-
|
| 580 |
-
|
| 581 |
-
|
| 582 |
-
|
| 583 |
-
|
| 584 |
-
|
| 585 |
-
|
| 586 |
-
|
| 587 |
-
|
| 588 |
-
|
| 589 |
-
|
| 590 |
-
|
| 591 |
-
|
| 592 |
-
|
| 593 |
-
|
| 594 |
-
|
| 595 |
-
|
| 596 |
-
|
| 597 |
-
|
| 598 |
-
|
| 599 |
-
|
| 600 |
-
|
| 601 |
-
opportunities_html = create_ip_opportunity_cards(opportunities)
|
| 602 |
-
prior_art_section = "### Prior Art Analysis\n\n*Prior Art Specialist is searching patent databases...*"
|
| 603 |
-
status = f"Step {step_info} Complete: IP Opportunity Agent found {len(opportunities)} new avenues"
|
| 604 |
-
yield opportunities_html, negotiation_display, prior_art_section, summary_section, figures_section, claims_section, status
|
| 605 |
-
continue
|
| 606 |
-
|
| 607 |
-
agent_name = data.get("agent_name", "Patent Agent")
|
| 608 |
-
content = data.get("content", "")
|
| 609 |
-
thought = data.get("thought", "")
|
| 610 |
-
sources = data.get("sources", [])
|
| 611 |
-
image_urls = data.get("image_urls", [])
|
| 612 |
-
|
| 613 |
-
formatted_content = format_patent_section(agent_name, content, thought, sources, image_urls)
|
| 614 |
-
|
| 615 |
-
# Update the appropriate section based on the agent's designated section_type
|
| 616 |
-
if section_type == "prior_art":
|
| 617 |
-
prior_art_section = formatted_content
|
| 618 |
-
summary_section = "### Invention Summary\n\n*Technical Writer is crafting your invention story...*"
|
| 619 |
-
|
| 620 |
-
# Update negotiation based on real patent count
|
| 621 |
-
num_patents = len(sources)
|
| 622 |
-
agent_responses = [{"name": agent_name, "num_patents": num_patents}]
|
| 623 |
-
negotiation_display = create_agent_negotiation_display(agent_responses, real_ai_results)
|
| 624 |
-
|
| 625 |
-
elif section_type == "summary":
|
| 626 |
-
summary_section = formatted_content
|
| 627 |
-
figures_section = "### Technical Figures\n\n*Technical Illustrator is designing patent drawings...*"
|
| 628 |
-
|
| 629 |
-
# This assumes prior_art ran first and initialized agent_responses
|
| 630 |
-
agent_responses.append({"name": agent_name})
|
| 631 |
-
negotiation_display = create_agent_negotiation_display(agent_responses, real_ai_results)
|
| 632 |
-
|
| 633 |
-
elif section_type == "figures":
|
| 634 |
-
figures_section = formatted_content
|
| 635 |
-
claims_section = "### Patent Claims\n\n*Patent Attorney is optimizing claim scope...*"
|
| 636 |
-
|
| 637 |
-
agent_responses.append({"name": agent_name})
|
| 638 |
-
negotiation_display = create_agent_negotiation_display(agent_responses, real_ai_results)
|
| 639 |
-
|
| 640 |
-
elif section_type == "claims":
|
| 641 |
-
claims_section = formatted_content
|
| 642 |
-
|
| 643 |
-
agent_responses.append({"name": agent_name})
|
| 644 |
-
negotiation_display = create_agent_negotiation_display(agent_responses, real_ai_results)
|
| 645 |
-
|
| 646 |
-
# Enhanced status with agent personality
|
| 647 |
-
if agent_name in AGENT_PERSONALITIES:
|
| 648 |
-
personality = AGENT_PERSONALITIES[agent_name]["personality"]
|
| 649 |
-
status = f"Step {step_info} Complete: {personality} has finished their analysis"
|
| 650 |
-
else:
|
| 651 |
-
status = f"Step {step_info} Complete: {agent_name} finished"
|
| 652 |
-
|
| 653 |
-
elif event_status == "assembling":
|
| 654 |
-
status = event.get("log", "Assembling patent application...")
|
| 655 |
-
|
| 656 |
-
elif event_status == "complete":
|
| 657 |
-
status = "Patent Application Complete - Ready for review and filing"
|
| 658 |
-
|
| 659 |
-
yield opportunities_html, negotiation_display, prior_art_section, summary_section, figures_section, claims_section, status
|
| 660 |
-
|
| 661 |
-
except json.JSONDecodeError as e:
|
| 662 |
-
print(f"Could not decode JSON from stream: {decoded_line}")
|
| 663 |
-
continue
|
| 664 |
|
| 665 |
-
|
| 666 |
-
|
| 667 |
-
status = "Connection Failed"
|
| 668 |
-
yield opportunities_html, negotiation_display, prior_art_section, summary_section, figures_section, claims_section, status
|
| 669 |
|
| 670 |
with gr.Blocks(theme=gr.themes.Base(primary_hue="green", neutral_hue="slate"), title="Patent Architect v2") as demo:
|
| 671 |
gr.HTML("""
|
|
@@ -709,7 +218,7 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="green", neutral_hue="slate"), t
|
|
| 709 |
color: #00ff41;
|
| 710 |
opacity: 0.8;
|
| 711 |
position: relative;
|
| 712 |
-
z-index: 1;">POWERED BY GEMINI
|
| 713 |
</div>
|
| 714 |
""")
|
| 715 |
|
|
@@ -795,25 +304,17 @@ with gr.Blocks(theme=gr.themes.Base(primary_hue="green", neutral_hue="slate"), t
|
|
| 795 |
invention_input = gr.Textbox(
|
| 796 |
lines=12,
|
| 797 |
label="Neural Disclosure Interface",
|
| 798 |
-
placeholder="""
|
| 799 |
-
|
| 800 |
-
|
| 801 |
-
▶ Technical architecture and component flow
|
| 802 |
-
▶ Novelty differentiators vs existing systems
|
| 803 |
-
▶ Advantage metrics and performance data
|
| 804 |
-
▶ Technical specifications and parameters
|
| 805 |
-
|
| 806 |
-
EXAMPLE NEURAL INPUT: "Autonomous beverage temperature regulation system utilizing phase-change material matrices with neural app integration, eliminating thermal degradation issues through adaptive preference algorithms..."
|
| 807 |
-
""",
|
| 808 |
-
info="Enhanced neural processing requires detailed technical specifications"
|
| 809 |
)
|
| 810 |
|
| 811 |
-
generate_btn = gr.Button("INITIATE
|
| 812 |
|
| 813 |
status_display = gr.Textbox(
|
| 814 |
label="System Status",
|
| 815 |
interactive=False,
|
| 816 |
-
value="
|
| 817 |
)
|
| 818 |
|
| 819 |
gr.HTML("""
|
|
@@ -824,7 +325,6 @@ EXAMPLE NEURAL INPUT: "Autonomous beverage temperature regulation system utilizi
|
|
| 824 |
</div>
|
| 825 |
""")
|
| 826 |
|
| 827 |
-
# Enhanced Technical Intelligence Dashboard
|
| 828 |
gr.HTML("""
|
| 829 |
<div style="background: linear-gradient(45deg, #0a0a0a, #1a1a1a);
|
| 830 |
border: 1px solid #ff8c00;
|
|
@@ -836,25 +336,14 @@ EXAMPLE NEURAL INPUT: "Autonomous beverage temperature regulation system utilizi
|
|
| 836 |
text-shadow: 0 0 5px #ff8c00;
|
| 837 |
font-size: 1.6em;
|
| 838 |
margin: 0;
|
| 839 |
-
text-transform: uppercase;">
|
| 840 |
</div>
|
| 841 |
""")
|
| 842 |
|
| 843 |
with gr.Row():
|
| 844 |
-
with gr.Column():
|
| 845 |
-
|
| 846 |
-
|
| 847 |
-
border: 1px solid #00ff41;
|
| 848 |
-
padding: 15px;
|
| 849 |
-
color: #00ff41;
|
| 850 |
-
font-family: 'Courier New', monospace;">
|
| 851 |
-
<h3 style="color: #00ff41; margin: 0;">IP OPPORTUNITY MATRIX</h3>
|
| 852 |
-
<p style="color: #ff8c00;">Patent vectors will materialize here</p>
|
| 853 |
-
</div>
|
| 854 |
-
""")
|
| 855 |
-
with gr.Column():
|
| 856 |
-
negotiation_display = gr.Markdown("### AGENT NEGOTIATION PROTOCOL\n\nMulti-agent consensus algorithm initializing...")
|
| 857 |
-
|
| 858 |
gr.HTML("""
|
| 859 |
<div style="height: 2px;
|
| 860 |
background: linear-gradient(90deg, #ff8c00, #ffff00, #00ff41, #ff8c00);
|
|
@@ -874,47 +363,46 @@ EXAMPLE NEURAL INPUT: "Autonomous beverage temperature regulation system utilizi
|
|
| 874 |
text-shadow: 0 0 5px #00ff41;
|
| 875 |
font-size: 1.6em;
|
| 876 |
margin: 0;
|
| 877 |
-
text-transform: uppercase;">
|
| 878 |
</div>
|
| 879 |
""")
|
| 880 |
|
| 881 |
with gr.Tabs():
|
| 882 |
-
with gr.TabItem("PRIOR ART
|
| 883 |
prior_art_output = gr.Markdown(
|
| 884 |
-
value="### Prior Art Analysis\n\
|
| 885 |
)
|
| 886 |
with gr.TabItem("TECHNICAL SUMMARY"):
|
| 887 |
summary_output = gr.Markdown(
|
| 888 |
-
value="### Invention Summary\n\
|
| 889 |
)
|
| 890 |
with gr.TabItem("TECHNICAL FIGURES"):
|
| 891 |
figures_output = gr.Markdown(
|
| 892 |
-
value="### Technical Figures\n\
|
| 893 |
)
|
| 894 |
with gr.TabItem("PATENT CLAIMS"):
|
| 895 |
claims_output = gr.Markdown(
|
| 896 |
-
value="### Patent Claims\n\
|
| 897 |
)
|
| 898 |
|
| 899 |
generate_btn.click(
|
| 900 |
fn=run_patent_architect_in_ui,
|
| 901 |
inputs=[invention_input],
|
| 902 |
-
outputs=[
|
| 903 |
)
|
| 904 |
|
| 905 |
gr.Examples(
|
| 906 |
[
|
| 907 |
-
["
|
| 908 |
-
["A modular vertical farming system with adaptive LED lighting using full-spectrum arrays (400-700nm) controlled by neural network analysis of plant reflectance spectra. The system employs RGB+NIR sensors to monitor chlorophyll content and adjusts light intensity (50-1000 μmol/m²/s) and spectrum ratios based on growth stage detection. Machine learning models trained on 500+ crop cycles optimize photosynthetic photon flux density while reducing energy consumption by 35% compared to static lighting systems."],
|
| 909 |
-
["A real-time presentation skills assessment device using micro-expression analysis with 60fps facial recognition and voice stress analysis at 16kHz sampling. The system employs convolutional neural networks trained on 10,000+ presentation recordings to detect confidence indicators including facial micro-movements, vocal pitch variations (±50Hz accuracy), and gesture patterns. Feedback is provided through bone conduction audio and haptic vibration patterns calibrated to individual baseline metrics."],
|
| 910 |
],
|
| 911 |
inputs=[invention_input],
|
| 912 |
-
label="
|
| 913 |
)
|
| 914 |
|
| 915 |
gr.HTML("""
|
| 916 |
<style>
|
| 917 |
-
/*
|
| 918 |
.gradio-button.primary {
|
| 919 |
background: linear-gradient(45deg, #00ff41, #ffff00) !important;
|
| 920 |
border: 2px solid #00ff41 !important;
|
|
@@ -935,13 +423,11 @@ EXAMPLE NEURAL INPUT: "Autonomous beverage temperature regulation system utilizi
|
|
| 935 |
border-color: #ffff00 !important;
|
| 936 |
}
|
| 937 |
|
| 938 |
-
/* Dark theme for the overall interface */
|
| 939 |
.gradio-container {
|
| 940 |
background: #0a0a0a !important;
|
| 941 |
font-family: 'Courier New', monospace !important;
|
| 942 |
}
|
| 943 |
|
| 944 |
-
/* Tab styling */
|
| 945 |
.tab-nav button {
|
| 946 |
background: linear-gradient(45deg, #1a1a1a, #0a0a0a) !important;
|
| 947 |
border: 1px solid #00ff41 !important;
|
|
@@ -957,7 +443,6 @@ EXAMPLE NEURAL INPUT: "Autonomous beverage temperature regulation system utilizi
|
|
| 957 |
box-shadow: 0 0 10px #00ff41 !important;
|
| 958 |
}
|
| 959 |
|
| 960 |
-
/* Input field styling */
|
| 961 |
.gr-textbox {
|
| 962 |
background: linear-gradient(45deg, #0a0a0a, #1a1a1a) !important;
|
| 963 |
border: 1px solid #00ff41 !important;
|
|
@@ -970,69 +455,19 @@ EXAMPLE NEURAL INPUT: "Autonomous beverage temperature regulation system utilizi
|
|
| 970 |
box-shadow: 0 0 10px #ffff00 !important;
|
| 971 |
}
|
| 972 |
|
| 973 |
-
/* Remove default fonts and prevent loading errors */
|
| 974 |
* {
|
| 975 |
font-family: 'Courier New', monospace !important;
|
| 976 |
}
|
| 977 |
-
|
| 978 |
-
/* Scanline effect overlay */
|
| 979 |
-
body::before {
|
| 980 |
-
content: '';
|
| 981 |
-
position: fixed;
|
| 982 |
-
top: 0;
|
| 983 |
-
left: 0;
|
| 984 |
-
width: 100%;
|
| 985 |
-
height: 100%;
|
| 986 |
-
background: repeating-linear-gradient(
|
| 987 |
-
0deg,
|
| 988 |
-
transparent,
|
| 989 |
-
transparent 2px,
|
| 990 |
-
rgba(0,255,65,0.03) 2px,
|
| 991 |
-
rgba(0,255,65,0.03) 4px
|
| 992 |
-
);
|
| 993 |
-
pointer-events: none;
|
| 994 |
-
z-index: 1000;
|
| 995 |
-
}
|
| 996 |
</style>
|
| 997 |
-
|
| 998 |
-
<script>
|
| 999 |
-
// Suppress browser errors and warnings
|
| 1000 |
-
const originalConsoleError = console.error;
|
| 1001 |
-
console.error = function(...args) {
|
| 1002 |
-
const message = args.join(' ');
|
| 1003 |
-
if (message.includes('manifest.json') ||
|
| 1004 |
-
message.includes('Failed to load resource') ||
|
| 1005 |
-
message.includes('postMessage') ||
|
| 1006 |
-
message.includes('preload CSS') ||
|
| 1007 |
-
message.includes('.woff2')) {
|
| 1008 |
-
return; // Skip these specific errors
|
| 1009 |
-
}
|
| 1010 |
-
originalConsoleError.apply(console, args);
|
| 1011 |
-
};
|
| 1012 |
-
|
| 1013 |
-
// Add glitch effect to title
|
| 1014 |
-
document.addEventListener('DOMContentLoaded', function() {
|
| 1015 |
-
const title = document.querySelector('h1');
|
| 1016 |
-
if (title) {
|
| 1017 |
-
setInterval(() => {
|
| 1018 |
-
if (Math.random() < 0.1) {
|
| 1019 |
-
title.style.textShadow = '2px 0 #ff8c00, -2px 0 #00ff41';
|
| 1020 |
-
setTimeout(() => {
|
| 1021 |
-
title.style.textShadow = '0 0 10px #00ff41, 0 0 20px #00ff41, 0 0 30px #00ff41';
|
| 1022 |
-
}, 100);
|
| 1023 |
-
}
|
| 1024 |
-
}, 2000);
|
| 1025 |
-
}
|
| 1026 |
-
});
|
| 1027 |
-
</script>
|
| 1028 |
""")
|
| 1029 |
|
| 1030 |
if __name__ == "__main__":
|
| 1031 |
-
print("PATENT ARCHITECT v2 -
|
| 1032 |
-
print(f"Backend: {
|
| 1033 |
-
|
| 1034 |
-
|
| 1035 |
-
|
|
|
|
| 1036 |
demo.queue().launch(
|
| 1037 |
share=False,
|
| 1038 |
show_error=True
|
|
|
|
| 2 |
import os
|
| 3 |
import requests
|
| 4 |
import json
|
| 5 |
+
from typing import Dict, List, Generator, Optional
|
| 6 |
from dotenv import load_dotenv
|
| 7 |
+
import base64
|
| 8 |
+
import tempfile
|
| 9 |
+
import re
|
| 10 |
+
import urllib.parse
|
| 11 |
|
| 12 |
# Load environment variables from .env file
|
| 13 |
load_dotenv()
|
| 14 |
|
| 15 |
+
# --- New Agentic Backend Integration ---
|
| 16 |
+
try:
|
| 17 |
+
from real_ai_agents_implementation import AgenticNegotiator, NegotiationState
|
| 18 |
+
AGENTIC_BACKEND_AVAILABLE = True
|
| 19 |
+
except ImportError as e:
|
| 20 |
+
print(f"Failed to import agentic backend: {e}")
|
| 21 |
+
AGENTIC_BACKEND_AVAILABLE = False
|
| 22 |
+
|
| 23 |
+
# Keep Gemini Image Generator for LaTeX compilation
|
| 24 |
try:
|
| 25 |
from gemini_image_generator import GeminiImageGenerator
|
| 26 |
GEMINI_IMAGE_AVAILABLE = True
|
| 27 |
except ImportError:
|
| 28 |
GEMINI_IMAGE_AVAILABLE = False
|
| 29 |
|
| 30 |
+
def compile_latex_to_image(latex_code: str) -> Optional[str]:
|
| 31 |
+
"""Try to compile LaTeX code to an image using a web service."""
|
| 32 |
+
if not latex_code:
|
| 33 |
+
return None
|
| 34 |
+
try:
|
| 35 |
+
# Prepare the LaTeX code by finding the relevant part
|
| 36 |
+
# A more robust regex to find either a full document or just a tikzpicture
|
| 37 |
+
match = re.search(r'(\\documentclass.*?\\end{document})|(\\begin{tikzpicture}.*?\\end{tikzpicture})', latex_code, re.DOTALL)
|
| 38 |
+
if match:
|
| 39 |
+
# Prioritize the full document if both are somehow present, otherwise take what was found
|
| 40 |
+
content_to_render = match.group(1) if match.group(1) else match.group(2)
|
| 41 |
+
else:
|
| 42 |
+
# Fallback if no standard block is found
|
| 43 |
+
content_to_render = latex_code
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
+
# URL encode the LaTeX content for the API
|
| 46 |
+
encoded_latex = urllib.parse.quote(content_to_render)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 47 |
|
| 48 |
+
# Use a reliable web service for compilation
|
| 49 |
+
api_url = f"https://latex.codecogs.com/png.latex?{encoded_latex}"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
+
response = requests.get(api_url, timeout=20)
|
| 52 |
+
if response.status_code == 200 and response.headers.get('content-type', '').startswith('image/'):
|
| 53 |
+
# Convert the successful image response to a base64 data URI
|
| 54 |
+
image_b64 = base64.b64encode(response.content).decode('utf-8')
|
| 55 |
+
return f"data:image/png;base64,{image_b64}"
|
| 56 |
+
else:
|
| 57 |
+
print(f"LaTeX compilation failed with status: {response.status_code}")
|
| 58 |
+
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 59 |
|
| 60 |
+
except Exception as e:
|
| 61 |
+
print(f"An error occurred during LaTeX compilation: {e}")
|
| 62 |
+
return None
|
| 63 |
+
|
| 64 |
+
def create_negotiation_transcript_display(transcript: List[Dict]) -> str:
|
| 65 |
+
"""Creates a markdown display for the agent negotiation transcript."""
|
| 66 |
+
if not transcript:
|
| 67 |
+
return "### Agent Negotiation Log\n\n*Awaiting instructions...*"
|
| 68 |
+
|
| 69 |
+
markdown = "### Agent Negotiation Log\n\n---\n\n"
|
| 70 |
+
for entry in transcript:
|
| 71 |
+
agent = entry.get('agent', 'System')
|
| 72 |
+
message = entry.get('message', '')
|
| 73 |
+
|
| 74 |
+
# Make the agent name bold and add color
|
| 75 |
+
if agent == "Chief Strategist":
|
| 76 |
+
color = "#ff8c00" # Orange
|
| 77 |
+
elif agent == "Conceptual Artist":
|
| 78 |
+
color = "#da70d6" # Orchid
|
| 79 |
+
elif agent == "System":
|
| 80 |
+
color = "#ff4d4d" # Red
|
| 81 |
+
else:
|
| 82 |
+
color = "#00ff41" # Green
|
| 83 |
|
| 84 |
+
markdown += f"<p style='color: {color}; margin-bottom: 5px;'><strong>🤖 {agent}:</strong></p>\n"
|
| 85 |
+
markdown += f"<p style='margin-left: 20px; margin-top: 0px;'>{message}</p>\n\n"
|
| 86 |
+
markdown += "---\n\n"
|
| 87 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
return markdown
|
| 89 |
|
| 90 |
+
def run_patent_architect_in_ui(invention_disclosure: str) -> Generator[List, None, None]:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 91 |
"""
|
| 92 |
+
This is the new main UI function that runs the true agentic workflow.
|
| 93 |
+
It no longer calls an external backend.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
"""
|
| 95 |
+
# Initial state for all output fields
|
| 96 |
+
negotiation_html = create_negotiation_transcript_display([])
|
| 97 |
+
prior_art_section = "### Prior Art Analysis\n\n*Awaiting agent analysis...*"
|
| 98 |
+
summary_section = "### Invention Summary\n\n*Awaiting agent analysis...*"
|
| 99 |
+
figures_section = "### Technical Figures\n\n*Awaiting agent analysis...*"
|
| 100 |
+
claims_section = "### Patent Claims\n\n*Awaiting agent analysis...*"
|
| 101 |
+
status = "System Initialized."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
+
yield [negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 104 |
|
|
|
|
|
|
|
| 105 |
if not invention_disclosure:
|
| 106 |
+
status = "Please provide an invention disclosure."
|
| 107 |
+
yield [negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 108 |
return
|
| 109 |
|
| 110 |
+
if not AGENTIC_BACKEND_AVAILABLE:
|
| 111 |
+
status = "ERROR: The agentic backend is not available. Check server logs."
|
| 112 |
+
negotiation_html = create_negotiation_transcript_display([{"agent": "System", "message": "CRITICAL ERROR: Could not import `AgenticNegotiator`. The application cannot run."}])
|
| 113 |
+
yield [negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status]
|
| 114 |
return
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
|
| 116 |
+
# --- Start the Real Agentic Workflow ---
|
| 117 |
+
negotiator = AgenticNegotiator(invention_disclosure)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
|
| 119 |
+
final_state = None
|
| 120 |
+
for state in negotiator.run_negotiation():
|
| 121 |
+
final_state = state
|
| 122 |
+
|
| 123 |
+
# Update negotiation transcript
|
| 124 |
+
negotiation_html = create_negotiation_transcript_display(state.negotiation_transcript)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
+
# Update status from the last message
|
| 127 |
+
if state.negotiation_transcript:
|
| 128 |
+
last_entry = state.negotiation_transcript[-1]
|
| 129 |
+
status = f"Active Agent: {last_entry['agent']}"
|
| 130 |
+
|
| 131 |
+
# As prior art becomes available, display it
|
| 132 |
+
if state.prior_art_analysis:
|
| 133 |
+
pa_data = state.prior_art_analysis
|
| 134 |
+
prior_art_section = f"### Prior Art & Strategy\n\n"
|
| 135 |
+
if state.strategic_mandate:
|
| 136 |
+
prior_art_section += f"**Strategic Mandate:**\n> {state.strategic_mandate}\n\n---\n\n"
|
| 137 |
+
prior_art_section += f"**Landscape Summary:** {pa_data.get('landscape_summary', 'N/A')}\n\n"
|
| 138 |
+
prior_art_section += f"**Key Concepts Identified:**\n"
|
| 139 |
+
for concept in pa_data.get('key_concepts', []):
|
| 140 |
+
prior_art_section += f"- {concept}\n"
|
| 141 |
+
prior_art_section += "\n**Simulated Representative Prior Art:**\n"
|
| 142 |
+
for art in pa_data.get('simulated_prior_art', []):
|
| 143 |
+
prior_art_section += f"- {art}\n"
|
| 144 |
+
|
| 145 |
+
# As sections get generated, display them
|
| 146 |
+
if state.technical_summary:
|
| 147 |
+
summary_section = f"### Invention Summary\n\n{state.technical_summary}"
|
| 148 |
|
| 149 |
+
if state.patent_claims:
|
| 150 |
+
claims_section = f"### Patent Claims\n\n{state.patent_claims}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 151 |
|
| 152 |
+
# Handle both Ideogram image and LaTeX figure description
|
| 153 |
+
if state.ideogram_image_b64 or state.figure_description:
|
| 154 |
+
figures_section = "### Technical Figures\n\n"
|
| 155 |
+
|
| 156 |
+
# Display the Ideogram image if it exists
|
| 157 |
+
if state.ideogram_image_b64:
|
| 158 |
+
figures_section += "### Conceptual Image (from Ideogram API)\n"
|
| 159 |
+
image_html = f"<img src='data:image/jpeg;base64,{state.ideogram_image_b64}' alt='Generated Conceptual Image' style='max-width: 100%; height: auto; border: 2px solid #ff8c00;'>"
|
| 160 |
+
figures_section += image_html + "\n\n---\n\n"
|
| 161 |
+
|
| 162 |
+
# Display the LaTeX figure description and compiled image if it exists
|
| 163 |
+
if state.figure_description:
|
| 164 |
+
figures_section += "### Technical Figure (from LaTeX)\n"
|
| 165 |
+
compiled_latex_image_uri = compile_latex_to_image(state.figure_description)
|
| 166 |
+
if compiled_latex_image_uri:
|
| 167 |
+
figures_section += f"<img src='{compiled_latex_image_uri}' alt='Compiled LaTeX Figure' style='max-width: 100%; height: auto; border: 2px solid #00ff41; background: white; padding: 10px;'>\n\n"
|
| 168 |
+
else:
|
| 169 |
+
figures_section += "*LaTeX compilation failed. Displaying raw code.*\n\n"
|
| 170 |
+
|
| 171 |
+
figures_section += "#### Raw LaTeX/TikZ Code:\n"
|
| 172 |
+
figures_section += state.figure_description
|
| 173 |
+
|
| 174 |
+
yield [negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 175 |
|
| 176 |
+
status = "Agentic Negotiation Complete."
|
| 177 |
+
yield [negotiation_html, prior_art_section, summary_section, figures_section, claims_section, status]
|
|
|
|
|
|
|
| 178 |
|
| 179 |
with gr.Blocks(theme=gr.themes.Base(primary_hue="green", neutral_hue="slate"), title="Patent Architect v2") as demo:
|
| 180 |
gr.HTML("""
|
|
|
|
| 218 |
color: #00ff41;
|
| 219 |
opacity: 0.8;
|
| 220 |
position: relative;
|
| 221 |
+
z-index: 1;">POWERED BY GEMINI & IDEOGRAM 3.0 + AUTONOMOUS AI AGENTS</p>
|
| 222 |
</div>
|
| 223 |
""")
|
| 224 |
|
|
|
|
| 304 |
invention_input = gr.Textbox(
|
| 305 |
lines=12,
|
| 306 |
label="Neural Disclosure Interface",
|
| 307 |
+
placeholder="""Enter your invention disclosure here. Be as detailed as possible.
|
| 308 |
+
The agentic system will analyze your input, formulate a patent strategy, and generate a draft application based on that strategy.""",
|
| 309 |
+
info="The new agentic backend requires a detailed technical disclosure to function effectively."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
)
|
| 311 |
|
| 312 |
+
generate_btn = gr.Button("INITIATE AGENTIC NEGOTIATION", variant="primary", size="lg")
|
| 313 |
|
| 314 |
status_display = gr.Textbox(
|
| 315 |
label="System Status",
|
| 316 |
interactive=False,
|
| 317 |
+
value="AGENTIC WORKFLOW READY"
|
| 318 |
)
|
| 319 |
|
| 320 |
gr.HTML("""
|
|
|
|
| 325 |
</div>
|
| 326 |
""")
|
| 327 |
|
|
|
|
| 328 |
gr.HTML("""
|
| 329 |
<div style="background: linear-gradient(45deg, #0a0a0a, #1a1a1a);
|
| 330 |
border: 1px solid #ff8c00;
|
|
|
|
| 336 |
text-shadow: 0 0 5px #ff8c00;
|
| 337 |
font-size: 1.6em;
|
| 338 |
margin: 0;
|
| 339 |
+
text-transform: uppercase;">LIVE AGENT NEGOTIATION & STRATEGY</h2>
|
| 340 |
</div>
|
| 341 |
""")
|
| 342 |
|
| 343 |
with gr.Row():
|
| 344 |
+
with gr.Column(scale=2):
|
| 345 |
+
negotiation_display = gr.HTML("...")
|
| 346 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 347 |
gr.HTML("""
|
| 348 |
<div style="height: 2px;
|
| 349 |
background: linear-gradient(90deg, #ff8c00, #ffff00, #00ff41, #ff8c00);
|
|
|
|
| 363 |
text-shadow: 0 0 5px #00ff41;
|
| 364 |
font-size: 1.6em;
|
| 365 |
margin: 0;
|
| 366 |
+
text-transform: uppercase;">STRATEGY-ALIGNED PATENT DRAFT</h2>
|
| 367 |
</div>
|
| 368 |
""")
|
| 369 |
|
| 370 |
with gr.Tabs():
|
| 371 |
+
with gr.TabItem("PRIOR ART & STRATEGY"):
|
| 372 |
prior_art_output = gr.Markdown(
|
| 373 |
+
value="### Prior Art Analysis\n\n*Results of the Prior Art Detective's investigation will appear here.*"
|
| 374 |
)
|
| 375 |
with gr.TabItem("TECHNICAL SUMMARY"):
|
| 376 |
summary_output = gr.Markdown(
|
| 377 |
+
value="### Invention Summary\n\n*The Technical Writer's summary, aligned with the final strategy, will appear here.*"
|
| 378 |
)
|
| 379 |
with gr.TabItem("TECHNICAL FIGURES"):
|
| 380 |
figures_output = gr.Markdown(
|
| 381 |
+
value="### Technical Figures\n\n*The Figure Drafter's output, illustrating the core strategic concept, will appear here.*"
|
| 382 |
)
|
| 383 |
with gr.TabItem("PATENT CLAIMS"):
|
| 384 |
claims_output = gr.Markdown(
|
| 385 |
+
value="### Patent Claims\n\n*The Claims Drafter's claims, focused on the strategic mandate, will appear here.*"
|
| 386 |
)
|
| 387 |
|
| 388 |
generate_btn.click(
|
| 389 |
fn=run_patent_architect_in_ui,
|
| 390 |
inputs=[invention_input],
|
| 391 |
+
outputs=[negotiation_display, prior_art_output, summary_output, figures_output, claims_output, status_display]
|
| 392 |
)
|
| 393 |
|
| 394 |
gr.Examples(
|
| 395 |
[
|
| 396 |
+
["My invention is a smart coffee mug that uses a novel phase-change material to keep coffee at a perfect temperature. It also has a mobile app that connects via Bluetooth to let the user set their preferred temperature. The key innovation is a machine learning algorithm that learns the user's drinking habits to pre-warm or cool the mug, optimizing energy use."],
|
| 397 |
+
["A modular vertical farming system with adaptive LED lighting using full-spectrum arrays (400-700nm) controlled by neural network analysis of plant reflectance spectra. The system employs RGB+NIR sensors to monitor chlorophyll content and adjusts light intensity (50-1000 μmol/m²/s) and spectrum ratios based on growth stage detection. Machine learning models trained on 500+ crop cycles optimize photosynthetic photon flux density while reducing energy consumption by 35% compared to static lighting systems."],
|
|
|
|
| 398 |
],
|
| 399 |
inputs=[invention_input],
|
| 400 |
+
label="HIGH-SPECIFICATION TECHNICAL INPUT EXAMPLES"
|
| 401 |
)
|
| 402 |
|
| 403 |
gr.HTML("""
|
| 404 |
<style>
|
| 405 |
+
/* Style remains the same */
|
| 406 |
.gradio-button.primary {
|
| 407 |
background: linear-gradient(45deg, #00ff41, #ffff00) !important;
|
| 408 |
border: 2px solid #00ff41 !important;
|
|
|
|
| 423 |
border-color: #ffff00 !important;
|
| 424 |
}
|
| 425 |
|
|
|
|
| 426 |
.gradio-container {
|
| 427 |
background: #0a0a0a !important;
|
| 428 |
font-family: 'Courier New', monospace !important;
|
| 429 |
}
|
| 430 |
|
|
|
|
| 431 |
.tab-nav button {
|
| 432 |
background: linear-gradient(45deg, #1a1a1a, #0a0a0a) !important;
|
| 433 |
border: 1px solid #00ff41 !important;
|
|
|
|
| 443 |
box-shadow: 0 0 10px #00ff41 !important;
|
| 444 |
}
|
| 445 |
|
|
|
|
| 446 |
.gr-textbox {
|
| 447 |
background: linear-gradient(45deg, #0a0a0a, #1a1a1a) !important;
|
| 448 |
border: 1px solid #00ff41 !important;
|
|
|
|
| 455 |
box-shadow: 0 0 10px #ffff00 !important;
|
| 456 |
}
|
| 457 |
|
|
|
|
| 458 |
* {
|
| 459 |
font-family: 'Courier New', monospace !important;
|
| 460 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 461 |
</style>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 462 |
""")
|
| 463 |
|
| 464 |
if __name__ == "__main__":
|
| 465 |
+
print("PATENT ARCHITECT v2 - True Agentic Negotiation Workflow")
|
| 466 |
+
print(f"Agentic Backend: {'ONLINE' if AGENTIC_BACKEND_AVAILABLE else 'OFFLINE'}")
|
| 467 |
+
if not os.getenv("GEMINI_API_KEY"):
|
| 468 |
+
print("⚠️ WARNING: GEMINI_API_KEY environment variable not set. Gemini-powered agents will not function.")
|
| 469 |
+
if not os.getenv("SEGMIND_API_KEY"):
|
| 470 |
+
print("⚠️ WARNING: SEGMIND_API_KEY environment variable not set. Ideogram image generation will not function.")
|
| 471 |
demo.queue().launch(
|
| 472 |
share=False,
|
| 473 |
show_error=True
|
real_ai_agents_implementation.py
CHANGED
|
@@ -1,551 +1,320 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
These agents address actual patent attorney pain points with measurable business value.
|
| 7 |
"""
|
| 8 |
|
| 9 |
-
import
|
| 10 |
import json
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 14 |
|
| 15 |
-
#
|
| 16 |
@dataclass
|
| 17 |
-
class
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
SOFTWARE = "software"
|
| 28 |
-
CHEMICAL = "chemical"
|
| 29 |
-
|
| 30 |
-
# ============================================================================
|
| 31 |
-
# AGENT 1: Technical Completeness Validator
|
| 32 |
-
# ============================================================================
|
| 33 |
-
|
| 34 |
-
class TechnicalCompletenessAgent:
|
| 35 |
-
"""
|
| 36 |
-
Real AI agent that ensures patent applications meet technical disclosure requirements.
|
| 37 |
-
|
| 38 |
-
Addresses: 35 U.S.C. §112 rejections for inadequate disclosure ($5K-15K prosecution costs)
|
| 39 |
-
"""
|
| 40 |
-
|
| 41 |
-
def __init__(self):
|
| 42 |
-
self.required_elements = {
|
| 43 |
-
InventionType.MECHANICAL: {
|
| 44 |
-
'materials': {
|
| 45 |
-
'importance': 'critical',
|
| 46 |
-
'examples': ['steel, aluminum, carbon fiber', 'specific alloy compositions'],
|
| 47 |
-
'suggestion': 'Specify materials used in each component with properties'
|
| 48 |
-
},
|
| 49 |
-
'dimensions': {
|
| 50 |
-
'importance': 'important',
|
| 51 |
-
'examples': ['length: 10-50cm', 'thickness: 2-5mm'],
|
| 52 |
-
'suggestion': 'Provide dimensional ranges that enable reproduction'
|
| 53 |
-
}
|
| 54 |
-
},
|
| 55 |
-
InventionType.ELECTRICAL: {
|
| 56 |
-
'voltages': {
|
| 57 |
-
'importance': 'critical',
|
| 58 |
-
'examples': ['5V DC', '120-240V AC', '3.3V logic levels'],
|
| 59 |
-
'suggestion': 'Specify all operating voltages and power requirements'
|
| 60 |
-
},
|
| 61 |
-
'frequencies': {
|
| 62 |
-
'importance': 'critical',
|
| 63 |
-
'examples': ['2.4GHz WiFi', '60Hz AC', '100MHz-1GHz'],
|
| 64 |
-
'suggestion': 'Define frequency ranges for all signals'
|
| 65 |
-
}
|
| 66 |
-
},
|
| 67 |
-
InventionType.SOFTWARE: {
|
| 68 |
-
'algorithms': {
|
| 69 |
-
'importance': 'critical',
|
| 70 |
-
'examples': ['machine learning (CNN)', 'sorting algorithm', 'encryption (AES-256)'],
|
| 71 |
-
'suggestion': 'Describe core algorithms with sufficient detail for implementation'
|
| 72 |
-
},
|
| 73 |
-
'performance_metrics': {
|
| 74 |
-
'importance': 'important',
|
| 75 |
-
'examples': ['response time: <100ms', 'accuracy: >95%', 'throughput: 1000 requests/sec'],
|
| 76 |
-
'suggestion': 'Provide quantitative performance specifications'
|
| 77 |
-
}
|
| 78 |
-
}
|
| 79 |
-
}
|
| 80 |
-
|
| 81 |
-
def classify_invention_type(self, invention_text: str) -> InventionType:
|
| 82 |
-
"""Classify invention type based on description content."""
|
| 83 |
-
text_lower = invention_text.lower()
|
| 84 |
-
|
| 85 |
-
if any(term in text_lower for term in ['algorithm', 'software', 'app', 'machine learning', 'ai']):
|
| 86 |
-
return InventionType.SOFTWARE
|
| 87 |
-
elif any(term in text_lower for term in ['electrical', 'electronic', 'circuit', 'voltage', 'sensor']):
|
| 88 |
-
return InventionType.ELECTRICAL
|
| 89 |
-
elif any(term in text_lower for term in ['chemical', 'composition', 'reaction', 'compound']):
|
| 90 |
-
return InventionType.CHEMICAL
|
| 91 |
-
else:
|
| 92 |
-
return InventionType.MECHANICAL
|
| 93 |
-
|
| 94 |
-
def detect_element_presence(self, invention_text: str, element_type: str) -> bool:
|
| 95 |
-
"""Detect if a technical element is adequately described."""
|
| 96 |
-
text_lower = invention_text.lower()
|
| 97 |
-
|
| 98 |
-
element_patterns = {
|
| 99 |
-
'materials': [r'\b\w+\s*(?:steel|aluminum|plastic|carbon|alloy|material)\b'],
|
| 100 |
-
'dimensions': [r'\b\d+\s*(?:mm|cm|m|inch|ft)\b'],
|
| 101 |
-
'voltages': [r'\b\d+\.?\d*\s*[vV]\b'],
|
| 102 |
-
'frequencies': [r'\b\d+\.?\d*\s*(?:Hz|khz|mhz|ghz)\b'],
|
| 103 |
-
'algorithms': [r'\b(?:algorithm|method|process|neural|cnn|lstm)\b'],
|
| 104 |
-
'performance_metrics': [r'\b\d+\.?\d*\s*(?:%|percent|accuracy|ms|seconds)\b']
|
| 105 |
-
}
|
| 106 |
-
|
| 107 |
-
patterns = element_patterns.get(element_type, [])
|
| 108 |
-
return any(re.search(pattern, text_lower) for pattern in patterns)
|
| 109 |
-
|
| 110 |
-
def analyze_disclosure(self, invention_text: str) -> Dict:
|
| 111 |
-
"""
|
| 112 |
-
Analyze invention disclosure for technical completeness.
|
| 113 |
-
|
| 114 |
-
Returns:
|
| 115 |
-
Dict with completeness analysis, missing elements, and recommendations
|
| 116 |
-
"""
|
| 117 |
-
invention_type = self.classify_invention_type(invention_text)
|
| 118 |
-
required_elements = self.required_elements.get(invention_type, {})
|
| 119 |
-
|
| 120 |
-
analysis_results = []
|
| 121 |
-
missing_critical = 0
|
| 122 |
-
missing_important = 0
|
| 123 |
-
|
| 124 |
-
for element_name, element_config in required_elements.items():
|
| 125 |
-
is_present = self.detect_element_presence(invention_text, element_name)
|
| 126 |
-
|
| 127 |
-
element_analysis = TechnicalElement(
|
| 128 |
-
element_type=element_name,
|
| 129 |
-
importance=element_config['importance'],
|
| 130 |
-
present=is_present,
|
| 131 |
-
suggestion=element_config['suggestion'],
|
| 132 |
-
examples=element_config['examples']
|
| 133 |
-
)
|
| 134 |
-
|
| 135 |
-
analysis_results.append(element_analysis)
|
| 136 |
-
|
| 137 |
-
if not is_present:
|
| 138 |
-
if element_config['importance'] == 'critical':
|
| 139 |
-
missing_critical += 1
|
| 140 |
-
elif element_config['importance'] == 'important':
|
| 141 |
-
missing_important += 1
|
| 142 |
-
|
| 143 |
-
# Calculate completeness score
|
| 144 |
-
total_elements = len(required_elements)
|
| 145 |
-
present_elements = sum(1 for el in analysis_results if el.present)
|
| 146 |
-
completeness_score = (present_elements / total_elements * 100) if total_elements > 0 else 0
|
| 147 |
-
|
| 148 |
-
# Determine prosecution risk
|
| 149 |
-
if missing_critical > 0:
|
| 150 |
-
prosecution_risk = "HIGH - Critical elements missing, likely §112 rejection"
|
| 151 |
-
elif missing_important > 1:
|
| 152 |
-
prosecution_risk = "MEDIUM - Important elements missing, possible objections"
|
| 153 |
-
else:
|
| 154 |
-
prosecution_risk = "LOW - Technical disclosure appears adequate"
|
| 155 |
-
|
| 156 |
-
return {
|
| 157 |
-
'invention_type': invention_type.value,
|
| 158 |
-
'completeness_score': completeness_score,
|
| 159 |
-
'prosecution_risk': prosecution_risk,
|
| 160 |
-
'missing_critical': missing_critical,
|
| 161 |
-
'missing_important': missing_important,
|
| 162 |
-
'missing_elements': [
|
| 163 |
-
{
|
| 164 |
-
'element': el.element_type,
|
| 165 |
-
'importance': el.importance,
|
| 166 |
-
'suggestion': el.suggestion,
|
| 167 |
-
'examples': el.examples
|
| 168 |
-
}
|
| 169 |
-
for el in analysis_results if not el.present
|
| 170 |
-
]
|
| 171 |
-
}
|
| 172 |
|
| 173 |
-
#
|
| 174 |
-
|
| 175 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
"""
|
| 186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
-
|
| 189 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
"""
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
|
|
|
|
|
|
| 195 |
|
| 196 |
-
|
| 197 |
-
'key_competitors': key_competitors,
|
| 198 |
-
'prosecution_risks': prosecution_risks,
|
| 199 |
-
'whitespace_opportunities': whitespace_opportunities,
|
| 200 |
-
'landscape_summary': self._create_landscape_summary(key_competitors, prosecution_risks)
|
| 201 |
-
}
|
| 202 |
-
|
| 203 |
-
def _identify_key_competitors(self, invention_text: str) -> List[Dict]:
|
| 204 |
-
"""Identify key competitors based on invention description."""
|
| 205 |
-
if 'coffee' in invention_text.lower():
|
| 206 |
-
return [
|
| 207 |
-
{'company': 'Ember Technologies', 'patents': 45, 'focus': 'Temperature control'},
|
| 208 |
-
{'company': 'YETI Holdings', 'patents': 23, 'focus': 'Insulation technology'}
|
| 209 |
-
]
|
| 210 |
-
elif 'sensor' in invention_text.lower():
|
| 211 |
-
return [
|
| 212 |
-
{'company': 'Honeywell', 'patents': 1200, 'focus': 'Industrial sensors'},
|
| 213 |
-
{'company': 'Bosch', 'patents': 890, 'focus': 'Automotive sensors'}
|
| 214 |
-
]
|
| 215 |
-
else:
|
| 216 |
-
return [
|
| 217 |
-
{'company': 'Generic Tech Corp', 'patents': 150, 'focus': 'Related technology'}
|
| 218 |
-
]
|
| 219 |
-
|
| 220 |
-
def _assess_prosecution_risks(self, invention_text: str) -> Dict:
|
| 221 |
-
"""Assess risks for patent prosecution."""
|
| 222 |
-
text_lower = invention_text.lower()
|
| 223 |
|
| 224 |
-
|
| 225 |
-
|
| 226 |
-
|
| 227 |
-
|
| 228 |
-
|
| 229 |
-
|
| 230 |
-
|
| 231 |
-
|
| 232 |
-
|
| 233 |
-
|
|
|
|
| 234 |
|
| 235 |
-
|
| 236 |
-
'overall_risk': risk_level,
|
| 237 |
-
'risk_factors': risk_factors,
|
| 238 |
-
'mitigation_strategies': [
|
| 239 |
-
'Focus on specific technical improvements',
|
| 240 |
-
'Emphasize novel combination of features'
|
| 241 |
-
]
|
| 242 |
-
}
|
| 243 |
-
|
| 244 |
-
def _find_whitespace_opportunities(self, invention_text: str) -> List[Dict]:
|
| 245 |
-
"""Find whitespace opportunities in the patent landscape."""
|
| 246 |
-
return [
|
| 247 |
-
{
|
| 248 |
-
'opportunity': 'Mobile app integration',
|
| 249 |
-
'description': 'Limited patents on smartphone-controlled devices in this space',
|
| 250 |
-
'potential_value': 'High - growing IoT market'
|
| 251 |
-
},
|
| 252 |
-
{
|
| 253 |
-
'opportunity': 'Machine learning optimization',
|
| 254 |
-
'description': 'Few patents combine your core technology with ML algorithms',
|
| 255 |
-
'potential_value': 'Medium - emerging technology trend'
|
| 256 |
-
}
|
| 257 |
-
]
|
| 258 |
-
|
| 259 |
-
def _create_landscape_summary(self, competitors: List[Dict], risks: Dict) -> str:
|
| 260 |
-
"""Create a summary of the competitive landscape."""
|
| 261 |
-
total_competitors = len(competitors)
|
| 262 |
-
total_patents = sum(comp.get('patents', 0) for comp in competitors)
|
| 263 |
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
|
|
|
| 270 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 271 |
|
| 272 |
-
|
| 273 |
-
# AGENT 3: Claim Architecture Strategist
|
| 274 |
-
# ============================================================================
|
| 275 |
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
"""
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
"""
|
| 290 |
-
prosecution_risks = prior_art_analysis.get('prosecution_risks', {})
|
| 291 |
-
|
| 292 |
-
# Design claim pyramid based on risk assessment
|
| 293 |
-
claim_pyramid = self._design_claim_pyramid(prosecution_risks)
|
| 294 |
|
| 295 |
-
|
| 296 |
-
|
| 297 |
-
|
| 298 |
-
|
| 299 |
-
'claim_pyramid': claim_pyramid,
|
| 300 |
-
'claim_strength_analysis': claim_strength,
|
| 301 |
-
'recommendation_summary': self._create_recommendation_summary(claim_strength)
|
| 302 |
}
|
| 303 |
-
|
| 304 |
-
def _design_claim_pyramid(self, prosecution_risks: Dict) -> Dict:
|
| 305 |
-
"""Design strategic claim pyramid."""
|
| 306 |
-
risk_level = prosecution_risks.get('overall_risk', 'MEDIUM')
|
| 307 |
-
|
| 308 |
-
if risk_level == 'HIGH':
|
| 309 |
-
# Conservative approach for high-risk fields
|
| 310 |
-
independent_claims = [
|
| 311 |
-
{'claim_number': 1, 'type': 'apparatus', 'scope': 'narrow', 'strategy': 'Specific implementation'}
|
| 312 |
-
]
|
| 313 |
-
else:
|
| 314 |
-
# More aggressive approach for lower-risk fields
|
| 315 |
-
independent_claims = [
|
| 316 |
-
{'claim_number': 1, 'type': 'apparatus', 'scope': 'broad', 'strategy': 'Cover core invention'},
|
| 317 |
-
{'claim_number': 8, 'type': 'method', 'scope': 'broad', 'strategy': 'Protect process aspects'}
|
| 318 |
-
]
|
| 319 |
-
|
| 320 |
-
return {
|
| 321 |
-
'independent_claims': independent_claims,
|
| 322 |
-
'dependent_claims': [
|
| 323 |
-
{'claim_number': 2, 'depends_on': 1, 'strategy': 'Narrow fallback position'},
|
| 324 |
-
{'claim_number': 3, 'depends_on': 1, 'strategy': 'Alternative limitation'}
|
| 325 |
-
]
|
| 326 |
-
}
|
| 327 |
-
|
| 328 |
-
def _analyze_claim_strength(self, claim_pyramid: Dict, prosecution_risks: Dict) -> Dict:
|
| 329 |
-
"""Analyze strength of proposed claims."""
|
| 330 |
-
risk_level = prosecution_risks.get('overall_risk', 'MEDIUM')
|
| 331 |
-
|
| 332 |
-
# Calculate strength based on risk level and claim scope
|
| 333 |
-
if risk_level == 'HIGH':
|
| 334 |
-
overall_strength = 60 # Conservative claims in crowded field
|
| 335 |
-
elif risk_level == 'MEDIUM':
|
| 336 |
-
overall_strength = 75 # Balanced approach
|
| 337 |
-
else:
|
| 338 |
-
overall_strength = 85 # Aggressive claims in open field
|
| 339 |
-
|
| 340 |
-
return {
|
| 341 |
-
'overall_strength': overall_strength,
|
| 342 |
-
'grantability': 'Good' if overall_strength > 70 else 'Moderate',
|
| 343 |
-
'recommendations': self._generate_strength_recommendations(overall_strength)
|
| 344 |
-
}
|
| 345 |
-
|
| 346 |
-
def _generate_strength_recommendations(self, strength: float) -> List[str]:
|
| 347 |
-
"""Generate recommendations for improving claim strength."""
|
| 348 |
-
recommendations = []
|
| 349 |
-
|
| 350 |
-
if strength < 70:
|
| 351 |
-
recommendations.append("Consider narrowing independent claims to improve grantability")
|
| 352 |
-
recommendations.append("Add more specific technical limitations")
|
| 353 |
-
|
| 354 |
-
recommendations.append("Ensure all claims are fully supported by specification")
|
| 355 |
-
recommendations.append("Consider adding method claims if not present")
|
| 356 |
-
|
| 357 |
-
return recommendations
|
| 358 |
-
|
| 359 |
-
def _create_recommendation_summary(self, claim_strength: Dict) -> str:
|
| 360 |
-
"""Create summary of claim architecture recommendations."""
|
| 361 |
-
overall_strength = claim_strength.get('overall_strength', 0)
|
| 362 |
-
|
| 363 |
-
if overall_strength >= 80:
|
| 364 |
-
assessment = "STRONG - Claims appear well-positioned for prosecution"
|
| 365 |
-
elif overall_strength >= 65:
|
| 366 |
-
assessment = "GOOD - Claims have solid foundation with room for improvement"
|
| 367 |
-
else:
|
| 368 |
-
assessment = "NEEDS WORK - Claims require significant refinement"
|
| 369 |
-
|
| 370 |
-
return f"""
|
| 371 |
-
Claim Architecture Assessment: {assessment}
|
| 372 |
-
Overall Strength: {overall_strength:.0f}/100
|
| 373 |
-
|
| 374 |
-
Key Recommendations:
|
| 375 |
-
• Focus on specific technical differentiation
|
| 376 |
-
• Prepare multiple claim strategies for prosecution
|
| 377 |
-
• Ensure strong specification support
|
| 378 |
-
"""
|
| 379 |
|
| 380 |
-
|
| 381 |
-
|
| 382 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 383 |
|
| 384 |
-
|
| 385 |
-
|
| 386 |
-
|
| 387 |
-
|
| 388 |
-
|
| 389 |
-
def __init__(self):
|
| 390 |
self.agents = {
|
| 391 |
-
|
| 392 |
-
|
| 393 |
-
|
|
|
|
|
|
|
|
|
|
| 394 |
}
|
| 395 |
-
|
| 396 |
-
def
|
| 397 |
-
"""
|
| 398 |
-
|
| 399 |
-
|
| 400 |
-
|
| 401 |
-
|
| 402 |
-
|
| 403 |
-
|
| 404 |
-
|
| 405 |
-
|
| 406 |
-
|
| 407 |
-
#
|
| 408 |
-
|
| 409 |
-
|
| 410 |
-
|
| 411 |
-
|
| 412 |
-
|
| 413 |
-
|
| 414 |
-
|
| 415 |
-
|
| 416 |
-
|
| 417 |
-
|
| 418 |
-
|
| 419 |
-
|
| 420 |
-
|
| 421 |
-
|
| 422 |
-
|
| 423 |
-
|
| 424 |
-
|
| 425 |
-
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
"
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
"""Estimate prosecution timeline based on readiness."""
|
| 465 |
-
if readiness_score >= 80:
|
| 466 |
-
return "12-18 months to allowance (well-prepared application)"
|
| 467 |
-
elif readiness_score >= 65:
|
| 468 |
-
return "18-24 months to allowance (likely 1-2 office actions)"
|
| 469 |
-
else:
|
| 470 |
-
return "24-36 months to allowance (multiple office actions expected)"
|
| 471 |
-
|
| 472 |
-
def _estimate_costs(self, readiness_score: float) -> str:
|
| 473 |
-
"""Estimate prosecution costs based on readiness."""
|
| 474 |
-
if readiness_score >= 80:
|
| 475 |
-
return "$8,000-12,000 (minimal prosecution required)"
|
| 476 |
-
elif readiness_score >= 65:
|
| 477 |
-
return "$12,000-18,000 (moderate prosecution complexity)"
|
| 478 |
else:
|
| 479 |
-
|
|
|
|
| 480 |
|
| 481 |
-
# ============================================================================
|
| 482 |
-
# TESTING AND VALIDATION
|
| 483 |
-
# ============================================================================
|
| 484 |
|
| 485 |
-
|
| 486 |
-
|
| 487 |
-
|
|
|
|
|
|
|
|
|
|
| 488 |
print("=" * 60)
|
| 489 |
|
| 490 |
-
|
|
|
|
|
|
|
|
|
|
| 491 |
test_invention = """
|
| 492 |
-
|
| 493 |
-
and smartphone app control. The mug includes a double-wall design with PCM chambers
|
| 494 |
-
that store and release thermal energy. A temperature sensor monitors the coffee
|
| 495 |
-
temperature and communicates with a mobile app via Bluetooth. The app allows users
|
| 496 |
-
to set preferred temperatures and receive notifications when coffee is ready.
|
| 497 |
-
|
| 498 |
-
The system uses a microcontroller to manage thermal regulation and wireless
|
| 499 |
-
communication. Machine learning algorithms analyze user preferences to optimize
|
| 500 |
-
heating patterns over time.
|
| 501 |
"""
|
| 502 |
|
| 503 |
-
|
| 504 |
-
coordinator = InterAgentCoordinator()
|
| 505 |
-
results = coordinator.orchestrate_patent_development(test_invention)
|
| 506 |
-
|
| 507 |
-
# Display results
|
| 508 |
-
print("\n📊 ANALYSIS RESULTS:")
|
| 509 |
-
print("=" * 40)
|
| 510 |
-
|
| 511 |
-
# Technical Analysis Results
|
| 512 |
-
technical = results['technical_analysis']
|
| 513 |
-
print(f"\n🔬 Technical Completeness: {technical['completeness_score']:.1f}%")
|
| 514 |
-
print(f" Prosecution Risk: {technical['prosecution_risk']}")
|
| 515 |
-
print(f" Missing Critical Elements: {technical['missing_critical']}")
|
| 516 |
-
if technical['missing_elements']:
|
| 517 |
-
print(" Missing Elements:")
|
| 518 |
-
for element in technical['missing_elements'][:3]:
|
| 519 |
-
print(f" • {element['element']}: {element['suggestion']}")
|
| 520 |
-
|
| 521 |
-
# Prior Art Results
|
| 522 |
-
prior_art = results['prior_art_analysis']
|
| 523 |
-
print(f"\n🔍 Prior Art Analysis:")
|
| 524 |
-
print(f" Risk Level: {prior_art['prosecution_risks']['overall_risk']}")
|
| 525 |
-
print(f" Key Competitors: {len(prior_art['key_competitors'])}")
|
| 526 |
-
for competitor in prior_art['key_competitors'][:2]:
|
| 527 |
-
print(f" • {competitor['company']}: {competitor['patents']} patents")
|
| 528 |
|
| 529 |
-
|
| 530 |
-
|
| 531 |
-
|
| 532 |
-
|
| 533 |
-
|
| 534 |
-
|
| 535 |
-
|
| 536 |
-
|
| 537 |
-
print(
|
| 538 |
-
print(f"
|
| 539 |
-
print(f"
|
| 540 |
-
print(f"
|
| 541 |
-
|
| 542 |
-
|
| 543 |
-
|
| 544 |
-
|
| 545 |
-
print("• Technical completeness validation prevents §112 rejections")
|
| 546 |
-
print("• Prior art landscape analysis reduces prosecution surprises")
|
| 547 |
-
print("• Claim architecture optimization maximizes patent value")
|
| 548 |
-
print("• Integrated assessment provides realistic business planning")
|
| 549 |
|
| 550 |
if __name__ == "__main__":
|
| 551 |
-
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
+
True Agentic Implementation for Patent Architect AI v2
|
| 4 |
+
This version implements a genuine, stateful, multi-agent negotiation workflow
|
| 5 |
+
where agent outputs dynamically influence subsequent agent actions.
|
|
|
|
| 6 |
"""
|
| 7 |
|
| 8 |
+
import os
|
| 9 |
import json
|
| 10 |
+
import re
|
| 11 |
+
import base64
|
| 12 |
+
import requests
|
| 13 |
+
from typing import Dict, List, Optional, Tuple, Generator
|
| 14 |
+
from dataclasses import dataclass, field
|
| 15 |
+
import google.generativeai as genai
|
| 16 |
+
from dotenv import load_dotenv
|
| 17 |
+
|
| 18 |
+
# --- Configuration ---
|
| 19 |
+
load_dotenv()
|
| 20 |
+
# Configure Gemini
|
| 21 |
+
try:
|
| 22 |
+
genai.configure(api_key=os.getenv("GEMINI_API_KEY"))
|
| 23 |
+
GEMINI_AVAILABLE = True
|
| 24 |
+
except (ValueError, TypeError) as e:
|
| 25 |
+
print(f"Gemini API key not found or invalid: {e}")
|
| 26 |
+
GEMINI_AVAILABLE = False
|
| 27 |
+
|
| 28 |
|
| 29 |
+
# --- Data Structures ---
|
| 30 |
@dataclass
|
| 31 |
+
class NegotiationState:
|
| 32 |
+
invention_disclosure: str
|
| 33 |
+
key_concepts: List[str] = field(default_factory=list)
|
| 34 |
+
prior_art_analysis: Dict = field(default_factory=dict)
|
| 35 |
+
strategic_mandate: str = ""
|
| 36 |
+
technical_summary: str = ""
|
| 37 |
+
patent_claims: str = ""
|
| 38 |
+
figure_description: str = ""
|
| 39 |
+
ideogram_image_b64: str = ""
|
| 40 |
+
negotiation_transcript: List[Dict] = field(default_factory=list)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
|
| 42 |
+
# --- Base Agent Class ---
|
| 43 |
+
class BaseAgent:
|
| 44 |
+
def __init__(self, model_name='gemini-1.5-flash'):
|
| 45 |
+
if not GEMINI_AVAILABLE:
|
| 46 |
+
self.model = None
|
| 47 |
+
return
|
| 48 |
+
self.model = genai.GenerativeModel(model_name)
|
| 49 |
|
| 50 |
+
def _execute_prompt(self, prompt: str) -> str:
|
| 51 |
+
if not self.model:
|
| 52 |
+
return f"Error: The '{self.__class__.__name__}' agent could not run because the Gemini API is not configured. Please set the GEMINI_API_KEY."
|
| 53 |
+
try:
|
| 54 |
+
response = self.model.generate_content(prompt)
|
| 55 |
+
return response.text
|
| 56 |
+
except Exception as e:
|
| 57 |
+
print(f"Error executing prompt for {self.__class__.__name__}: {e}")
|
| 58 |
+
return f"Error: Could not get a response from the model. Details: {e}"
|
| 59 |
+
|
| 60 |
+
# --- Specialized Agents ---
|
| 61 |
+
class PriorArtDetective(BaseAgent):
|
| 62 |
+
def analyze(self, invention_disclosure: str) -> Dict:
|
| 63 |
+
prompt = f"""
|
| 64 |
+
Analyze the following invention disclosure to identify the key technical concepts and potential areas of prior art.
|
| 65 |
+
Invention: "{invention_disclosure}"
|
| 66 |
+
|
| 67 |
+
1. List the 3-5 most important technical keywords or concepts.
|
| 68 |
+
2. For each concept, generate a list of 2-3 realistic-sounding, representative prior art titles that likely exist.
|
| 69 |
+
3. Based on these, write a brief, 2-3 sentence summary of the prior art landscape, assessing how crowded it might be.
|
| 70 |
+
|
| 71 |
+
Return the response as a JSON object with keys: "key_concepts", "simulated_prior_art", and "landscape_summary".
|
| 72 |
"""
|
| 73 |
+
response_text = self._execute_prompt(prompt)
|
| 74 |
+
try:
|
| 75 |
+
# Clean the response text before parsing
|
| 76 |
+
clean_response = response_text.strip().replace("```json", "").replace("```", "")
|
| 77 |
+
return json.loads(clean_response)
|
| 78 |
+
except json.JSONDecodeError:
|
| 79 |
+
return {
|
| 80 |
+
"key_concepts": [],
|
| 81 |
+
"simulated_prior_art": [],
|
| 82 |
+
"landscape_summary": "Error parsing prior art analysis from LLM response.",
|
| 83 |
+
}
|
| 84 |
+
|
| 85 |
+
class ChiefStrategistAgent(BaseAgent):
|
| 86 |
+
def formulate_strategy(self, invention_disclosure: str, prior_art_analysis: Dict) -> str:
|
| 87 |
+
prompt = f"""
|
| 88 |
+
You are a Chief Patent Strategist. Your job is to determine the strongest angle for a successful patent application.
|
| 89 |
|
| 90 |
+
Invention Disclosure:
|
| 91 |
+
"{invention_disclosure}"
|
| 92 |
+
|
| 93 |
+
Prior Art Analysis:
|
| 94 |
+
- Key Concepts: {prior_art_analysis.get('key_concepts', [])}
|
| 95 |
+
- Simulated Prior Art: {prior_art_analysis.get('simulated_prior_art', [])}
|
| 96 |
+
- Landscape Summary: {prior_art_analysis.get('landscape_summary', '')}
|
| 97 |
+
|
| 98 |
+
Based on the above, formulate a clear, one-sentence "Strategic Mandate". This mandate will direct all other agents. It must identify the single most patentable aspect of the invention to focus on.
|
| 99 |
+
|
| 100 |
+
Example Mandates:
|
| 101 |
+
- "The strategic focus shall be on the novel method for data encryption, not the hardware implementation."
|
| 102 |
+
- "The patentability of this invention rests on the unique chemical composition of the coating material."
|
| 103 |
+
- "We will patent the specific algorithm for adaptive lighting control, as the general hardware is well-known."
|
| 104 |
+
|
| 105 |
+
Formulate the Strategic Mandate for the provided invention.
|
| 106 |
"""
|
| 107 |
+
return self._execute_prompt(prompt)
|
| 108 |
+
|
| 109 |
+
class TechnicalWriterAgent(BaseAgent):
|
| 110 |
+
def write_summary(self, invention_disclosure: str, strategic_mandate: str) -> str:
|
| 111 |
+
prompt = f"""
|
| 112 |
+
You are a professional patent writer. Your task is to write a "Summary of the Invention" section for a patent application.
|
| 113 |
|
| 114 |
+
Invention Disclosure: "{invention_disclosure}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
|
| 116 |
+
**CRITICAL INSTRUCTION:** You must follow this Strategic Mandate provided by the Chief Strategist:
|
| 117 |
+
**Strategic Mandate: "{strategic_mandate}"**
|
| 118 |
+
|
| 119 |
+
Write a concise, professional summary (2-3 paragraphs). Ensure that the summary heavily emphasizes the aspect highlighted in the Strategic Mandate as the core of the invention.
|
| 120 |
+
"""
|
| 121 |
+
return self._execute_prompt(prompt)
|
| 122 |
+
|
| 123 |
+
class ClaimsDrafterAgent(BaseAgent):
|
| 124 |
+
def draft_claims(self, invention_disclosure: str, strategic_mandate: str) -> str:
|
| 125 |
+
prompt = f"""
|
| 126 |
+
You are a patent attorney specializing in claim drafting.
|
| 127 |
|
| 128 |
+
Invention Disclosure: "{invention_disclosure}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 129 |
|
| 130 |
+
**CRITICAL INSTRUCTION:** Your claim set MUST be aligned with the following mandate:
|
| 131 |
+
**Strategic Mandate: "{strategic_mandate}"**
|
| 132 |
+
|
| 133 |
+
Draft a set of 5-7 patent claims.
|
| 134 |
+
- The independent claim (Claim 1) must be directly focused on the feature identified in the Strategic Mandate.
|
| 135 |
+
- Dependent claims should add further specifics and variations.
|
| 136 |
+
- Ensure the claims are clear, concise, and properly formatted.
|
| 137 |
"""
|
| 138 |
+
return self._execute_prompt(prompt)
|
| 139 |
+
|
| 140 |
+
class FigureDrafterAgent(BaseAgent):
|
| 141 |
+
def describe_figure(self, invention_disclosure: str, strategic_mandate: str) -> str:
|
| 142 |
+
prompt = f"""
|
| 143 |
+
You are a patent illustrator's assistant. You need to describe a key technical figure for a patent application.
|
| 144 |
|
| 145 |
+
Invention Disclosure: "{invention_disclosure}"
|
|
|
|
|
|
|
| 146 |
|
| 147 |
+
**CRITICAL INSTRUCTION:** The figure must visually represent the core idea from the mandate:
|
| 148 |
+
**Strategic Mandate: "{strategic_mandate}"**
|
| 149 |
+
|
| 150 |
+
1. Decide on the best type of figure to illustrate the mandate (e.g., flowchart, system diagram, cross-section).
|
| 151 |
+
2. Write a brief description of this figure.
|
| 152 |
+
3. Generate the LaTeX/TikZ code to create this figure.
|
| 153 |
+
|
| 154 |
+
Return a single response containing both the description and the LaTeX code block.
|
| 155 |
"""
|
| 156 |
+
return self._execute_prompt(prompt)
|
| 157 |
+
|
| 158 |
+
class SegmindIdeogramAgent:
|
| 159 |
+
def __init__(self):
|
| 160 |
+
self.api_key = os.getenv("SEGMIND_API_KEY", "SG_f5de4e5bf40aa615") # Use user's key as default
|
| 161 |
+
self.url = "https://api.segmind.com/v1/ideogram-3"
|
| 162 |
+
|
| 163 |
+
def generate_image(self, technical_summary: str, strategic_mandate: str) -> Optional[str]:
|
| 164 |
+
if not self.api_key:
|
| 165 |
+
return None
|
| 166 |
+
|
| 167 |
+
# Create a more cinematic prompt for image generation
|
| 168 |
+
image_prompt = f"""
|
| 169 |
+
Create a photorealistic, cinematic photograph representing the following invention.
|
| 170 |
+
The image should focus on the core concept defined by the strategic mandate.
|
| 171 |
+
|
| 172 |
+
Invention Summary: "{technical_summary}"
|
| 173 |
+
Core Concept (Strategic Mandate): "{strategic_mandate}"
|
| 174 |
+
|
| 175 |
+
Translate this technical concept into a visually stunning and professional marketing image.
|
| 176 |
+
Emphasize the most innovative aspect. For example, if it's an algorithm, show a sleek user interface or an abstract representation of data flow, not just the hardware.
|
| 177 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
+
data = {
|
| 180 |
+
"prompt": image_prompt,
|
| 181 |
+
"resolution": "1024x1024",
|
| 182 |
+
"style_type": "REALISTIC"
|
|
|
|
|
|
|
|
|
|
| 183 |
}
|
| 184 |
+
headers = {'x-api-key': self.api_key}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 185 |
|
| 186 |
+
try:
|
| 187 |
+
response = requests.post(self.url, json=data, headers=headers)
|
| 188 |
+
if response.status_code == 200:
|
| 189 |
+
return base64.b64encode(response.content).decode('utf-8')
|
| 190 |
+
else:
|
| 191 |
+
print(f"Segmind API Error: {response.status_code} - {response.text}")
|
| 192 |
+
return None
|
| 193 |
+
except Exception as e:
|
| 194 |
+
print(f"Error calling Segmind API: {e}")
|
| 195 |
+
return None
|
| 196 |
|
| 197 |
+
|
| 198 |
+
# --- The Orchestrator ---
|
| 199 |
+
class AgenticNegotiator:
|
| 200 |
+
def __init__(self, invention_disclosure: str):
|
| 201 |
+
self.state = NegotiationState(invention_disclosure=invention_disclosure)
|
|
|
|
| 202 |
self.agents = {
|
| 203 |
+
"Prior Art Detective": PriorArtDetective(),
|
| 204 |
+
"Chief Strategist": ChiefStrategistAgent(),
|
| 205 |
+
"Technical Writer": TechnicalWriterAgent(),
|
| 206 |
+
"Claims Drafter": ClaimsDrafterAgent(),
|
| 207 |
+
"Figure Drafter": FigureDrafterAgent(),
|
| 208 |
+
"Conceptual Artist": SegmindIdeogramAgent(),
|
| 209 |
}
|
| 210 |
+
|
| 211 |
+
def _update_transcript(self, agent_name: str, message: str, data: Optional[Dict] = None):
|
| 212 |
+
entry = {"agent": agent_name, "message": message, "data": data or {}}
|
| 213 |
+
self.state.negotiation_transcript.append(entry)
|
| 214 |
+
|
| 215 |
+
def run_negotiation(self) -> Generator[NegotiationState, None, None]:
|
| 216 |
+
# Step 0: Check for Gemini API Key
|
| 217 |
+
if not GEMINI_AVAILABLE:
|
| 218 |
+
self._update_transcript("System", "CRITICAL ERROR: `GEMINI_API_KEY` is not set. The agentic workflow cannot proceed. Please configure the environment variable.")
|
| 219 |
+
yield self.state
|
| 220 |
+
return
|
| 221 |
+
|
| 222 |
+
# Step 1: Prior Art Detective
|
| 223 |
+
agent_name = "Prior Art Detective"
|
| 224 |
+
self._update_transcript(agent_name, "Analyzing the invention to understand the technical landscape...")
|
| 225 |
+
yield self.state
|
| 226 |
+
|
| 227 |
+
prior_art_result = self.agents[agent_name].analyze(self.state.invention_disclosure)
|
| 228 |
+
self.state.prior_art_analysis = prior_art_result
|
| 229 |
+
self.state.key_concepts = prior_art_result.get("key_concepts", [])
|
| 230 |
+
self._update_transcript(agent_name, f"Analysis complete. The landscape appears to be: {prior_art_result.get('landscape_summary', 'N/A')}", prior_art_result)
|
| 231 |
+
yield self.state
|
| 232 |
+
|
| 233 |
+
# Step 2: Chief Strategist
|
| 234 |
+
agent_name = "Chief Strategist"
|
| 235 |
+
self._update_transcript(agent_name, "Reviewing prior art to determine the most defensible patenting strategy...")
|
| 236 |
+
yield self.state
|
| 237 |
+
|
| 238 |
+
mandate = self.agents[agent_name].formulate_strategy(self.state.invention_disclosure, self.state.prior_art_analysis)
|
| 239 |
+
self.state.strategic_mandate = mandate
|
| 240 |
+
self._update_transcript(agent_name, f"Strategy formulated. All agents will now adhere to the following mandate: **{mandate}**")
|
| 241 |
+
yield self.state
|
| 242 |
+
|
| 243 |
+
# Step 3: Guided Content Generation
|
| 244 |
+
# Technical Summary
|
| 245 |
+
agent_name = "Technical Writer"
|
| 246 |
+
self._update_transcript(agent_name, "Acknowledged. Drafting the technical summary to align with the strategic mandate.")
|
| 247 |
+
yield self.state
|
| 248 |
+
summary = self.agents[agent_name].write_summary(self.state.invention_disclosure, self.state.strategic_mandate)
|
| 249 |
+
self.state.technical_summary = summary
|
| 250 |
+
self._update_transcript(agent_name, "Technical summary drafted.")
|
| 251 |
+
yield self.state
|
| 252 |
+
|
| 253 |
+
# Patent Claims
|
| 254 |
+
agent_name = "Claims Drafter"
|
| 255 |
+
self._update_transcript(agent_name, "Understood. Drafting patent claims focused on the mandated novel aspect.")
|
| 256 |
+
yield self.state
|
| 257 |
+
claims = self.agents[agent_name].draft_claims(self.state.invention_disclosure, self.state.strategic_mandate)
|
| 258 |
+
self.state.patent_claims = claims
|
| 259 |
+
self._update_transcript(agent_name, "Patent claims drafted.")
|
| 260 |
+
yield self.state
|
| 261 |
+
|
| 262 |
+
# Figure Description (LaTeX)
|
| 263 |
+
agent_name = "Figure Drafter"
|
| 264 |
+
self._update_transcript(agent_name, "Affirmative. Designing a technical figure that visually represents the core strategic mandate.")
|
| 265 |
+
yield self.state
|
| 266 |
+
figure_desc = self.agents[agent_name].describe_figure(self.state.invention_disclosure, self.state.strategic_mandate)
|
| 267 |
+
self.state.figure_description = figure_desc
|
| 268 |
+
self._update_transcript(agent_name, "Technical figure description and LaTeX code generated.")
|
| 269 |
+
yield self.state
|
| 270 |
+
|
| 271 |
+
# Conceptual Image (Ideogram)
|
| 272 |
+
agent_name = "Conceptual Artist"
|
| 273 |
+
self._update_transcript(agent_name, "Now generating a high-fidelity conceptual image based on the strategy...")
|
| 274 |
+
yield self.state
|
| 275 |
+
image_b64 = self.agents[agent_name].generate_image(self.state.technical_summary, self.state.strategic_mandate)
|
| 276 |
+
if image_b64:
|
| 277 |
+
self.state.ideogram_image_b64 = image_b64
|
| 278 |
+
self._update_transcript(agent_name, "Conceptual image generated successfully.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
else:
|
| 280 |
+
self._update_transcript(agent_name, "Failed to generate conceptual image. The API may be unavailable or the key may be invalid.")
|
| 281 |
+
yield self.state
|
| 282 |
|
|
|
|
|
|
|
|
|
|
| 283 |
|
| 284 |
+
self._update_transcript("AgenticNegotiator", "All tasks complete. The patent application is ready for assembly.")
|
| 285 |
+
yield self.state
|
| 286 |
+
|
| 287 |
+
def test_agentic_negotiation():
|
| 288 |
+
"""Test the new agentic negotiation workflow."""
|
| 289 |
+
print("🤖 Testing True Agentic Workflow")
|
| 290 |
print("=" * 60)
|
| 291 |
|
| 292 |
+
if not GEMINI_AVAILABLE:
|
| 293 |
+
print("\n❌ Cannot run test: GEMINI_API_KEY is not configured.")
|
| 294 |
+
return
|
| 295 |
+
|
| 296 |
test_invention = """
|
| 297 |
+
My invention is a smart coffee mug that uses a novel phase-change material to keep coffee at a perfect temperature. It also has a mobile app that connects via Bluetooth to let the user set their preferred temperature. The key innovation is a machine learning algorithm that learns the user's drinking habits to pre-warm or cool the mug, optimizing energy use.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 298 |
"""
|
| 299 |
|
| 300 |
+
negotiator = AgenticNegotiator(invention_disclosure=test_invention)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
|
| 302 |
+
final_state = None
|
| 303 |
+
for i, state in enumerate(negotiator.run_negotiation()):
|
| 304 |
+
print(f"\n--- Turn {i+1} ---")
|
| 305 |
+
last_message = state.negotiation_transcript[-1]
|
| 306 |
+
print(f"**{last_message['agent']}:** {last_message['message']}")
|
| 307 |
+
final_state = state
|
| 308 |
+
|
| 309 |
+
print("\n\n✅ Negotiation Complete!")
|
| 310 |
+
print("=" * 60)
|
| 311 |
+
print(f"\n**Final Strategic Mandate:**\n{final_state.strategic_mandate}")
|
| 312 |
+
print(f"\n**Generated Claims Preview:**\n{final_state.patent_claims[:300]}...")
|
| 313 |
+
print(f"\n**Generated Figure Description Preview:**\n{final_state.figure_description[:300]}...")
|
| 314 |
+
if final_state.ideogram_image_b64:
|
| 315 |
+
print(f"\n**Ideogram Image:** Generated successfully (Base64 data)")
|
| 316 |
+
else:
|
| 317 |
+
print(f"\n**Ideogram Image:** Failed to generate.")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
|
| 319 |
if __name__ == "__main__":
|
| 320 |
+
test_agentic_negotiation()
|
requirements.txt
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
-
gradio=
|
| 2 |
-
requests=
|
| 3 |
-
openai=
|
| 4 |
-
pillow=
|
| 5 |
-
python-dotenv=
|
| 6 |
-
google-generativeai=
|
|
|
|
|
|
| 1 |
+
gradio>=4.44.0
|
| 2 |
+
requests>=2.31.0
|
| 3 |
+
openai>=1.51.0
|
| 4 |
+
pillow>=10.0.0
|
| 5 |
+
python-dotenv>=1.0.0
|
| 6 |
+
google-generativeai>=0.8.3
|
| 7 |
+
segmind>=0.2.2
|