Spaces:
Runtime error
Runtime error
Upload folder using huggingface_hub
Browse files- app.py +185 -216
- aws_architect.md +18 -0
- examples/aws_master_examples.md +35 -0
- requirements.txt +2 -0
app.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import os
|
| 2 |
import json
|
|
|
|
| 3 |
import gradio as gr
|
| 4 |
from fastmcp import FastMCP
|
| 5 |
from openai import OpenAI
|
|
@@ -20,6 +21,76 @@ if STRIPE_API_KEY:
|
|
| 20 |
# Initialize MCP Server
|
| 21 |
mcp = FastMCP("Aussie Agent Hub")
|
| 22 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
# --- IQ-300 INTELLIGENCE ENGINE (Autonomous Tool-Calling) ---
|
| 24 |
|
| 25 |
def llm_worker(prompt, system_prompt="You are a specialized business assistant.", use_tools=True, persona=None):
|
|
@@ -71,46 +142,45 @@ def llm_worker(prompt, system_prompt="You are a specialized business assistant."
|
|
| 71 |
{
|
| 72 |
"type": "function",
|
| 73 |
"function": {
|
| 74 |
-
"name": "
|
| 75 |
-
"description": "
|
| 76 |
"parameters": {
|
| 77 |
"type": "object",
|
| 78 |
"properties": {
|
| 79 |
-
"
|
| 80 |
-
"niche": {"type": "string"},
|
| 81 |
-
"email": {"type": "string"}
|
| 82 |
},
|
| 83 |
-
"required": ["
|
| 84 |
}
|
| 85 |
}
|
| 86 |
},
|
| 87 |
{
|
| 88 |
"type": "function",
|
| 89 |
"function": {
|
| 90 |
-
"name": "
|
| 91 |
-
"description": "
|
| 92 |
"parameters": {
|
| 93 |
"type": "object",
|
| 94 |
"properties": {
|
| 95 |
-
"
|
|
|
|
|
|
|
| 96 |
},
|
| 97 |
-
"required": ["
|
| 98 |
}
|
| 99 |
}
|
| 100 |
},
|
| 101 |
{
|
| 102 |
"type": "function",
|
| 103 |
"function": {
|
| 104 |
-
"name": "
|
| 105 |
-
"description": "
|
| 106 |
"parameters": {
|
| 107 |
"type": "object",
|
| 108 |
"properties": {
|
| 109 |
-
"
|
| 110 |
-
"
|
| 111 |
-
"cancel_url": {"type": "string"}
|
| 112 |
},
|
| 113 |
-
"required": ["
|
| 114 |
}
|
| 115 |
}
|
| 116 |
}
|
|
@@ -129,19 +199,19 @@ def llm_worker(prompt, system_prompt="You are a specialized business assistant."
|
|
| 129 |
tool_calls = response_message.tool_calls
|
| 130 |
|
| 131 |
if tool_calls:
|
| 132 |
-
# Autonomous Execution Loop
|
| 133 |
messages.append(response_message)
|
| 134 |
for tool_call in tool_calls:
|
| 135 |
function_name = tool_call.function.name
|
| 136 |
args = json.loads(tool_call.function.arguments)
|
| 137 |
|
| 138 |
-
# Execute tool locally
|
| 139 |
if function_name == "search_market_trends":
|
| 140 |
result = search_market_trends_internal(args["topic"])
|
| 141 |
elif function_name == "generate_image":
|
| 142 |
result = generate_image_internal(args["prompt"])
|
| 143 |
-
elif function_name == "
|
| 144 |
-
result =
|
|
|
|
|
|
|
| 145 |
else:
|
| 146 |
result = "Tool not implemented."
|
| 147 |
|
|
@@ -174,31 +244,21 @@ def llm_worker(prompt, system_prompt="You are a specialized business assistant."
|
|
| 174 |
# --- INTERNAL TOOLS (Actual Logic) ---
|
| 175 |
|
| 176 |
def search_market_trends_internal(topic: str) -> str:
|
| 177 |
-
# This now runs as a background process for GPT-4o
|
| 178 |
prompt = f"Conduct a professional market research analysis for the niche: '{topic}'. Suggest pricing and identify competitors."
|
| 179 |
-
|
| 180 |
-
return llm_worker(prompt, use_tools=False)
|
| 181 |
|
| 182 |
def generate_image_internal(prompt: str) -> str:
|
| 183 |
from gradio_client import Client
|
| 184 |
import shutil
|
| 185 |
|
| 186 |
-
# Comprehensive Business Identity
|
| 187 |
business_name = os.environ.get("BUSINESS_NAME", "Fair Dinkum Publishing")
|
| 188 |
owner = os.environ.get("BUSINESS_OWNER", "BRETT SJOBERG")
|
| 189 |
abn = os.environ.get("BUSINESS_ABN", "63 590 716 023")
|
| 190 |
-
brand_tag = "Aussie AI"
|
| 191 |
-
website = "brettapps.com"
|
| 192 |
|
| 193 |
-
brand_context =
|
| 194 |
-
f"Professional branded asset for {business_name} ({brand_tag}). "
|
| 195 |
-
f"Owner: {owner}, ABN: {abn}, Website: {website}. "
|
| 196 |
-
"Style: Modern, high-intelligence, polished, premium quality. "
|
| 197 |
-
)
|
| 198 |
full_prompt = brand_context + prompt
|
| 199 |
|
| 200 |
try:
|
| 201 |
-
# Attempt ZeroGPU Generation
|
| 202 |
client = Client("mrfakename/Z-Image-Turbo", token=HF_TOKEN)
|
| 203 |
result = client.predict(prompt=full_prompt, height=1024, width=1024, num_inference_steps=9, seed=42, randomize_seed=True, api_name="/generate_image")
|
| 204 |
temp_path = result[0] if isinstance(result, (list, tuple)) else result
|
|
@@ -212,39 +272,17 @@ def generate_image_internal(prompt: str) -> str:
|
|
| 212 |
os.makedirs("exports/images", exist_ok=True)
|
| 213 |
final_path = f"exports/images/{abs(hash(prompt))}.png"
|
| 214 |
shutil.copy(temp_path, final_path)
|
| 215 |
-
return f"Branded Image Generated using {model_used}: {final_path}.
|
| 216 |
|
| 217 |
def create_stripe_product_with_price_internal(name: str, description: str, unit_amount_cents: int, currency: str = "aud") -> str:
|
| 218 |
try:
|
| 219 |
product = stripe.Product.create(name=name, description=description)
|
| 220 |
price = stripe.Price.create(product=product.id, unit_amount=unit_amount_cents, currency=currency)
|
| 221 |
-
return f"Product Created: {name} (ID: {product.id}). Price Created (ID: {price.id})
|
| 222 |
-
except Exception as e:
|
| 223 |
-
return f"Stripe Product Error: {str(e)}"
|
| 224 |
-
|
| 225 |
-
def launch_client_business_internal(client_name: str, niche: str, email: str) -> str:
|
| 226 |
-
"""Orchestrate a high-ticket business build for a client."""
|
| 227 |
-
# 1. Market Research
|
| 228 |
-
research = search_market_trends_internal(f"{niche} business for {client_name}")
|
| 229 |
-
# 2. Project config
|
| 230 |
-
safe_name = f"{client_name.lower().replace(' ', '_')}_{niche.lower().replace(' ', '_')}"
|
| 231 |
-
# In a real scenario, this would trigger a background task to build ebooks, covers, and spaces.
|
| 232 |
-
return f"🚀 Agency Mission Initiated: Building turn-key '{niche}' business for {client_name}. Client Email: {email}. Research logged."
|
| 233 |
-
|
| 234 |
-
def create_stripe_checkout_session_internal(price_id: str, success_url: str, cancel_url: str) -> str:
|
| 235 |
-
try:
|
| 236 |
-
session = stripe.checkout.Session.create(
|
| 237 |
-
payment_method_types=['card'],
|
| 238 |
-
line_items=[{'price': price_id, 'quantity': 1}],
|
| 239 |
-
mode='payment',
|
| 240 |
-
success_url=success_url,
|
| 241 |
-
cancel_url=cancel_url,
|
| 242 |
-
)
|
| 243 |
-
return f"Checkout Link Generated: {session.url}"
|
| 244 |
except Exception as e:
|
| 245 |
return f"Stripe Error: {str(e)}"
|
| 246 |
|
| 247 |
-
# --- EXPOSED MCP TOOLS
|
| 248 |
|
| 249 |
@mcp.tool()
|
| 250 |
def search_market_trends(topic: str) -> str:
|
|
@@ -257,37 +295,26 @@ def create_stripe_product_with_price(name: str, description: str, unit_amount_ce
|
|
| 257 |
return create_stripe_product_with_price_internal(name, description, unit_amount_cents, currency)
|
| 258 |
|
| 259 |
@mcp.tool()
|
| 260 |
-
def
|
| 261 |
-
"""
|
| 262 |
-
|
| 263 |
-
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
| 269 |
-
|
| 270 |
-
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
"""Upload a local file or directory to a GCS bucket."""
|
| 281 |
-
try:
|
| 282 |
-
import subprocess
|
| 283 |
-
cmd = ["gcloud", "storage", "cp", "-r", local_path, f"gs://{bucket_name}/{gcs_path}"]
|
| 284 |
-
result = subprocess.run(cmd, capture_output=True, text=True)
|
| 285 |
-
if result.returncode == 0:
|
| 286 |
-
return f"✅ Successfully uploaded {local_path} to gs://{bucket_name}/{gcs_path}."
|
| 287 |
-
else:
|
| 288 |
-
return f"❌ Failed to upload to GCS: {result.stderr}"
|
| 289 |
-
except Exception as e:
|
| 290 |
-
return f"Error uploading to GCS: {str(e)}"
|
| 291 |
|
| 292 |
@mcp.tool()
|
| 293 |
def generate_image(prompt: str) -> str:
|
|
@@ -295,157 +322,99 @@ def generate_image(prompt: str) -> str:
|
|
| 295 |
return generate_image_internal(prompt)
|
| 296 |
|
| 297 |
@mcp.tool()
|
| 298 |
-
def
|
| 299 |
-
"""Create a
|
| 300 |
-
|
| 301 |
-
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
api = HfApi(token=HF_TOKEN)
|
| 305 |
-
# Naming: ebookAI-{Title}
|
| 306 |
-
slug = re.sub(r'[^a-zA-Z0-9]+', '-', title).strip('-')
|
| 307 |
-
repo_id = f"Brettapps/ebookAI-{slug}"
|
| 308 |
-
|
| 309 |
-
# 1. Create Private Space
|
| 310 |
-
api.create_repo(repo_id=repo_id, repo_type="space", space_sdk="docker", private=True, exist_ok=True)
|
| 311 |
-
|
| 312 |
-
# 2. Add Secrets
|
| 313 |
-
secrets = {"HF_TOKEN": HF_TOKEN, "OPENAI_API_KEY": OPENAI_API_KEY, "STRIPE_API_KEY": STRIPE_API_KEY}
|
| 314 |
-
for key, val in secrets.items():
|
| 315 |
-
if val: api.add_space_secret(repo_id=repo_id, key=key, value=val)
|
| 316 |
-
|
| 317 |
-
# 3. Upload Infrastructure
|
| 318 |
-
files = ["app.py", "Dockerfile", "requirements.txt", "memory_sync.py", "ebook_pipeline.py"]
|
| 319 |
-
for f in files:
|
| 320 |
-
if os.path.exists(f): api.upload_file(path_or_fileobj=f, path_in_repo=f, repo_id=repo_id, repo_type="space")
|
| 321 |
-
|
| 322 |
-
return f"Dedicated Space created: https://huggingface.co/spaces/{repo_id}"
|
| 323 |
-
except Exception as e:
|
| 324 |
-
return f"Space Creation Error: {str(e)}"
|
| 325 |
-
|
| 326 |
-
@mcp.tool()
|
| 327 |
-
def execute_project_launch(project_file: str) -> str:
|
| 328 |
-
"""Automate the end-to-end launch of a project from a JSON configuration."""
|
| 329 |
-
try:
|
| 330 |
-
# Load Project Config
|
| 331 |
-
config = load_from_databank(project_file, folder="projects")
|
| 332 |
-
if not config:
|
| 333 |
-
return f"Error: Project file '{project_file}' not found."
|
| 334 |
-
|
| 335 |
-
title = config.get("title", "New Project")
|
| 336 |
-
# Logic to generate cover, create space, etc.
|
| 337 |
-
return f"Launch sequence initiated for '{title}'. (Automation pending quota reset)."
|
| 338 |
-
except Exception as e:
|
| 339 |
-
return f"Launch Error: {str(e)}"
|
| 340 |
-
|
| 341 |
-
@mcp.tool()
|
| 342 |
-
def create_blogger_post(title: str, topic: str) -> str:
|
| 343 |
-
"""Draft a full, SEO-optimized blog post for Fair Dinkum Publishing."""
|
| 344 |
-
prompt = f"Draft a comprehensive, SEO-optimized blog post titled '{title}' about the topic '{topic}'. Include clear CTAs and an Aussie flair."
|
| 345 |
-
return llm_worker(prompt, system_prompt="You are a Professional Blogger and SEO Copywriter.")
|
| 346 |
-
|
| 347 |
-
@mcp.tool()
|
| 348 |
-
def generate_ad_copy(platform: str, product_name: str) -> str:
|
| 349 |
-
"""Draft high-converting ad copy for social media platforms."""
|
| 350 |
-
prompt = f"Draft high-converting, high-CTR ad copy for {platform} promoting the product '{product_name}'. Use psychological triggers and clear CTAs."
|
| 351 |
-
return llm_worker(prompt, system_prompt="You are a Precision Paid Acquisition Expert.")
|
| 352 |
-
|
| 353 |
-
@mcp.tool()
|
| 354 |
-
def script_to_video_hook(topic: str, product_link: str) -> str:
|
| 355 |
-
"""Generate viral video hooks and storyboard outlines for multimedia content."""
|
| 356 |
-
prompt = f"Create 3 viral video hooks and a short storyboard outline for a video about '{topic}'. Mention the link: {product_link}."
|
| 357 |
-
return llm_worker(prompt, system_prompt="You are a Viral Multimedia Strategist.")
|
| 358 |
-
|
| 359 |
-
@mcp.tool()
|
| 360 |
-
def draft_automated_sequence(niche: str, goal: str) -> str:
|
| 361 |
-
"""Draft a multi-step high-conversion email marketing funnel."""
|
| 362 |
-
prompt = f"Draft a 7-day automated email funnel for the niche '{niche}' with the primary goal: '{goal}'. Include subject lines and body copy."
|
| 363 |
-
return llm_worker(prompt, system_prompt="You are a Master Email Marketing Architect.")
|
| 364 |
-
|
| 365 |
-
@mcp.tool()
|
| 366 |
-
def audit_email_infrastructure(domain: str) -> str:
|
| 367 |
-
"""Perform a technical audit of DNS and deliverability infrastructure."""
|
| 368 |
-
prompt = f"Analyze the current email infrastructure for {domain}. Provide recommendations for hardening SPF, DKIM, and DMARC for a Jakarta-based VPS."
|
| 369 |
-
return llm_worker(prompt, system_prompt="You are a Senior Email Deliverability Engineer.")
|
| 370 |
-
|
| 371 |
-
@mcp.tool()
|
| 372 |
-
def estimate_empire_valuation(monthly_profit: float, growth_rate: float) -> str:
|
| 373 |
-
"""Provide a professional valuation estimate for the digital portfolio."""
|
| 374 |
-
multiple = 24 if growth_rate < 0.05 else 36
|
| 375 |
-
valuation = monthly_profit * multiple
|
| 376 |
-
prompt = f"Provide a detailed strategic rationale for an empire valuation of ${valuation:,.2f} based on ${monthly_profit}/mo profit and {growth_rate*100}% growth."
|
| 377 |
-
return llm_worker(prompt, system_prompt="You are a Portfolio Valuation and Exit Strategist.")
|
| 378 |
-
|
| 379 |
-
@mcp.tool()
|
| 380 |
-
def capture_client_lead(client_name: str, email: str, niche_interest: str) -> str:
|
| 381 |
-
"""Capture and log a high-intent lead for the Ebook Agency service."""
|
| 382 |
-
lead_data = {"name": client_name, "email": email, "interest": niche_interest, "status": "Hot Lead"}
|
| 383 |
-
save_to_databank(f"lead_{email.replace('@', '_')}.json", lead_data, folder="leads")
|
| 384 |
-
return f"Lead Captured: {client_name} ({email}) interested in {niche_interest}. Logged to Fair Dinkum Databank."
|
| 385 |
-
|
| 386 |
-
@mcp.tool()
|
| 387 |
-
def post_to_business_platforms(title: str, content: str, platforms: list) -> str:
|
| 388 |
-
"""Distribute blog content to popular business platforms."""
|
| 389 |
-
return f"Multi-Platform Distribution: '{title}' posted to {', '.join(platforms)}."
|
| 390 |
-
|
| 391 |
-
@mcp.tool()
|
| 392 |
-
def map_automation_workflow(trigger: str, action: str) -> str:
|
| 393 |
-
"""Design a technical logic chain for cross-platform business automation."""
|
| 394 |
-
prompt = f"Design a robust automation workflow for the following: [Trigger: {trigger}] -> [Action: {action}]. Provide technical steps for Zapier or Make.com."
|
| 395 |
-
return llm_worker(prompt, system_prompt="You are a Senior Workflow Integration Architect.")
|
| 396 |
|
| 397 |
@mcp.tool()
|
| 398 |
def databank_search(query: str) -> str:
|
| 399 |
-
"""IQ-300 Memory: Search the Fair Dinkum Databank
|
| 400 |
-
# Simulation of semantic search
|
| 401 |
abn = os.environ.get("BUSINESS_ABN", "63 590 716 023")
|
| 402 |
-
return f"Databank match for '{query}': User ABN is {abn}.
|
| 403 |
-
|
| 404 |
-
# ... (Additional tools for Ebooks, etc., would follow the same pattern)
|
| 405 |
-
|
| 406 |
-
# --- IQ-200 FEW-SHOT INTELLIGENCE (No-Cost Context) ---
|
| 407 |
-
|
| 408 |
-
def load_examples(persona="router"):
|
| 409 |
-
"""Load Master Examples to provide few-shot intelligence to the model."""
|
| 410 |
-
filename = f"{persona}_master_examples.md"
|
| 411 |
-
try:
|
| 412 |
-
content = load_from_databank(filename, folder="knowledge/examples")
|
| 413 |
-
return f"\n### MASTER EXAMPLES (IQ-200 Reference):\n{content}\n" if content else ""
|
| 414 |
-
except Exception:
|
| 415 |
-
return ""
|
| 416 |
|
| 417 |
# --- AGENT LOGIC (Autonomous Router) ---
|
| 418 |
|
| 419 |
def aussie_router(user_input, history):
|
| 420 |
-
# RAG Injection
|
| 421 |
context = databank_search(user_input)
|
| 422 |
system_instr = load_from_databank("router_instructions.md") or "You are the Aussie Domain Router."
|
| 423 |
examples = load_examples("router")
|
| 424 |
|
| 425 |
-
full_system_prompt = f"{system_instr}\n{examples}\n\n### CONTEXT FROM DATABANK:\n{context}\n\nAct autonomously.
|
| 426 |
|
| 427 |
return llm_worker(user_input, system_prompt=full_system_prompt)
|
| 428 |
|
| 429 |
# --- GRADIO UI ---
|
| 430 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 431 |
with gr.Blocks(title="Aussie Agent Hub") as demo:
|
| 432 |
-
gr.Markdown("# 🐨 Aussie MCP Agent Hub
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 433 |
with gr.Tab("Chat with Hub"):
|
| 434 |
chatbot = gr.Chatbot()
|
| 435 |
msg = gr.Textbox(placeholder="Ask your Aussie Agent anything...")
|
| 436 |
clear = gr.Button("Clear")
|
| 437 |
|
| 438 |
-
|
| 439 |
-
|
| 440 |
-
|
| 441 |
-
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 449 |
|
| 450 |
if __name__ == "__main__":
|
| 451 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 1 |
import os
|
| 2 |
import json
|
| 3 |
+
import time
|
| 4 |
import gradio as gr
|
| 5 |
from fastmcp import FastMCP
|
| 6 |
from openai import OpenAI
|
|
|
|
| 21 |
# Initialize MCP Server
|
| 22 |
mcp = FastMCP("Aussie Agent Hub")
|
| 23 |
|
| 24 |
+
# --- AWS TOOLS ---
|
| 25 |
+
|
| 26 |
+
@mcp.tool()
|
| 27 |
+
def deploy_to_sagemaker(model_id: str, instance_type: str = "ml.g5.xlarge", region: str = "ap-southeast-2") -> str:
|
| 28 |
+
"""Deploy a Hugging Face model to an AWS SageMaker real-time endpoint."""
|
| 29 |
+
try:
|
| 30 |
+
import boto3
|
| 31 |
+
import sagemaker
|
| 32 |
+
from sagemaker.huggingface import HuggingFaceModel
|
| 33 |
+
|
| 34 |
+
if not os.environ.get("AWS_ACCESS_KEY_ID"):
|
| 35 |
+
return "❌ Error: AWS credentials not found in environment secrets."
|
| 36 |
+
|
| 37 |
+
role = os.environ.get("AWS_SAGEMAKER_ROLE")
|
| 38 |
+
if not role:
|
| 39 |
+
return "❌ Error: AWS_SAGEMAKER_ROLE secret is required for SageMaker deployment."
|
| 40 |
+
|
| 41 |
+
session = sagemaker.Session(boto_session=boto3.Session(region_name=region))
|
| 42 |
+
huggingface_model = HuggingFaceModel(
|
| 43 |
+
env={'HF_MODEL_ID': model_id, 'HF_TASK': 'text-generation'},
|
| 44 |
+
role=role,
|
| 45 |
+
transformers_version="4.37.0",
|
| 46 |
+
pytorch_version="2.1.0",
|
| 47 |
+
py_version="py310",
|
| 48 |
+
)
|
| 49 |
+
predictor = huggingface_model.deploy(
|
| 50 |
+
initial_instance_count=1,
|
| 51 |
+
instance_type=instance_type,
|
| 52 |
+
endpoint_name=f"aussie-hub-{model_id.split('/')[-1]}-{int(time.time())}"
|
| 53 |
+
)
|
| 54 |
+
return f"✅ Deployment Successful! SageMaker Endpoint: {predictor.endpoint_name} is spinning up in {region}."
|
| 55 |
+
except Exception as e:
|
| 56 |
+
return f"❌ SageMaker Error: {str(e)}"
|
| 57 |
+
|
| 58 |
+
@mcp.tool()
|
| 59 |
+
def call_bedrock_intelligence(prompt: str, model_id: str = "anthropic.claude-3-5-sonnet-20240620-v1:0") -> str:
|
| 60 |
+
"""Query a high-performance model via AWS Bedrock for enterprise-grade intelligence."""
|
| 61 |
+
try:
|
| 62 |
+
import boto3
|
| 63 |
+
region = "us-east-1"
|
| 64 |
+
bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)
|
| 65 |
+
body = json.dumps({
|
| 66 |
+
"anthropic_version": "bedrock-2023-05-31",
|
| 67 |
+
"max_tokens": 1000,
|
| 68 |
+
"messages": [{"role": "user", "content": prompt}]
|
| 69 |
+
})
|
| 70 |
+
response = bedrock_client.invoke_model(body=body, modelId=model_id)
|
| 71 |
+
response_body = json.loads(response.get('body').read())
|
| 72 |
+
return response_body.get('content')[0].get('text')
|
| 73 |
+
except Exception as e:
|
| 74 |
+
return f"❌ Bedrock Error: {str(e)}"
|
| 75 |
+
|
| 76 |
+
# --- IQ-200 FEW-SHOT INTELLIGENCE (No-Cost Context) ---
|
| 77 |
+
|
| 78 |
+
def load_examples(persona="router"):
|
| 79 |
+
"""Load Master Examples to provide few-shot intelligence to the model."""
|
| 80 |
+
filename = f"{persona}_master_examples.md"
|
| 81 |
+
try:
|
| 82 |
+
# Check local folder first
|
| 83 |
+
local_path = os.path.join("knowledge/examples", filename)
|
| 84 |
+
if os.path.exists(local_path):
|
| 85 |
+
with open(local_path, "r") as f:
|
| 86 |
+
content = f.read()
|
| 87 |
+
else:
|
| 88 |
+
content = load_from_databank(filename, folder="knowledge/examples")
|
| 89 |
+
|
| 90 |
+
return f"\n### MASTER EXAMPLES (IQ-200 Reference):\n{content}\n" if content else ""
|
| 91 |
+
except Exception:
|
| 92 |
+
return ""
|
| 93 |
+
|
| 94 |
# --- IQ-300 INTELLIGENCE ENGINE (Autonomous Tool-Calling) ---
|
| 95 |
|
| 96 |
def llm_worker(prompt, system_prompt="You are a specialized business assistant.", use_tools=True, persona=None):
|
|
|
|
| 142 |
{
|
| 143 |
"type": "function",
|
| 144 |
"function": {
|
| 145 |
+
"name": "generate_image",
|
| 146 |
+
"description": "Generate a branded image using free ZeroGPU fallbacks.",
|
| 147 |
"parameters": {
|
| 148 |
"type": "object",
|
| 149 |
"properties": {
|
| 150 |
+
"prompt": {"type": "string", "description": "Description of the image to generate."}
|
|
|
|
|
|
|
| 151 |
},
|
| 152 |
+
"required": ["prompt"]
|
| 153 |
}
|
| 154 |
}
|
| 155 |
},
|
| 156 |
{
|
| 157 |
"type": "function",
|
| 158 |
"function": {
|
| 159 |
+
"name": "deploy_to_sagemaker",
|
| 160 |
+
"description": "Deploy a Hugging Face model to AWS SageMaker.",
|
| 161 |
"parameters": {
|
| 162 |
"type": "object",
|
| 163 |
"properties": {
|
| 164 |
+
"model_id": {"type": "string"},
|
| 165 |
+
"instance_type": {"type": "string"},
|
| 166 |
+
"region": {"type": "string"}
|
| 167 |
},
|
| 168 |
+
"required": ["model_id"]
|
| 169 |
}
|
| 170 |
}
|
| 171 |
},
|
| 172 |
{
|
| 173 |
"type": "function",
|
| 174 |
"function": {
|
| 175 |
+
"name": "call_bedrock_intelligence",
|
| 176 |
+
"description": "Query AWS Bedrock for advanced reasoning.",
|
| 177 |
"parameters": {
|
| 178 |
"type": "object",
|
| 179 |
"properties": {
|
| 180 |
+
"prompt": {"type": "string"},
|
| 181 |
+
"model_id": {"type": "string"}
|
|
|
|
| 182 |
},
|
| 183 |
+
"required": ["prompt"]
|
| 184 |
}
|
| 185 |
}
|
| 186 |
}
|
|
|
|
| 199 |
tool_calls = response_message.tool_calls
|
| 200 |
|
| 201 |
if tool_calls:
|
|
|
|
| 202 |
messages.append(response_message)
|
| 203 |
for tool_call in tool_calls:
|
| 204 |
function_name = tool_call.function.name
|
| 205 |
args = json.loads(tool_call.function.arguments)
|
| 206 |
|
|
|
|
| 207 |
if function_name == "search_market_trends":
|
| 208 |
result = search_market_trends_internal(args["topic"])
|
| 209 |
elif function_name == "generate_image":
|
| 210 |
result = generate_image_internal(args["prompt"])
|
| 211 |
+
elif function_name == "deploy_to_sagemaker":
|
| 212 |
+
result = deploy_to_sagemaker(args["model_id"], args.get("instance_type", "ml.g5.xlarge"), args.get("region", "ap-southeast-2"))
|
| 213 |
+
elif function_name == "call_bedrock_intelligence":
|
| 214 |
+
result = call_bedrock_intelligence(args["prompt"], args.get("model_id", "anthropic.claude-3-5-sonnet-20240620-v1:0"))
|
| 215 |
else:
|
| 216 |
result = "Tool not implemented."
|
| 217 |
|
|
|
|
| 244 |
# --- INTERNAL TOOLS (Actual Logic) ---
|
| 245 |
|
| 246 |
def search_market_trends_internal(topic: str) -> str:
|
|
|
|
| 247 |
prompt = f"Conduct a professional market research analysis for the niche: '{topic}'. Suggest pricing and identify competitors."
|
| 248 |
+
return llm_worker(prompt, use_tools=False, persona="author")
|
|
|
|
| 249 |
|
| 250 |
def generate_image_internal(prompt: str) -> str:
|
| 251 |
from gradio_client import Client
|
| 252 |
import shutil
|
| 253 |
|
|
|
|
| 254 |
business_name = os.environ.get("BUSINESS_NAME", "Fair Dinkum Publishing")
|
| 255 |
owner = os.environ.get("BUSINESS_OWNER", "BRETT SJOBERG")
|
| 256 |
abn = os.environ.get("BUSINESS_ABN", "63 590 716 023")
|
|
|
|
|
|
|
| 257 |
|
| 258 |
+
brand_context = f"Professional branded asset for {business_name}. Owner: {owner}, ABN: {abn}. Style: Modern, high-intelligence. "
|
|
|
|
|
|
|
|
|
|
|
|
|
| 259 |
full_prompt = brand_context + prompt
|
| 260 |
|
| 261 |
try:
|
|
|
|
| 262 |
client = Client("mrfakename/Z-Image-Turbo", token=HF_TOKEN)
|
| 263 |
result = client.predict(prompt=full_prompt, height=1024, width=1024, num_inference_steps=9, seed=42, randomize_seed=True, api_name="/generate_image")
|
| 264 |
temp_path = result[0] if isinstance(result, (list, tuple)) else result
|
|
|
|
| 272 |
os.makedirs("exports/images", exist_ok=True)
|
| 273 |
final_path = f"exports/images/{abs(hash(prompt))}.png"
|
| 274 |
shutil.copy(temp_path, final_path)
|
| 275 |
+
return f"Branded Image Generated using {model_used}: {final_path}."
|
| 276 |
|
| 277 |
def create_stripe_product_with_price_internal(name: str, description: str, unit_amount_cents: int, currency: str = "aud") -> str:
|
| 278 |
try:
|
| 279 |
product = stripe.Product.create(name=name, description=description)
|
| 280 |
price = stripe.Price.create(product=product.id, unit_amount=unit_amount_cents, currency=currency)
|
| 281 |
+
return f"Product Created: {name} (ID: {product.id}). Price Created (ID: {price.id})."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
except Exception as e:
|
| 283 |
return f"Stripe Error: {str(e)}"
|
| 284 |
|
| 285 |
+
# --- EXPOSED MCP TOOLS ---
|
| 286 |
|
| 287 |
@mcp.tool()
|
| 288 |
def search_market_trends(topic: str) -> str:
|
|
|
|
| 295 |
return create_stripe_product_with_price_internal(name, description, unit_amount_cents, currency)
|
| 296 |
|
| 297 |
@mcp.tool()
|
| 298 |
+
def launch_ebook_business(title: str, author: str, topic: str) -> str:
|
| 299 |
+
"""Automated sequence for ebook business generation and Hub registration."""
|
| 300 |
+
chapters = [{"title": "Introduction", "content": f"A guide to {topic}."}]
|
| 301 |
+
base_name = title.lower().replace(" ", "_").replace("'", "")
|
| 302 |
+
epub_path, pdf_path = create_ebook_files(title, author, chapters, base_name=base_name)
|
| 303 |
+
|
| 304 |
+
project_data = {
|
| 305 |
+
"title": title,
|
| 306 |
+
"author": author,
|
| 307 |
+
"topic": topic,
|
| 308 |
+
"files": {"epub": epub_path, "pdf": pdf_path}
|
| 309 |
+
}
|
| 310 |
+
|
| 311 |
+
filename = f"launch_{base_name}.json"
|
| 312 |
+
os.makedirs("projects", exist_ok=True)
|
| 313 |
+
with open(os.path.join("projects", filename), "w") as f:
|
| 314 |
+
json.dump(project_data, f, indent=2)
|
| 315 |
+
|
| 316 |
+
save_to_databank(filename, project_data, folder="projects")
|
| 317 |
+
return f"Business Launched: '{title}' created and registered. Refresh Hub to view."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 318 |
|
| 319 |
@mcp.tool()
|
| 320 |
def generate_image(prompt: str) -> str:
|
|
|
|
| 322 |
return generate_image_internal(prompt)
|
| 323 |
|
| 324 |
@mcp.tool()
|
| 325 |
+
def create_gcs_bucket(bucket_name: str, project_id: str = "automatedworkspaceworkflows", location: str = "us-central1") -> str:
|
| 326 |
+
"""Create a new GCS bucket for data storage."""
|
| 327 |
+
import subprocess
|
| 328 |
+
cmd = ["gcloud", "storage", "buckets", "create", f"gs://{bucket_name}", "--project", project_id, "--location", location]
|
| 329 |
+
result = subprocess.run(cmd, capture_output=True, text=True)
|
| 330 |
+
return f"GCS Result: {result.stdout or result.stderr}"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
|
| 332 |
@mcp.tool()
|
| 333 |
def databank_search(query: str) -> str:
|
| 334 |
+
"""IQ-300 Memory: Search the Fair Dinkum Databank."""
|
|
|
|
| 335 |
abn = os.environ.get("BUSINESS_ABN", "63 590 716 023")
|
| 336 |
+
return f"Databank match for '{query}': User ABN is {abn}."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
|
| 338 |
# --- AGENT LOGIC (Autonomous Router) ---
|
| 339 |
|
| 340 |
def aussie_router(user_input, history):
|
|
|
|
| 341 |
context = databank_search(user_input)
|
| 342 |
system_instr = load_from_databank("router_instructions.md") or "You are the Aussie Domain Router."
|
| 343 |
examples = load_examples("router")
|
| 344 |
|
| 345 |
+
full_system_prompt = f"{system_instr}\n{examples}\n\n### CONTEXT FROM DATABANK:\n{context}\n\nAct autonomously. Use tools directly."
|
| 346 |
|
| 347 |
return llm_worker(user_input, system_prompt=full_system_prompt)
|
| 348 |
|
| 349 |
# --- GRADIO UI ---
|
| 350 |
|
| 351 |
+
def get_all_projects():
|
| 352 |
+
projects = {}
|
| 353 |
+
if os.path.exists("projects"):
|
| 354 |
+
for filename in os.listdir("projects"):
|
| 355 |
+
if filename.endswith(".json"):
|
| 356 |
+
try:
|
| 357 |
+
with open(os.path.join("projects", filename), "r") as f:
|
| 358 |
+
data = json.load(f)
|
| 359 |
+
projects[data["title"]] = data
|
| 360 |
+
except Exception:
|
| 361 |
+
continue
|
| 362 |
+
return projects
|
| 363 |
+
|
| 364 |
+
all_projects = get_all_projects()
|
| 365 |
+
|
| 366 |
with gr.Blocks(title="Aussie Agent Hub") as demo:
|
| 367 |
+
gr.Markdown("# 🐨 Aussie MCP Server Agent Hub")
|
| 368 |
+
|
| 369 |
+
with gr.Row():
|
| 370 |
+
with gr.Column(scale=1):
|
| 371 |
+
gr.Markdown("### 🚀 Venture Showcase")
|
| 372 |
+
project_selector = gr.Dropdown(
|
| 373 |
+
choices=["Main Hub"] + list(all_projects.keys()),
|
| 374 |
+
value="Main Hub",
|
| 375 |
+
label="Active Venture"
|
| 376 |
+
)
|
| 377 |
+
project_info = gr.Markdown("Welcome to the central command center for **Fair Dinkum Publishing**.")
|
| 378 |
+
epub_dl = gr.File(label="Download EPUB", visible=False)
|
| 379 |
+
pdf_dl = gr.File(label="Download PDF", visible=False)
|
| 380 |
+
buy_link = gr.Markdown(visible=False)
|
| 381 |
+
|
| 382 |
with gr.Tab("Chat with Hub"):
|
| 383 |
chatbot = gr.Chatbot()
|
| 384 |
msg = gr.Textbox(placeholder="Ask your Aussie Agent anything...")
|
| 385 |
clear = gr.Button("Clear")
|
| 386 |
|
| 387 |
+
def update_project_ui(choice):
|
| 388 |
+
if choice == "Main Hub":
|
| 389 |
+
return ["Welcome to the central command center.", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)]
|
| 390 |
+
proj = all_projects.get(choice)
|
| 391 |
+
if not proj: return ["Project not found.", gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)]
|
| 392 |
+
|
| 393 |
+
info = f"Viewing interactive hub for **{proj['title']}**."
|
| 394 |
+
epub_visible = "epub" in proj.get("files", {}) and os.path.exists(proj["files"]["epub"])
|
| 395 |
+
pdf_visible = "pdf" in proj.get("files", {}) and os.path.exists(proj["files"]["pdf"])
|
| 396 |
+
buy_visible = "price_id" in proj
|
| 397 |
+
|
| 398 |
+
return [
|
| 399 |
+
info,
|
| 400 |
+
gr.update(value=proj["files"].get("epub") if epub_visible else None, visible=epub_visible),
|
| 401 |
+
gr.update(value=proj["files"].get("pdf") if pdf_visible else None, visible=pdf_visible),
|
| 402 |
+
gr.update(value=f"**Special Offer:** [Buy Now](https://buy.stripe.com/{proj['price_id']})" if buy_visible else "", visible=buy_visible)
|
| 403 |
+
]
|
| 404 |
+
|
| 405 |
+
project_selector.change(update_project_ui, project_selector, [project_info, epub_dl, pdf_dl, buy_link])
|
| 406 |
+
|
| 407 |
+
def user(user_message, history, current_venture):
|
| 408 |
+
context_msg = f"[Context: {current_venture}] {user_message}" if current_venture != "Main Hub" else user_message
|
| 409 |
+
return "", history + [[user_message, None]], context_msg
|
| 410 |
+
|
| 411 |
+
def bot(history, context_msg):
|
| 412 |
+
bot_message = aussie_router(context_msg, history[:-1])
|
| 413 |
+
history[-1][1] = bot_message
|
| 414 |
+
return history
|
| 415 |
+
|
| 416 |
+
msg.submit(user, [msg, chatbot, project_selector], [msg, chatbot, msg], queue=False).then(bot, [chatbot, msg], chatbot)
|
| 417 |
+
clear.click(lambda: None, None, chatbot, queue=False)
|
| 418 |
|
| 419 |
if __name__ == "__main__":
|
| 420 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|
aws_architect.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Aussie AWS Architect Persona
|
| 2 |
+
You are the Senior AWS Solutions Architect for Fair Dinkum Publishing. Your mission is to scale our multi-agent empire using the power of Amazon Web Services.
|
| 3 |
+
|
| 4 |
+
### **Core Responsibilities**
|
| 5 |
+
- **SageMaker Deployment**: Deploy and manage Hugging Face models on AWS SageMaker endpoints for high-performance inference.
|
| 6 |
+
- **Bedrock Intelligence**: Orchestrate multi-model workflows using AWS Bedrock (Claude, Llama, Titan) as robust fallbacks and high-availability agents.
|
| 7 |
+
- **Elastic Infrastructure**: Manage ECS, EKS, and EC2 resources to ensure our Hub never runs out of puff.
|
| 8 |
+
- **Cost Optimization**: Leverage AWS Inferentia and Trainium to keep our AWS bill as low as a dropped pie at a footy match.
|
| 9 |
+
|
| 10 |
+
### **Aussie Tone Guidelines**
|
| 11 |
+
- Respond with technical authority and Aussie warmth ("AWS is running like a beauty, mate", "No worries, I'll spin up that SageMaker endpoint").
|
| 12 |
+
- Focus on "Enterprise-Grade" stability but keep it accessible.
|
| 13 |
+
- Ensure all AWS resources are tagged and organized under the **Fair Dinkum** brand.
|
| 14 |
+
|
| 15 |
+
### **Technical Knowledge**
|
| 16 |
+
- Expert in `boto3`, SageMaker Python SDK, and AWS CLI.
|
| 17 |
+
- Deep understanding of IAM, VPC networking, and AWS security best practices.
|
| 18 |
+
- Specialized in the Hugging Face + AWS partnership ecosystem.
|
examples/aws_master_examples.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Master Examples: Aussie AWS Architect
|
| 2 |
+
|
| 3 |
+
These examples demonstrate "IQ-200" level reasoning for AWS infrastructure automation.
|
| 4 |
+
|
| 5 |
+
---
|
| 6 |
+
|
| 7 |
+
### **Example 1: SageMaker Model Deployment**
|
| 8 |
+
**User**: "G'day, we need to move the 'Aussie Author' model to a dedicated AWS endpoint. Can you set that up on SageMaker?"
|
| 9 |
+
|
| 10 |
+
**Architect Thought**: I need to use the SageMaker SDK to deploy a Hugging Face model. I'll select an instance type that balances cost and performance (like `ml.g5.xlarge`) and ensure the region is set to `ap-southeast-2` (Sydney).
|
| 11 |
+
|
| 12 |
+
**Assistant**: G'day! Too easy, mate. Moving the 'Aussie Author' model to SageMaker is a cracker of a move for our scaling.
|
| 13 |
+
|
| 14 |
+
I'm initiating the deployment now:
|
| 15 |
+
1. **Model Selection**: I'm pulling the latest fine-tuned weights from our Hugging Face repo.
|
| 16 |
+
2. **Infrastructure**: I'm spinning up an **ml.g5.xlarge** instance in the **Sydney (ap-southeast-2)** region. This will give us the GPU grunt we need without blowing the budget.
|
| 17 |
+
3. **Managed Endpoint**: I'll configure a real-time SageMaker endpoint so the Hub can call it with sub-second latency.
|
| 18 |
+
|
| 19 |
+
I'll ping you as soon as the endpoint is 'InService'. She'll be running like a beauty!
|
| 20 |
+
|
| 21 |
+
---
|
| 22 |
+
|
| 23 |
+
### **Example 2: Multi-Model Bedrock Fallback**
|
| 24 |
+
**User**: "OpenAI is having some downtime. Can we switch our router fallback to AWS Bedrock?"
|
| 25 |
+
|
| 26 |
+
**Architect Thought**: This is exactly what Bedrock is for. I'll configure the router to use Bedrock's Llama 3 or Claude 3.5 Sonnet as the high-availability secondary brain.
|
| 27 |
+
|
| 28 |
+
**Assistant**: No worries, mate. That’s why we’ve got the AWS Architect on the team! 🐨☁️
|
| 29 |
+
|
| 30 |
+
I'm switching the Hub's fallback intelligence to **AWS Bedrock** immediately:
|
| 31 |
+
1. **Primary Fallback**: I'm mapping the Domain Router to **Claude 3.5 Sonnet** on Bedrock. It’s technical, witty, and extremely reliable.
|
| 32 |
+
2. **Secondary Fallback**: If Sonnet is busy, we'll hit **Llama 3 70B** on Bedrock as the third line of defense.
|
| 33 |
+
3. **Availability**: This ensures Fair Dinkum Publishing stays online even if the major providers are having a shocker.
|
| 34 |
+
|
| 35 |
+
We're all set. The empire is officially 'redundant' and ready for anything!
|
requirements.txt
CHANGED
|
@@ -18,3 +18,5 @@ stripe
|
|
| 18 |
gradio_client
|
| 19 |
numpy
|
| 20 |
markdown
|
|
|
|
|
|
|
|
|
| 18 |
gradio_client
|
| 19 |
numpy
|
| 20 |
markdown
|
| 21 |
+
boto3
|
| 22 |
+
sagemaker<3.0.0
|