-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshell.py
More file actions
169 lines (145 loc) · 6.07 KB
/
shell.py
File metadata and controls
169 lines (145 loc) · 6.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
import os
import cmd
import sys
import glob
import subprocess
from utils import logger, fetch_topic_data, generate_podcast_script, generate_audio_file, generate_audiobook, extract_content
from groq import Groq
def split_content_for_llm(content: str, max_tokens: int = 6000) -> list:
"""
Split content into smaller chunks to fit within the token limit.
"""
words = content.split()
chunk_size = max_tokens // 2
return [' '.join(words[i:i + chunk_size]) for i in range(0, len(words), chunk_size)]
class Whisper(cmd.Cmd):
"""
Command-line interface for WhisperCast.
"""
os.system('clear')
intro = "Welcome to WhisperCast! Type 'help' to list commands."
prompt = "\n(whisper) "
def __init__(self, completekey="tab", stdin=None, stdout=None):
super().__init__(completekey, stdin, stdout)
def do_podcast(self, arg: str) -> None:
"""
Generate a podcast based on the given topic.
"""
logger.info(f"Podcast generation started")
content = fetch_topic_data(arg)
content = generate_podcast_script(arg, content, 5)
generate_audio_file(content, arg.capitalize())
def do_audiobook(self, arg: str) -> None:
"""
Generate an audiobook from the given file.
"""
logger.info(f"Generating audiobook for '{arg}'")
content = extract_content(arg)
content = generate_audiobook(content)
generate_audio_file(content, "User_Audiobook")
def do_sensei(self, arg: str) -> None:
"""
Teach the user about a file and allow them to ask questions.
"""
if not arg.strip():
logger.error("No file provided. Please specify a file.")
print("Usage: sensei <file_path>")
return
file_path = arg.strip()
if not os.path.isfile(file_path):
logger.error(f"File not found: {file_path}")
print(f"File not found: {file_path}")
return
logger.info(f"Extracting content from file: {file_path}")
content = extract_content(file_path)
if not content:
logger.error("Failed to extract content from the file.")
print("Failed to extract content from the file.")
return
content_chunks = split_content_for_llm(content)
print("\nYou can now ask questions about the file. Type 'exit' to quit Sensei mode.")
while True:
question = input("\nYour question: ").strip()
if question.lower() == "exit":
print("Exiting Sensei mode.")
break
elif question.lower() == "clear":
os.system("clear")
try:
logger.info(f"Processing question: {question}")
client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
aggregated_answer = []
for i, chunk in enumerate(content_chunks):
prompt = f"""
You are an expert teacher. Based on the following content, answer the user's question:
Content:
\"\"\"{chunk}\"\"\"
Question:
\"\"\"{question}\"\"\"
Provide a clear and concise answer.
"""
response = client.chat.completions.create(
model="llama3-70b-8192",
messages=[{"role": "user", "content": prompt}],
temperature=0.7,
max_tokens=512
)
answer = response.choices[0].message.content.strip()
aggregated_answer.append(answer)
final_answer = "\n".join(aggregated_answer)
print(f"\nAnswer: {final_answer}")
except Exception as e:
logger.error(f"Error while answering question: {e}")
print("An error occurred while processing your question. Please try again.")
def do_clear(self, args: str) -> None:
"""
Clear the terminal screen.
"""
os.system('clear')
def do_ls(self, args: str) -> None:
"""
List all available audio files in the output directory.
"""
output_dir = "output"
if not os.path.exists(output_dir):
logger.warning("Output directory does not exist.")
return
audio_files = glob.glob(os.path.join(output_dir, "*.wav"))
if not audio_files:
logger.info("No audio files found in the output directory.")
return
print("\nAvailable audio files:")
for idx, file in enumerate(audio_files, start=1):
print(f"{idx}. {os.path.basename(file)}")
@logger.catch
def do_play(self, arg: str) -> None:
"""
Play an audio file by selecting its number from the ls command.
"""
try:
output_dir = "output"
audio_files = glob.glob(os.path.join(output_dir, "*.wav"))
if not audio_files:
logger.error("No audio files available to play.")
print("No audio files available. Use 'ls' to check.")
return
try:
file_index = int(arg) - 1
if file_index < 0 or file_index >= len(audio_files):
logger.error("Invalid file number selected.")
logger.info("Invalid file number. Use 'ls' to list available files.")
return
file_to_play = audio_files[file_index]
logger.info(f"Playing: {file_to_play}")
logger.info(f"Playing: {os.path.basename(file_to_play)}")
subprocess.run(["afplay", file_to_play])
except ValueError:
logger.error("Invalid input. Please provide a valid file number.")
except Exception as e:
logger.critical(f"Error while playing audio: {e}")
def do_bye(self, arg: str) -> None:
"""
Exit the WhisperCast CLI.
"""
logger.info("Shutting down whisper..\nDone")
sys.exit(0)