Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import gradio as gr
|
| 3 |
+
import anthropic
|
| 4 |
+
from pypdf import PdfReader
|
| 5 |
+
|
| 6 |
+
# ββ Anthropic client ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 7 |
+
# Set ANTHROPIC_API_KEY in your HuggingFace Space β Settings β Repository secrets
|
| 8 |
+
client = anthropic.Anthropic(api_key=os.environ.get("ANTHROPIC_API_KEY"))
|
| 9 |
+
|
| 10 |
+
SYSTEM_PROMPT = """You are an expert problem analyst and innovation coach helping interns understand real-world problems and brainstorm creative solutions.
|
| 11 |
+
|
| 12 |
+
When given a transcription or document, you will:
|
| 13 |
+
|
| 14 |
+
1. **PROBLEM UNDERSTANDING**
|
| 15 |
+
- Identify and clearly articulate the core problem being discussed
|
| 16 |
+
- Highlight key pain points, stakeholders, and context
|
| 17 |
+
- Summarize what is known vs unknown about the problem
|
| 18 |
+
|
| 19 |
+
2. **ROOT CAUSE ANALYSIS**
|
| 20 |
+
- Break down WHY this problem exists
|
| 21 |
+
- Identify underlying causes (technical, organizational, process-related)
|
| 22 |
+
|
| 23 |
+
3. **BRAINSTORMING IDEAS**
|
| 24 |
+
- Generate 5β8 diverse, creative solution directions
|
| 25 |
+
- Include both quick wins and long-term strategic ideas
|
| 26 |
+
- Think across technology, process, and people dimensions
|
| 27 |
+
|
| 28 |
+
4. **NEXT STEPS FOR INTERNS**
|
| 29 |
+
- Suggest 3 concrete actions the intern can take immediately to explore this further
|
| 30 |
+
|
| 31 |
+
Keep your tone encouraging, clear, and structured. Use headers and bullet points for readability."""
|
| 32 |
+
|
| 33 |
+
|
| 34 |
+
def extract_text_from_pdf(pdf_file) -> str:
|
| 35 |
+
"""Extract all text from an uploaded PDF file."""
|
| 36 |
+
reader = PdfReader(pdf_file)
|
| 37 |
+
pages_text = []
|
| 38 |
+
for page in reader.pages:
|
| 39 |
+
text = page.extract_text()
|
| 40 |
+
if text:
|
| 41 |
+
pages_text.append(text.strip())
|
| 42 |
+
return "\n\n".join(pages_text)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def run_agent(text_input: str, pdf_file, progress=gr.Progress()):
|
| 46 |
+
"""
|
| 47 |
+
Core agent function.
|
| 48 |
+
Accepts either pasted text or a PDF upload, then streams the analysis.
|
| 49 |
+
"""
|
| 50 |
+
# ββ Determine input source ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 51 |
+
content = ""
|
| 52 |
+
|
| 53 |
+
if pdf_file is not None:
|
| 54 |
+
progress(0.1, desc="Reading PDF...")
|
| 55 |
+
try:
|
| 56 |
+
content = extract_text_from_pdf(pdf_file)
|
| 57 |
+
if not content.strip():
|
| 58 |
+
yield "β οΈ Could not extract text from this PDF. It may be scanned/image-based. Please paste the text manually."
|
| 59 |
+
return
|
| 60 |
+
except Exception as e:
|
| 61 |
+
yield f"β οΈ Error reading PDF: {str(e)}"
|
| 62 |
+
return
|
| 63 |
+
|
| 64 |
+
elif text_input and text_input.strip():
|
| 65 |
+
content = text_input.strip()
|
| 66 |
+
|
| 67 |
+
else:
|
| 68 |
+
yield "β οΈ Please paste a transcription or upload a PDF file to get started."
|
| 69 |
+
return
|
| 70 |
+
|
| 71 |
+
if len(content) < 50:
|
| 72 |
+
yield "β οΈ The input seems too short. Please provide more context for a meaningful analysis."
|
| 73 |
+
return
|
| 74 |
+
|
| 75 |
+
# ββ Truncate very long inputs to stay within token limits βββββββββββββββββ
|
| 76 |
+
MAX_CHARS = 12000
|
| 77 |
+
if len(content) > MAX_CHARS:
|
| 78 |
+
content = content[:MAX_CHARS] + "\n\n[... content truncated for length ...]"
|
| 79 |
+
|
| 80 |
+
progress(0.3, desc="Analyzing problem...")
|
| 81 |
+
|
| 82 |
+
user_message = f"""Here is the transcription / document content to analyze:
|
| 83 |
+
|
| 84 |
+
---
|
| 85 |
+
{content}
|
| 86 |
+
---
|
| 87 |
+
|
| 88 |
+
Please provide a full problem analysis and brainstorming session based on this content."""
|
| 89 |
+
|
| 90 |
+
# ββ Stream from Anthropic API βββββββββββββββββββββββββββββββββββββββββββββ
|
| 91 |
+
output = ""
|
| 92 |
+
try:
|
| 93 |
+
with client.messages.stream(
|
| 94 |
+
model="claude-sonnet-4-20250514",
|
| 95 |
+
max_tokens=2048,
|
| 96 |
+
system=SYSTEM_PROMPT,
|
| 97 |
+
messages=[{"role": "user", "content": user_message}],
|
| 98 |
+
) as stream:
|
| 99 |
+
progress(0.5, desc="Generating insights...")
|
| 100 |
+
for text_chunk in stream.text_stream:
|
| 101 |
+
output += text_chunk
|
| 102 |
+
yield output
|
| 103 |
+
|
| 104 |
+
except anthropic.AuthenticationError:
|
| 105 |
+
yield "β οΈ Invalid API key. Please set your ANTHROPIC_API_KEY in the Space secrets."
|
| 106 |
+
except anthropic.RateLimitError:
|
| 107 |
+
yield "β οΈ Rate limit hit. Please wait a moment and try again."
|
| 108 |
+
except Exception as e:
|
| 109 |
+
yield f"β οΈ Unexpected error: {str(e)}"
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
# ββ Gradio UI βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 113 |
+
with gr.Blocks(
|
| 114 |
+
title="Intern Problem Brainstormer",
|
| 115 |
+
theme=gr.themes.Soft(
|
| 116 |
+
primary_hue="violet",
|
| 117 |
+
secondary_hue="slate",
|
| 118 |
+
font=[gr.themes.GoogleFont("Inter"), "sans-serif"],
|
| 119 |
+
),
|
| 120 |
+
css="""
|
| 121 |
+
#header { text-align: center; padding: 1.5rem 0 0.5rem; }
|
| 122 |
+
#header h1 { font-size: 2rem; font-weight: 700; margin-bottom: 0.25rem; }
|
| 123 |
+
#header p { color: #6b7280; font-size: 0.95rem; }
|
| 124 |
+
.input-box textarea { font-size: 14px !important; line-height: 1.6 !important; }
|
| 125 |
+
#run-btn { font-size: 1rem !important; padding: 0.65rem 2rem !important; }
|
| 126 |
+
#output-box { font-size: 14px; line-height: 1.75; }
|
| 127 |
+
.gr-tab-item { font-weight: 500; }
|
| 128 |
+
""",
|
| 129 |
+
) as demo:
|
| 130 |
+
|
| 131 |
+
# Header
|
| 132 |
+
gr.HTML("""
|
| 133 |
+
<div id="header">
|
| 134 |
+
<h1>π§ Intern Problem Brainstormer</h1>
|
| 135 |
+
<p>Paste a meeting transcription or upload a PDF β get instant problem analysis & brainstormed solutions.</p>
|
| 136 |
+
</div>
|
| 137 |
+
""")
|
| 138 |
+
|
| 139 |
+
gr.Markdown("---")
|
| 140 |
+
|
| 141 |
+
with gr.Row(equal_height=False):
|
| 142 |
+
# ββ Left column: Input ββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 143 |
+
with gr.Column(scale=1):
|
| 144 |
+
gr.Markdown("### π₯ Input")
|
| 145 |
+
|
| 146 |
+
with gr.Tabs():
|
| 147 |
+
with gr.Tab("π Paste Text"):
|
| 148 |
+
text_input = gr.Textbox(
|
| 149 |
+
label="Transcription or problem description",
|
| 150 |
+
placeholder="Paste your meeting notes, transcription, or problem statement here...",
|
| 151 |
+
lines=14,
|
| 152 |
+
max_lines=30,
|
| 153 |
+
elem_classes=["input-box"],
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
with gr.Tab("π Upload PDF"):
|
| 157 |
+
pdf_input = gr.File(
|
| 158 |
+
label="Upload a PDF document",
|
| 159 |
+
file_types=[".pdf"],
|
| 160 |
+
file_count="single",
|
| 161 |
+
)
|
| 162 |
+
gr.Markdown(
|
| 163 |
+
"<small style='color:#6b7280'>Text-based PDFs only. Scanned PDFs won't work.</small>"
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
run_btn = gr.Button(
|
| 167 |
+
"β‘ Analyse & Brainstorm",
|
| 168 |
+
variant="primary",
|
| 169 |
+
elem_id="run-btn",
|
| 170 |
+
)
|
| 171 |
+
|
| 172 |
+
with gr.Accordion("βΉοΈ How to use", open=False):
|
| 173 |
+
gr.Markdown("""
|
| 174 |
+
**Option 1 β Paste Text**
|
| 175 |
+
Copy-paste any transcription, meeting notes, or problem description into the text box.
|
| 176 |
+
|
| 177 |
+
**Option 2 β Upload PDF**
|
| 178 |
+
Upload a text-based PDF (e.g. a research doc, spec, or report).
|
| 179 |
+
|
| 180 |
+
**Then click β‘ Analyse & Brainstorm** to get:
|
| 181 |
+
- A clear articulation of the core problem
|
| 182 |
+
- Root cause analysis
|
| 183 |
+
- 5β8 creative brainstormed ideas
|
| 184 |
+
- Concrete next steps for you as an intern
|
| 185 |
+
""")
|
| 186 |
+
|
| 187 |
+
# ββ Right column: Output ββββββββββββββββββββββββββββββββββββββββββββββ
|
| 188 |
+
with gr.Column(scale=1):
|
| 189 |
+
gr.Markdown("### π‘ Analysis & Ideas")
|
| 190 |
+
output = gr.Markdown(
|
| 191 |
+
value="*Your analysis will appear here...*",
|
| 192 |
+
elem_id="output-box",
|
| 193 |
+
)
|
| 194 |
+
|
| 195 |
+
# ββ Examples ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 196 |
+
gr.Markdown("---")
|
| 197 |
+
gr.Markdown("### π§ͺ Try an example")
|
| 198 |
+
gr.Examples(
|
| 199 |
+
examples=[
|
| 200 |
+
[
|
| 201 |
+
"In today's standup, the team discussed that customers are complaining that the onboarding flow takes too long. New users drop off after the third step in the sign-up process. We don't have clear data on exactly which step causes the most drop-off. The product team thinks it might be the email verification step but engineering says it could be the profile setup form. We have about 2 weeks before the next release and the CEO wants this fixed before the investor demo.",
|
| 202 |
+
None,
|
| 203 |
+
],
|
| 204 |
+
[
|
| 205 |
+
"Meeting transcript: So the main issue we're facing is that our data pipeline fails every Friday evening when batch jobs run. The on-call engineer has to manually restart it each time. It's been happening for three months. We've tried looking at the logs but they're not detailed enough. The infrastructure team is overwhelmed and can't prioritize it. Meanwhile the analytics team can't get their Monday morning reports on time which is affecting business decisions.",
|
| 206 |
+
None,
|
| 207 |
+
],
|
| 208 |
+
],
|
| 209 |
+
inputs=[text_input, pdf_input],
|
| 210 |
+
label="Click an example to load it, then hit Analyse & Brainstorm",
|
| 211 |
+
)
|
| 212 |
+
|
| 213 |
+
# ββ Wire up βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 214 |
+
run_btn.click(
|
| 215 |
+
fn=run_agent,
|
| 216 |
+
inputs=[text_input, pdf_input],
|
| 217 |
+
outputs=output,
|
| 218 |
+
show_progress="full",
|
| 219 |
+
)
|
| 220 |
+
|
| 221 |
+
# Also allow Ctrl+Enter from the text box
|
| 222 |
+
text_input.submit(
|
| 223 |
+
fn=run_agent,
|
| 224 |
+
inputs=[text_input, pdf_input],
|
| 225 |
+
outputs=output,
|
| 226 |
+
show_progress="full",
|
| 227 |
+
)
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
if __name__ == "__main__":
|
| 231 |
+
demo.launch()
|