peace2024 commited on
Commit
1abe985
·
1 Parent(s): c62c5a1

update chat vector

Browse files
Dockerfile CHANGED
@@ -20,6 +20,9 @@ RUN apt-get update && \
20
  build-essential \
21
  && rm -rf /var/lib/apt/lists/*
22
 
 
 
 
23
  # Create non-root user to avoid git permission issues
24
  RUN useradd -m appuser && chown -R appuser /app
25
 
@@ -47,6 +50,9 @@ RUN pip install --no-cache-dir --upgrade pip && \
47
  # Copy the entire app source code
48
  COPY . .
49
 
 
 
 
50
  # Create necessary directories
51
  RUN mkdir -p vector_store logs
52
 
@@ -60,5 +66,5 @@ RUN pip install torch torchvision torchaudio --index-url https://download.pytorc
60
  HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
61
  CMD curl -f http://localhost:7860/docs || exit 1
62
 
63
- # Run the FastAPI app via Uvicorn
64
- CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "7860", "--workers", "1"]
 
20
  build-essential \
21
  && rm -rf /var/lib/apt/lists/*
22
 
23
+ # Install supervisord
24
+ RUN apt-get update && apt-get install -y supervisor && rm -rf /var/lib/apt/lists/*
25
+
26
  # Create non-root user to avoid git permission issues
27
  RUN useradd -m appuser && chown -R appuser /app
28
 
 
50
  # Copy the entire app source code
51
  COPY . .
52
 
53
+ # Copy supervisord config
54
+ COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
55
+
56
  # Create necessary directories
57
  RUN mkdir -p vector_store logs
58
 
 
66
  HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \
67
  CMD curl -f http://localhost:7860/docs || exit 1
68
 
69
+ # Run supervisord
70
+ CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
app/agent/custom_chatbot.py CHANGED
@@ -7,7 +7,8 @@ from dotenv import load_dotenv
7
  from langchain_groq import ChatGroq
8
 
9
  from langchain_openai import OpenAIEmbeddings
10
- from langchain_community.vectorstores import FAISS
 
11
  from langchain.text_splitter import RecursiveCharacterTextSplitter
12
  from langchain.chains.combine_documents import create_stuff_documents_chain
13
  from langchain_core.prompts import ChatPromptTemplate
@@ -27,9 +28,24 @@ if not groq_api_key:
27
  logger.error("❌ GROQ_API_KEY is not set in the environment.")
28
  raise RuntimeError("GROQ_API_KEY must be set in .env or environment variables.")
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  # LLM Initialization
31
  try:
32
- llm = ChatGroq(groq_api_key=groq_api_key, model_name="Llama3-8b-8192")
33
  logger.info("✅ ChatGroq LLM initialized successfully.")
34
  except Exception as e:
35
  logger.exception("❌ Failed to initialize ChatGroq LLM.")
@@ -45,31 +61,20 @@ Answer the question based only on the provided context.
45
  Question: {input}
46
  """)
47
 
 
 
 
 
 
 
 
 
 
48
  # Input schema
49
  class ChatRequest(BaseModel):
50
  query: str
51
  user_id: int
52
 
53
- # Load vector store for a given user
54
- def load_user_vector_store(user_id: int):
55
- user_path = f"vector_store/user_{user_id}"
56
- index_file = os.path.join(user_path, "index.faiss")
57
-
58
- logger.info(f"🔍 Looking for vector store at {index_file}")
59
- if not os.path.exists(index_file):
60
- msg = f"No vector store found for user {user_id}"
61
- logger.warning(f"📭 {msg}")
62
- raise FileNotFoundError(msg)
63
-
64
- try:
65
- embeddings = OpenAIEmbeddings()
66
- vector_store = FAISS.load_local(user_path, embeddings,allow_dangerous_deserialization=True)
67
- logger.info(f"📦 Vector store loaded for user {user_id}")
68
- return vector_store
69
- except Exception as e:
70
- logger.exception(f"❌ Failed to load vector store for user {user_id}")
71
- raise
72
-
73
  # Main chatbot endpoint
74
  @router.post("/custom-chatbot")
75
  async def custom_chatbot(request: ChatRequest):
@@ -78,25 +83,28 @@ async def custom_chatbot(request: ChatRequest):
78
  logger.info(f"🤖 Received query from user {user_id}: {query}")
79
 
80
  try:
81
- vector_store = load_user_vector_store(user_id)
82
- retriever = vector_store.as_retriever()
 
83
 
 
84
  doc_chain = create_stuff_documents_chain(llm, prompt_template)
85
  rag_chain = create_retrieval_chain(retriever, doc_chain)
86
 
87
  response = rag_chain.invoke({"input": query})
88
- logger.info(f"✅ Response generated for user {user_id}")
89
 
90
  return {
91
  "answer": response["answer"],
92
  "sources": [doc.page_content for doc in response.get("context", [])],
93
  }
94
 
95
- except FileNotFoundError as e:
96
- logger.warning(f"🚫 {e}")
97
- raise HTTPException(status_code=404, detail=str(e))
98
-
99
  except Exception as e:
100
- logger.exception(" Unexpected error in custom chatbot endpoint.")
101
- raise HTTPException(status_code=500, detail="Internal server error")
 
 
 
 
 
102
 
 
7
  from langchain_groq import ChatGroq
8
 
9
  from langchain_openai import OpenAIEmbeddings
10
+ from langchain_community.vectorstores import SupabaseVectorStore
11
+ from supabase.client import create_client
12
  from langchain.text_splitter import RecursiveCharacterTextSplitter
13
  from langchain.chains.combine_documents import create_stuff_documents_chain
14
  from langchain_core.prompts import ChatPromptTemplate
 
28
  logger.error("❌ GROQ_API_KEY is not set in the environment.")
29
  raise RuntimeError("GROQ_API_KEY must be set in .env or environment variables.")
30
 
31
+ # Supabase Initialization
32
+ supabase_url = os.getenv("SUPABASE_URL")
33
+ supabase_key = os.getenv("SUPABASE_KEY")
34
+
35
+ if not supabase_url or not supabase_key:
36
+ logger.error("❌ SUPABASE_URL or SUPABASE_KEY is not set in the environment.")
37
+ raise RuntimeError("SUPABASE_URL and SUPABASE_KEY must be set in .env or environment variables.")
38
+
39
+ try:
40
+ supabase_client = create_client(supabase_url, supabase_key)
41
+ logger.info("✅ Supabase client initialized successfully.")
42
+ except Exception as e:
43
+ logger.exception("❌ Failed to initialize Supabase client.")
44
+ raise
45
+
46
  # LLM Initialization
47
  try:
48
+ llm = ChatGroq(groq_api_key=groq_api_key, model_name="llama-3.3-70b-versatile")
49
  logger.info("✅ ChatGroq LLM initialized successfully.")
50
  except Exception as e:
51
  logger.exception("❌ Failed to initialize ChatGroq LLM.")
 
61
  Question: {input}
62
  """)
63
 
64
+ generic_prompt_template = ChatPromptTemplate.from_template("""
65
+ You are a helpful AI assistant. Answer the following question:
66
+ <context>
67
+ {context}
68
+ </context>
69
+
70
+ Question: {input}
71
+ """)
72
+
73
  # Input schema
74
  class ChatRequest(BaseModel):
75
  query: str
76
  user_id: int
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  # Main chatbot endpoint
79
  @router.post("/custom-chatbot")
80
  async def custom_chatbot(request: ChatRequest):
 
83
  logger.info(f"🤖 Received query from user {user_id}: {query}")
84
 
85
  try:
86
+ embeddings = OpenAIEmbeddings()
87
+ # Changed table_name and query_name to fixed values, and added filter to query
88
+ vector_store = SupabaseVectorStore(client=supabase_client, embedding=embeddings, table_name="documents", query_name="match_documents")
89
 
90
+ retriever = vector_store.as_retriever(search_kwargs={"filter": {"user_id": user_id}})
91
  doc_chain = create_stuff_documents_chain(llm, prompt_template)
92
  rag_chain = create_retrieval_chain(retriever, doc_chain)
93
 
94
  response = rag_chain.invoke({"input": query})
95
+ logger.info(f"✅ Response generated for user {user_id} using RAG.")
96
 
97
  return {
98
  "answer": response["answer"],
99
  "sources": [doc.page_content for doc in response.get("context", [])],
100
  }
101
 
 
 
 
 
102
  except Exception as e:
103
+ logger.warning(f"🤷 Falling back to generic response due to: {e}")
104
+ generic_chain = create_stuff_documents_chain(llm, generic_prompt_template)
105
+ generic_response = generic_chain.invoke({"input": query, "context": []}) # Pass empty context for generic response
106
+ return {
107
+ "answer": generic_response,
108
+ "sources": []
109
+ }
110
 
app/main.py CHANGED
@@ -52,11 +52,6 @@ async def root():
52
  "status": "running"
53
  }
54
 
55
- @app.get("/health")
56
- async def health_check():
57
- """Health check endpoint for Hugging Face Spaces"""
58
- return {"status": "healthy", "service": "dubsway-video-ai"}
59
-
60
  @app.on_event("startup")
61
  async def startup_event():
62
  logger.info("✅ FastAPI app started")
 
52
  "status": "running"
53
  }
54
 
 
 
 
 
 
55
  @app.on_event("startup")
56
  async def startup_event():
57
  logger.info("✅ FastAPI app started")
app/utils/agentic_integration.py CHANGED
@@ -221,7 +221,7 @@ class MCPToolManager:
221
  if self.groq_api_key:
222
  try:
223
  from langchain_groq import ChatGroq
224
- llm = ChatGroq(groq_api_key=self.groq_api_key, model_name="llama3-8b-8192")
225
  # This would use Groq for sentiment analysis
226
  return {"positive": 0.6, "negative": 0.2, "neutral": 0.2}
227
  except:
@@ -234,7 +234,7 @@ class MCPToolManager:
234
  if self.groq_api_key:
235
  try:
236
  from langchain_groq import ChatGroq
237
- llm = ChatGroq(groq_api_key=self.groq_api_key, model_name="llama3-8b-8192")
238
  # This would use Groq for topic extraction
239
  return ["technology", "innovation", "business"]
240
  except:
@@ -247,7 +247,7 @@ class MCPToolManager:
247
  if self.groq_api_key:
248
  try:
249
  from langchain_groq import ChatGroq
250
- llm = ChatGroq(groq_api_key=self.groq_api_key, model_name="llama3-8b-8192")
251
  # This would use Groq to add context
252
  return f"Enhanced context for: {content}"
253
  except:
@@ -299,7 +299,7 @@ def integrate_agentic_analysis():
299
 
300
  Benefits:
301
  - Multi-modal analysis (audio + visual)
302
- - Context-aware summarization using Groq Llama3-8b-8192
303
  - Beautiful, comprehensive reports
304
  - Enhanced vector embeddings for better RAG
305
  - Web search integration for context
 
221
  if self.groq_api_key:
222
  try:
223
  from langchain_groq import ChatGroq
224
+ llm = ChatGroq(groq_api_key=self.groq_api_key, model_name="llama-3.3-70b-versatile")
225
  # This would use Groq for sentiment analysis
226
  return {"positive": 0.6, "negative": 0.2, "neutral": 0.2}
227
  except:
 
234
  if self.groq_api_key:
235
  try:
236
  from langchain_groq import ChatGroq
237
+ llm = ChatGroq(groq_api_key=self.groq_api_key, model_name="llama-3.3-70b-versatile")
238
  # This would use Groq for topic extraction
239
  return ["technology", "innovation", "business"]
240
  except:
 
247
  if self.groq_api_key:
248
  try:
249
  from langchain_groq import ChatGroq
250
+ llm = ChatGroq(groq_api_key=self.groq_api_key, model_name="llama-3.3-70b-versatile")
251
  # This would use Groq to add context
252
  return f"Enhanced context for: {content}"
253
  except:
 
299
 
300
  Benefits:
301
  - Multi-modal analysis (audio + visual)
302
+ - Context-aware summarization using Groq llama-3.3-70b-versatile
303
  - Beautiful, comprehensive reports
304
  - Enhanced vector embeddings for better RAG
305
  - Web search integration for context
app/utils/enhanced_analysis.py CHANGED
@@ -82,7 +82,7 @@ class MultiModalAnalyzer:
82
 
83
  self.llm = ChatGroq(
84
  groq_api_key=groq_api_key,
85
- model_name="llama3-8b-8192",
86
  temperature=0.1,
87
  max_tokens=2000
88
  )
@@ -325,7 +325,7 @@ Based on the analysis, consider:
325
  - Target audience insights
326
 
327
  ---
328
- *Report generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} using Groq Llama3-8b-8192*
329
  """
330
 
331
  return report_template
 
82
 
83
  self.llm = ChatGroq(
84
  groq_api_key=groq_api_key,
85
+ model_name="llama-3.3-70b-versatile",
86
  temperature=0.1,
87
  max_tokens=2000
88
  )
 
325
  - Target audience insights
326
 
327
  ---
328
+ *Report generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} using Groq llama-3.3-70b-versatile*
329
  """
330
 
331
  return report_template
app/utils/lightweight_agentic.py CHANGED
@@ -74,7 +74,7 @@ class LightweightAgenticProcessor:
74
  # Initialize Groq
75
  llm = ChatGroq(
76
  groq_api_key=self.groq_api_key,
77
- model_name="llama3-8b-8192",
78
  temperature=0.1,
79
  max_tokens=1000
80
  )
@@ -128,7 +128,7 @@ class LightweightAgenticProcessor:
128
  ## 📝 Basic Summary
129
  {summary}
130
 
131
- ## 🤖 Enhanced Analysis (Groq Llama3-8b-8192)
132
  {enhanced_analysis.get('enhanced_analysis', 'Analysis not available')}
133
 
134
  ## 🎯 Key Insights
@@ -136,13 +136,13 @@ class LightweightAgenticProcessor:
136
 
137
  ## 📊 Analysis Details
138
  - **Processing Method**: Lightweight Agentic Analysis
139
- - **LLM Provider**: Groq Llama3-8b-8192
140
  - **Enhanced Features**: Text-based analysis and reasoning
141
  - **Topics**: {', '.join(enhanced_analysis.get('topics', ['General']))}
142
  - **Sentiment**: {enhanced_analysis.get('sentiment', {})}
143
 
144
  ---
145
- *Report generated using Groq Llama3-8b-8192*
146
  """
147
  else:
148
  return f"""
 
74
  # Initialize Groq
75
  llm = ChatGroq(
76
  groq_api_key=self.groq_api_key,
77
+ model_name="llama-3.3-70b-versatile",
78
  temperature=0.1,
79
  max_tokens=1000
80
  )
 
128
  ## 📝 Basic Summary
129
  {summary}
130
 
131
+ ## 🤖 Enhanced Analysis (Groq llama-3.3-70b-versatile)
132
  {enhanced_analysis.get('enhanced_analysis', 'Analysis not available')}
133
 
134
  ## 🎯 Key Insights
 
136
 
137
  ## 📊 Analysis Details
138
  - **Processing Method**: Lightweight Agentic Analysis
139
+ - **LLM Provider**: Groq llama-3.3-70b-versatile
140
  - **Enhanced Features**: Text-based analysis and reasoning
141
  - **Topics**: {', '.join(enhanced_analysis.get('topics', ['General']))}
142
  - **Sentiment**: {enhanced_analysis.get('sentiment', {})}
143
 
144
  ---
145
+ *Report generated using Groq llama-3.3-70b-versatile*
146
  """
147
  else:
148
  return f"""
app/utils/whisper_llm.py CHANGED
@@ -2,6 +2,7 @@ import os
2
  import logging
3
  import requests
4
  import tempfile
 
5
  import torch
6
  from transformers import pipeline
7
  from faster_whisper import WhisperModel
@@ -9,7 +10,11 @@ from faster_whisper import WhisperModel
9
  from langchain.text_splitter import RecursiveCharacterTextSplitter
10
  from langchain_openai import OpenAIEmbeddings
11
  from langchain_core.documents import Document
12
- from langchain_community.vectorstores import FAISS
 
 
 
 
13
 
14
  from sqlalchemy import select
15
  from sqlalchemy.ext.asyncio import AsyncSession
@@ -26,14 +31,26 @@ if not logger.handlers:
26
 
27
  # Whisper Model Initialization
28
  def get_whisper_model():
29
- if torch.cuda.is_available():
30
- device = "cuda"
31
- compute_type = "float32"
32
- logger.info("GPU detected: Using CUDA with float32 compute")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  else:
34
- device = "cpu"
35
- compute_type = "int8"
36
- logger.warning("GPU not available: Falling back to CPU with int8 compute")
37
 
38
  try:
39
  model = WhisperModel("base", device=device, compute_type=compute_type)
@@ -45,6 +62,21 @@ def get_whisper_model():
45
 
46
  whisper_model = get_whisper_model()
47
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  # Summarizer
49
  try:
50
  summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
@@ -152,50 +184,65 @@ async def analyze(video_url: str, user_id: int, db: AsyncSession):
152
 
153
  # Step 2: Transcribe
154
  try:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  logger.info("Transcribing audio with Faster-Whisper...")
156
-
157
  # Get transcription result
158
  result = whisper_model.transcribe(tmp_path)
159
-
160
  # Handle different return formats from faster-whisper
161
  if isinstance(result, tuple):
162
  segments, info = result
163
  else:
164
- # If it's not a tuple, it might be just segments
165
  segments = result
166
  info = None
167
-
168
  # Extract text from segments
169
  if segments:
170
  text = " ".join(segment.text for segment in segments if hasattr(segment, 'text') and segment.text)
171
  else:
172
  text = ""
173
-
174
  logger.info(f"Transcription completed. Length: {len(text)} characters.")
175
-
176
  # Log additional info if available
177
  if info:
178
  logger.info(f"Transcription info: language={getattr(info, 'language', 'unknown')}, language_probability={getattr(info, 'language_probability', 'unknown')}")
179
-
180
  # Handle empty transcription
181
  if not text or len(text.strip()) == 0:
182
  logger.warning("Transcription resulted in empty text, using fallback")
183
  text = "No speech detected in video"
184
-
 
 
 
185
  except Exception as e:
186
  logger.error(f"Transcription failed: {e}")
187
  logger.error(f"Error type: {type(e)}")
188
  import traceback
189
  logger.error(f"Traceback: {traceback.format_exc()}")
190
-
191
  # Provide fallback text instead of failing completely
192
  logger.warning("Using fallback text due to transcription failure")
193
  text = "Transcription failed - video may be corrupted or have no audio"
194
-
195
- # Clean up temp file
196
  try:
197
  os.unlink(tmp_path)
198
- except:
199
  pass
200
 
201
  # Step 3: Summarize
@@ -217,33 +264,28 @@ async def analyze(video_url: str, user_id: int, db: AsyncSession):
217
  except:
218
  pass
219
 
220
- # Step 4: Save to FAISS store
221
  try:
222
- logger.info("Creating/updating FAISS vector store for user...")
223
- documents = [Document(page_content=summary)]
224
- embeddings = OpenAIEmbeddings()
225
-
226
- user_vector_path = f"vector_store/user_{user_id}"
227
- os.makedirs(user_vector_path, exist_ok=True)
228
-
229
- if os.path.exists(os.path.join(user_vector_path, "index.faiss")):
230
- # Load existing vector store - safe to use allow_dangerous_deserialization
231
- # since we're loading our own created files
232
- vector_store = FAISS.load_local(user_vector_path, embeddings, allow_dangerous_deserialization=True)
233
- vector_store.add_documents(documents)
234
  else:
235
- # Create new vector store
236
- vector_store = FAISS.from_documents(documents, embeddings)
 
 
 
 
 
 
 
 
 
 
 
237
 
238
- vector_store.save_local(user_vector_path)
239
- logger.info(f"Vector store saved at: {user_vector_path}")
240
  except Exception as e:
241
- logger.error(f"Failed to create vector store: {e}")
242
- # Clean up temp file
243
- try:
244
- os.unlink(tmp_path)
245
- except:
246
- pass
247
  raise
248
 
249
  # Clean up temp file
 
2
  import logging
3
  import requests
4
  import tempfile
5
+ import uuid
6
  import torch
7
  from transformers import pipeline
8
  from faster_whisper import WhisperModel
 
10
  from langchain.text_splitter import RecursiveCharacterTextSplitter
11
  from langchain_openai import OpenAIEmbeddings
12
  from langchain_core.documents import Document
13
+ from supabase.client import create_client
14
+ try:
15
+ import av # Optional: used to pre-check audio streams for robustness
16
+ except Exception: # pragma: no cover
17
+ av = None
18
 
19
  from sqlalchemy import select
20
  from sqlalchemy.ext.asyncio import AsyncSession
 
31
 
32
  # Whisper Model Initialization
33
  def get_whisper_model():
34
+ # Allow overrides via env vars
35
+ env_device = os.getenv("FASTER_WHISPER_DEVICE")
36
+ env_compute = os.getenv("FASTER_WHISPER_COMPUTE")
37
+
38
+ if env_device:
39
+ device = env_device
40
+ logger.info(f"Using device from env FASTER_WHISPER_DEVICE={env_device}")
41
+ else:
42
+ if torch.cuda.is_available():
43
+ device = "cuda"
44
+ logger.info("GPU detected: Using CUDA")
45
+ else:
46
+ device = "cpu"
47
+ logger.warning("GPU not available: Falling back to CPU")
48
+
49
+ if env_compute:
50
+ compute_type = env_compute
51
+ logger.info(f"Using compute_type from env FASTER_WHISPER_COMPUTE={env_compute}")
52
  else:
53
+ compute_type = "float32" if device == "cuda" else "int8"
 
 
54
 
55
  try:
56
  model = WhisperModel("base", device=device, compute_type=compute_type)
 
62
 
63
  whisper_model = get_whisper_model()
64
 
65
+ # Supabase Initialization
66
+ supabase_url = os.getenv("SUPABASE_URL")
67
+ supabase_key = os.getenv("SUPABASE_KEY")
68
+
69
+ if not supabase_url or not supabase_key:
70
+ logger.error("❌ SUPABASE_URL or SUPABASE_KEY is not set in the environment.")
71
+ raise RuntimeError("SUPABASE_URL and SUPABASE_KEY must be set in .env or environment variables.")
72
+
73
+ try:
74
+ supabase_client = create_client(supabase_url, supabase_key)
75
+ logger.info("✅ Supabase client initialized successfully.")
76
+ except Exception as e:
77
+ logger.exception("❌ Failed to initialize Supabase client.")
78
+ raise
79
+
80
  # Summarizer
81
  try:
82
  summarizer = pipeline("summarization", model="facebook/bart-large-cnn")
 
184
 
185
  # Step 2: Transcribe
186
  try:
187
+ # Optional pre-check: ensure the file has an audio stream
188
+ if av is not None:
189
+ try:
190
+ with av.open(tmp_path) as container:
191
+ has_audio = any(s.type == "audio" for s in container.streams)
192
+ if not has_audio:
193
+ logger.error("No valid audio stream in file; skipping transcription")
194
+ raise IndexError("No audio stream")
195
+ except IndexError:
196
+ raise
197
+ except Exception:
198
+ # If PyAV check fails, continue and let transcribe attempt
199
+ pass
200
+
201
  logger.info("Transcribing audio with Faster-Whisper...")
202
+
203
  # Get transcription result
204
  result = whisper_model.transcribe(tmp_path)
205
+
206
  # Handle different return formats from faster-whisper
207
  if isinstance(result, tuple):
208
  segments, info = result
209
  else:
 
210
  segments = result
211
  info = None
212
+
213
  # Extract text from segments
214
  if segments:
215
  text = " ".join(segment.text for segment in segments if hasattr(segment, 'text') and segment.text)
216
  else:
217
  text = ""
218
+
219
  logger.info(f"Transcription completed. Length: {len(text)} characters.")
220
+
221
  # Log additional info if available
222
  if info:
223
  logger.info(f"Transcription info: language={getattr(info, 'language', 'unknown')}, language_probability={getattr(info, 'language_probability', 'unknown')}")
224
+
225
  # Handle empty transcription
226
  if not text or len(text.strip()) == 0:
227
  logger.warning("Transcription resulted in empty text, using fallback")
228
  text = "No speech detected in video"
229
+
230
+ except IndexError:
231
+ logger.error("No valid audio stream in file; skipping transcription")
232
+ text = "Transcription failed - video may be corrupted or have no audio"
233
  except Exception as e:
234
  logger.error(f"Transcription failed: {e}")
235
  logger.error(f"Error type: {type(e)}")
236
  import traceback
237
  logger.error(f"Traceback: {traceback.format_exc()}")
 
238
  # Provide fallback text instead of failing completely
239
  logger.warning("Using fallback text due to transcription failure")
240
  text = "Transcription failed - video may be corrupted or have no audio"
241
+ finally:
242
+ # Always attempt to clean up temp file
243
  try:
244
  os.unlink(tmp_path)
245
+ except Exception:
246
  pass
247
 
248
  # Step 3: Summarize
 
264
  except:
265
  pass
266
 
267
+ # Step 4: Save to Supabase vector store (explicit user_id)
268
  try:
269
+ logger.info("Saving summary to Supabase vector store for user...")
270
+ if not summary or not summary.strip():
271
+ logger.warning("Empty summary; skipping Supabase insert")
 
 
 
 
 
 
 
 
 
272
  else:
273
+ embeddings = OpenAIEmbeddings()
274
+ embedding_vector = embeddings.embed_query(summary)
275
+
276
+ document_id = str(uuid.uuid4())
277
+ payload = {
278
+ "id": document_id,
279
+ "user_id": user_id,
280
+ "content": summary,
281
+ "embedding": embedding_vector,
282
+ "metadata": {"user_id": user_id, "video_url": video_url},
283
+ }
284
+ supabase_client.table("documents").insert(payload).execute()
285
+ logger.info(f"Summary saved to Supabase for user: {user_id}")
286
 
 
 
287
  except Exception as e:
288
+ logger.error(f"Failed to save to Supabase vector store: {e}")
 
 
 
 
 
289
  raise
290
 
291
  # Clean up temp file
requirements-hf.txt CHANGED
@@ -3,7 +3,7 @@ fastapi==0.104.1
3
  uvicorn[standard]==0.24.0
4
  python-dotenv==1.0.0
5
  python-multipart==0.0.6
6
- pydantic[email]==2.5.0
7
 
8
  # Database
9
  asyncpg==0.29.0
@@ -23,7 +23,7 @@ langchain-groq==0.0.1
23
 
24
  # Embedding & vector DB
25
  sentence-transformers==2.2.2
26
- faiss-cpu==1.7.4
27
 
28
  # Transcription
29
  faster-whisper==1.0.1
 
3
  uvicorn[standard]==0.24.0
4
  python-dotenv==1.0.0
5
  python-multipart==0.0.6
6
+ pydantic[email]==2.11.7
7
 
8
  # Database
9
  asyncpg==0.29.0
 
23
 
24
  # Embedding & vector DB
25
  sentence-transformers==2.2.2
26
+ supabase==2.18.1
27
 
28
  # Transcription
29
  faster-whisper==1.0.1
requirements-old.txt ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ # Tools & Transcription
4
+ transformers
5
+ whisper
6
+ faster-whisper==1.0.1
7
+ ctranslate2>=4.6.0
8
+ PyPDF2
9
+ pypdf
10
+ reportlab
11
+ bs4
12
+ beautifulsoup4
13
+
14
+ # Enhanced Analysis & MCP/ACP
15
+ opencv-python
16
+ pillow
17
+ duckduckgo-search
18
+ wikipedia-api
19
+ easyocr
20
+ langchain-groq
21
+ timm
22
+
23
+ # Optional
24
+ sse-starlette
25
+ wikipedia
26
+ arxiv
27
+ cassio
28
+ streamlit
29
+ supabase
30
+ # CUDA-enabled Torch (installed separately)
31
+ # torch==2.2.2+cu121 and torchvision==0.17.2+cu121
32
+ # Must be installed via pip with specific index:
33
+ # pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
requirements-windows.txt ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Windows-compatible requirements file
2
+ # This avoids compilation issues by using pre-compiled packages
3
+
4
+ # Core FastAPI dependencies
5
+ fastapi==0.104.1
6
+ uvicorn[standard]==0.24.0
7
+ python-dotenv==1.0.0
8
+ python-multipart==0.0.6
9
+ pydantic[email]==2.11.7
10
+ requests==2.31.0
11
+ boto3==1.34.0
12
+
13
+ # Database
14
+ asyncpg==0.29.0
15
+ sqlalchemy==2.0.23
16
+ aiosqlite==0.19.0
17
+ databases
18
+ psycopg2-binary
19
+
20
+ # Auth
21
+ passlib[bcrypt]==1.7.4
22
+ python-jose[cryptography]==3.3.0
23
+
24
+ # LLM & RAG - using compatible versions
25
+ langchain==0.1.13
26
+ langchain-openai==0.1.7
27
+ langchain-community==0.0.38
28
+ langchain-core==0.1.53
29
+ langchain-groq==0.0.1
30
+ langchainhub
31
+ langserve
32
+ langchain-objectbox
33
+
34
+ # Embedding & vector DB
35
+ sentence-transformers==2.2.2
36
+ supabase==2.18.1
37
+ chromadb
38
+
39
+ # Transcription - using latest compatible versions
40
+ faster-whisper==1.0.1
41
+ ctranslate2>=4.6.0
42
+ transformers==4.35.2
43
+ whisper
44
+
45
+ # PDF & Reports
46
+ PyPDF2==3.0.1
47
+ reportlab==4.0.7
48
+ beautifulsoup4==4.12.2
49
+ bs4
50
+ pypdf
51
+
52
+ # Enhanced Analysis
53
+ duckduckgo-search==4.1.1
54
+ wikipedia-api==0.6.0
55
+ timm==0.9.12
56
+ opencv-python
57
+ pillow
58
+ easyocr
59
+
60
+ # Optional
61
+ sse-starlette
62
+ wikipedia
63
+ arxiv
64
+ cassio
65
+ streamlit
66
+
67
+ # Pre-compiled numpy and scipy to avoid compilation
68
+ numpy>=1.24.0,<2.0
69
+ scipy>=1.10.0
70
+
71
+ # CUDA-enabled Torch (install separately if needed)
72
+ # pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
73
+
requirements.txt CHANGED
@@ -1,66 +1,68 @@
1
- # Core
2
- fastapi
3
- uvicorn
4
- boto3
5
- requests
6
- python-dotenv
7
- python-multipart
8
- pydantic[email]>=1.10,<2.0 # V1 for compatibility with many frameworks
9
 
10
- # DB
 
 
 
 
 
 
 
 
 
11
  asyncpg
12
- sqlalchemy>=2.0
13
  databases
14
  psycopg2-binary
15
- aiosqlite
16
 
17
  # Auth
18
- passlib[bcrypt]
19
- python-jose[cryptography]
20
 
21
  # LLM & RAG
22
  langchain==0.1.13
23
  langchain-openai==0.1.7
24
  langchain-community==0.0.38
25
  langchain-core==0.1.53
26
- langchain-groq
27
  langchainhub
28
  langserve
29
  langchain-objectbox
30
 
31
  # Embedding & vector DB
32
  sentence-transformers==2.2.2
33
- faiss-cpu
34
  chromadb
35
 
36
- # Tools & Transcription
37
- transformers
38
- whisper
39
  faster-whisper==1.0.1
40
- ctranslate2>=4.0,<5
41
- PyPDF2
42
- pypdf
43
- reportlab
44
- bs4
45
- beautifulsoup4
46
 
47
- # Enhanced Analysis & MCP/ACP
48
- opencv-python
49
- pillow
50
- duckduckgo-search
51
- wikipedia-api
52
- easyocr
53
- langchain-groq
54
- timm
 
 
 
 
 
 
55
 
56
  # Optional
 
57
  sse-starlette
58
  wikipedia
59
  arxiv
60
  cassio
61
  streamlit
62
-
63
  # CUDA-enabled Torch (installed separately)
64
  # torch==2.2.2+cu121 and torchvision==0.17.2+cu121
65
  # Must be installed via pip with specific index:
66
- # pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
 
1
+ # Merged requirements from requirements.txt and requirements-hf.txt
 
 
 
 
 
 
 
2
 
3
+ # Core FastAPI dependencies
4
+ fastapi==0.104.1
5
+ uvicorn[standard]==0.24.0
6
+ python-dotenv==1.0.0
7
+ python-multipart==0.0.6
8
+ pydantic[email]==2.11.7
9
+ requests==2.31.0
10
+ boto3==1.34.0
11
+
12
+ # Database
13
  asyncpg
14
+ aiosqlite
15
  databases
16
  psycopg2-binary
 
17
 
18
  # Auth
19
+ passlib[bcrypt]==1.7.4
20
+ python-jose[cryptography]==3.3.0
21
 
22
  # LLM & RAG
23
  langchain==0.1.13
24
  langchain-openai==0.1.7
25
  langchain-community==0.0.38
26
  langchain-core==0.1.53
27
+ langchain-groq==0.0.1
28
  langchainhub
29
  langserve
30
  langchain-objectbox
31
 
32
  # Embedding & vector DB
33
  sentence-transformers==2.2.2
34
+ supabase==2.18.1
35
  chromadb
36
 
37
+ # Transcription
 
 
38
  faster-whisper==1.0.1
39
+ ctranslate2
40
+ transformers==4.35.2
41
+ whisper # from requirements.txt, not explicitly in hf
 
 
 
42
 
43
+ # PDF & Reports
44
+ PyPDF2==3.0.1
45
+ reportlab==4.0.7
46
+ beautifulsoup4==4.12.2
47
+ bs4 # from requirements.txt
48
+ pypdf # from requirements.txt
49
+
50
+ # Enhanced Analysis
51
+ duckduckgo-search==4.1.1
52
+ wikipedia-api==0.6.0
53
+ timm==0.9.12
54
+ opencv-python # from requirements.txt
55
+ pillow # from requirements.txt
56
+ easyocr # from requirements.txt
57
 
58
  # Optional
59
+ faiss-gpu
60
  sse-starlette
61
  wikipedia
62
  arxiv
63
  cassio
64
  streamlit
 
65
  # CUDA-enabled Torch (installed separately)
66
  # torch==2.2.2+cu121 and torchvision==0.17.2+cu121
67
  # Must be installed via pip with specific index:
68
+ # pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121
supervisord.conf ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [supervisord]
2
+ nodaemon=true
3
+ logfile=/dev/null
4
+ loglevel=info
5
+
6
+ [program:web]
7
+ command=uvicorn app.main:app --host 0.0.0.0 --port 7860 --workers 1
8
+ directory=/app
9
+ stdout_logfile=/dev/stdout
10
+ stdout_logfile_maxbytes=0
11
+ stderr_logfile=/dev/stderr
12
+ stderr_logfile_maxbytes=0
13
+ environment=PYTHONUNBUFFERED=1,PYTHONDONTWRITEBYTECODE=1
14
+
15
+ [program:worker]
16
+ command=python worker/daemon.py
17
+ directory=/app
18
+ stdout_logfile=/dev/stdout
19
+ stdout_logfile_maxbytes=0
20
+ stderr_logfile=/dev/stderr
21
+ stderr_logfile_maxbytes=0
22
+ environment=PYTHONUNBUFFERED=1,PYTHONDONTWRITEBYTECODE=1