Alireza1913 commited on
Commit
55edef0
Β·
verified Β·
1 Parent(s): 8989a1a

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +237 -0
app.py ADDED
@@ -0,0 +1,237 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ from openai import OpenAI
4
+
5
+ API_KEY = os.environ.get("AVALAI_API_KEY", "")
6
+ BASE_URL = "https://api.avalai.ir/v1"
7
+ MODEL = "claude-sonnet-4-6"
8
+
9
+ SYSTEM_PROMPT = """You are an expert API architect and indie hacker advisor.
10
+
11
+ You know every major API deeply:
12
+
13
+ PAYMENT: Stripe, Paddle, LemonSqueezy, PayPal, Razorpay
14
+ AI/ML: OpenAI, Anthropic Claude, Replicate, HuggingFace Inference, AssemblyAI, ElevenLabs
15
+ COMMUNICATION: Twilio (SMS/Voice), SendGrid (email), Resend, Mailgun, WhatsApp Business
16
+ DATA/ENRICHMENT: Clearbit, Apollo.io, Hunter.io, Proxycurl
17
+ MAPS/LOCATION: Google Maps, Mapbox, HERE, OpenStreetMap
18
+ MEDIA: Cloudinary, Mux (video), Imgix, Transloadit
19
+ FINANCE: Alpha Vantage, Polygon.io, CoinGecko, Plaid, Finnhub
20
+ SEARCH: Algolia, Typesense, Meilisearch
21
+ AUTH: Auth0, Clerk, Supabase Auth, Firebase Auth
22
+ DATABASE: Supabase, Firebase, PlanetScale, Neon, Upstash
23
+ SCRAPING: Apify, ScraperAPI, Browserless, Firecrawl
24
+ ANALYTICS: Mixpanel, PostHog, Amplitude, Plausible
25
+
26
+ When a user describes their product idea, recommend the perfect API stack.
27
+
28
+ Your response MUST follow this exact format:
29
+
30
+ ## 🎯 Your Idea in One Line
31
+ (restate the idea clearly)
32
+
33
+ ## πŸ”§ Recommended API Stack
34
+
35
+ For each API (recommend 3-5 total):
36
+
37
+ ### [API Name] β€” [Role in the product]
38
+ - **What it does for you:** (one sentence)
39
+ - **Pricing:** (free tier + paid, be specific with numbers)
40
+ - **Docs:** (exact URL)
41
+ - **Why not alternatives:** (one sentence)
42
+ - **Integration difficulty:** Easy / Medium / Hard
43
+
44
+ ## πŸ’° Monthly Cost Estimate
45
+ | Users | Est. Cost |
46
+ |-------|-----------|
47
+ | 100 | $X/month |
48
+ | 1,000 | $X/month |
49
+ | 10,000| $X/month |
50
+
51
+ ## ⚑ Build Order
52
+ 1. First: [API] β€” because...
53
+ 2. Second: [API] β€” because...
54
+ 3. Third: [API] β€” because...
55
+
56
+ ## 🚨 Top Mistake to Avoid
57
+ (the most common mistake with this stack)
58
+
59
+ Be specific, honest about pricing, always mention free tiers."""
60
+
61
+
62
+ def get_client():
63
+ return OpenAI(
64
+ api_key=API_KEY,
65
+ base_url=BASE_URL
66
+ )
67
+
68
+
69
+ def get_stack(idea, budget, level, market):
70
+ if not idea.strip():
71
+ return "⚠️ Please describe your product idea."
72
+
73
+ if not API_KEY:
74
+ return (
75
+ "⚠️ **AVALAI_API_KEY is not set.**\n\n"
76
+ "Go to: **Space Settings β†’ Secrets β†’ New secret**\n"
77
+ "- Name: `AVALAI_API_KEY`\n"
78
+ "- Value: your key from [avalai.ir](https://avalai.ir)"
79
+ )
80
+
81
+ try:
82
+ client = get_client()
83
+ prompt = f"""Product idea: {idea}
84
+
85
+ Monthly API budget: {budget}
86
+ Technical level: {level}
87
+ Target market: {market}
88
+
89
+ Recommend the best API stack for this product."""
90
+
91
+ response = client.chat.completions.create(
92
+ model=MODEL,
93
+ messages=[
94
+ {"role": "system", "content": SYSTEM_PROMPT},
95
+ {"role": "user", "content": prompt}
96
+ ],
97
+ max_tokens=1500,
98
+ temperature=0.7
99
+ )
100
+ return response.choices[0].message.content
101
+
102
+ except Exception as e:
103
+ err = str(e)
104
+ if "401" in err or "auth" in err.lower():
105
+ return "❌ Invalid API key. Check your AVALAI_API_KEY in Space Settings."
106
+ if "429" in err:
107
+ return "❌ Rate limit hit. Please wait a moment and try again."
108
+ if "model" in err.lower():
109
+ return f"❌ Model error β€” check if `claude-sonnet-4-6` is available on your AvΠ°Π»AI plan.\n\nDetails: {err}"
110
+ return f"❌ Error: {err}"
111
+
112
+
113
+ def ask_followup(question, prev):
114
+ if not question.strip():
115
+ return ""
116
+ if not prev or prev.startswith("⚠️") or prev.startswith("❌"):
117
+ return "⚠️ Please generate a stack recommendation first."
118
+
119
+ try:
120
+ client = get_client()
121
+ response = client.chat.completions.create(
122
+ model=MODEL,
123
+ messages=[
124
+ {"role": "system", "content": SYSTEM_PROMPT},
125
+ {
126
+ "role": "user",
127
+ "content": (
128
+ f"Previous recommendation:\n{prev}\n\n"
129
+ f"Follow-up question: {question}\n\n"
130
+ f"Answer concisely and helpfully."
131
+ )
132
+ }
133
+ ],
134
+ max_tokens=800,
135
+ temperature=0.7
136
+ )
137
+ return response.choices[0].message.content
138
+
139
+ except Exception as e:
140
+ return f"❌ Error: {str(e)}"
141
+
142
+
143
+ EXAMPLES = [
144
+ ["A Notion-like notes app with AI summarization", "$50/month", "Intermediate", "Students"],
145
+ ["SMS marketing platform for small restaurants", "$30/month", "Beginner", "Restaurant owners"],
146
+ ["Job board that auto-matches candidates with AI", "$100/month", "Advanced", "Tech recruiters"],
147
+ ["Podcast transcription and highlight tool", "$20/month", "Beginner", "Podcasters"],
148
+ ["Crypto portfolio tracker with price alerts", "$0 (free only)", "Intermediate", "Retail investors"],
149
+ ]
150
+
151
+ css = """
152
+ .gradio-container { max-width: 900px !important; margin: auto; }
153
+ footer { display: none !important; }
154
+ """
155
+
156
+ with gr.Blocks(css=css, title="API Stack Finder") as demo:
157
+ gr.Markdown("""
158
+ # πŸ”§ API Stack Finder
159
+ **Describe your product idea β†’ Get the perfect API stack, pricing, and build order**
160
+
161
+ Powered by **Claude Sonnet 4.6** via [AvΠ°Π»AI](https://avalai.ir)
162
+ """)
163
+
164
+ with gr.Row():
165
+ with gr.Column(scale=3):
166
+ idea_input = gr.Textbox(
167
+ label="Describe your product idea",
168
+ placeholder="e.g. A platform where freelancers can sell services and get paid instantly...",
169
+ lines=4
170
+ )
171
+ with gr.Column(scale=1):
172
+ budget_input = gr.Dropdown(
173
+ choices=[
174
+ "$0 (free only)",
175
+ "$10/month",
176
+ "$30/month",
177
+ "$50/month",
178
+ "$100/month",
179
+ "$500/month",
180
+ "Unlimited"
181
+ ],
182
+ value="$30/month",
183
+ label="Monthly API budget"
184
+ )
185
+ level_input = gr.Dropdown(
186
+ choices=["Beginner", "Intermediate", "Advanced"],
187
+ value="Intermediate",
188
+ label="Technical level"
189
+ )
190
+ market_input = gr.Textbox(
191
+ label="Target market",
192
+ placeholder="e.g. Small business owners",
193
+ value="General consumers"
194
+ )
195
+
196
+ gr.Markdown("**Try an example:**")
197
+ with gr.Row():
198
+ for ex in EXAMPLES:
199
+ gr.Button(ex[0][:32] + "...", size="sm").click(
200
+ lambda e=ex: (e[0], e[1], e[2], e[3]),
201
+ outputs=[idea_input, budget_input, level_input, market_input]
202
+ )
203
+
204
+ submit_btn = gr.Button("πŸ” Find My API Stack", variant="primary", size="lg")
205
+ output = gr.Markdown("*Your API stack will appear here...*")
206
+
207
+ gr.Markdown("---")
208
+ gr.Markdown("### πŸ’¬ Ask a follow-up")
209
+
210
+ with gr.Row():
211
+ followup_input = gr.Textbox(
212
+ label="Follow-up question",
213
+ placeholder="e.g. Is there a free alternative to Stripe? / How do I add auth cheaply?",
214
+ scale=4
215
+ )
216
+ followup_btn = gr.Button("Ask", scale=1, variant="secondary")
217
+
218
+ followup_output = gr.Markdown()
219
+
220
+ submit_btn.click(
221
+ get_stack,
222
+ inputs=[idea_input, budget_input, level_input, market_input],
223
+ outputs=output
224
+ )
225
+ followup_btn.click(
226
+ ask_followup,
227
+ inputs=[followup_input, output],
228
+ outputs=followup_output
229
+ )
230
+
231
+ gr.Markdown("""
232
+ ---
233
+ πŸ€– Model: `claude-sonnet-4-6` Β· πŸ”‘ API: [avalai.ir](https://avalai.ir)
234
+ """)
235
+
236
+ if __name__ == "__main__":
237
+ demo.launch()