Spaces:
Sleeping
Sleeping
| import asyncio | |
| import json | |
| import queue | |
| import requests | |
| from threading import Thread | |
| from queue import Queue | |
| from fastapi import FastAPI, HTTPException | |
| from fastapi.responses import StreamingResponse | |
| from pydantic import BaseModel | |
| from bs4 import BeautifulSoup | |
| from langchain_groq import ChatGroq | |
| from crewai import Agent, Task, Crew, Process | |
| app = FastAPI() | |
| class SwarmRequest(BaseModel): | |
| url: str | |
| groq_key: str | |
| def scrape_website(url: str) -> str: | |
| try: | |
| headers = {'User-Agent': 'Mozilla/5.0'} | |
| response = requests.get(url, headers=headers, timeout=10) | |
| soup = BeautifulSoup(response.text, 'html.parser') | |
| for script in soup(["script", "style"]): | |
| script.extract() | |
| text = soup.get_text(separator=' ', strip=True) | |
| return text[:4000] | |
| except Exception as e: | |
| return f"Failed to scrape: {e}" | |
| def execute_swarm(target_url: str, groq_key: str, event_queue: Queue): | |
| try: | |
| event_queue.put({"agent": "System", "message": f"Initializing Swarm for {target_url}..."}) | |
| raw_data = scrape_website(target_url) | |
| event_queue.put({"agent": "Scout", "message": "Website data extracted and sanitized. Handing to analysis."}) | |
| # Callback handler to stream internal Agent steps | |
| def step_tracker(step_output): | |
| try: | |
| # Extract the actual log string | |
| log_text = getattr(step_output, 'log', str(step_output)) | |
| # Logic to strip out the verbose CrewAI tool descriptions and repetitive "Action: None" | |
| if "Thought:" in log_text: | |
| # Capture everything between Thought: and Action: | |
| clean_thought = log_text.split("Thought:")[1].split("Action:")[0].strip() | |
| if clean_thought: | |
| event_queue.put({"agent": "Internal Brain", "message": clean_thought}) | |
| elif "Action:" in log_text and "Action Input:" in log_text: | |
| action = log_text.split("Action:")[1].split("Action Input:")[0].strip() | |
| if action != "None": | |
| event_queue.put({"agent": "Action", "message": f"Delegating to tool: {action}"}) | |
| except Exception: | |
| event_queue.put({"agent": "Internal CPU", "message": "Synchronizing agent pathways..."}) | |
| llm = ChatGroq( | |
| temperature=0.3, | |
| groq_api_key=groq_key, | |
| model_name="llama-3.3-70b-versatile" | |
| ) | |
| scout = Agent( | |
| role='Intel Recon', | |
| goal='Identify exactly what this company sells.', | |
| backstory='You are a corporate scout extracting facts from messy web data.', | |
| verbose=False, llm=llm, step_callback=step_tracker | |
| ) | |
| strategist = Agent( | |
| role='M&A Risk Strategist', | |
| goal='Identify the 3 biggest competitive threats based on the Intel report.', | |
| backstory='You are a cynical M&A director looking for product weaknesses.', | |
| verbose=False, llm=llm, step_callback=step_tracker | |
| ) | |
| financial = Agent( | |
| role='Financial Analyst', | |
| goal='Estimate the likely cost-structure and monetization strategy of this SaaS.', | |
| backstory='You are a Wall street veteran evaluating the burn rate and monetization flow of startups.', | |
| verbose=False, llm=llm, step_callback=step_tracker | |
| ) | |
| reviewer = Agent( | |
| role='Executive Director', | |
| goal='Combine the risks and financial intel into a single, brutal M&A Executive Summary.', | |
| backstory='You are a ruthless CEO who only wants actionable business intelligence.', | |
| verbose=False, llm=llm, step_callback=step_tracker | |
| ) | |
| t1 = Task(description=f'Scrape data: {raw_data}', expected_output='A 2-paragraph summary.', agent=scout) | |
| t2 = Task(description='Identify 3 brutal risks.', expected_output='3 bullet points.', agent=strategist) | |
| t3 = Task(description='Analyze monetization.', expected_output='A 1 paragraph financial estimation.', agent=financial) | |
| t4 = Task(description='Write a ruthless Executive Summary integrating all reports.', expected_output='A 4-paragraph M&A brief.', agent=reviewer) | |
| event_queue.put({"agent": "System", "message": "4-Node Swarm Assembled. Igniting Groq APIs."}) | |
| ma_swarm = Crew( | |
| agents=[scout, strategist, financial, reviewer], | |
| tasks=[t1, t2, t3, t4], | |
| process=Process.sequential, | |
| verbose=0 | |
| ) | |
| final_result = ma_swarm.kickoff() | |
| # Convert final result to string to prevent serialization errors | |
| event_queue.put({"agent": "System", "message": "Swarm successfully terminated.", "final_report": str(final_result)}) | |
| except Exception as e: | |
| event_queue.put({"agent": "System", "error": str(e)}) | |
| async def trigger_ma_swarm(payload: SwarmRequest): | |
| if not payload.url or not payload.groq_key: | |
| raise HTTPException(status_code=400, detail="Missing URL or Groq Key") | |
| q = Queue() | |
| # Detach the swarm into a background thread | |
| Thread(target=execute_swarm, args=(payload.url, payload.groq_key, q), daemon=True).start() | |
| # Generator creating Server-Sent Events (SSE) | |
| def event_stream(): | |
| while True: | |
| try: | |
| # Wait for agents to talk | |
| msg = q.get(timeout=25) | |
| # If we get the final report or error, close the stream | |
| if "final_report" in msg or "error" in msg: | |
| yield f"data: {json.dumps(msg)}\n\n" | |
| break | |
| # Stream the agent's thought | |
| yield f"data: {json.dumps(msg)}\n\n" | |
| except queue.Empty: | |
| # Keep Cloudflare tunnel alive every 25 seconds | |
| yield f"data: {json.dumps({'agent': 'System', 'message': 'Processing...'})}\n\n" | |
| # Push chunks of data over the HTTP tunnel continuously | |
| return StreamingResponse(event_stream(), media_type="text/event-stream") | |
| def health_check(): | |
| return {"status": "M&A Ghost Matrix Streaming Node Online"} | |
| # --- GHOST MATRIX HASH DIFFERENTIAL --- | |
| class Class_rVcopYpZak: | |
| """c6b4cdbe4dd74358b45ccffe94076cff""" | |
| def do_nothing(self): | |
| x = 27953 | |
| return x * 4.221127725427827 | |
| class Class_idNTGalehk: | |
| """f77cac23783542f489f9b2c479bf91ec""" | |
| def do_nothing(self): | |
| x = 87422 | |
| return x * 1.9187418287300368 | |
| class Class_FzmtrNOfLF: | |
| """903bbcf8e47241f2852d9512382a9d1c""" | |
| def do_nothing(self): | |
| x = 9030 | |
| return x * 3.9653914279410114 | |
| class Class_cUSEWKYHcU: | |
| """cae6baff22ee4076929530b78a9283f4""" | |
| def do_nothing(self): | |
| x = 95094 | |
| return x * 7.03896972323605 | |
| class Class_paPGRRqsbB: | |
| """ba3fe6705e4e4d7a8266f9e3b2ab72de""" | |
| def do_nothing(self): | |
| x = 38532 | |
| return x * 4.712351329016485 | |
| class Class_kKIefYWptF: | |
| """b852e14233b44253b943694f205c99a3""" | |
| def do_nothing(self): | |
| x = 27923 | |
| return x * 3.3860617250919716 | |
| class Class_xDOpEgZOat: | |
| """54ed51feab1a458bb7cc0c547c7fbddf""" | |
| def do_nothing(self): | |
| x = 24132 | |
| return x * 7.819095584816826 | |
| class Class_GZDGAhwvio: | |
| """a9907aa632f64f1eabc5579bb06358f4""" | |
| def do_nothing(self): | |
| x = 67998 | |
| return x * 7.9701217363023575 | |
| class Class_cQOfNhCpUP: | |
| """a017bf9c42964f3cbff2d13708227b1d""" | |
| def do_nothing(self): | |
| x = 41349 | |
| return x * 9.195735309377763 | |
| class Class_JtklmvJAPf: | |
| """1371730961cd4f0989cd65e67a5e0c6d""" | |
| def do_nothing(self): | |
| x = 79194 | |
| return x * 0.1572539263441643 | |
| class Class_QoJXOhnqJs: | |
| """eb7c884791784b699c8fe8855b0b596d""" | |
| def do_nothing(self): | |
| x = 24131 | |
| return x * 7.781665853025276 | |
| class Class_AZEvLnrDSq: | |
| """3c690aaaacbf4a049fc17889def52f0c""" | |
| def do_nothing(self): | |
| x = 46000 | |
| return x * 2.3807511769470904 | |