Naveen-2007 commited on
Commit
6ceb8b5
Β·
1 Parent(s): 2fccaae

Fix Video Brain URL handling, add API health check, improve error diagnostics

Browse files
Files changed (3) hide show
  1. README.md +14 -6
  2. app/api.py +13 -2
  3. streamlit_app.py +65 -7
README.md CHANGED
@@ -19,28 +19,36 @@ An AI-powered search and research assistant with multiple modes:
19
  - **Agentic**: Multi-agent RAG with planning
20
  - **Analysis**: Data analysis and insights
21
  - **Summarize**: Summarize content and documents
 
 
22
 
23
  ## Features
24
 
25
- - πŸ” Real-time web search with Tavily
26
  - πŸ“š Document upload and RAG
27
  - πŸ€– LangGraph-powered pipelines
28
  - πŸ’‘ Follow-up question suggestions
29
  - πŸ–ΌοΈ Image search integration
30
  - πŸ“Š Knowledge panels
 
31
 
32
- ## Environment Variables
33
 
34
- Set these secrets in your Hugging Face Space:
35
 
36
- - `GROQ_API_KEY`: Your Groq API key
37
- - `TAVILY_API_KEY`: Your Tavily API key
 
 
 
 
 
38
 
39
  ## Tech Stack
40
 
41
  - FastAPI backend
42
  - Streamlit frontend
43
  - LangChain + LangGraph
44
- - Groq LLM (llama3-70b-8192)
45
  - FAISS vector store
46
  - Sentence Transformers embeddings
 
19
  - **Agentic**: Multi-agent RAG with planning
20
  - **Analysis**: Data analysis and insights
21
  - **Summarize**: Summarize content and documents
22
+ - **Product MVP**: Generate MVP blueprints from ideas
23
+ - **Video Brain**: Analyze YouTube videos
24
 
25
  ## Features
26
 
27
+ - πŸ” Real-time web search with Tavily (with AI answers)
28
  - πŸ“š Document upload and RAG
29
  - πŸ€– LangGraph-powered pipelines
30
  - πŸ’‘ Follow-up question suggestions
31
  - πŸ–ΌοΈ Image search integration
32
  - πŸ“Š Knowledge panels
33
+ - πŸŽ₯ YouTube video analysis
34
 
35
+ ## Environment Variables (Required!)
36
 
37
+ ⚠️ **IMPORTANT**: Set these secrets in your Hugging Face Space settings:
38
 
