Spaces:
Sleeping
Sleeping
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,177 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
from openai import OpenAI
|
3 |
+
import tiktoken
|
4 |
+
|
5 |
+
import nltk
|
6 |
+
nltk.download('punkt')
|
7 |
+
from nltk.tokenize import sent_tokenize
|
8 |
+
|
9 |
+
from pypdf import PdfReader, PageRange
|
10 |
+
|
11 |
+
## Function to read the uploaded PDF
|
12 |
+
def read_data_from_PDF(input_path):
|
13 |
+
input_text = ''
|
14 |
+
print ('Reading PDF from path', input_path)
|
15 |
+
reader = PdfReader(input_path)
|
16 |
+
number_of_pages = len(reader.pages)
|
17 |
+
print ('PDF has been read with ', number_of_pages, ' pages')
|
18 |
+
for page in reader.pages:
|
19 |
+
input_text += page.extract_text() + "\n"
|
20 |
+
return input_text
|
21 |
+
|
22 |
+
|
23 |
+
## Function to split the text into sentences
|
24 |
+
def split_text (input_text):
|
25 |
+
split_texts = sent_tokenize(input_text)
|
26 |
+
return split_texts
|
27 |
+
|
28 |
+
|
29 |
+
## Function to create chunks while considering sentences
|
30 |
+
def create_chunks(split_sents, max_token_len=50):
|
31 |
+
enc = tiktoken.encoding_for_model("gpt-4o-mini")
|
32 |
+
current_token_len = 0
|
33 |
+
input_chunks = []
|
34 |
+
current_chunk = ""
|
35 |
+
for sents in split_sents:
|
36 |
+
sent_token_len = len(enc.encode(sents))
|
37 |
+
if (current_token_len + sent_token_len) > max_token_len:
|
38 |
+
input_chunks.append(current_chunk)
|
39 |
+
current_chunk = ""
|
40 |
+
current_token_len = 0
|
41 |
+
current_chunk = current_chunk + sents
|
42 |
+
current_token_len = current_token_len + sent_token_len
|
43 |
+
if current_chunk != "":
|
44 |
+
input_chunks.append(current_chunk)
|
45 |
+
return input_chunks
|
46 |
+
|
47 |
+
|
48 |
+
## Function to create chunks
|
49 |
+
def create_input_chunks(input_text):
|
50 |
+
split_sents = split_text(input_text)
|
51 |
+
input_chunks = create_chunks(split_sents, max_token_len=3000)
|
52 |
+
return input_chunks
|
53 |
+
|
54 |
+
|
55 |
+
## Function to create summary of the given input text
|
56 |
+
def create_summary_points(input_chunks):
|
57 |
+
client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
|
58 |
+
instructPrompt = """
|
59 |
+
You are provided with a piece of text regarding a subject. Please identify the key facts and highlights about this piece of text.
|
60 |
+
Please provide the output in the form of a list something like -
|
61 |
+
|
62 |
+
- Highlight 1
|
63 |
+
- Highlight 2
|
64 |
+
- Highlight 3
|
65 |
+
"""
|
66 |
+
podcastFacts = []
|
67 |
+
for text in input_chunks:
|
68 |
+
request = instructPrompt + '\n' + text
|
69 |
+
chatOutput = client.chat.completions.create(model="gpt-4o-mini",
|
70 |
+
messages=[{"role": "system", "content": "You are a helpful assistant."},
|
71 |
+
{"role": "user", "content": request}
|
72 |
+
]
|
73 |
+
)
|
74 |
+
podcastFacts.append(chatOutput.choices[0].message.content)
|
75 |
+
return "\n".join(podcastFacts)
|
76 |
+
|
77 |
+
|
78 |
+
## Two different prompt styles for the podcast conversation
|
79 |
+
debate_podcast_prompt = """
|
80 |
+
Could you simulate a podcast conversation in a debate-style between two experts, \"Sid\" and \"Darren\", discussing the following key points extracted from a research paper?
|
81 |
+
Some things that you need to keep in mind while creating the conversation:
|
82 |
+
- In the debate, Sid takes a stance that has a positive view of the findings and supports the implications and findings represented by these key points. They provide their reasoning and analogical examples to back up their interpretations.
|
83 |
+
- Conversely, Darren adopts a more critical or alternative viewpoint. They question some of the findings by discussing potential drawbacks, limitations, or different outcomes.
|
84 |
+
- The conversation should see both experts engaging with each key point, presenting their views, challenging each other's interpretations, and discussing the broader implications of their arguments.
|
85 |
+
- The debate should be balanced, allowing each expert to articulate their perspective comprehensively.
|
86 |
+
- Conclude the conversation with each expert summarizing their overall position on the topic.
|
87 |
+
Here's some of the facts from the topic.
|
88 |
+
"""
|
89 |
+
|
90 |
+
casual_podcast_prompt = """
|
91 |
+
Could you simulate a podcast conversation between \"Sid\" and \"Darren\" having a conversation about the following facts?
|
92 |
+
Some things I'd like to ask:
|
93 |
+
- Use \"Sid:\" and \"Darren:\" to indicate who is speaking.
|
94 |
+
- Start the dialog with a casual discussion on what each person is drinking right now.
|
95 |
+
- Make the dialog about this as long as possible and make it sound funny
|
96 |
+
- Sid is the one presenting the information, Darren is asking intelligent questions that help Sid elaborate the facts.
|
97 |
+
Here's some of the facts from the topic.
|
98 |
+
"""
|
99 |
+
|
100 |
+
styles = {'casual':casual_podcast_prompt,
|
101 |
+
'debate': debate_podcast_prompt}
|
102 |
+
|
103 |
+
|
104 |
+
## Function to create the podcast script
|
105 |
+
def create_podcast_script(podcast_points, output_style):
|
106 |
+
client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
|
107 |
+
instructPrompt = styles[output_style]
|
108 |
+
request = instructPrompt + '\n' + podcast_points
|
109 |
+
chatOutput = client.chat.completions.create(model="gpt-4o-mini",
|
110 |
+
messages=[{"role": "system", "content": "You are a helpful assistant."},
|
111 |
+
{"role": "user", "content": request}
|
112 |
+
]
|
113 |
+
)
|
114 |
+
return chatOutput.choices[0].message.content
|
115 |
+
|
116 |
+
|
117 |
+
## Function to call all the podcast script generation steps
|
118 |
+
def create_podcast(input_path, output_style):
|
119 |
+
input_text = read_data_from_PDF(input_path)
|
120 |
+
input_chunks = create_input_chunks(input_text)
|
121 |
+
podcastHighlights = create_summary_points(input_chunks)
|
122 |
+
podcastScript = create_podcast_script(podcastHighlights, output_style)
|
123 |
+
return podcastScript
|
124 |
+
|
125 |
+
|
126 |
+
## Function to generate speech from input text
|
127 |
+
def openai_generation(input_text, speaker_voice, model_choice="tts-1"):
|
128 |
+
client = OpenAI(api_key=userdata.get('OPENAI_API_KEY'))
|
129 |
+
response = client.audio.speech.create(
|
130 |
+
model=model_choice,
|
131 |
+
voice=speaker_voice,
|
132 |
+
input=input_text
|
133 |
+
)
|
134 |
+
return response.read()
|
135 |
+
|
136 |
+
|
137 |
+
## Function to generate complete audio podcast from script
|
138 |
+
## NOTE: this function assumes that there are only two speakers; please modify if you have multiple speakers in the script
|
139 |
+
def create_podcast_audio(podcastScript, speakerName1="Sid", speakerChoice1='onyx', speakerName2="Darren", speakerChoice2='echo'):
|
140 |
+
genPodcast = []
|
141 |
+
podcastLines = podcastScript.split('\n\n')
|
142 |
+
podcastLineNumber = 0
|
143 |
+
for line in podcastLines:
|
144 |
+
if podcastLineNumber % 2 == 0:
|
145 |
+
speakerChoice = speakerChoice1
|
146 |
+
line = line.replace(speakerName1+":", '')
|
147 |
+
else:
|
148 |
+
speakerChoice = speakerChoice2
|
149 |
+
line = line.replace(speakerName2+":", '')
|
150 |
+
genVoice = openai_generation(input_text=line, speaker_voice=speakerChoice, model_choice="tts-1")
|
151 |
+
genPodcast.append(genVoice)
|
152 |
+
podcastLineNumber += 1
|
153 |
+
with open("genPodcast.mp3", "wb") as f:
|
154 |
+
for pod in genPodcast:
|
155 |
+
f.write(pod)
|
156 |
+
return "genPodcast.mp3"
|
157 |
+
|
158 |
+
import gradio as gr
|
159 |
+
|
160 |
+
def upload_file(file):
|
161 |
+
return file.name
|
162 |
+
|
163 |
+
with gr.Blocks() as demo:
|
164 |
+
file_output = gr.File()
|
165 |
+
upload_button = gr.UploadButton("Click to Upload a PDF", file_types=[".pdf"], file_count="single")
|
166 |
+
upload_button.upload(upload_file, upload_button, file_output)
|
167 |
+
podcast_style = gr.Dropdown(styles.keys(), label="podcast_style")
|
168 |
+
generate_podcast_button = gr.Button("Generate Podcast Script")
|
169 |
+
podcast_script = gr.Textbox(interactive=True, label="podcast_script")
|
170 |
+
|
171 |
+
generate_podcast_button.click(fn=create_podcast, inputs=[file_output, podcast_style], outputs=podcast_script, api_name="generate_podcast_script")
|
172 |
+
|
173 |
+
generate_audio_button = gr.Button("Generate Audio Version")
|
174 |
+
podcast_audio = gr.Audio(label="podcast_audio", interactive=False, type="filepath")
|
175 |
+
generate_audio_button.click(fn=create_podcast_audio, inputs=podcast_script, outputs=podcast_audio, api_name="generate_podcast_audio")
|
176 |
+
|
177 |
+
demo.launch(debug=True, share=True)
|