Spaces:
Running
Running
navalnica
commited on
Commit
·
69c0ff1
0
Parent(s):
first commit
Browse files- .gitignore +3 -0
- data/11labs_tts_voices.csv +0 -0
- data/samples_to_split.py +53 -0
- pg.ipynb +164 -0
- prompts.py +61 -0
- requirements.txt +9 -0
- utils.py +49 -0
.gitignore
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
__pycache__
|
2 |
+
data/books
|
3 |
+
.env
|
data/11labs_tts_voices.csv
ADDED
The diff for this file is too large to render.
See raw diff
|
|
data/samples_to_split.py
ADDED
@@ -0,0 +1,53 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
GATSBY_1 = """\
|
2 |
+
“Gatz is my name.”
|
3 |
+
|
4 |
+
“—Mr. Gatz. I thought you might want to take the body West.”
|
5 |
+
|
6 |
+
He shook his head.
|
7 |
+
|
8 |
+
“Jimmy always liked it better down East. He rose up to his position in
|
9 |
+
the East. Were you a friend of my boy’s, Mr.—?”
|
10 |
+
|
11 |
+
“We were close friends.”
|
12 |
+
|
13 |
+
“He had a big future before him, you know. He was only a young man,
|
14 |
+
but he had a lot of brain power here.”
|
15 |
+
|
16 |
+
He touched his head impressively, and I nodded.
|
17 |
+
|
18 |
+
“If he’d of lived, he’d of been a great man. A man like James J.
|
19 |
+
Hill. He’d of helped build up the country.”
|
20 |
+
|
21 |
+
“That’s true,” I said, uncomfortably.
|
22 |
+
|
23 |
+
He fumbled at the embroidered coverlet, trying to take it from the
|
24 |
+
bed, and lay down stiffly—was instantly asleep.
|
25 |
+
"""
|
26 |
+
|
27 |
+
GATSBY_2 = """\
|
28 |
+
“If you’ll get up.”
|
29 |
+
|
30 |
+
“I will. Good night, Mr. Carraway. See you anon.”
|
31 |
+
|
32 |
+
“Of course you will,” confirmed Daisy. “In fact I think I’ll arrange a
|
33 |
+
marriage. Come over often, Nick, and I’ll sort of—oh—fling you
|
34 |
+
together. You know—lock you up accidentally in linen closets and push
|
35 |
+
you out to sea in a boat, and all that sort of thing—”
|
36 |
+
|
37 |
+
“Good night,” called Miss Baker from the stairs. “I haven’t heard a
|
38 |
+
word.”
|
39 |
+
|
40 |
+
“She’s a nice girl,” said Tom after a moment. “They oughtn’t to let
|
41 |
+
her run around the country this way.”
|
42 |
+
|
43 |
+
“Who oughtn’t to?” inquired Daisy coldly.
|
44 |
+
|
45 |
+
“Her family.”
|
46 |
+
|
47 |
+
“Her family is one aunt about a thousand years old. Besides, Nick’s
|
48 |
+
going to look after her, aren’t you, Nick? She’s going to spend lots
|
49 |
+
of weekends out here this summer. I think the home influence will be
|
50 |
+
very good for her.”
|
51 |
+
|
52 |
+
Daisy and Tom looked at each other for a moment in silence.
|
53 |
+
"""
|
pg.ipynb
ADDED
@@ -0,0 +1,164 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"cells": [
|
3 |
+
{
|
4 |
+
"cell_type": "code",
|
5 |
+
"execution_count": 1,
|
6 |
+
"metadata": {},
|
7 |
+
"outputs": [],
|
8 |
+
"source": [
|
9 |
+
"%load_ext autoreload\n",
|
10 |
+
"%autoreload 2"
|
11 |
+
]
|
12 |
+
},
|
13 |
+
{
|
14 |
+
"cell_type": "code",
|
15 |
+
"execution_count": 2,
|
16 |
+
"metadata": {},
|
17 |
+
"outputs": [
|
18 |
+
{
|
19 |
+
"data": {
|
20 |
+
"text/plain": [
|
21 |
+
"True"
|
22 |
+
]
|
23 |
+
},
|
24 |
+
"execution_count": 2,
|
25 |
+
"metadata": {},
|
26 |
+
"output_type": "execute_result"
|
27 |
+
}
|
28 |
+
],
|
29 |
+
"source": [
|
30 |
+
"import os\n",
|
31 |
+
"\n",
|
32 |
+
"import dotenv\n",
|
33 |
+
"from httpx import Timeout\n",
|
34 |
+
"from langchain_core.prompts import (\n",
|
35 |
+
" ChatPromptTemplate,\n",
|
36 |
+
" SystemMessagePromptTemplate,\n",
|
37 |
+
" HumanMessagePromptTemplate,\n",
|
38 |
+
")\n",
|
39 |
+
"from langchain_openai import ChatOpenAI\n",
|
40 |
+
"from pydantic import BaseModel\n",
|
41 |
+
"from langchain_community.callbacks import get_openai_callback\n",
|
42 |
+
"\n",
|
43 |
+
"dotenv.load_dotenv()"
|
44 |
+
]
|
45 |
+
},
|
46 |
+
{
|
47 |
+
"cell_type": "code",
|
48 |
+
"execution_count": 3,
|
49 |
+
"metadata": {},
|
50 |
+
"outputs": [],
|
51 |
+
"source": [
|
52 |
+
"import data.samples_to_split as samples\n",
|
53 |
+
"from utils import GPTModels, create_split_text_chain"
|
54 |
+
]
|
55 |
+
},
|
56 |
+
{
|
57 |
+
"cell_type": "code",
|
58 |
+
"execution_count": 5,
|
59 |
+
"metadata": {},
|
60 |
+
"outputs": [
|
61 |
+
{
|
62 |
+
"name": "stdout",
|
63 |
+
"output_type": "stream",
|
64 |
+
"text": [
|
65 |
+
"characters: ['narrator', 'Mr. Carraway', 'Daisy', 'Miss Baker', 'Tom', 'Nick']\n",
|
66 |
+
"[narrator] “If you’ll get up.”\n",
|
67 |
+
"[Mr. Carraway] “I will. Good night, Mr. Carraway. See you anon.”\n",
|
68 |
+
"[Daisy] “Of course you will,” confirmed Daisy. “In fact I think I’ll arrange a marriage. Come over often, Nick, and I’ll sort of—oh—fling you together. You know—lock you up accidentally in linen closets and push you out to sea in a boat, and all that sort of thing—”\n",
|
69 |
+
"[Miss Baker] “Good night,” called Miss Baker from the stairs. “I haven’t heard a word.”\n",
|
70 |
+
"[Tom] “She’s a nice girl,” said Tom after a moment. “They oughtn’t to let her run around the country this way.”\n",
|
71 |
+
"[Daisy] “Who oughtn’t to?” inquired Daisy coldly.\n",
|
72 |
+
"[narrator] “Her family.”\n",
|
73 |
+
"[narrator] “Her family is one aunt about a thousand years old. Besides, Nick’s going to look after her, aren’t you, Nick? She’s going to spend lots of weekends out here this summer. I think the home influence will be very good for her.”\n",
|
74 |
+
"[narrator] Daisy and Tom looked at each other for a moment in silence.\n"
|
75 |
+
]
|
76 |
+
}
|
77 |
+
],
|
78 |
+
"source": [
|
79 |
+
"chain = create_split_text_chain(llm_model=GPTModels.GPT_4_TURBO_2024_04_09)\n",
|
80 |
+
"with get_openai_callback() as cb:\n",
|
81 |
+
" res = chain.invoke({'text': samples.GATSBY_2})\n",
|
82 |
+
"print(res.to_pretty_text())"
|
83 |
+
]
|
84 |
+
},
|
85 |
+
{
|
86 |
+
"cell_type": "code",
|
87 |
+
"execution_count": 6,
|
88 |
+
"metadata": {},
|
89 |
+
"outputs": [
|
90 |
+
{
|
91 |
+
"data": {
|
92 |
+
"text/plain": [
|
93 |
+
"Tokens Used: 1579\n",
|
94 |
+
"\tPrompt Tokens: 1253\n",
|
95 |
+
"\tCompletion Tokens: 326\n",
|
96 |
+
"Successful Requests: 1\n",
|
97 |
+
"Total Cost (USD): $0.02231"
|
98 |
+
]
|
99 |
+
},
|
100 |
+
"execution_count": 6,
|
101 |
+
"metadata": {},
|
102 |
+
"output_type": "execute_result"
|
103 |
+
}
|
104 |
+
],
|
105 |
+
"source": [
|
106 |
+
"cb"
|
107 |
+
]
|
108 |
+
},
|
109 |
+
{
|
110 |
+
"cell_type": "code",
|
111 |
+
"execution_count": 7,
|
112 |
+
"metadata": {},
|
113 |
+
"outputs": [
|
114 |
+
{
|
115 |
+
"name": "stdout",
|
116 |
+
"output_type": "stream",
|
117 |
+
"text": [
|
118 |
+
"characters: ['narrator', 'Mr. Carraway', 'Daisy', 'Miss Baker', 'Tom', 'Nick']\n",
|
119 |
+
"[narrator] “If you’ll get up.”\n",
|
120 |
+
"[Mr. Carraway] “I will. Good night, Mr. Carraway. See you anon.”\n",
|
121 |
+
"[Daisy] “Of course you will,” confirmed Daisy. “In fact I think I’ll arrange a marriage. Come over often, Nick, and I’ll sort of—oh—fling you together. You know—lock you up accidentally in linen closets and push you out to sea in a boat, and all that sort of thing—”\n",
|
122 |
+
"[Miss Baker] “Good night,” called Miss Baker from the stairs. “I haven’t heard a word.”\n",
|
123 |
+
"[Tom] “She’s a nice girl,” said Tom after a moment. “They oughtn’t to let her run around the country this way.”\n",
|
124 |
+
"[Daisy] “Who oughtn’t to?” inquired Daisy coldly.\n",
|
125 |
+
"[narrator] “Her family.”\n",
|
126 |
+
"[narrator] “Her family is one aunt about a thousand years old. Besides, Nick’s going to look after her, aren’t you, Nick? She’s going to spend lots of weekends out here this summer. I think the home influence will be very good for her.”\n",
|
127 |
+
"[narrator] Daisy and Tom looked at each other for a moment in silence.\n"
|
128 |
+
]
|
129 |
+
}
|
130 |
+
],
|
131 |
+
"source": [
|
132 |
+
"print(res.to_pretty_text())"
|
133 |
+
]
|
134 |
+
},
|
135 |
+
{
|
136 |
+
"cell_type": "code",
|
137 |
+
"execution_count": null,
|
138 |
+
"metadata": {},
|
139 |
+
"outputs": [],
|
140 |
+
"source": []
|
141 |
+
}
|
142 |
+
],
|
143 |
+
"metadata": {
|
144 |
+
"kernelspec": {
|
145 |
+
"display_name": "ai-audio-books",
|
146 |
+
"language": "python",
|
147 |
+
"name": "python3"
|
148 |
+
},
|
149 |
+
"language_info": {
|
150 |
+
"codemirror_mode": {
|
151 |
+
"name": "ipython",
|
152 |
+
"version": 3
|
153 |
+
},
|
154 |
+
"file_extension": ".py",
|
155 |
+
"mimetype": "text/x-python",
|
156 |
+
"name": "python",
|
157 |
+
"nbconvert_exporter": "python",
|
158 |
+
"pygments_lexer": "ipython3",
|
159 |
+
"version": "3.12.4"
|
160 |
+
}
|
161 |
+
},
|
162 |
+
"nbformat": 4,
|
163 |
+
"nbformat_minor": 2
|
164 |
+
}
|
prompts.py
ADDED
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class SplitTextPrompt:
|
2 |
+
SYSTEM = """\
|
3 |
+
You are a helpful assistant proficient in literature and language.
|
4 |
+
Imagine you are helping to prepare the provided text for narration to create the audio book.
|
5 |
+
We need to understand how many voice actors we need to hire and how to split the text between them.
|
6 |
+
|
7 |
+
Your task is to help with this process, namely:
|
8 |
+
1. Identify all book characters occuring in the text, including "narrator".
|
9 |
+
We will hire individual voice actor for each one of them.
|
10 |
+
2. Split the text provided by characters. Let's refer to each split as "part".
|
11 |
+
Order of parts MUST be the same as in the original text.
|
12 |
+
|
13 |
+
Details:
|
14 |
+
- First, analyze the whole text to extract the list of characters.
|
15 |
+
Put found characters to corresponding output field.
|
16 |
+
- Then, analyze the text top-down and as you proceed fill the "parts" field
|
17 |
+
- Each part must be attributed to a single character.
|
18 |
+
Character must belong to the "characters" list
|
19 |
+
- Use "narrator" character for any descriptive or narrative text,
|
20 |
+
such as actions ("He shook his head"), narrative parts ("I thought")
|
21 |
+
thoughts, or descriptions that aren't part of spoken dialogue
|
22 |
+
- In some books narrator is one of the main characters, having its own name and phrases.
|
23 |
+
In this case, use regualar character name instead of "narrator" role
|
24 |
+
- If it's impossible to identify character name from the text provided, use codes "c1", "c2", etc,
|
25 |
+
where "c" prefix means character and number is used to enumerate unknown characters
|
26 |
+
|
27 |
+
Format your answer as a following JSON:
|
28 |
+
{{
|
29 |
+
"characters": [list of unique character names that are found in the text provided],
|
30 |
+
"parts":
|
31 |
+
[
|
32 |
+
{{
|
33 |
+
"character": <character name>, "text": <the part's text>
|
34 |
+
}}
|
35 |
+
]
|
36 |
+
}}
|
37 |
+
|
38 |
+
Ensure the order of the parts in the JSON output matches the original order of the text.
|
39 |
+
|
40 |
+
Example of text split by characters, already in the target format.
|
41 |
+
{{
|
42 |
+
"characters": ["Mr. Gatz", "narrator"],
|
43 |
+
"parts":
|
44 |
+
[
|
45 |
+
{{"character": "Mr. Gatz", "text": "“Gatz is my name.”"}},
|
46 |
+
{{"character": "narrator", "text": "“—Mr. Gatz. I thought you might want to take the body West.” He shook his head."}},
|
47 |
+
{{"character": "Mr. Gatz", "text": "“Jimmy always liked it better down East. He rose up to his position in the East. Were you a friend of my boy’s, Mr.—?”"}},
|
48 |
+
{{"character": "narrator", "text": "“We were close friends.”"}},
|
49 |
+
{{"character": "Mr. Gatz", "text": "“He had a big future before him, you know. He was only a young man, but he had a lot of brain power here.”"}},
|
50 |
+
{{"character": "narrator", "text": "He touched his head impressively, and I nodded."}},
|
51 |
+
{{"character": "Mr. Gatz", "text": "“If he’d of lived, he’d of been a great man. A man like James J. Hill. He’d of helped build up the country.”"}},
|
52 |
+
{{"character": "narrator", "text": "“That’s true,” I said, uncomfortably."}},
|
53 |
+
{{"character": "Mr. Gatz", "text": "He fumbled at the embroidered coverlet, trying to take it from the bed, and lay down stiffly—was instantly asleep."}},
|
54 |
+
]
|
55 |
+
}}
|
56 |
+
"""
|
57 |
+
|
58 |
+
USER = """\
|
59 |
+
Here is the book sample:
|
60 |
+
---
|
61 |
+
{text}"""
|
requirements.txt
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
langchain
|
2 |
+
langchain-openai
|
3 |
+
langchain-community
|
4 |
+
jupyter
|
5 |
+
openai
|
6 |
+
elevenlabs
|
7 |
+
gradio
|
8 |
+
python-dotenv
|
9 |
+
streamlit
|
utils.py
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from enum import StrEnum
|
2 |
+
|
3 |
+
from httpx import Timeout
|
4 |
+
from langchain_core.prompts import (
|
5 |
+
ChatPromptTemplate,
|
6 |
+
HumanMessagePromptTemplate,
|
7 |
+
SystemMessagePromptTemplate,
|
8 |
+
)
|
9 |
+
from langchain_openai import ChatOpenAI
|
10 |
+
from pydantic import BaseModel
|
11 |
+
|
12 |
+
from prompts import SplitTextPrompt
|
13 |
+
|
14 |
+
|
15 |
+
class GPTModels(StrEnum):
|
16 |
+
GPT_4_TURBO_2024_04_09 = "gpt-4-turbo-2024-04-09"
|
17 |
+
GPT_4o_MINI = "gpt-4o-mini"
|
18 |
+
|
19 |
+
|
20 |
+
class TextPart(BaseModel):
|
21 |
+
character: str
|
22 |
+
text: str
|
23 |
+
|
24 |
+
|
25 |
+
class SplitTextOutput(BaseModel):
|
26 |
+
characters: list[str]
|
27 |
+
parts: list[TextPart]
|
28 |
+
|
29 |
+
def to_pretty_text(self):
|
30 |
+
lines = []
|
31 |
+
lines.append(f"characters: {self.characters}")
|
32 |
+
lines.extend(f"[{part.character}] {part.text}" for part in self.parts)
|
33 |
+
res = "\n".join(lines)
|
34 |
+
return res
|
35 |
+
|
36 |
+
|
37 |
+
def create_split_text_chain(llm_model: GPTModels):
|
38 |
+
llm = ChatOpenAI(model=llm_model, temperature=0.0, timeout=Timeout(60, connect=4))
|
39 |
+
llm = llm.with_structured_output(SplitTextOutput)
|
40 |
+
|
41 |
+
prompt = ChatPromptTemplate.from_messages(
|
42 |
+
[
|
43 |
+
SystemMessagePromptTemplate.from_template(SplitTextPrompt.SYSTEM),
|
44 |
+
HumanMessagePromptTemplate.from_template(SplitTextPrompt.USER),
|
45 |
+
]
|
46 |
+
)
|
47 |
+
|
48 |
+
chain = prompt | llm
|
49 |
+
return chain
|