Spaces:
Build error
Build error
| """ | |
| Prompt Marketplace Module | |
| Enables users to create, sell, purchase, and use AI prompts | |
| """ | |
| import os | |
| import json | |
| import uuid | |
| import logging | |
| from typing import Dict, Any, List, Optional | |
| from datetime import datetime | |
| from prompts.prompt_templates import PromptTemplate, PromptTemplateManager | |
| # Setup logging | |
| logging.basicConfig(level=logging.INFO) | |
| logger = logging.getLogger("prompt_marketplace") | |
| class PromptMarketplace: | |
| """Manages the prompt marketplace functionality""" | |
| def __init__(self, data_dir: str = None): | |
| """Initialize the prompt marketplace""" | |
| self.data_dir = data_dir or os.path.join(os.path.dirname(__file__), "marketplace_data") | |
| # Create data directory if it doesn't exist | |
| os.makedirs(self.data_dir, exist_ok=True) | |
| # Paths for data files | |
| self.purchases_file = os.path.join(self.data_dir, "purchases.json") | |
| self.sales_file = os.path.join(self.data_dir, "sales.json") | |
| self.stats_file = os.path.join(self.data_dir, "stats.json") | |
| # Initialize data files if they don't exist | |
| self._initialize_data_files() | |
| # Create prompt template manager | |
| self.template_manager = PromptTemplateManager() | |
| def _initialize_data_files(self): | |
| """Initialize data files if they don't exist""" | |
| if not os.path.exists(self.purchases_file): | |
| with open(self.purchases_file, "w") as f: | |
| json.dump([], f) | |
| if not os.path.exists(self.sales_file): | |
| with open(self.sales_file, "w") as f: | |
| json.dump([], f) | |
| if not os.path.exists(self.stats_file): | |
| with open(self.stats_file, "w") as f: | |
| json.dump({ | |
| "total_sales": 0, | |
| "total_revenue": 0, | |
| "prompt_usage": {}, | |
| "popular_categories": {} | |
| }, f, indent=2) | |
| def list_marketplace_prompts(self, category: str = None, sort_by: str = "popular") -> List[Dict[str, Any]]: | |
| """ | |
| List prompts available in the marketplace | |
| Args: | |
| category: Optional category to filter by | |
| sort_by: Sorting method ('popular', 'newest', 'price_low', 'price_high') | |
| Returns: | |
| List of prompt templates available for purchase | |
| """ | |
| # Get all public templates | |
| all_templates = self.template_manager.get_public_templates() | |
| # Filter by category if specified | |
| if category: | |
| all_templates = [t for t in all_templates if t.category.lower() == category.lower()] | |
| # Convert to dictionaries for easier manipulation | |
| templates_dict = [t.to_dict() for t in all_templates] | |
| # Add usage statistics | |
| templates_with_stats = self._add_stats_to_templates(templates_dict) | |
| # Sort the templates | |
| if sort_by == "popular": | |
| templates_with_stats.sort(key=lambda x: x.get("stats", {}).get("usage_count", 0), reverse=True) | |
| elif sort_by == "newest": | |
| templates_with_stats.sort(key=lambda x: x.get("created_at", ""), reverse=True) | |
| elif sort_by == "price_low": | |
| templates_with_stats.sort(key=lambda x: x.get("price", 0)) | |
| elif sort_by == "price_high": | |
| templates_with_stats.sort(key=lambda x: x.get("price", 0), reverse=True) | |
| return templates_with_stats | |
| def _add_stats_to_templates(self, templates: List[Dict[str, Any]]) -> List[Dict[str, Any]]: | |
| """Add usage statistics to template dictionaries""" | |
| try: | |
| with open(self.stats_file, "r") as f: | |
| stats = json.load(f) | |
| prompt_usage = stats.get("prompt_usage", {}) | |
| # Add stats to each template | |
| for template in templates: | |
| template_id = template.get("id") | |
| template["stats"] = { | |
| "usage_count": prompt_usage.get(template_id, {}).get("count", 0), | |
| "purchase_count": prompt_usage.get(template_id, {}).get("purchases", 0), | |
| "rating": prompt_usage.get(template_id, {}).get("avg_rating", 0), | |
| "reviews": prompt_usage.get(template_id, {}).get("review_count", 0) | |
| } | |
| return templates | |
| except Exception as e: | |
| logger.error(f"Error adding stats to templates: {e}") | |
| return templates | |
| def get_prompt_details(self, prompt_id: str) -> Dict[str, Any]: | |
| """ | |
| Get detailed information about a marketplace prompt | |
| Args: | |
| prompt_id: ID of the prompt template | |
| Returns: | |
| Detailed prompt information including stats and sample outputs | |
| """ | |
| prompt = self.template_manager.get_template(prompt_id) | |
| if not prompt: | |
| return {"success": False, "error": "Prompt not found"} | |
| if not prompt.is_public and prompt.created_by != "system": | |
| return {"success": False, "error": "Prompt is not available in the marketplace"} | |
| # Get prompt details | |
| prompt_dict = prompt.to_dict() | |
| # Add stats | |
| prompt_dict = self._add_stats_to_templates([prompt_dict])[0] | |
| # Get purchase information | |
| prompt_dict["purchases"] = self._get_prompt_purchases(prompt_id) | |
| return { | |
| "success": True, | |
| "prompt": prompt_dict | |
| } | |
| def _get_prompt_purchases(self, prompt_id: str) -> Dict[str, Any]: | |
| """Get purchase information for a prompt""" | |
| try: | |
| with open(self.sales_file, "r") as f: | |
| sales = json.load(f) | |
| # Filter sales for this prompt | |
| prompt_sales = [s for s in sales if s.get("prompt_id") == prompt_id] | |
| return { | |
| "total": len(prompt_sales), | |
| "recent": len([s for s in prompt_sales if | |
| (datetime.now() - datetime.fromisoformat(s.get("timestamp", ""))).days < 7]) | |
| } | |
| except Exception as e: | |
| logger.error(f"Error getting prompt purchases: {e}") | |
| return {"total": 0, "recent": 0} | |
| def create_prompt_for_sale(self, | |
| name: str, | |
| description: str, | |
| template: str, | |
| system_message: str, | |
| category: str, | |
| price: float, | |
| parameters: Dict[str, Any], | |
| created_by: str, | |
| provider_defaults: Dict[str, Any] = None) -> Dict[str, Any]: | |
| """ | |
| Create a new prompt template for sale in the marketplace | |
| Args: | |
| name: Name of the prompt template | |
| description: Description of what the prompt does | |
| template: The prompt template text | |
| system_message: System message for the prompt | |
| category: Category for the prompt | |
| price: Price in credits | |
| parameters: Dictionary of parameters for the prompt | |
| created_by: User ID of the creator | |
| provider_defaults: Default settings for different providers | |
| Returns: | |
| Result dictionary with success status and prompt information | |
| """ | |
| # Validate inputs | |
| if not name or not template: | |
| return {"success": False, "error": "Name and template are required"} | |
| if price < 0: | |
| return {"success": False, "error": "Price cannot be negative"} | |
| # Create the prompt template | |
| new_prompt = PromptTemplate( | |
| name=name, | |
| description=description, | |
| template=template, | |
| system_message=system_message, | |
| category=category, | |
| is_public=True, # It's for sale, so make it public | |
| created_by=created_by, | |
| price=price, | |
| parameters=parameters, | |
| provider_defaults=provider_defaults or {} | |
| ) | |
| # Save the prompt | |
| created_prompt = self.template_manager.create_template(new_prompt) | |
| # Initialize stats for this prompt | |
| self._initialize_prompt_stats(created_prompt.id) | |
| return { | |
| "success": True, | |
| "prompt": created_prompt.to_dict(), | |
| "message": "Prompt successfully created and listed in the marketplace" | |
| } | |
| def _initialize_prompt_stats(self, prompt_id: str): | |
| """Initialize statistics for a new prompt""" | |
| try: | |
| with open(self.stats_file, "r") as f: | |
| stats = json.load(f) | |
| prompt_usage = stats.get("prompt_usage", {}) | |
| prompt_usage[prompt_id] = { | |
| "count": 0, | |
| "purchases": 0, | |
| "avg_rating": 0, | |
| "review_count": 0, | |
| "last_used": None | |
| } | |
| stats["prompt_usage"] = prompt_usage | |
| with open(self.stats_file, "w") as f: | |
| json.dump(stats, f, indent=2) | |
| except Exception as e: | |
| logger.error(f"Error initializing prompt stats: {e}") | |
| def purchase_prompt(self, prompt_id: str, user_id: str, credits_available: float) -> Dict[str, Any]: | |
| """ | |
| Purchase a prompt from the marketplace | |
| Args: | |
| prompt_id: ID of the prompt to purchase | |
| user_id: ID of the user making the purchase | |
| credits_available: Credits available to the user | |
| Returns: | |
| Result dictionary with success status and transaction details | |
| """ | |
| # Get the prompt | |
| prompt = self.template_manager.get_template(prompt_id) | |
| if not prompt: | |
| return {"success": False, "error": "Prompt not found"} | |
| if not prompt.is_public: | |
| return {"success": False, "error": "Prompt is not available for purchase"} | |
| # Check if user already owns this prompt | |
| if self._user_owns_prompt(user_id, prompt_id): | |
| return {"success": False, "error": "You already own this prompt"} | |
| # Check if user has enough credits | |
| if credits_available < prompt.price: | |
| return {"success": False, "error": "Insufficient credits", "credits_needed": prompt.price} | |
| # Process the purchase | |
| purchase_id = str(uuid.uuid4()) | |
| purchase_time = datetime.now().isoformat() | |
| purchase_record = { | |
| "id": purchase_id, | |
| "prompt_id": prompt_id, | |
| "user_id": user_id, | |
| "seller_id": prompt.created_by, | |
| "price": prompt.price, | |
| "timestamp": purchase_time | |
| } | |
| # Record the purchase | |
| self._record_purchase(purchase_record) | |
| # Record the sale | |
| self._record_sale(purchase_record) | |
| # Update statistics | |
| self._update_stats_after_purchase(prompt_id) | |
| return { | |
| "success": True, | |
| "transaction": { | |
| "id": purchase_id, | |
| "prompt_id": prompt_id, | |
| "prompt_name": prompt.name, | |
| "price": prompt.price, | |
| "timestamp": purchase_time | |
| }, | |
| "credits_used": prompt.price, | |
| "message": f"Successfully purchased prompt: {prompt.name}" | |
| } | |
| def _user_owns_prompt(self, user_id: str, prompt_id: str) -> bool: | |
| """Check if a user already owns a prompt""" | |
| try: | |
| with open(self.purchases_file, "r") as f: | |
| purchases = json.load(f) | |
| # Check if the user has already purchased this prompt | |
| for purchase in purchases: | |
| if purchase.get("user_id") == user_id and purchase.get("prompt_id") == prompt_id: | |
| return True | |
| return False | |
| except Exception as e: | |
| logger.error(f"Error checking if user owns prompt: {e}") | |
| return False | |
| def _record_purchase(self, purchase_record: Dict[str, Any]): | |
| """Record a prompt purchase""" | |
| try: | |
| with open(self.purchases_file, "r") as f: | |
| purchases = json.load(f) | |
| purchases.append(purchase_record) | |
| with open(self.purchases_file, "w") as f: | |
| json.dump(purchases, f, indent=2) | |
| except Exception as e: | |
| logger.error(f"Error recording purchase: {e}") | |
| def _record_sale(self, purchase_record: Dict[str, Any]): | |
| """Record a prompt sale""" | |
| try: | |
| with open(self.sales_file, "r") as f: | |
| sales = json.load(f) | |
| sales.append(purchase_record) | |
| with open(self.sales_file, "w") as f: | |
| json.dump(sales, f, indent=2) | |
| except Exception as e: | |
| logger.error(f"Error recording sale: {e}") | |
| def _update_stats_after_purchase(self, prompt_id: str): | |
| """Update statistics after a prompt purchase""" | |
| try: | |
| with open(self.stats_file, "r") as f: | |
| stats = json.load(f) | |
| # Update prompt-specific stats | |
| prompt_usage = stats.get("prompt_usage", {}) | |
| if prompt_id not in prompt_usage: | |
| prompt_usage[prompt_id] = { | |
| "count": 0, | |
| "purchases": 0, | |
| "avg_rating": 0, | |
| "review_count": 0 | |
| } | |
| prompt_usage[prompt_id]["purchases"] = prompt_usage[prompt_id].get("purchases", 0) + 1 | |
| # Update global stats | |
| stats["total_sales"] = stats.get("total_sales", 0) + 1 | |
| # Get the prompt price | |
| prompt = self.template_manager.get_template(prompt_id) | |
| if prompt: | |
| stats["total_revenue"] = stats.get("total_revenue", 0) + prompt.price | |
| # Update category popularity | |
| category = prompt.category | |
| popular_categories = stats.get("popular_categories", {}) | |
| popular_categories[category] = popular_categories.get(category, 0) + 1 | |
| stats["popular_categories"] = popular_categories | |
| # Save updated stats | |
| with open(self.stats_file, "w") as f: | |
| json.dump(stats, f, indent=2) | |
| except Exception as e: | |
| logger.error(f"Error updating stats after purchase: {e}") | |
| def get_user_purchased_prompts(self, user_id: str) -> List[Dict[str, Any]]: | |
| """ | |
| Get prompts purchased by a specific user | |
| Args: | |
| user_id: ID of the user | |
| Returns: | |
| List of prompts owned by the user | |
| """ | |
| purchased_prompt_ids = self._get_user_purchased_prompt_ids(user_id) | |
| # Get the prompt details for each purchased prompt | |
| purchased_prompts = [] | |
| for prompt_id in purchased_prompt_ids: | |
| prompt = self.template_manager.get_template(prompt_id) | |
| if prompt: | |
| prompt_dict = prompt.to_dict() | |
| purchased_prompts.append(prompt_dict) | |
| return purchased_prompts | |
| def _get_user_purchased_prompt_ids(self, user_id: str) -> List[str]: | |
| """Get IDs of prompts purchased by a user""" | |
| try: | |
| with open(self.purchases_file, "r") as f: | |
| purchases = json.load(f) | |
| # Get unique prompt IDs purchased by this user | |
| prompt_ids = set() | |
| for purchase in purchases: | |
| if purchase.get("user_id") == user_id: | |
| prompt_ids.add(purchase.get("prompt_id")) | |
| return list(prompt_ids) | |
| except Exception as e: | |
| logger.error(f"Error getting user purchased prompt IDs: {e}") | |
| return [] | |
| def get_user_sales(self, user_id: str) -> Dict[str, Any]: | |
| """ | |
| Get sales information for a specific seller | |
| Args: | |
| user_id: ID of the seller | |
| Returns: | |
| Dictionary with sales information | |
| """ | |
| try: | |
| with open(self.sales_file, "r") as f: | |
| sales = json.load(f) | |
| # Filter sales by this seller | |
| user_sales = [s for s in sales if s.get("seller_id") == user_id] | |
| # Calculate total revenue | |
| total_revenue = sum(s.get("price", 0) for s in user_sales) | |
| # Group sales by prompt | |
| sales_by_prompt = {} | |
| for sale in user_sales: | |
| prompt_id = sale.get("prompt_id") | |
| if prompt_id not in sales_by_prompt: | |
| sales_by_prompt[prompt_id] = [] | |
| sales_by_prompt[prompt_id].append(sale) | |
| # Get prompt details and calculate stats for each prompt | |
| prompt_sales = [] | |
| for prompt_id, sales_list in sales_by_prompt.items(): | |
| prompt = self.template_manager.get_template(prompt_id) | |
| if not prompt: | |
| continue | |
| prompt_revenue = sum(s.get("price", 0) for s in sales_list) | |
| prompt_sales.append({ | |
| "prompt_id": prompt_id, | |
| "prompt_name": prompt.name, | |
| "price": prompt.price, | |
| "sales_count": len(sales_list), | |
| "revenue": prompt_revenue, | |
| "last_sale": max(s.get("timestamp", "") for s in sales_list) | |
| }) | |
| # Sort by revenue | |
| prompt_sales.sort(key=lambda x: x.get("revenue", 0), reverse=True) | |
| return { | |
| "success": True, | |
| "total_sales": len(user_sales), | |
| "total_revenue": total_revenue, | |
| "prompt_count": len(prompt_sales), | |
| "prompts": prompt_sales | |
| } | |
| except Exception as e: | |
| logger.error(f"Error getting user sales: {e}") | |
| return { | |
| "success": False, | |
| "error": str(e) | |
| } | |
| def record_prompt_usage(self, prompt_id: str, user_id: str, provider: str = None) -> bool: | |
| """ | |
| Record usage of a prompt | |
| Args: | |
| prompt_id: ID of the prompt used | |
| user_id: ID of the user using the prompt | |
| provider: Optional provider used | |
| Returns: | |
| Success status | |
| """ | |
| try: | |
| with open(self.stats_file, "r") as f: | |
| stats = json.load(f) | |
| # Update prompt usage stats | |
| prompt_usage = stats.get("prompt_usage", {}) | |
| if prompt_id not in prompt_usage: | |
| prompt_usage[prompt_id] = { | |
| "count": 0, | |
| "purchases": 0, | |
| "avg_rating": 0, | |
| "review_count": 0 | |
| } | |
| prompt_usage[prompt_id]["count"] = prompt_usage[prompt_id].get("count", 0) + 1 | |
| prompt_usage[prompt_id]["last_used"] = datetime.now().isoformat() | |
| # Track provider usage if provided | |
| if provider: | |
| providers = prompt_usage[prompt_id].get("providers", {}) | |
| providers[provider] = providers.get(provider, 0) + 1 | |
| prompt_usage[prompt_id]["providers"] = providers | |
| # Save updated stats | |
| with open(self.stats_file, "w") as f: | |
| json.dump(stats, f, indent=2) | |
| return True | |
| except Exception as e: | |
| logger.error(f"Error recording prompt usage: {e}") | |
| return False | |
| def rate_prompt(self, prompt_id: str, user_id: str, rating: int, review: str = None) -> Dict[str, Any]: | |
| """ | |
| Rate and review a prompt | |
| Args: | |
| prompt_id: ID of the prompt to rate | |
| user_id: ID of the user providing the rating | |
| rating: Rating value (1-5) | |
| review: Optional review text | |
| Returns: | |
| Result dictionary with success status | |
| """ | |
| # Validate rating | |
| if rating < 1 or rating > 5: | |
| return {"success": False, "error": "Rating must be between 1 and 5"} | |
| # Check if the user owns the prompt | |
| if not self._user_owns_prompt(user_id, prompt_id): | |
| return {"success": False, "error": "You must purchase a prompt before rating it"} | |
| try: | |
| # Update the stats with the new rating | |
| with open(self.stats_file, "r") as f: | |
| stats = json.load(f) | |
| prompt_usage = stats.get("prompt_usage", {}) | |
| if prompt_id not in prompt_usage: | |
| return {"success": False, "error": "Prompt not found"} | |
| # Calculate new average rating | |
| current_avg = prompt_usage[prompt_id].get("avg_rating", 0) | |
| current_count = prompt_usage[prompt_id].get("review_count", 0) | |
| if current_count == 0: | |
| new_avg = rating | |
| else: | |
| new_avg = (current_avg * current_count + rating) / (current_count + 1) | |
| prompt_usage[prompt_id]["avg_rating"] = new_avg | |
| prompt_usage[prompt_id]["review_count"] = current_count + 1 | |
| # Save the review if provided | |
| if review: | |
| reviews = prompt_usage[prompt_id].get("reviews", []) | |
| reviews.append({ | |
| "user_id": user_id, | |
| "rating": rating, | |
| "review": review, | |
| "timestamp": datetime.now().isoformat() | |
| }) | |
| prompt_usage[prompt_id]["reviews"] = reviews | |
| # Save updated stats | |
| with open(self.stats_file, "w") as f: | |
| json.dump(stats, f, indent=2) | |
| return { | |
| "success": True, | |
| "message": "Rating submitted successfully", | |
| "new_rating": new_avg, | |
| "review_count": current_count + 1 | |
| } | |
| except Exception as e: | |
| logger.error(f"Error rating prompt: {e}") | |
| return { | |
| "success": False, | |
| "error": str(e) | |
| } | |
| def get_marketplace_stats(self) -> Dict[str, Any]: | |
| """Get overall marketplace statistics""" | |
| try: | |
| with open(self.stats_file, "r") as f: | |
| stats = json.load(f) | |
| # Get the top prompts by usage | |
| prompt_usage = stats.get("prompt_usage", {}) | |
| top_prompts = [] | |
| for prompt_id, usage in prompt_usage.items(): | |
| prompt = self.template_manager.get_template(prompt_id) | |
| if not prompt: | |
| continue | |
| top_prompts.append({ | |
| "id": prompt_id, | |
| "name": prompt.name, | |
| "creator": prompt.created_by, | |
| "category": prompt.category, | |
| "price": prompt.price, | |
| "usage_count": usage.get("count", 0), | |
| "purchase_count": usage.get("purchases", 0), | |
| "rating": usage.get("avg_rating", 0), | |
| "review_count": usage.get("review_count", 0) | |
| }) | |
| # Sort by usage count | |
| top_prompts.sort(key=lambda x: x.get("usage_count", 0), reverse=True) | |
| top_prompts = top_prompts[:10] # Get top 10 | |
| # Get top categories | |
| categories = stats.get("popular_categories", {}) | |
| top_categories = [{"category": k, "count": v} for k, v in categories.items()] | |
| top_categories.sort(key=lambda x: x.get("count", 0), reverse=True) | |
| return { | |
| "success": True, | |
| "total_sales": stats.get("total_sales", 0), | |
| "total_revenue": stats.get("total_revenue", 0), | |
| "top_prompts": top_prompts, | |
| "top_categories": top_categories | |
| } | |
| except Exception as e: | |
| logger.error(f"Error getting marketplace stats: {e}") | |
| return { | |
| "success": False, | |
| "error": str(e) | |
| } | |
| # Example usage | |
| if __name__ == "__main__": | |
| # Initialize the marketplace | |
| marketplace = PromptMarketplace() | |
| # Create a sample prompt for sale | |
| prompt_result = marketplace.create_prompt_for_sale( | |
| name="Advanced SEO Article Writer", | |
| description="Generate comprehensive SEO-optimized articles with proper keyword placement and structure", | |
| template="Write a {length} word SEO-optimized article about {topic}. Target the keyword {keyword} with a keyword density of {density}%. Include {headings} headings, a compelling introduction, and a conclusion with call-to-action.", | |
| system_message="You are an expert SEO content writer who creates engaging, well-researched content that ranks well in search engines.", | |
| category="marketing", | |
| price=25.0, | |
| parameters={ | |
| "topic": {"type": "string", "description": "Main topic of the article", "required": True}, | |
| "keyword": {"type": "string", "description": "Target keyword to optimize for", "required": True}, | |
| "length": {"type": "number", "description": "Word count", "default": 1500}, | |
| "density": {"type": "number", "description": "Keyword density percentage", "default": 2}, | |
| "headings": {"type": "number", "description": "Number of headings to include", "default": 5} | |
| }, | |
| created_by="seller123", | |
| provider_defaults={ | |
| "openai": {"model": "gpt-4-turbo"} | |
| } | |
| ) | |
| print(f"Created prompt: {prompt_result['success']}") | |
| if prompt_result['success']: | |
| # Simulate a purchase | |
| purchase_result = marketplace.purchase_prompt( | |
| prompt_id=prompt_result['prompt']['id'], | |
| user_id="buyer456", | |
| credits_available=100.0 | |
| ) | |
| print(f"Purchase result: {purchase_result['success']}") | |
| # Record usage of the prompt | |
| marketplace.record_prompt_usage( | |
| prompt_id=prompt_result['prompt']['id'], | |
| user_id="buyer456", | |
| provider="openai" | |
| ) | |
| # Rate the prompt | |
| rating_result = marketplace.rate_prompt( | |
| prompt_id=prompt_result['prompt']['id'], | |
| user_id="buyer456", | |
| rating=5, | |
| review="This prompt generated an excellent SEO article that ranked quickly!" | |
| ) | |
| print(f"Rating result: {rating_result['success']}") | |
| # Get marketplace stats | |
| stats = marketplace.get_marketplace_stats() | |
| print(f"Marketplace stats: {stats['success']}") | |
| if stats['success']: | |
| print(f"Total sales: {stats['total_sales']}") |