[FIX] DOCS & EXA

pull/1103/head
Aksh Parekh 1 week ago
parent d8198dd23a
commit 700bb8c6c2

@ -25,17 +25,6 @@ To run the AI Job Search Swarm, you'll need to set up your Python environment an
### Installation Steps ### Installation Steps
1. **Clone the repository** (if you haven't already):
```bash
git clone https://github.com/kyegomez/swarms.git
cd swarms
```
2. **Create a virtual environment** and activate it:
```bash
python -m venv venv
source venv/bin/activate
```
3. **Install dependencies**:
The `job_finding.py` script relies on several libraries. These can be installed using the `requirements.txt` file located at the root of the project. The `job_finding.py` script relies on several libraries. These can be installed using the `requirements.txt` file located at the root of the project.
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
@ -67,282 +56,247 @@ The script is designed to run with a pre-filled user requirement for demonstrati
```python ```python
from typing import List from typing import List
import os
from dotenv import load_dotenv
from loguru import logger from loguru import logger
import httpx
from swarms.structs.agent import Agent from swarms.structs.agent import Agent
from swarms.structs.conversation import Conversation from swarms.structs.conversation import Conversation
from swarms.utils.history_output_formatter import history_output_formatter from swarms.utils.history_output_formatter import history_output_formatter
from swarms.utils.any_to_str import any_to_str from swarms_tools import exa_search
# --- Exa Search Tool Integration ---
def exa_search(
query: str,
characters: int = 500,
sources: int = 3,
) -> str:
"""
Perform a highly summarized Exa web search for job listings and career information.
Args:
query (str): Search query for jobs or career info.
characters (int): Max characters for summary.
sources (int): Number of sources.
Returns:
str: Condensed summary of search results.
"""
api_key = os.getenv("EXA_API_KEY")
if not api_key:
raise ValueError("EXA_API_KEY environment variable is not set")
headers = {
"x-api-key": api_key,
"content-type": "application/json",
}
payload = {
"query": query,
"type": "auto",
"numResults": sources,
"contents": {
"text": True,
"summary": {
"schema": {
"type": "object",
"required": ["answer"],
"additionalProperties": False,
"properties": {
"answer": {
"type": "string",
"description": "Highly condensed summary of the search result",
}
},
}
},
"context": {"maxCharacters": characters},
},
}
try:
logger.info(f"[SEARCH] Exa job search: {query[:50]}...")
response = httpx.post(
"https://api.exa.ai/search",
json=payload,
headers=headers,
timeout=30,
)
response.raise_for_status()
json_data = response.json()
return any_to_str(json_data)
except Exception as e:
logger.error(f"Exa search failed: {e}")
return f"Search failed: {str(e)}. Please try again."
# Load environment variables
load_dotenv()
# System prompts for each agent # System prompts for each agent
INTAKE_AGENT_PROMPT = """
REQUIREMENTS_ANALYZER_PROMPT = """ You are an M&A Intake Specialist responsible for gathering comprehensive information about a potential transaction.
You are the Requirements Analyzer Agent for Job Search.
ROLE: ROLE:
Extract and clarify job search requirements from user input to create optimized search queries. Engage with the user to understand the full context of the potential M&A deal, extracting critical details that will guide subsequent analyses.
RESPONSIBILITIES: RESPONSIBILITIES:
- Engage with the user to understand: - Conduct a thorough initial interview to understand:
* Desired job titles and roles * Transaction type (acquisition, merger, divestiture)
* Required skills and qualifications * Industry and sector specifics
* Preferred locations (remote, hybrid, on-site) * Target company profile and size
* Salary expectations * Strategic objectives
* Company size and culture preferences * Buyer/seller perspective
* Industry preferences * Timeline and urgency
* Experience level * Budget constraints
* Work authorization status * Specific concerns or focus areas
* Career goals and priorities
- Analyze user responses to identify:
* Key search terms and keywords
* Must-have vs nice-to-have requirements
* Deal-breakers or constraints
* Priority factors in job selection
- Generate optimized search queries:
* Create 3-5 targeted search queries based on user requirements
* Combine job titles, skills, locations, and key criteria
* Format queries for maximum relevance
OUTPUT FORMAT: OUTPUT FORMAT:
Provide a comprehensive requirements analysis: Provide a comprehensive Deal Brief that includes:
1. User Profile Summary: 1. Transaction Overview
- Job titles of interest - Proposed transaction type
- Key skills and qualifications - Key parties involved
- Location preferences - Initial strategic rationale
- Salary range
- Priority factors 2. Stakeholder Context
- Buyer's background and motivations
2. Search Strategy: - Target company's current position
- List of 3-5 optimized search queries - Key decision-makers
- Rationale for each query
- Expected result types 3. Initial Assessment
- Preliminary strategic fit
3. Clarifications Needed (if any): - Potential challenges or red flags
- Questions to refine search - Recommended focus areas for deeper analysis
- Missing information
4. Information Gaps
- Questions that need further clarification
- Additional data points required
IMPORTANT: IMPORTANT:
- Always include ALL user responses verbatim in your analysis - Be thorough and systematic
- Format search queries clearly for the next agent - Ask probing questions to uncover nuanced details
- Be specific and actionable in your recommendations - Maintain a neutral, professional tone
- Ask follow-up questions if requirements are unclear - Prepare a foundation for subsequent in-depth analysis
""" """
SEARCH_EXECUTOR_PROMPT = """ MARKET_ANALYSIS_PROMPT = """
You are the Search Executor Agent for Job Search. You are an M&A Market Intelligence Analyst tasked with conducting comprehensive market research.
ROLE: ROLE:
Execute job searches using exa_search and analyze results for relevance. Perform an in-depth analysis of market dynamics, competitive landscape, and strategic implications for the potential transaction.
TOOLS: TOOLS:
You have access to the exa_search tool. Use it to find current job listings and career opportunities. You have access to the exa_search tool for gathering real-time market intelligence.
RESPONSIBILITIES: RESPONSIBILITIES:
- Execute searches using queries from the Requirements Analyzer 1. Conduct Market Research
- Use exa_search for EACH query provided - Use exa_search to gather current market insights
- Analyze search results for: - Analyze industry trends, size, and growth potential
* Job title match - Identify key players and market share distribution
* Skills alignment
* Location compatibility 2. Competitive Landscape Analysis
* Salary range fit - Map out competitive ecosystem
* Company reputation - Assess target company's market positioning
* Role responsibilities - Identify potential competitive advantages or vulnerabilities
* Growth opportunities
3. Strategic Fit Evaluation
- Categorize results: - Analyze alignment with buyer's strategic objectives
* Strong Match (80-100% alignment) - Assess potential market entry or expansion opportunities
* Good Match (60-79% alignment) - Evaluate potential for market disruption
* Moderate Match (40-59% alignment)
* Weak Match (<40% alignment) 4. External Factor Assessment
- Examine regulatory environment
- For each job listing, extract: - Analyze technological disruption potential
* Job title and company - Consider macroeconomic impacts
* Location and work arrangement
* Key requirements
* Salary range (if available)
* Application link or contact
* Match score and reasoning
OUTPUT FORMAT: OUTPUT FORMAT:
Provide structured search results: Provide a comprehensive Market Analysis Report:
1. Search Execution Summary: 1. Market Overview
- Queries executed - Market size and growth trajectory
- Total results found - Key industry trends
- Distribution by match category - Competitive landscape summary
2. Detailed Job Listings (organized by match strength): 2. Strategic Fit Assessment
For each job: - Market attractiveness score (1-10)
- Company and Job Title - Strategic alignment evaluation
- Location and Work Type - Potential synergies and opportunities
- Key Requirements
- Why it's a match (or not) 3. Risk and Opportunity Mapping
- Match Score (percentage) - Key market opportunities
- Application link - Potential competitive threats
- Source (cite exa_search) - Regulatory and technological risk factors
3. Search Insights: 4. Recommended Next Steps
- Common themes in results - Areas requiring deeper investigation
- Gap analysis (requirements not met) - Initial strategic recommendations
- Market observations
INSTRUCTIONS:
- Always use exa_search for EVERY query provided
- Cite exa_search results clearly
- Be objective in match assessment
- Provide actionable insights
""" """
RESULTS_CURATOR_PROMPT = """ FINANCIAL_VALUATION_PROMPT = """
You are the Results Curator Agent for Job Search. You are an M&A Financial Analysis and Risk Expert. Perform comprehensive financial evaluation and risk assessment.
ROLE: RESPONSIBILITIES:
Filter, organize, and present job search results to the user for decision-making. 1. Financial Health Analysis
- Analyze revenue trends and quality
- Evaluate profitability metrics (EBITDA, margins)
- Conduct cash flow analysis
- Assess balance sheet strength
- Review working capital requirements
2. Valuation Analysis
- Perform comparable company analysis
- Conduct precedent transaction analysis
- Develop Discounted Cash Flow (DCF) model
- Assess asset-based valuation
3. Synergy and Risk Assessment
- Quantify potential revenue and cost synergies
- Identify financial and operational risks
- Evaluate integration complexity
- Assess potential deal-breakers
OUTPUT FORMAT:
1. Comprehensive Financial Analysis Report
2. Valuation Range (low, mid, high scenarios)
3. Synergy Potential Breakdown
4. Detailed Risk Matrix
5. Recommended Pricing Strategy
"""
DEAL_STRUCTURING_PROMPT = """
You are an M&A Deal Structuring Advisor. Recommend the optimal transaction structure.
RESPONSIBILITIES: RESPONSIBILITIES:
- Review all search results from the Search Executor 1. Transaction Structure Design
- Filter and prioritize based on: - Evaluate asset vs stock purchase options
* Match scores - Analyze cash vs stock consideration
* User requirements - Design earnout provisions
* Application deadlines - Develop contingent payment structures
* Job quality indicators
2. Financing Strategy
- Organize results into: - Recommend debt/equity mix
* Top Recommendations (top 3-5 best matches) - Identify optimal financing sources
* Strong Alternatives (next 5-10 options) - Assess impact on buyer's capital structure
* Worth Considering (other relevant matches)
3. Tax and Legal Optimization
- For top recommendations, provide: - Design tax-efficient structure
* Detailed comparison - Consider jurisdictional implications
* Pros and cons for each - Minimize tax liabilities
* Application strategy suggestions
* Next steps 4. Deal Protection Mechanisms
- Develop escrow arrangements
- Engage user for feedback: - Design representations and warranties
* Present curated results clearly - Create indemnification provisions
* Ask which jobs interest them - Recommend non-compete agreements
* Identify what's missing
* Determine if new search is needed
OUTPUT FORMAT: OUTPUT FORMAT:
Provide a curated job search report: 1. Recommended Deal Structure
2. Detailed Payment Terms
1. Executive Summary: 3. Key Contractual Protections
- Total jobs reviewed 4. Tax Optimization Strategy
- Number of strong matches 5. Rationale for Proposed Structure
- Key findings """
2. Top Recommendations (detailed):
For each (max 5):
- Company & Title
- Why it's a top match
- Key highlights
- Potential concerns
- Recommendation strength (1-10)
- Application priority (High/Medium/Low)
3. Strong Alternatives (brief list):
- Company & Title
- One-line match summary
- Match score
4. User Decision Point:
Ask the user:
- "Which of these jobs interest you most?"
- "What's missing from these results?"
- "Should we refine the search or proceed with applications?"
- "Any requirements you'd like to adjust?"
5. Next Steps:
Based on user response, either:
- Proceed with selected jobs
- Run new search with adjusted criteria
- Deep dive into specific opportunities
IMPORTANT: INTEGRATION_PLANNING_PROMPT = """
- Make it easy for users to make decisions You are an M&A Integration Planning Expert. Develop a comprehensive post-merger integration roadmap.
- Be honest about job fit
- Provide clear paths forward RESPONSIBILITIES:
- Always ask for user feedback before concluding 1. Immediate Integration Priorities
- Define critical day-1 actions
- Develop communication strategy
- Identify quick win opportunities
2. 100-Day Integration Plan
- Design organizational structure alignment
- Establish governance framework
- Create detailed integration milestones
3. Functional Integration Strategy
- Plan operations consolidation
- Design systems and technology integration
- Align sales and marketing approaches
- Develop cultural integration plan
4. Synergy Realization
- Create detailed synergy capture timeline
- Establish performance tracking mechanisms
- Define accountability framework
OUTPUT FORMAT:
1. Comprehensive Integration Roadmap
2. Detailed 100-Day Plan
3. Functional Integration Strategies
4. Synergy Realization Timeline
5. Risk Mitigation Recommendations
"""
FINAL_RECOMMENDATION_PROMPT = """
You are the Senior M&A Advisory Partner. Synthesize all analyses into a comprehensive recommendation.
RESPONSIBILITIES:
1. Executive Summary
- Summarize transaction overview
- Highlight strategic rationale
- Articulate key value drivers
2. Investment Thesis Validation
- Assess strategic benefits
- Evaluate financial attractiveness
- Project long-term potential
3. Comprehensive Risk Assessment
- Summarize top risks
- Provide mitigation strategies
- Identify potential deal-breakers
4. Final Recommendation
- Provide clear GO/NO-GO recommendation
- Specify recommended offer range
- Outline key proceeding conditions
OUTPUT FORMAT:
1. Executive-Level Recommendation Report
2. Decision Framework
3. Risk-Adjusted Strategic Perspective
4. Actionable Next Steps
5. Recommendation Confidence Level
""" """
class JobSearchSwarm: class MAAdvisorySwarm:
def __init__( def __init__(
self, self,
name: str = "AI Job Search Swarm", name: str = "M&A Advisory Swarm",
description: str = "An intelligent job search system that finds your ideal role", description: str = "Comprehensive AI-driven M&A advisory system",
max_loops: int = 1, max_loops: int = 1,
user_name: str = "Job Seeker", user_name: str = "M&A Advisor",
output_type: str = "json", output_type: str = "json",
): ):
self.max_loops = max_loops self.max_loops = max_loops
@ -356,8 +310,8 @@ class JobSearchSwarm:
self.exa_search_results = [] self.exa_search_results = []
self.search_queries = [] self.search_queries = []
self.current_iteration = 0 self.current_iteration = 0
self.max_iterations = 10 # Prevent infinite loops self.max_iterations = 1 # Limiting to 1 iteration for full sequential demo
self.search_concluded = False self.analysis_concluded = False
self.handle_initial_processing() self.handle_initial_processing()
@ -366,35 +320,59 @@ class JobSearchSwarm:
role="System", role="System",
content=f"Company: {self.name}\n" content=f"Company: {self.name}\n"
f"Description: {self.description}\n" f"Description: {self.description}\n"
f"Mission: Find the perfect job match for {self.user_name}" f"Mission: Provide comprehensive M&A advisory for {self.user_name}"
) )
def _initialize_agents(self) -> List[Agent]: def _initialize_agents(self) -> List[Agent]:
return [ return [
Agent( Agent(
agent_name="Sarah-Requirements-Analyzer", agent_name="Emma-Intake-Specialist",
agent_description="Analyzes user requirements and creates optimized job search queries.", agent_description="Gathers comprehensive initial information about the potential M&A transaction.",
system_prompt=REQUIREMENTS_ANALYZER_PROMPT, system_prompt=INTAKE_AGENT_PROMPT,
max_loops=self.max_loops,
dynamic_temperature_enabled=True,
output_type="final",
),
Agent(
agent_name="Marcus-Market-Analyst",
agent_description="Conducts in-depth market research and competitive analysis.",
system_prompt=MARKET_ANALYSIS_PROMPT,
max_loops=self.max_loops,
dynamic_temperature_enabled=True,
output_type="final",
),
Agent(
agent_name="Sophia-Financial-Analyst",
agent_description="Performs comprehensive financial valuation and risk assessment.",
system_prompt=FINANCIAL_VALUATION_PROMPT,
max_loops=self.max_loops, max_loops=self.max_loops,
dynamic_temperature_enabled=True, dynamic_temperature_enabled=True,
output_type="final", output_type="final",
), ),
Agent( Agent(
agent_name="David-Search-Executor", agent_name="David-Deal-Structuring-Advisor",
agent_description="Executes job searches and analyzes results for relevance.", agent_description="Recommends optimal deal structure and terms.",
system_prompt=SEARCH_EXECUTOR_PROMPT, system_prompt=DEAL_STRUCTURING_PROMPT,
max_loops=self.max_loops, max_loops=self.max_loops,
dynamic_temperature_enabled=True, dynamic_temperature_enabled=True,
output_type="final", output_type="final",
), ),
Agent( Agent(
agent_name="Lisa-Results-Curator", agent_name="Nathan-Integration-Planner",
agent_description="Curates and presents job results for user decision-making.", agent_description="Develops comprehensive post-merger integration roadmap.",
system_prompt=RESULTS_CURATOR_PROMPT, system_prompt=INTEGRATION_PLANNING_PROMPT,
max_loops=self.max_loops, max_loops=self.max_loops,
dynamic_temperature_enabled=True, dynamic_temperature_enabled=True,
output_type="final", output_type="final",
), ),
Agent(
agent_name="Alex-Final-Recommendation-Partner",
agent_description="Synthesizes all analyses into a comprehensive recommendation.",
system_prompt=FINAL_RECOMMENDATION_PROMPT,
max_loops=self.max_loops,
dynamic_temperature_enabled=True,
output_type="final",
)
] ]
def find_agent_by_name(self, name: str) -> Agent: def find_agent_by_name(self, name: str) -> Agent:
@ -403,55 +381,51 @@ class JobSearchSwarm:
return agent return agent
return None return None
def analyze_requirements(self, user_input: str): def intake_and_scoping(self, user_input: str):
"""Phase 1: Analyze user requirements and generate search queries""" """Phase 1: Intake and initial deal scoping"""
sarah_agent = self.find_agent_by_name("Requirements-Analyzer") emma_agent = self.find_agent_by_name("Intake-Specialist")
sarah_output = sarah_agent.run( emma_output = emma_agent.run(
f"User Input: {user_input}\n\n" f"User Input: {user_input}\n\n"
f"Conversation History: {self.conversation.get_str()}\n\n" f"Conversation History: {self.conversation.get_str()}\n\n"
f"Analyze the user's job search requirements and generate 3-5 optimized search queries. " f"Analyze the potential M&A transaction, extract key details, and prepare a comprehensive deal brief. "
f"If information is unclear, ask clarifying questions." f"If information is unclear, ask clarifying questions."
) )
self.conversation.add( self.conversation.add(
role="Requirements-Analyzer", content=sarah_output role="Intake-Specialist", content=emma_output
) )
# Extract search queries from Sarah's output # Extract potential search queries for market research
self.search_queries = self._extract_search_queries(sarah_output) self.search_queries = self._extract_search_queries(emma_output)
return sarah_output return emma_output
def _extract_search_queries(self, analyzer_output: str) -> List[str]: def _extract_search_queries(self, intake_output: str) -> List[str]:
"""Extract search queries from Requirements Analyzer output""" """Extract search queries from Intake Specialist output"""
queries = [] queries = []
lines = analyzer_output.split('\n') lines = intake_output.split('\n')
# Look for lines that appear to be search queries # Look for lines that could be good search queries
for line in lines: for line in lines:
line = line.strip() line = line.strip()
# Simple heuristic: lines with certain keywords or patterns # Simple heuristic: lines with potential research keywords
if any(keyword in line.lower() for keyword in ['query:', 'search:', 'query']): if any(keyword in line.lower() for keyword in ['market', 'industry', 'trend', 'competitor', 'analysis']):
# Extract the actual query if len(line) > 20: # Ensure query is substantial
if ':' in line: queries.append(line)
query = line.split(':', 1)[1].strip()
if query and len(query) > 10: # Fallback queries if none found
queries.append(query)
# If no queries found, create default ones based on common patterns
if not queries: if not queries:
logger.warning("No explicit queries found, generating fallback queries")
queries = [ queries = [
"software engineer jobs remote", "M&A trends in technology sector",
"data scientist positions", "Market analysis for potential business acquisition",
"product manager opportunities" "Competitive landscape in enterprise software"
] ]
return queries[:5] # Limit to 5 queries return queries[:3] # Limit to 3 queries
def execute_searches(self): def market_research(self):
"""Phase 2: Execute searches using exa_search and analyze results""" """Phase 2: Conduct market research using exa_search"""
# Execute exa_search for each query # Execute exa_search for each query
self.exa_search_results = [] self.exa_search_results = []
for query in self.search_queries: for query in self.search_queries:
@ -461,107 +435,138 @@ class JobSearchSwarm:
"exa_result": result "exa_result": result
}) })
# Pass results to Search Executor agent # Pass results to Market Analysis agent
david_agent = self.find_agent_by_name("Search-Executor") marcus_agent = self.find_agent_by_name("Market-Analyst")
# Build exa context # Build exa context
exa_context = "\n\n[Exa Search Results]\n" exa_context = "\n\n[Exa Market Research Results]\n"
for item in self.exa_search_results: for item in self.exa_search_results:
exa_context += f"Query: {item['query']}\nResults: {item['exa_result']}\n\n" exa_context += f"Query: {item['query']}\nResults: {item['exa_result']}\n\n"
david_output = david_agent.run( marcus_output = marcus_agent.run(
f"Conversation History: {self.conversation.get_str()}\n\n" f"Conversation History: {self.conversation.get_str()}\n\n"
f"{exa_context}\n" f"{exa_context}\n"
f"Analyze these job search results. Categorize each job by match strength and provide detailed analysis." f"Analyze these market research results. Provide comprehensive market intelligence and strategic insights."
)
self.conversation.add(
role="Market-Analyst", content=marcus_output
)
return marcus_output
def financial_valuation(self):
"""Phase 3: Perform comprehensive financial valuation and risk assessment"""
sophia_agent = self.find_agent_by_name("Financial-Analyst")
sophia_output = sophia_agent.run(
f"Conversation History: {self.conversation.get_str()}\n\n"
f"Perform comprehensive financial analysis and risk assessment based on previous insights."
)
self.conversation.add(
role="Financial-Analyst", content=sophia_output
)
return sophia_output
def deal_structuring(self):
"""Phase 4: Recommend optimal deal structure"""
david_agent = self.find_agent_by_name("Deal-Structuring-Advisor")
david_output = david_agent.run(
f"Conversation History: {self.conversation.get_str()}\n\n"
f"Recommend the optimal transaction structure and terms based on all prior analyses."
) )
self.conversation.add( self.conversation.add(
role="Search-Executor", content=david_output role="Deal-Structuring-Advisor", content=david_output
) )
return david_output return david_output
def curate_results(self) -> str: def integration_planning(self):
"""Phase 3: Curate results and get user feedback""" """Phase 5: Develop post-merger integration roadmap"""
lisa_agent = self.find_agent_by_name("Results-Curator") nathan_agent = self.find_agent_by_name("Integration-Planner")
lisa_output = lisa_agent.run( nathan_output = nathan_agent.run(
f"Conversation History: {self.conversation.get_str()}\n\n" f"Conversation History: {self.conversation.get_str()}\n\n"
f"Curate the job search results, present top recommendations, and ask the user for feedback. " f"Create a comprehensive integration plan to realize deal value."
f"Determine if we should continue searching or if the user has found suitable options."
) )
self.conversation.add( self.conversation.add(
role="Results-Curator", content=lisa_output role="Integration-Planner", content=nathan_output
) )
return lisa_output return nathan_output
def end(self) -> tuple[bool, str]: def final_recommendation(self):
""" """Phase 6: Synthesize all analyses into a comprehensive recommendation"""
Conclude the job search without user interaction. alex_agent = self.find_agent_by_name("Final-Recommendation-Partner")
alex_output = alex_agent.run(
f"Conversation History: {self.conversation.get_str()}\n\n"
f"Synthesize all agent analyses into a comprehensive, actionable M&A recommendation."
)
self.conversation.add(
role="Final-Recommendation-Partner", content=alex_output
)
return alex_output
Returns:
tuple[bool, str]: (needs_refinement, user_feedback)
"""
return False, "Search completed successfully."
def run(self, initial_user_input: str): def run(self, initial_user_input: str):
""" """
Run the job search swarm with continuous optimization. Run the M&A advisory swarm with continuous analysis.
Args: Args:
initial_user_input: User's initial job search requirements initial_user_input: User's initial M&A transaction details
""" """
self.conversation.add(role=self.user_name, content=initial_user_input) self.conversation.add(role=self.user_name, content=initial_user_input)
user_input = initial_user_input while not self.analysis_concluded and self.current_iteration < self.max_iterations:
while not self.search_concluded and self.current_iteration < self.max_iterations:
self.current_iteration += 1 self.current_iteration += 1
logger.info(f"Starting search iteration {self.current_iteration}") logger.info(f"Starting analysis iteration {self.current_iteration}")
# Phase 1: Analyze requirements # Phase 1: Intake and Scoping
print(f"\n{'='*60}") print(f"\n{'='*60}")
print(f"ITERATION {self.current_iteration} - ANALYZING REQUIREMENTS") print("ITERATION - INTAKE AND SCOPING")
print(f"{'='*60}\n") print(f"{'='*60}\n")
self.analyze_requirements(user_input) self.intake_and_scoping(initial_user_input)
# Phase 2: Execute searches # Phase 2: Market Research (with exa_search)
print(f"\n{'='*60}") print(f"\n{'='*60}")
print(f"ITERATION {self.current_iteration} - EXECUTING JOB SEARCHES") print("ITERATION - MARKET RESEARCH")
print(f"{'='*60}\n") print(f"{'='*60}\n")
self.execute_searches() self.market_research()
# Phase 3: Curate and present results # Phase 3: Financial Valuation
print(f"\n{'='*60}") print(f"\n{'='*60}")
print(f"ITERATION {self.current_iteration} - CURATING RESULTS") print("ITERATION - FINANCIAL VALUATION")
print(f"{'='*60}\n") print(f"{'='*60}\n")
self.curate_results() self.financial_valuation()
# Phase 4: Get user feedback # Phase 4: Deal Structuring
needs_refinement, user_feedback = self.end() print(f"\n{'='*60}")
print("ITERATION - DEAL STRUCTURING")
# Add user feedback to conversation print(f"{'='*60}\n")
self.conversation.add( self.deal_structuring()
role=self.user_name,
content=f"User Feedback: {user_feedback}"
)
# Check if we should continue # Phase 5: Integration Planning
if not needs_refinement:
self.search_concluded = True
print(f"\n{'='*60}") print(f"\n{'='*60}")
print("SEARCH CONCLUDED - USER SATISFIED WITH RESULTS") print("ITERATION - INTEGRATION PLANNING")
print(f"{'='*60}\n") print(f"{'='*60}\n")
else: self.integration_planning()
# In production, get new user input here
# Phase 6: Final Recommendation
print(f"\n{'='*60}") print(f"\n{'='*60}")
print("SEARCH REQUIRES REFINEMENT") print("ITERATION - FINAL RECOMMENDATION")
print(f"{'='*60}\n") print(f"{'='*60}\n")
# For demo, we'll stop after first iteration self.final_recommendation()
self.search_concluded = True
# Conclude analysis after one full sequence for demo purposes
self.analysis_concluded = True
# Return formatted conversation history # Return formatted conversation history
return history_output_formatter( return history_output_formatter(
@ -569,38 +574,43 @@ class JobSearchSwarm:
) )
def main(): def main():
"""Main entry point for job search swarm""" """Main entry point for M&A advisory swarm"""
# Example 1: Pre-filled user requirements (for testing) # Example M&A transaction details
user_requirements = """ transaction_details = """
I'm looking for a senior software engineer position with the following requirements: We are exploring a potential acquisition of DataPulse Analytics by TechNova Solutions.
- Job Title: Senior Software Engineer or Staff Engineer
- Skills: Python, distributed systems, cloud architecture (AWS/GCP), Kubernetes Transaction Context:
- Location: Remote (US-based) or San Francisco Bay Area - Buyer: TechNova Solutions (NASDAQ: TNVA) - $500M annual revenue enterprise software company
- Salary: $180k - $250k - Target: DataPulse Analytics - Series B AI-driven analytics startup based in San Francisco
- Company: Mid-size to large tech companies, prefer companies with strong engineering culture - Primary Objectives:
- Experience Level: 7+ years * Expand predictive analytics capabilities in healthcare and financial services
- Industry: SaaS, Cloud Infrastructure, or Developer Tools * Accelerate AI-powered business intelligence product roadmap
- Work Authorization: US Citizen * Acquire top-tier machine learning engineering talent
- Priorities: Technical challenges, work-life balance, remote flexibility, equity upside
- Deal-breakers: No pure management roles, no strict return-to-office policies Key Considerations:
- Deep integration of DataPulse's proprietary AI models into TechNova's existing platform
- Retention of key DataPulse leadership and engineering team
- Projected 3-year ROI and synergy potential
- Regulatory and compliance alignment
- Technology stack compatibility
""" """
# Initialize the swarm # Initialize the swarm
job_search_swarm = JobSearchSwarm( ma_advisory_swarm = MAAdvisorySwarm(
name="AI-Powered Job Search Engine", name="AI-Powered M&A Advisory System",
description="Intelligent job search system that continuously refines results until the perfect match is found", description="Comprehensive AI-driven M&A advisory and market intelligence platform",
user_name="Job Seeker", user_name="Corporate Development Team",
output_type="json", output_type="json",
max_loops=1, max_loops=1,
) )
# Run the swarm # Run the swarm
print("\n" + "="*60) print("\n" + "="*60)
print("INITIALIZING JOB SEARCH SWARM") print("INITIALIZING M&A ADVISORY SWARM")
print("="*60 + "\n") print("="*60 + "\n")
job_search_swarm.run(initial_user_input=user_requirements) ma_advisory_swarm.run(initial_user_input=transaction_details)
if __name__ == "__main__": if __name__ == "__main__":
main() main()

