toniewing/microservice-layer-13
0
1import asyncio2import json3import queue4import requests5from threading import Thread6from queue import Queue7from fastapi import FastAPI, HTTPException8from fastapi.responses import StreamingResponse9from pydantic import BaseModel10from bs4 import BeautifulSoup11from langchain_groq import ChatGroq12from crewai import Agent, Task, Crew, Process13 14app = FastAPI()15 16class SwarmRequest(BaseModel):17 url: str18 groq_key: str19 20def scrape_website(url: str) -> str:21 try:22 headers = {'User-Agent': 'Mozilla/5.0'}23 response = requests.get(url, headers=headers, timeout=10)24 soup = BeautifulSoup(response.text, 'html.parser')25 for script in soup(["script", "style"]):26 script.extract()27 text = soup.get_text(separator=' ', strip=True)28 return text[:4000]29 except Exception as e:30 return f"Failed to scrape: {e}"31 32def execute_swarm(target_url: str, groq_key: str, event_queue: Queue):33 try:34 event_queue.put({"agent": "System", "message": f"Initializing Swarm for {target_url}..."})35 raw_data = scrape_website(target_url)36 event_queue.put({"agent": "Scout", "message": "Website data extracted and sanitized. Handing to analysis."})37 38 # Callback handler to stream internal Agent steps39 def step_tracker(step_output):40 try:41 # Extract the actual log string42 log_text = getattr(step_output, 'log', str(step_output))43 44 # Logic to strip out the verbose CrewAI tool descriptions and repetitive "Action: None"45 if "Thought:" in log_text:46 # Capture everything between Thought: and Action:47 clean_thought = log_text.split("Thought:")[1].split("Action:")[0].strip()48 if clean_thought:49 event_queue.put({"agent": "Internal Brain", "message": clean_thought})50 elif "Action:" in log_text and "Action Input:" in log_text:51 action = log_text.split("Action:")[1].split("Action Input:")[0].strip()52 if action != "None":53 event_queue.put({"agent": "Action", "message": f"Delegating to tool: {action}"})54 except Exception:55 event_queue.put({"agent": "Internal CPU", "message": "Synchronizing agent pathways..."})56 57 llm = ChatGroq(58 temperature=0.3,59 groq_api_key=groq_key,60 model_name="llama-3.1-8b-instant" 61 )62 63 scout = Agent(64 role='Intel Recon',65 goal='Identify exactly what this company sells.',66 backstory='You are a corporate scout extracting facts from messy web data.',67 verbose=False, llm=llm, step_callback=step_tracker68 )69 70 strategist = Agent(71 role='M&A Risk Strategist',72 goal='Identify the 3 biggest competitive threats based on the Intel report.',73 backstory='You are a cynical M&A director looking for product weaknesses.',74 verbose=False, llm=llm, step_callback=step_tracker75 )76 77 financial = Agent(78 role='Financial Analyst',79 goal='Estimate the likely cost-structure and monetization strategy of this SaaS.',80 backstory='You are a Wall street veteran evaluating the burn rate and monetization flow of startups.',81 verbose=False, llm=llm, step_callback=step_tracker82 )83 84 reviewer = Agent(85 role='Executive Director',86 goal='Combine the risks and financial intel into a single, brutal M&A Executive Summary.',87 backstory='You are a ruthless CEO who only wants actionable business intelligence.',88 verbose=False, llm=llm, step_callback=step_tracker89 )90 91 t1 = Task(description=f'Scrape data: {raw_data}', expected_output='A 2-paragraph summary.', agent=scout)92 t2 = Task(description='Identify 3 brutal risks.', expected_output='3 bullet points.', agent=strategist)93 t3 = Task(description='Analyze monetization.', expected_output='A 1 paragraph financial estimation.', agent=financial)94 t4 = Task(description='Write a ruthless Executive Summary integrating all reports.', expected_output='A 4-paragraph M&A brief.', agent=reviewer)95 96 event_queue.put({"agent": "System", "message": "4-Node Swarm Assembled. Igniting Groq APIs."})97 98 ma_swarm = Crew(99 agents=[scout, strategist, financial, reviewer],100 tasks=[t1, t2, t3, t4],101 process=Process.sequential,102 verbose=0,103 max_rpm=15104 )105 106 final_result = ma_swarm.kickoff()107 # Convert final result to string to prevent serialization errors108 event_queue.put({"agent": "System", "message": "Swarm successfully terminated.", "final_report": str(final_result)})109 110 except Exception as e:111 event_queue.put({"agent": "System", "error": str(e)})112 113@app.post("/swarm")114async def trigger_ma_swarm(payload: SwarmRequest):115 if not payload.url or not payload.groq_key:116 raise HTTPException(status_code=400, detail="Missing URL or Groq Key")117 118 q = Queue()119 # Detach the swarm into a background thread120 Thread(target=execute_swarm, args=(payload.url, payload.groq_key, q), daemon=True).start()121 122 # Generator creating Server-Sent Events (SSE)123 def event_stream():124 while True:125 try:126 # Wait for agents to talk127 msg = q.get(timeout=25) 128 129 # If we get the final report or error, close the stream130 if "final_report" in msg or "error" in msg:131 yield f"data: {json.dumps(msg)}\n\n"132 break133 134 # Stream the agent's thought135 yield f"data: {json.dumps(msg)}\n\n"136 137 except queue.Empty:138 # Keep Cloudflare tunnel alive every 25 seconds139 yield f"data: {json.dumps({'agent': 'System', 'message': 'Processing...'})}\n\n"140 141 # Push chunks of data over the HTTP tunnel continuously142 return StreamingResponse(event_stream(), media_type="text/event-stream")143 144@app.get("/")145def health_check():146 return {"status": "M&A Ghost Matrix Streaming Node Online"}147
148
149# --- GHOST MATRIX HASH DIFFERENTIAL ---
150
151class Class_dJFPKBMgje:
152 """f83d8da41f2d44178fb2fe21c946b031"""
153 def do_nothing(self):
154 x = 94013
155 return x * 7.2991468625342195
156
157class Class_GHrDpqAlhB:
158 """fa15c4be8f2f4aa9ba1438710dc78fb1"""
159 def do_nothing(self):
160 x = 89027
161 return x * 8.899009877605067
162
163class Class_ekwDuUBvuW:
164 """fd2658b9e213409eb5ab28d13adeacb4"""
165 def do_nothing(self):
166 x = 99945
167 return x * 2.978269265004507
168
169class Class_xviMYQAxEM:
170 """40ffee09d5ed491a974d42d3d2107b63"""
171 def do_nothing(self):
172 x = 14526
173 return x * 2.7617174108643314
174
175class Class_awSXqpnWqc:
176 """4dbabc47f1b54666afb467411fd01d21"""
177 def do_nothing(self):
178 x = 80675
179 return x * 8.375863439828494
180
181class Class_Qnzsqupaxd:
182 """754d6f8f29cd4ef4bd2b55555ddaef02"""
183 def do_nothing(self):
184 x = 88227
185 return x * 1.5362309000968442
186
187class Class_cTMUiGDeCg:
188 """0f3761be372345b18ef8f541bff34bb8"""
189 def do_nothing(self):
190 x = 85711
191 return x * 1.6646967249974796
192 