SitegeistAI / app.py
Alejandro Ardila
First attempt
d0c87f7
import gradio as gr
import modal
import json
# --- Configuration ---
MODAL_APP_NAME = "sitegeist-ai-app"
def analyze_web_content(urls_json: str, deep_analysis: bool = False, analysis_prompt: str = "Summarize the content and identify key themes."):
"""
MCP Tool: Analyzes web content from one or more URLs.
Performs deep analysis with marketing metrics if a single URL is provided and deep_analysis is True.
Otherwise, performs a swarm analysis for multiple URLs or a single URL without deep_analysis.
Args:
urls_json (str): A JSON string representing a list of URLs. e.g., '["http://example.com", "http://another.com"]'
deep_analysis (bool): If True and only one URL is provided, performs an in-depth analysis.
analysis_prompt (str): The specific analysis to perform on the content.
"""
print(f"Received request: deep_analysis={deep_analysis}, prompt='{analysis_prompt}', urls_json='{urls_json}'")
try:
urls = json.loads(urls_json)
if not isinstance(urls, list) or not all(isinstance(url, str) for url in urls):
raise ValueError("Input must be a JSON string of a list of URLs.")
if not urls:
return json.dumps({"status": "error", "message": "URL list cannot be empty."})
except json.JSONDecodeError:
return json.dumps({"status": "error", "message": "Invalid JSON format for URLs."})
except ValueError as ve:
return json.dumps({"status": "error", "message": str(ve)})
result = None
try:
if len(urls) == 1 and deep_analysis:
print(f"Calling Modal: deep_analyze_url for {urls[0]}")
# Lookup the Modal function
modal_deep_analyze = modal.Function.lookup(MODAL_APP_NAME, "deep_analyze_url")
if modal_deep_analyze is None:
return json.dumps({"status": "error", "message": f"Could not find Modal function 'deep_analyze_url' in app '{MODAL_APP_NAME}'."})
# Call the Modal function remotely
result = modal_deep_analyze.remote(url=urls[0])
else:
print(f"Calling Modal: swarm_analyze_urls for {len(urls)} URLs")
# Lookup the Modal function
modal_swarm_analyze = modal.Function.lookup(MODAL_APP_NAME, "swarm_analyze_urls")
if modal_swarm_analyze is None:
return json.dumps({"status": "error", "message": f"Could not find Modal function 'swarm_analyze_urls' in app '{MODAL_APP_NAME}'."})
# Call the Modal function remotely
result = modal_swarm_analyze.remote(urls=urls, analysis_prompt=analysis_prompt)
return json.dumps(result, indent=2) # Return the result from Modal as a JSON string
except modal.exception.NotFoundError as e:
print(f"Modal function not found: {e}")
return json.dumps({"status": "error", "message": f"Modal function lookup failed. Ensure '{MODAL_APP_NAME}' is deployed and functions are correctly named. Details: {e}"})
except Exception as e:
print(f"An unexpected error occurred: {e}")
return json.dumps({"status": "error", "message": f"An unexpected error occurred: {str(e)}"})
# --- Gradio Interface for Testing (if not using MCP directly) ---
# This allows you to test the analyze_web_content function via a web UI.
# You would typically expose `analyze_web_content` directly as an MCP tool.
with gr.Blocks() as demo:
gr.Markdown("# Sitegeist AI: Marketing & Content Intelligence Engine")
gr.Markdown(
"Enter URLs as a JSON list (e.g., `[\"http://url1.com\", \"http://url2.com\"]`). "
"The Modal backend calls are mocked and will return predefined data."
)
with gr.Row():
urls_input = gr.Textbox(label="URLs (JSON list)", placeholder='["https://example.com"]')
deep_analysis_checkbox = gr.Checkbox(label="Perform Deep Analysis (for single URL)", value=False)
analysis_prompt_input = gr.Textbox(label="Analysis Prompt", value="Summarize the content.")
submit_button = gr.Button("Analyze Content")
output_json = gr.JSON(label="Analysis Result")
submit_button.click(
analyze_web_content,
inputs=[urls_input, deep_analysis_checkbox, analysis_prompt_input],
outputs=output_json
)
if __name__ == "__main__":
# To run this Gradio app: python app.py
# Ensure your Modal token is configured (`modal token set`)
# And the Modal app (`modal_app.py`) is deployed (`modal deploy modal_app.py`)
# or runnable locally if you are testing `modal run modal_app.py` in another terminal.
# For the Gradio app to successfully call `modal.Function.lookup()`,
# it generally expects the Modal app to be deployed, or you need to be
# running within a `modal.stub.run()` context if calling local stubs
# from another Modal process, which is more advanced.
# The simplest way for this sketch is to deploy `modal_app.py` first.
print("Attempting to launch Gradio demo...")
print("REMINDER: For Gradio to connect to Modal functions,")
print(f"1. Deploy 'modal_app.py' using 'modal deploy modal_app.py'.")
print(f"2. Ensure your Modal token is set up.")
print(f"3. The MODAL_APP_NAME ('{MODAL_APP_NAME}') in app.py must match the app name in modal_app.py.")
demo.launch(mcp_server=True)