siddhartharyaai commited on
Commit
a91583a
·
verified ·
1 Parent(s): 8d7ff01

Update utils.py

Browse files
Files changed (1) hide show
  1. utils.py +38 -89
utils.py CHANGED
@@ -14,12 +14,7 @@ import numpy as np
14
  import torch
15
  import logging
16
 
17
- # Configure Logging
18
- logging.basicConfig(
19
- filename="debug.log",
20
- level=logging.DEBUG,
21
- format="%(asctime)s - %(levelname)s - %(message)s"
22
- )
23
 
24
  class DialogueItem(BaseModel):
25
  speaker: Literal["Jane", "John"]
@@ -39,109 +34,63 @@ def extract_text_from_url(url):
39
  try:
40
  response = requests.get(url, headers=headers)
41
  response.raise_for_status()
42
-
43
  soup = BeautifulSoup(response.text, 'html.parser')
44
  for script in soup(["script", "style"]):
45
  script.decompose()
46
-
47
- text = soup.get_text(separator=' ')
48
- return text.strip() if text else "No readable content extracted."
49
 
50
  except requests.exceptions.RequestException as e:
51
  logging.error(f"Error extracting text from URL: {str(e)}")
52
  return f"Failed to extract text from URL: {str(e)}"
53
 
54
- def generate_script(prompt, text, tone, length, host_name, guest_name, sponsor_style, sponsor_provided):
55
  """
56
- Calls the LLM to generate a structured podcast script from research text.
57
  """
58
- groq_client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
 
 
 
 
 
 
 
 
 
59
 
60
  try:
61
- logging.info("Calling LLM for script generation.")
62
- response = groq_client.chat.completions.create(
63
- messages=[
64
- {"role": "system", "content": prompt},
65
- {"role": "user", "content": text}
66
- ],
67
- model="DeepSeek-R1-Distill-Llama-70B",
68
- max_tokens=4096,
69
- temperature=0.6
70
- )
71
-
72
- if not response.choices or not response.choices[0].message.content:
73
- logging.error("LLM returned an empty response. Retrying with fallback prompt...")
74
- return Dialogue(dialogue=[DialogueItem(speaker="Jane", display_speaker="Jane", text="Sorry, no data available.")])
75
-
76
- script_content = response.choices[0].message.content.strip()
77
- dialogue_items = parse_script_to_dialogue(script_content, host_name, guest_name)
78
-
79
- if not dialogue_items:
80
- raise ValueError("Script parsing failed. No valid dialogue found.")
81
-
82
- return Dialogue(dialogue=dialogue_items)
83
 
84
  except Exception as e:
85
- logging.error(f"Failed to generate script: {str(e)}")
86
- return Dialogue(dialogue=[DialogueItem(speaker="Jane", display_speaker="Jane", text="I'm sorry, something went wrong.")])
87
-
88
- def truncate_text(text, max_tokens=2048):
89
- """
90
- Truncates input text to ensure it doesn't exceed token limits.
91
- """
92
- tokenizer = tiktoken.get_encoding("cl100k_base")
93
- tokens = tokenizer.encode(text)
94
-
95
- if len(tokens) > max_tokens:
96
- return tokenizer.decode(tokens[:max_tokens])
97
-
98
- return text
99
 
100
- def generate_audio_mp3(text, speaker):
101
  """
102
- Uses Groq's LLM to generate realistic text-to-speech (TTS) audio.
103
  """
104
- groq_client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
105
- response = groq_client.chat.completions.create(
106
- messages=[{"role": "system", "content": f"Generate a realistic voice for {speaker}: {text}"}],
107
- model="llama-3.3-70b-versatile",
108
- max_tokens=512,
109
- temperature=0.6
110
- )
111
 
112
- speech_text = response.choices[0].message.content.strip()
113
- temp_audio = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
 
 
 
114
 
115
  try:
116
- temp_audio.write(speech_text.encode('utf-8'))
117
- temp_audio.close()
118
-
119
- # ✅ Verify MP3 File Integrity Before Returning
120
- audio_test = AudioSegment.from_file(temp_audio.name, format="mp3")
121
- if len(audio_test) == 0:
122
- raise ValueError("Generated MP3 file is empty or corrupted.")
123
-
124
- return temp_audio.name
125
-
126
- except Exception as e:
127
- logging.error(f"Failed to generate MP3 file: {str(e)}")
128
 
