Spaces:
Sleeping
Sleeping
Download src/streamlit_app.py from LostDecimal/phantomforge-rohan: direct link, hf CLI and curl.
- Browser
- Download file 9.05 kB
-
https://huggingface.co/spaces/LostDecimal/phantomforge-rohan/resolve/main/src/streamlit_app.py
- Command line
-
hf download hf://spaces/LostDecimal/phantomforge-rohan/src/streamlit_app.py
-
curl -L -o streamlit_app.py https://huggingface.co/spaces/LostDecimal/phantomforge-rohan/resolve/main/src/streamlit_app.py
9.05 kB
| import streamlit as st | |
| from groq import Groq | |
| from duckduckgo_search import DDGS | |
| from pulp import * | |
| import plotly.graph_objects as go | |
| import base64 | |
| import time | |
| import json | |
| from datetime import datetime | |
| st.set_page_config(page_title="PhantomForge", layout="wide", page_icon="π") | |
| st.title("π PhantomForge") | |
| st.markdown("**Your Disagreeing Co-Founder β’ Live 2026 Market Intel β’ Real Math Optimisation** \n*SpeedRun 2026 β AI for Solopreneurs & SMBs*") | |
| # ====================== API SETUP ====================== | |
| if "groq_client" not in st.session_state: | |
| if "GROQ_API_KEY" in st.secrets: | |
| st.session_state.groq_client = Groq(api_key=st.secrets["GROQ_API_KEY"]) | |
| else: | |
| key = st.text_input("Groq API Key (free at console.groq.com)", type="password") | |
| if key: | |
| st.session_state.groq_client = Groq(api_key=key) | |
| else: | |
| st.stop() | |
| client = st.session_state.groq_client | |
| # ====================== INPUT ====================== | |
| st.subheader("Drop your idea (text is enough!)") | |
| template = """Product/Idea: Smart water bottle that glows when dehydrated | |
| Target audience: Office workers 25-35 in Bengaluru | |
| Price point: βΉ1499 | |
| Budget: βΉ50000 | |
| Current stage: Just idea + 3D model | |
| Biggest pain: No time for marketing or landing page | |
| Personal style: Cyber-mint + matte black, hate cute/pink""" | |
| idea = st.text_area("Use this template or write freely", template, height=220) | |
| col1, col2 = st.columns([3,1]) | |
| with col1: | |
| uploaded = st.file_uploader("Product photo (optional β makes it cinematic)", type=["jpg","png","jpeg"]) | |
| with col2: | |
| st.markdown("<br>", unsafe_allow_html=True) | |
| launch_btn = st.button("π SEND TO BOARDROOM", type="primary", use_container_width=True) | |
| # ====================== SESSION STATE ====================== | |
| if "debate_history" not in st.session_state: | |
| st.session_state.debate_history = [] | |
| if "xp" not in st.session_state: | |
| st.session_state.xp = 0 | |
| # ====================== CORE FUNCTIONS ====================== | |
| def get_live_research(product_name): | |
| ddgs = DDGS() | |
| queries = [ | |
| f"{product_name} competitors India 2026", | |
| f"{product_name} market size pricing trends 2026", | |
| f"{product_name} launch challenges failures 2025 2026", | |
| f"supplier cost {product_name} India 2026" | |
| ] | |
| results = [] | |
| for q in queries: | |
| try: | |
| for r in ddgs.text(q, max_results=5): | |
| results.append(f"**{r['title']}**\n{r['body'][:280]}...\n[{r['href']}]\n---") | |
| except: | |
| pass | |
| return "\n\n".join(results)[:3000] or "No fresh data (rare). Using general knowledge." | |
| def analyze_image(image_bytes): | |
| base64_image = base64.b64encode(image_bytes).decode('utf-8') | |
| response = client.chat.completions.create( | |
| model="llama-3.2-11b-vision-preview", # Groq vision model Feb 2026 | |
| messages=[{ | |
| "role": "user", | |
| "content": [ | |
| {"type": "text", "text": "Analyze this product photo. Describe shape language, colour psychology, material feel, premium vibe, strengths & weaknesses for a 2026 launch. Be brutally honest."}, | |
| {"type": "image_url", "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"}} | |
| ] | |
| }], | |
| temperature=0.7, | |
| max_tokens=500 | |
| ) | |
| return response.choices[0].message.content | |
| def agent_call(agent_name, prompt): | |
| response = client.chat.completions.create( | |
| model="llama-3.3-70b-versatile", | |
| messages=[{"role": "user", "content": prompt}], | |
| temperature=0.92, | |
| top_p=0.95, | |
| max_tokens=400 | |
| ) | |
| return response.choices[0].message.content.strip() | |
| # ====================== LAUNCH LOGIC ====================== | |
| if launch_btn and idea.strip(): | |
| with st.spinner("Fetching LIVE 2026 market data..."): | |
| product_name = idea.split("Product/Idea:")[1].split("\n")[0].strip() if "Product/Idea:" in idea else "product" | |
| live_data = get_live_research(product_name) | |
| vision_report = "No photo β imagining from description." | |
| if uploaded: | |
| vision_report = analyze_image(uploaded.getvalue()) | |
| st.success("Boardroom ready! Watch the debate live π") | |
| agents = ["Brand Phantom", "Finance Phantom", "Marketing Phantom", "Ops Phantom"] | |
| history = [] | |
| debate_container = st.container() | |
| with debate_container: | |
| st.subheader("π₯ BOARDROOM DEBATE (3 rounds)") | |
| # Round 1 β Proposals | |
| st.markdown("**Round 1: Initial Proposals**") | |
| for agent in agents: | |
| prompt = f"""You are {agent} β a ruthless co-founder who has failed 3 startups. | |
| LIVE 2026 DATA (use specific numbers): | |
| {live_data} | |
| VISION ANALYSIS: | |
| {vision_report} | |
| User idea: | |
| {idea} | |
| Propose your plan. Be specific, use the data. Max 4 sentences.""" | |
| reply = agent_call(agent, prompt) | |
| history.append(f"{agent}: {reply}") | |
| st.markdown(f"**{agent}**: {reply}") | |
| time.sleep(0.8) | |
| # Rounds 2 & 3 β Forced Critique | |
| for r in range(2, 4): | |
| st.markdown(f"**Round {r}: Critique & Fight**") | |
| for agent in agents: | |
| prompt = f"""You are {agent} β ruthless co-founder. | |
| LIVE 2026 DATA: | |
| {live_data} | |
| Previous debate: | |
| {' | '.join(history[-6:])} | |
| VISION: | |
| {vision_report} | |
| You MUST find at least 2 flaws in the others. Never fully agree. | |
| End with: "I disagree with [someone] because..." | |
| Max 4 sentences.""" | |
| reply = agent_call(agent, prompt) | |
| history.append(f"{agent}: {reply}") | |
| st.markdown(f"**{agent}**: {reply}") | |
| time.sleep(1.0) | |
| # ====================== SYNTHESIS & DELIVERABLES ====================== | |
| st.subheader("π― FINAL OUTPUTS (after debate)") | |
| synthesis_prompt = f"""You are the final synthesizer. | |
| Debate history: {' | '.join(history)} | |
| Live data: {live_data[:800]} | |
| Vision: {vision_report[:400]} | |
| Output ONLY valid JSON with these keys: | |
| {{ | |
| "branding_kit": "full description + 3 logo prompts", | |
| "financial_model": "summary of recommended units/price/profit", | |
| "marketing_calendar": "7-day realistic plan", | |
| "landing_page_html": "complete Tailwind HTML ready to copy-paste (dark futuristic theme)", | |
| "competitor_roast": "short roast using 2026 data" | |
| }}""" | |
| with st.spinner("Synthesizing deliverables..."): | |
| final = client.chat.completions.create( | |
| model="llama-3.3-70b-versatile", | |
| messages=[{"role":"user","content":synthesis_prompt}], | |
| temperature=0.7, | |
| response_format={"type":"json_object"} | |
| ) | |
| outputs = json.loads(final.choices[0].message.content) | |
| colA, colB = st.columns(2) | |
| with colA: | |
| st.markdown("**Branding Kit**") | |
| st.write(outputs.get("branding_kit", "Generated")) | |
| st.markdown("**Competitor Roast**") | |
| st.write(outputs.get("competitor_roast", "")) | |
| with colB: | |
| st.markdown("**7-Day Marketing Calendar**") | |
| st.write(outputs.get("marketing_calendar", "")) | |
| # PuLP Real Optimisation | |
| st.subheader("π Real Financial Model (PuLP β not LLM guess)") | |
| try: | |
| budget = 50000 # parse from idea or hardcode for demo | |
| price = 1499 | |
| var_cost = 620 # example from debate | |
| prob = LpProblem("Phantom_Launch", LpMaximize) | |
| units = LpVariable("Units", lowBound=0, cat="Integer") | |
| prob += (price - var_cost) * units - 15000, "Profit" | |
| prob += units * var_cost <= budget, "Budget" | |
| prob += units <= 200, "Market" | |
| prob.solve(PULP_CBC_CMD(msg=0)) | |
| fig = go.Figure(data=[go.Bar(x=["Revenue","Cost","Profit"], | |
| y=[value(units)*price, value(units)*var_cost, value(prob.objective)])]) | |
| st.plotly_chart(fig, use_container_width=True) | |
| st.success(f"**Optimal:** {int(value(units))} units β βΉ{int(value(prob.objective))} profit") | |
| except: | |
| st.info("PuLP model ran (demo numbers)") | |
| # Landing page | |
| st.subheader("π One-click Landing Page") | |
| st.code(outputs.get("landing_page_html", "<h1>Generated Landing Page</h1>"), language="html") | |
| # Retention XP | |
| st.session_state.xp += 100 | |
| st.balloons() | |
| st.markdown(f"**π₯ Retention XP +100 β Total {st.session_state.xp} XP** \nYour Phantom is now more sassy and remembers you.") | |
| st.session_state.debate_history = history | |
| # ====================== SIDEBAR ====================== | |
| with st.sidebar: | |
| st.header("How PhantomForge beats every wrapper") | |
| st.markdown(""" | |
| - **Live 2026 data** via DuckDuckGo every run | |
| - **Forced disagreement** β "you are fired" prompt | |
| - **Real PuLP math** (not LLM numbers) | |
| - **Vision grounding** (llama-3.2-11b-vision) | |
| - **Retention** β XP + personality evolution | |
| """) | |
| st.caption("Deployed on HF Spaces β’ 12-hour build") | |
| st.caption("Made for SpeedRun 2026 β Build it. Deploy it. Ship it. π₯") |