39
+ 1. Go to your Space Settings β†’ Variables and secrets
40
+ 2. Add these as **Secrets** (not Repository secrets):
41
+
42
+ - `GROQ_API_KEY`: Your Groq API key (get from https://console.groq.com)
43
+ - `TAVILY_API_KEY`: Your Tavily API key (get from https://tavily.com)
44
+
45
+ Without these keys, web search and LLM responses will not work!
46
 
47
  ## Tech Stack
48
 
49
  - FastAPI backend
50
  - Streamlit frontend
51
  - LangChain + LangGraph
52
+ - Groq LLM (compound-beta)
53
  - FAISS vector store
54
  - Sentence Transformers embeddings
app/api.py CHANGED
@@ -52,14 +52,25 @@ app.add_middleware(
52
  allow_credentials=True,
53
  )
54
 
 
55
 
56
  # =======================================================
57
  # Health Check Endpoint
58
  # =======================================================
59
  @app.get("/health")
60
  async def health_check():
61
- """Health check endpoint for container orchestration"""
62
- return {"status": "healthy", "service": "perplexity-clone-api"}
 
 
 
 
 
 
 
 
 
 
63
 
64
 
65
  # =======================================================
 
52
  allow_credentials=True,
53
  )
54
 
55
+ import os
56
 
57
  # =======================================================
58
  # Health Check Endpoint
59
  # =======================================================
60
  @app.get("/health")
61
  async def health_check():
62
+ """Health check endpoint - shows API key status"""
63
+ groq_key = os.getenv("GROQ_API_KEY", "")
64
+ tavily_key = os.getenv("TAVILY_API_KEY", "")
65
+
66
+ return {
67
+ "status": "healthy",
68
+ "service": "perplexity-clone-api",
69
+ "api_keys": {
70
+ "groq": "configured" if groq_key else "MISSING",
71
+ "tavily": "configured" if tavily_key else "MISSING"
72
+ }
73
+ }
74
 
75
 
76
  # =======================================================
streamlit_app.py CHANGED
@@ -42,6 +42,11 @@ if "product_ideas" not in st.session_state:
42
  API_URL = os.getenv("BACKEND_URL", "http://127.0.0.1:8000")
43
  WORKSPACE = "default"
44
 
 
 
 
 
 
45
  # MODE MAPPING - All 8 modes with correct backend endpoints
46
  MODES = {
47
  "Automatic": {
@@ -456,6 +461,37 @@ def get_css():
456
  st.markdown(get_css(), unsafe_allow_html=True)
457
 
458
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
459
  # =====================================
460
  # HELPER FUNCTIONS
461
  # =====================================
@@ -635,11 +671,16 @@ if st.session_state.mode == "Video Brain" and not st.session_state.current_resul
635
  <div style="text-align: center; padding: 20px; margin: 20px auto; max-width: 700px;
636
  background: linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%);
637
  border-radius: 16px; color: white;">
638
- <h3 style="margin: 0; font-size: 24px;">πŸŽ₯ Video Brain – Understand Any YouTube Lecture</h3>
639
- <p style="margin: 10px 0 0; opacity: 0.9;">πŸ”΅ Paste YouTube URL below, then ask questions</p>
640
  </div>
641
  """, unsafe_allow_html=True)
642
 
 
 
 
 
 
643
  # YouTube URL input - auto-loads on change
644
  youtube_url = st.text_input(
645
  "YouTube URL",
@@ -689,26 +730,43 @@ if st.session_state.uploaded_files:
689
  # =====================================
690
  if submit and query.strip():
691
  extra_data = None
 
692
 
693
  # For Video Brain mode, include the YouTube URL
694
  if st.session_state.mode == "Video Brain":
695
- if st.session_state.video_loaded and st.session_state.youtube_url:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
696
  extra_data = {"youtube_url": st.session_state.youtube_url}
697
  else:
698
- st.warning("⚠️ Please load a YouTube video first!")
699
  st.stop()
700
 
701
  # For Product MVP mode, save to ideas history
702
  if st.session_state.mode == "Product MVP":
703
  st.session_state.product_ideas.append({
704
- "idea": query.strip(),
705
  "time": "just now"
706
  })
707
 
708
  with st.spinner(f"πŸ”„ {st.session_state.mode}..."):
709
- result = call_api(query.strip(), st.session_state.mode, extra_data)
710
  st.session_state.current_result = {
711
- "query": query.strip(),
712
  "mode": st.session_state.mode,
713
  "data": result
714
  }
 
42
  API_URL = os.getenv("BACKEND_URL", "http://127.0.0.1:8000")
43
  WORKSPACE = "default"
44
 
45
+ # Check API health on startup
46
+ if "api_checked" not in st.session_state:
47
+ st.session_state.api_checked = False
48
+ st.session_state.api_status = None
49
+
50
  # MODE MAPPING - All 8 modes with correct backend endpoints
51
  MODES = {
52
  "Automatic": {
 
461
  st.markdown(get_css(), unsafe_allow_html=True)
462
 
463
 
464
+ # =====================================
465
+ # API HEALTH CHECK
466
+ # =====================================
467
+ def check_api_health():
468
+ """Check if API is healthy and keys are configured."""
469
+ try:
470
+ resp = requests.get(f"{API_URL}/health", timeout=5)
471
+ if resp.ok:
472
+ return resp.json()
473
+ except:
474
+ pass
475
+ return None
476
+
477
+ # Check API on first load
478
+ if not st.session_state.api_checked:
479
+ st.session_state.api_status = check_api_health()
480
+ st.session_state.api_checked = True
481
+
482
+ # Show warnings if API keys are missing
483
+ if st.session_state.api_status:
484
+ api_keys = st.session_state.api_status.get("api_keys", {})
485
+ missing_keys = []
486
+ if api_keys.get("groq") == "MISSING":
487
+ missing_keys.append("GROQ_API_KEY")
488
+ if api_keys.get("tavily") == "MISSING":
489
+ missing_keys.append("TAVILY_API_KEY")
490
+
491
+ if missing_keys:
492
+ st.error(f"⚠️ Missing API keys: {', '.join(missing_keys)}. Please configure them in your Hugging Face Space settings under 'Variables and secrets'.")
493
+
494
+
495
  # =====================================
496
  # HELPER FUNCTIONS
497
  # =====================================
 
671
  <div style="text-align: center; padding: 20px; margin: 20px auto; max-width: 700px;
672
  background: linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%);
673
  border-radius: 16px; color: white;">
674
+ <h3 style="margin: 0; font-size: 24px;">πŸŽ₯ Video Brain – Understand Any YouTube Video</h3>
675
+ <p style="margin: 10px 0 0; opacity: 0.9;">πŸ”΅ Two ways to use:</p>
676
  </div>
677
  """, unsafe_allow_html=True)
678
 
679
+ st.markdown("""
680
+ **Option 1:** Paste a YouTube URL directly in the search box and click Search
681
+ **Option 2:** Load the URL below first, then ask questions
682
+ """)
683
+
684
  # YouTube URL input - auto-loads on change
685
  youtube_url = st.text_input(
686
  "YouTube URL",
 
730
  # =====================================
731
  if submit and query.strip():
732
  extra_data = None
733
+ actual_query = query.strip()
734
 
735
  # For Video Brain mode, include the YouTube URL
736
  if st.session_state.mode == "Video Brain":
737
+ # Check if query itself contains a YouTube URL
738
+ query_text = query.strip()
739
+ url_in_query = None
740
+ for word in query_text.split():
741
+ if "youtube.com" in word or "youtu.be" in word:
742
+ url_in_query = word
743
+ break
744
+
745
+ if url_in_query:
746
+ # User pasted URL directly in the query
747
+ st.session_state.youtube_url = url_in_query
748
+ st.session_state.video_loaded = True
749
+ extra_data = {"youtube_url": url_in_query}
750
+ # If query is JUST the URL, ask a default question
751
+ if query_text == url_in_query:
752
+ actual_query = "Summarize this video and give me the key takeaways"
753
+ elif st.session_state.video_loaded and st.session_state.youtube_url:
754
  extra_data = {"youtube_url": st.session_state.youtube_url}
755
  else:
756
+ st.warning("⚠️ Please paste a YouTube URL in the search box or load one above!")
757
  st.stop()
758
 
759
  # For Product MVP mode, save to ideas history
760
  if st.session_state.mode == "Product MVP":
761
  st.session_state.product_ideas.append({
762
+ "idea": actual_query,
763
  "time": "just now"
764
  })
765
 
766
  with st.spinner(f"πŸ”„ {st.session_state.mode}..."):
767
+ result = call_api(actual_query, st.session_state.mode, extra_data)
768
  st.session_state.current_result = {
769
+ "query": actual_query,
770
  "mode": st.session_state.mode,
771
  "data": result
772
  }