code-generation-system / src /pipeline.py
purav-2008's picture
Publishing to public space for live url
d0fdbcd
Raw History Blame Contribute Delete
19.1 kB
"""
Multi-stage generation pipeline orchestrator.
Implements the 4-stage compiler-like system for code generation.
"""
import json
import os
from typing import Any, Dict, List, Optional, Tuple
from datetime import datetime
import re
# Mock LLM calls for now - will be replaced with actual API calls
try:
import anthropic
HAS_ANTHROPIC = True
except ImportError:
HAS_ANTHROPIC = False
from validator import Validator
from repair_engine import RepairEngine
class IntentExtractor:
"""Stage 1: Extract structured intent from natural language."""
def __init__(self, use_llm: bool = True):
self.use_llm = use_llm and HAS_ANTHROPIC
def extract(self, user_prompt: str) -> Dict[str, Any]:
"""Extract structured intent from user prompt."""
if self.use_llm:
return self._extract_with_llm(user_prompt)
else:
return self._extract_pattern_based(user_prompt)
def _extract_pattern_based(self, prompt: str) -> Dict[str, Any]:
"""Pattern-based intent extraction (fallback)."""
intent = {
"app_name": self._extract_app_name(prompt),
"app_description": prompt[:200],
"key_features": self._extract_features(prompt),
"user_roles": self._extract_roles(prompt),
"core_entities": self._extract_entities(prompt),
"business_requirements": self._extract_requirements(prompt),
"constraints": self._extract_constraints(prompt),
}
return intent
def _extract_app_name(self, prompt: str) -> str:
"""Extract app name from prompt."""
# Look for "Build a X" or "Create a X"
match = re.search(r'(?:Build|Create|Make|Generate)\s+(?:a\s+)?([A-Z][a-zA-Z\s]+?)(?:\s+with|\s+that|\.|$)', prompt)
if match:
return match.group(1).strip().replace(" ", "")
return "GeneratedApp"
def _extract_features(self, prompt: str) -> List[str]:
"""Extract key features."""
features = []
# Common feature keywords
feature_keywords = [
"login", "authentication", "contacts", "dashboard", "analytics",
"admin", "payments", "role-based", "access", "premium", "plan",
"reports", "export", "import", "notifications", "search"
]
for keyword in feature_keywords:
if keyword.lower() in prompt.lower():
features.append(keyword)
return features or ["basic_crud"]
def _extract_roles(self, prompt: str) -> List[str]:
"""Extract user roles."""
roles = []
role_keywords = {"admin": "admin", "user": "user", "guest": "guest", "customer": "user"}
for keyword, role in role_keywords.items():
if keyword.lower() in prompt.lower():
roles.append(role)
return roles or ["user"]
def _extract_entities(self, prompt: str) -> List[str]:
"""Extract core data entities."""
entities = []
entity_keywords = {
"contact": "Contact",
"user": "User",
"product": "Product",
"order": "Order",
"payment": "Payment",
"report": "Report",
"dashboard": "Dashboard",
}
for keyword, entity in entity_keywords.items():
if keyword.lower() in prompt.lower():
entities.append(entity)
return entities or ["Item"]
def _extract_requirements(self, prompt: str) -> List[str]:
"""Extract business requirements."""
return [
"User authentication and authorization",
"Role-based access control",
"Data persistence",
"API endpoints for CRUD operations",
]
def _extract_constraints(self, prompt: str) -> List[str]:
"""Extract constraints."""
constraints = []
if "premium" in prompt.lower():
constraints.append("Payment processing required")
if "real-time" in prompt.lower():
constraints.append("Real-time synchronization needed")
return constraints
def _extract_with_llm(self, prompt: str) -> Dict[str, Any]:
"""Extract intent using Anthropic API."""
try:
client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
extraction_prompt = f"""Extract structured intent from this user prompt:
"{prompt}"
Return a JSON with these fields:
- app_name: string (extract or generate a name)
- app_description: string (2-3 sentences)
- key_features: list[string] (extracted features)
- user_roles: list[string] (roles mentioned)
- core_entities: list[string] (data models)
- business_requirements: list[string] (business rules)
- constraints: list[string] (any constraints mentioned)
Return ONLY valid JSON, no markdown formatting."""
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[{"role": "user", "content": extraction_prompt}]
)
response_text = message.content[0].text
return json.loads(response_text)
except Exception as e:
print(f"LLM extraction failed: {e}, falling back to pattern-based")
return self._extract_pattern_based(prompt)
class SystemDesignLayer:
"""Stage 2: Convert intent to system design."""
def __init__(self, use_llm: bool = True):
self.use_llm = use_llm and HAS_ANTHROPIC
def design(self, intent: Dict[str, Any]) -> Dict[str, Any]:
"""Generate system design from intent."""
if self.use_llm:
return self._design_with_llm(intent)
else:
return self._design_rule_based(intent)
def _design_rule_based(self, intent: Dict[str, Any]) -> Dict[str, Any]:
"""Rule-based system design."""
design = {
"entities": self._generate_entities(intent),
"user_flows": self._generate_flows(intent),
"roles_and_permissions": self._generate_rbac(intent),
"data_models": intent["core_entities"],
"api_patterns": ["REST"],
"ui_structure": self._generate_ui_structure(intent),
}
return design
def _generate_entities(self, intent: Dict[str, Any]) -> Dict[str, List[str]]:
"""Generate entity definitions."""
entities = {}
for entity in intent["core_entities"]:
if entity.lower() == "user":
entities[entity] = ["id", "name", "email", "role", "created_at"]
elif entity.lower() == "contact":
entities[entity] = ["id", "name", "email", "phone", "owner_id"]
elif entity.lower() == "product":
entities[entity] = ["id", "name", "price", "description"]
elif entity.lower() == "order":
entities[entity] = ["id", "user_id", "total", "status", "created_at"]
else:
entities[entity] = ["id", "name", "created_at"]
return entities
def _generate_flows(self, intent: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate user flows."""
flows = [
{"name": "Authentication", "steps": ["Login", "Verify", "Redirect to Dashboard"]},
{"name": "CRUD Operations", "steps": ["View", "Create", "Update", "Delete"]},
]
if "admin" in intent["user_roles"]:
flows.append({"name": "Admin Panel", "steps": ["View Analytics", "Manage Users", "View Reports"]})
return flows
def _generate_rbac(self, intent: Dict[str, Any]) -> Dict[str, List[str]]:
"""Generate role-based access control."""
rbac = {}
for role in intent["user_roles"]:
if role == "admin":
rbac[role] = ["read_all", "write_all", "delete_all", "manage_users"]
elif role == "user":
rbac[role] = ["read_own", "write_own", "delete_own"]
else:
rbac[role] = ["read_public"]
return rbac
def _generate_ui_structure(self, intent: Dict[str, Any]) -> List[str]:
"""Generate UI page structure."""
pages = ["/login", "/dashboard", "/profile"]
if "contacts" in str(intent["key_features"]).lower():
pages.append("/contacts")
if "admin" in intent["user_roles"]:
pages.append("/admin")
if "analytics" in str(intent["key_features"]).lower():
pages.append("/analytics")
return pages
def _design_with_llm(self, intent: Dict[str, Any]) -> Dict[str, Any]:
"""Generate system design using LLM."""
try:
client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
design_prompt = f"""Design a system architecture based on this intent:
{json.dumps(intent, indent=2)}
Return a JSON with these fields:
- entities: dict mapping entity names to attribute lists
- user_flows: list of flow objects with name and steps
- roles_and_permissions: dict mapping roles to permissions
- data_models: list of entity names
- api_patterns: list (e.g., ["REST", "GraphQL"])
- ui_structure: list of page paths
Return ONLY valid JSON."""
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=2048,
messages=[{"role": "user", "content": design_prompt}]
)
response_text = message.content[0].text
return json.loads(response_text)
except Exception as e:
print(f"LLM design failed: {e}, using rule-based")
return self._design_rule_based(intent)
class SchemaGenerator:
"""Stage 3: Generate complete schemas (DB, API, UI, Auth)."""
def __init__(self, use_llm: bool = True):
self.use_llm = use_llm and HAS_ANTHROPIC
def generate(self, design: Dict[str, Any], intent: Dict[str, Any]) -> Dict[str, Any]:
"""Generate complete schema from design."""
if self.use_llm:
return self._generate_with_llm(design, intent)
else:
return self._generate_rule_based(design, intent)
def _generate_rule_based(self, design: Dict[str, Any], intent: Dict[str, Any]) -> Dict[str, Any]:
"""Rule-based schema generation."""
schema = {
"app_name": intent["app_name"],
"app_description": intent["app_description"],
"database_schema": self._generate_db_schema(design),
"api_schema": self._generate_api_schema(design),
"ui_schema": self._generate_ui_schema(design),
"auth_config": self._generate_auth_config(design),
"roles": self._generate_roles(design),
"business_logic": self._generate_business_logic(intent),
}
return schema
def _generate_db_schema(self, design: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate database schema."""
tables = []
for entity, attributes in design.get("entities", {}).items():
table = {
"name": entity.lower() + "s",
"fields": [
{"name": "id", "type": "string", "required": True},
] + [
{"name": attr, "type": "string", "required": True}
for attr in attributes if attr != "id"
],
"primary_key": "id",
"indexes": ["id"]
}
tables.append(table)
return tables
def _generate_api_schema(self, design: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate API schema."""
endpoints = []
for entity in design.get("data_models", []):
base_path = f"/api/{entity.lower()}s"
endpoints.extend([
{"path": base_path, "method": "GET", "description": f"List {entity}s"},
{"path": f"{base_path}/{{id}}", "method": "GET", "description": f"Get {entity}"},
{"path": base_path, "method": "POST", "description": f"Create {entity}"},
{"path": f"{base_path}/{{id}}", "method": "PUT", "description": f"Update {entity}"},
{"path": f"{base_path}/{{id}}", "method": "DELETE", "description": f"Delete {entity}"},
])
return endpoints
def _generate_ui_schema(self, design: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate UI schema."""
pages = []
for path in design.get("ui_structure", []):
page = {
"path": path,
"title": path.replace("/", " ").title(),
"components": [
{"name": "header", "type": "header"},
{"name": "content", "type": "container"},
{"name": "footer", "type": "footer"},
]
}
pages.append(page)
return pages
def _generate_auth_config(self, design: Dict[str, Any]) -> Dict[str, Any]:
"""Generate authentication config."""
return {
"type": "jwt",
"secret_key": "generated-secret",
"expiry": 3600,
"refresh_token_expiry": 86400,
}
def _generate_roles(self, design: Dict[str, Any]) -> List[Dict[str, Any]]:
"""Generate roles from RBAC."""
roles = []
for role_name, permissions in design.get("roles_and_permissions", {}).items():
roles.append({
"name": role_name,
"permissions": permissions,
"description": f"Role: {role_name}"
})
return roles
def _generate_business_logic(self, intent: Dict[str, Any]) -> Dict[str, Any]:
"""Generate business logic rules."""
logic = {
"validation_rules": [
"Email must be valid format",
"Password must be at least 8 characters",
],
"access_control": "Role-based access control enabled",
"premium_features": "premium" in str(intent).lower(),
}
return logic
def _generate_with_llm(self, design: Dict[str, Any], intent: Dict[str, Any]) -> Dict[str, Any]:
"""Generate schemas using LLM."""
try:
client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
schema_prompt = f"""Generate complete schemas from this design and intent:
Design: {json.dumps(design, indent=2)}
Intent: {json.dumps(intent, indent=2)}
Return a JSON with these fields:
- app_name: string
- app_description: string
- database_schema: list of tables (each with name, fields, primary_key)
- api_schema: list of endpoints (path, method, description)
- ui_schema: list of pages (path, title, components)
- auth_config: object with type, expiry, etc.
- roles: list of role objects (name, permissions, description)
- business_logic: object with business rules
All table fields must be objects with: name, type, required
Valid types: string, number, boolean, date, email, enum
All API endpoints must have valid HTTP methods: GET, POST, PUT, DELETE
Return ONLY valid JSON."""
message = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=4096,
messages=[{"role": "user", "content": schema_prompt}]
)
response_text = message.content[0].text
return json.loads(response_text)
except Exception as e:
print(f"LLM schema generation failed: {e}, using rule-based")
return self._generate_rule_based(design, intent)
class RefinementLayer:
"""Stage 4: Refine and validate schemas across all layers."""
def __init__(self):
self.validator = Validator()
self.repair_engine = RepairEngine()
def refine(self, schema: Dict[str, Any], max_iterations: int = 3) -> Tuple[Dict[str, Any], Dict[str, Any]]:
"""Validate and repair schema iteratively."""
metadata = {
"iterations": 0,
"validation_results": [],
"repairs": [],
"final_status": "unknown",
}
for i in range(max_iterations):
metadata["iterations"] = i + 1
# Validate
result = self.validator.validate_complete(schema)
metadata["validation_results"].append(result.to_dict())
if result.is_valid:
metadata["final_status"] = "valid"
return schema, metadata
# Repair
schema, repairs = self.repair_engine.repair_config(schema)
metadata["repairs"].extend(repairs)
metadata["final_status"] = "repaired_with_warnings" if metadata["validation_results"][-1]["errors"] else "valid"
return schema, metadata
class Pipeline:
"""Main orchestrator for the 4-stage pipeline."""
def __init__(self, use_llm: bool = True):
self.intent_extractor = IntentExtractor(use_llm=use_llm)
self.system_design = SystemDesignLayer(use_llm=use_llm)
self.schema_generator = SchemaGenerator(use_llm=use_llm)
self.refinement = RefinementLayer()
self.use_llm = use_llm
def generate(self, user_prompt: str) -> Tuple[Dict[str, Any], Dict[str, Any]]:
"""Run complete pipeline: prompt → config."""
execution_log = {
"timestamp": datetime.now().isoformat(),
"user_prompt": user_prompt[:500],
"stages": {}
}
try:
# Stage 1: Intent Extraction
intent = self.intent_extractor.extract(user_prompt)
execution_log["stages"]["intent_extraction"] = {"status": "completed"}
# Stage 2: System Design
design = self.system_design.design(intent)
execution_log["stages"]["system_design"] = {"status": "completed"}
# Stage 3: Schema Generation
schema = self.schema_generator.generate(design, intent)
execution_log["stages"]["schema_generation"] = {"status": "completed"}
# Stage 4: Refinement
refined_schema, refinement_metadata = self.refinement.refine(schema)
execution_log["stages"]["refinement"] = refinement_metadata
execution_log["final_status"] = "success"
return refined_schema, execution_log
except Exception as e:
execution_log["final_status"] = "error"
execution_log["error"] = str(e)
return {}, execution_log