Spaces:
Sleeping
Sleeping
Download src/agents.py from vaibhavbasidoni/startup-validator: direct link, hf CLI and curl.
- Browser
- Download file 6.86 kB
-
https://huggingface.co/spaces/vaibhavbasidoni/startup-validator/resolve/main/src/agents.py
- Command line
-
hf download hf://spaces/vaibhavbasidoni/startup-validator/src/agents.py
-
curl -L -o agents.py https://huggingface.co/spaces/vaibhavbasidoni/startup-validator/resolve/main/src/agents.py
6.86 kB
| import os | |
| import json | |
| from urllib.parse import urlparse | |
| from langchain_openai import ChatOpenAI | |
| from langchain_core.messages import SystemMessage, HumanMessage | |
| from src.state import AgentState | |
| from src.tools import web_search, hn_search, github_search | |
| from langgraph.prebuilt import create_react_agent | |
| # Initialize the OpenAI model we will use for our agents. | |
| def get_llm(): | |
| return ChatOpenAI(model="gpt-4o-mini", temperature=0.2) | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Source Extraction Utility | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| def _extract_sources(messages): | |
| """ | |
| Parse the ReAct agent's tool-response messages and pull out | |
| every (title, url) pair that was returned by our tools. | |
| """ | |
| sources = [] | |
| seen_urls = set() | |
| for msg in messages: | |
| # Only look at ToolMessage objects | |
| if not (hasattr(msg, "type") and msg.type == "tool"): | |
| continue | |
| content = getattr(msg, "content", "") | |
| if not content: | |
| continue | |
| lines = content.split("\n") | |
| current_title = None | |
| for line in lines: | |
| stripped = line.strip() | |
| # Capture title / repo name from the line before the URL | |
| if stripped.startswith("Title:"): | |
| current_title = stripped[len("Title:"):].strip() | |
| elif stripped.startswith("Repo:"): | |
| current_title = stripped[len("Repo:"):].strip() | |
| # Capture URL | |
| elif stripped.startswith("URL:"): | |
| url = stripped[len("URL:"):].strip() | |
| if url and url.startswith("http") and url not in seen_urls: | |
| seen_urls.add(url) | |
| domain = urlparse(url).netloc.replace("www.", "") | |
| sources.append({ | |
| "title": current_title or domain, | |
| "url": url, | |
| "domain": domain, | |
| }) | |
| current_title = None | |
| return sources | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Agent 1: Competitor Analysis | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| def competitor_agent(state: AgentState) -> dict: | |
| idea = state["idea"] | |
| print(f"[Agent: Competitor] Starting research on idea: {idea[:30]}...") | |
| llm = get_llm() | |
| agent = create_react_agent(llm, tools=[web_search]) | |
| prompt = f"""You are a top-tier startup analyst. Your job is to find direct and indirect competitors for this startup idea: '{idea}' | |
| Use the web_search tool to find existing companies doing this. | |
| Provide a concise summary (max 3-4 sentences) of who the biggest players are and how crowded the space is.""" | |
| response = agent.invoke({"messages": [HumanMessage(content=prompt)]}) | |
| final_message = response["messages"][-1].content | |
| sources = _extract_sources(response["messages"]) | |
| return {"results": [{"agent": "competitor_analysis", "findings": final_message, "sources": sources}]} | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Agent 2: Market Sizing | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| def market_sizing_agent(state: AgentState) -> dict: | |
| idea = state["idea"] | |
| print(f"[Agent: Market Sizing] Starting research on idea: {idea[:30]}...") | |
| llm = get_llm() | |
| agent = create_react_agent(llm, tools=[web_search]) | |
| prompt = f"""You are a market researcher. Estimate the Total Addressable Market (TAM) for this startup idea: '{idea}' | |
| Use the web_search tool to find market reports, industry growth rates (CAGR), and overall market value. | |
| Provide a concise summary (max 3-4 sentences) with rough dollar estimates if possible.""" | |
| response = agent.invoke({"messages": [HumanMessage(content=prompt)]}) | |
| final_message = response["messages"][-1].content | |
| sources = _extract_sources(response["messages"]) | |
| return {"results": [{"agent": "market_sizing", "findings": final_message, "sources": sources}]} | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Agent 3: Community Sentiment | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| def sentiment_agent(state: AgentState) -> dict: | |
| idea = state["idea"] | |
| print(f"[Agent: Sentiment] Starting research on idea: {idea[:30]}...") | |
| llm = get_llm() | |
| agent = create_react_agent(llm, tools=[hn_search]) | |
| prompt = f"""You are a community manager and developer advocate. Analyze the sentiment around this startup idea: '{idea}' | |
| Use the hn_search tool to find past discussions, Show HN posts, or similar concepts on HackerNews. | |
| Provide a concise summary (max 3-4 sentences) of whether the tech community is generally positive, skeptical, or ignores this problem.""" | |
| response = agent.invoke({"messages": [HumanMessage(content=prompt)]}) | |
| final_message = response["messages"][-1].content | |
| sources = _extract_sources(response["messages"]) | |
| return {"results": [{"agent": "community_sentiment", "findings": final_message, "sources": sources}]} | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Agent 4: Open-Source Risk Detection | |
| # ββββββββββββββββββββββββββββββββββββββββββββββ | |
| def os_risk_agent(state: AgentState) -> dict: | |
| idea = state["idea"] | |
| print(f"[Agent: OS Risk] Starting research on idea: {idea[:30]}...") | |
| llm = get_llm() | |
| agent = create_react_agent(llm, tools=[github_search]) | |
| prompt = f"""You are a technical due diligence expert. Find open-source alternatives to this startup idea: '{idea}' | |
| Use the github_search tool to find repositories that solve the same problem. | |
| Provide a concise summary (max 3-4 sentences) naming the top repos (if any) and whether they are a major threat to a paid SaaS product.""" | |
| response = agent.invoke({"messages": [HumanMessage(content=prompt)]}) | |
| final_message = response["messages"][-1].content | |
| sources = _extract_sources(response["messages"]) | |
| return {"results": [{"agent": "os_risk", "findings": final_message, "sources": sources}]} | |