Wall06 commited on
Commit
334ff37
·
verified ·
1 Parent(s): a8ea82b

Upload folder using huggingface_hub

Browse files
Files changed (6) hide show
  1. Dockerfile +6 -0
  2. ai_engine.py +38 -0
  3. database.py +13 -0
  4. main.py +56 -0
  5. requirements.txt +8 -0
  6. scraper.py +9 -0
Dockerfile ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ FROM python:3.9-slim
2
+ WORKDIR /app
3
+ COPY requirements.txt .
4
+ RUN pip install --no-cache-dir -r requirements.txt
5
+ COPY . .
6
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
ai_engine.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import google.generativeai as genai
2
+ import os
3
+ import json
4
+
5
+ # Configure the Gemini API
6
+ genai.configure(api_key=os.getenv("GOOGLE_API_KEY"))
7
+
8
+ # Initialize the model (Flash is the free, fast model)
9
+ model = genai.GenerativeModel(
10
+ model_name='gemini-1.5-flash',
11
+ generation_config={"response_mime_type": "application/json"} # Forces perfect JSON!
12
+ )
13
+
14
+ def analyze_lead(name: str, company: str, company_summary: str) -> dict:
15
+ prompt = f"""
16
+ You are a B2B sales expert. Analyze this lead.
17
+ Lead: {name} at {company}. Info: {company_summary}
18
+
19
+ Return ONLY this JSON structure:
20
+ {{
21
+ "score": <integer 1-10>,
22
+ "score_reason": "<one sentence why this score>",
23
+ "cold_email": "<a 100-word personalized cold email pitching AI automation services. Start with Hi {name},. End by asking for a 10-min chat.>"
24
+ }}
25
+ """
26
+
27
+ try:
28
+ response = model.generate_content(prompt)
29
+ # Because we forced JSON mime type, this is 100% safe to parse
30
+ return json.loads(response.text)
31
+
32
+ except Exception as e:
33
+ # Fallback if something goes wrong
34
+ return {
35
+ "score": 0,
36
+ "score_reason": f"AI Error: {str(e)}",
37
+ "cold_email": "Error generating email."
38
+ }
database.py ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from supabase import create_client
2
+ import os
3
+
4
+ supabase = create_client(os.getenv("SUPABASE_URL", ""), os.getenv("SUPABASE_KEY", ""))
5
+
6
+ def save_lead(data: dict):
7
+ return supabase.table("leads").insert(data).execute()
8
+
9
+ def get_pending_leads():
10
+ return supabase.table("leads").select("*").eq("status", "pending").execute().data
11
+
12
+ def update_lead_status(lead_id: int, status: str):
13
+ return supabase.table("leads").update({"status": status}).eq("id", lead_id).execute()
main.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, UploadFile, File
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from dotenv import load_dotenv
4
+ import pandas as pd
5
+ import io
6
+ import os
7
+
8
+ from scraper import scrape_company
9
+ from ai_engine import analyze_lead
10
+ from database import save_lead, get_pending_leads, update_lead_status
11
+
12
+ load_dotenv()
13
+
14
+ app = FastAPI()
15
+
16
+ app.add_middleware(
17
+ CORSMiddleware,
18
+ allow_origins=["*"], # Allow all origins for Vercel integration
19
+ allow_credentials=True,
20
+ allow_methods=["*"],
21
+ allow_headers=["*"],
22
+ )
23
+
24
+ @app.post("/process-csv")
25
+ async def process_csv(file: UploadFile = File(...)):
26
+ contents = await file.read()
27
+ df = pd.read_csv(io.BytesIO(contents))
28
+
29
+ for _, row in df.iterrows():
30
+ summary = scrape_company(row["url"])
31
+ result = analyze_lead(row["name"], row["company"], summary)
32
+
33
+ save_lead({
34
+ "name": row["name"],
35
+ "company": row["company"],
36
+ "url": row["url"],
37
+ "email": row.get("email", ""),
38
+ "company_summary": summary,
39
+ "score": result["score"],
40
+ "score_reason": result["score_reason"],
41
+ "cold_email": result["cold_email"]
42
+ })
43
+ return {"status": "success"}
44
+
45
+ @app.get("/get-leads")
46
+ def fetch_leads():
47
+ return get_pending_leads()
48
+
49
+ @app.post("/update-lead/{lead_id}")
50
+ def update_lead(lead_id: int, status: str = "approved"):
51
+ update_lead_status(lead_id, status)
52
+ return {"status": "updated"}
53
+
54
+ @app.get("/")
55
+ def read_root():
56
+ return {"message": "Lead Qualifier API is running!"}
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ fastapi
2
+ uvicorn
3
+ google-generativeai
4
+ supabase
5
+ requests
6
+ python-dotenv
7
+ python-multipart
8
+ pandas
scraper.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+
3
+ def scrape_company(url: str) -> str:
4
+ try:
5
+ # Using Jina AI reader to bypass JS blocking and get clean markdown
6
+ res = requests.get(f"https://r.jina.ai/{url}", timeout=15)
7
+ return res.text[:800] if res.status_code == 200 else "No description found."
8
+ except Exception as e:
9
+ return f"Scraping error: {str(e)}"