129
- # ✅ Fallback: Generate a silent MP3 file to prevent ffmpeg crashes
130
- silent_audio = AudioSegment.silent(duration=2000) # 2 seconds of silence
131
- fallback_mp3 = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
132
- silent_audio.export(fallback_mp3.name, format="mp3")
133
- return fallback_mp3.name
134
-
135
- def research_topic(topic: str) -> str:
136
- """
137
- Uses Open Deep Researcher to fetch the latest web-based research.
138
- """
139
- from run_agents import run_deep_research_agent # Ensure Open Deep Researcher is connected.
140
 
141
- try:
142
- logging.info(f"Running Open Deep Researcher for topic: {topic}")
143
- research_result = run_deep_research_agent(topic)
144
- return research_result if research_result else f"No new information found for '{topic}'."
145
  except Exception as e:
146
- logging.error(f"Error during research: {str(e)}")
147
- return f"Error during research: {str(e)}"
 
14
  import torch
15
  import logging
16
 
17
+ logging.basicConfig(filename="debug.log", level=logging.DEBUG)
 
 
 
 
 
18
 
19
  class DialogueItem(BaseModel):
20
  speaker: Literal["Jane", "John"]
 
34
  try:
35
  response = requests.get(url, headers=headers)
36
  response.raise_for_status()
 
37
  soup = BeautifulSoup(response.text, 'html.parser')
38
  for script in soup(["script", "style"]):
39
  script.decompose()
40
+ return soup.get_text(separator=' ').strip()
 
 
41
 
42
  except requests.exceptions.RequestException as e:
43
  logging.error(f"Error extracting text from URL: {str(e)}")
44
  return f"Failed to extract text from URL: {str(e)}"
45
 
46
+ def transcribe_youtube_video(video_url):
47
  """
48
+ Uses yt-dlp to extract audio from a YouTube video and transcribe it.
49
  """
50
+ temp_audio_file = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
51
+ ydl_opts = {
52
+ 'format': 'bestaudio/best',
53
+ 'postprocessors': [{
54
+ 'key': 'FFmpegExtractAudio',
55
+ 'preferredcodec': 'mp3',
56
+ 'preferredquality': '192',
57
+ }],
58
+ 'outtmpl': temp_audio_file.name,
59
+ }
60
 
61
  try:
62
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
63
+ ydl.download([video_url])
64
+
65
+ return transcribe_audio(temp_audio_file.name)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  except Exception as e:
68
+ logging.error(f"Error downloading/transcribing YouTube video: {str(e)}")
69
+ return f"Error processing YouTube video: {str(e)}"
 
 
 
 
 
 
 
 
 
 
 
 
70
 
71
+ def transcribe_audio(file_path):
72
  """
73
+ Uses Deepgram API to transcribe audio.
74
  """
75
+ DEEPGRAM_API_KEY = os.environ.get("DEEPGRAM_API_KEY")
76
+ if not DEEPGRAM_API_KEY:
77
+ logging.error("Deepgram API key is missing.")
78
+ return "Deepgram API key is missing."
 
 
 
79
 
80
+ url = "https://api.deepgram.com/v1/listen?model=nova-2&smart_format=true"
81
+ headers = {
82
+ "Authorization": f"Token {DEEPGRAM_API_KEY}",
83
+ "Content-Type": "audio/mpeg"
84
+ }
85
 
86
  try:
87
+ with open(file_path, "rb") as f:
88
+ response = requests.post(url, headers=headers, data=f)
 
 
 
 
 
 
 
 
 
 
89
 
90
+ response.raise_for_status()
91
+ data = response.json()
92
+ return data["results"]["channels"][0]["alternatives"][0].get("transcript", "")
 
 
 
 
 
 
 
 
93
 
 
 
 
 
94
  except Exception as e:
95
+ logging.error(f"Error transcribing audio: {str(e)}")
96
+ return f"Error transcribing audio: {str(e)}"