navalnica commited on
Commit
69c0ff1
·
0 Parent(s):

first commit

Browse files
Files changed (7) hide show
  1. .gitignore +3 -0
  2. data/11labs_tts_voices.csv +0 -0
  3. data/samples_to_split.py +53 -0
  4. pg.ipynb +164 -0
  5. prompts.py +61 -0
  6. requirements.txt +9 -0
  7. 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