@ -1,79 +1,9 @@
from typing import List from typing import List
import os
from dotenv import load_dotenv
from loguru import logger from loguru import logger
import httpx
from swarms.structs.agent import Agent from swarms.structs.agent import Agent
from swarms.structs.conversation import Conversation from swarms.structs.conversation import Conversation
from swarms.utils.history_output_formatter import history_output_formatter from swarms.utils.history_output_formatter import history_output_formatter
from swarms.utils.any_to_str import any_to_str from swarms_tools import exa_search
# --- Exa Search Tool Integration ---
def exa_search(
query: str,
characters: int = 500,
sources: int = 3,
) -> str:
"""
Perform a highly summarized Exa web search for job listings and career information.
Args:
query (str): Search query for jobs or career info.
characters (int): Max characters for summary.
sources (int): Number of sources.
Returns:
str: Condensed summary of search results.
"""
api_key = os.getenv("EXA_API_KEY")
if not api_key:
raise ValueError("EXA_API_KEY environment variable is not set")
headers = {
"x-api-key": api_key,
"content-type": "application/json",
}
payload = {
"query": query,
"type": "auto",
"numResults": sources,
"contents": {
"text": True,
"summary": {
"schema": {
"type": "object",
"required": ["answer"],
"additionalProperties": False,
"properties": {
"answer": {
"type": "string",
"description": "Highly condensed summary of the search result",
}
},
}
},
"context": {"maxCharacters": characters},
},
}
try:
logger.info(f"[SEARCH] Exa job search: {query[:50]}...")
response = httpx.post(
"https://api.exa.ai/search",
json=payload,
headers=headers,
timeout=30,
)
response.raise_for_status()
json_data = response.json()
return any_to_str(json_data)
except Exception as e:
logger.error(f"Exa search failed: {e}")
return f"Search failed: {str(e)}. Please try again."
# Load environment variables
load_dotenv()
# System prompts for each agent # System prompts for each agent

Loading…
Cancel
Save