Skip to content

Commit a0ccdbe

Browse files
committed
cutsom llm
1 parent da712f6 commit a0ccdbe

10 files changed

+150
-33
lines changed

app.py

Lines changed: 68 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import traceback
55
from flask import Flask, render_template, request, jsonify, send_file, Response
66
import openai
7+
from together import Together
78
from reportlab.lib.pagesizes import letter
89
from reportlab.lib import colors
910
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
@@ -23,8 +24,15 @@
2324
progress_queue = Queue()
2425

2526
OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')
27+
TOGETHER_API_KEY = os.getenv('TOGETHER_API_KEY')
28+
2629
if not OPENAI_API_KEY:
2730
raise ValueError("No OpenAI API key found. Please set the OPENAI_API_KEY environment variable.")
31+
if not TOGETHER_API_KEY:
32+
raise ValueError("No Together API key found. Please set the TOGETHER_API_KEY environment variable.")
33+
34+
# Initialize Together client
35+
together_client = Together(api_key=TOGETHER_API_KEY)
2836

2937
# Initialize SQLite database
3038
def init_db():
@@ -41,34 +49,71 @@ def init_db():
4149

4250
init_db()
4351

44-
async def generate_chunk(model, topic, current_word_count, language, is_new_chapter=False):
52+
async def generate_chunk(api, model, topic, current_word_count, language, is_new_chapter=False):
4553
if is_new_chapter:
46-
prompt = f"Write the beginning of a new chapter for a book about {topic} in {language}. This is around word {current_word_count} of the book. Start with a chapter title."
54+
prompt = f"Write a detailed chapter for a book about {topic} in {language}. This is around word {current_word_count} of the book. Start with a chapter title, then write at least 500 words of content."
4755
else:
48-
prompt = f"Continue writing a book about {topic} in {language}. This is around word {current_word_count} of the book. Make sure the narrative flows smoothly from the previous section."
56+
prompt = f"Continue writing a detailed book about {topic} in {language}. This is around word {current_word_count} of the book. Write at least 500 words, ensuring the narrative flows smoothly from the previous section."
4957

5058
try:
51-
async with aiohttp.ClientSession() as session:
52-
async with session.post(
53-
"https://api.openai.com/v1/chat/completions",
54-
headers={"Authorization": f"Bearer {OPENAI_API_KEY}"},
55-
json={
56-
"model": model,
57-
"messages": [
58-
{"role": "system", "content": f"You are an author writing a book in {language}. Format your response as a part of a book chapter."},
59-
{"role": "user", "content": prompt}
59+
if api == 'openai':
60+
async with aiohttp.ClientSession() as session:
61+
async with session.post(
62+
"https://api.openai.com/v1/chat/completions",
63+
headers={"Authorization": f"Bearer {OPENAI_API_KEY}"},
64+
json={
65+
"model": model,
66+
"messages": [
67+
{"role": "system", "content": f"You are an author writing a book in {language}. Format your response as a part of a book chapter."},
68+
{"role": "user", "content": prompt}
69+
],
70+
"max_tokens": 3000
71+
}
72+
) as response:
73+
result = await response.json()
74+
if 'choices' not in result or len(result['choices']) == 0:
75+
raise ValueError(f"Unexpected API response: {result}")
76+
return result['choices'][0]['message']['content'].strip()
77+
elif api == 'together':
78+
response = together_client.chat.completions.create(
79+
model=model,
80+
messages=[
81+
{"role": "system", "content": f"You are an author writing a detailed book in {language}. Provide long, comprehensive responses with at least 500 words per chunk."},
82+
{"role": "user", "content": prompt}
83+
],
84+
max_tokens=2000,
85+
temperature=0.7,
86+
top_p=0.9,
87+
top_k=50,
88+
repetition_penalty=1.03,
89+
stop=None
90+
)
91+
generated_text = response.choices[0].message.content.strip()
92+
93+
# Ensure minimum word count
94+
while len(generated_text.split()) < 500:
95+
additional_prompt = f"Continue the previous text, adding more details and expanding the narrative. Write at least {500 - len(generated_text.split())} more words."
96+
additional_response = together_client.chat.completions.create(
97+
model=model,
98+
messages=[
99+
{"role": "system", "content": f"You are an author writing a detailed book in {language}. Provide long, comprehensive responses."},
100+
{"role": "user", "content": generated_text},
101+
{"role": "user", "content": additional_prompt}
60102
],
61-
"max_tokens": 3000
62-
}
63-
) as response:
64-
result = await response.json()
65-
if 'choices' not in result or len(result['choices']) == 0:
66-
raise ValueError(f"Unexpected API response: {result}")
67-
return result['choices'][0]['message']['content'].strip()
103+
max_tokens=1000,
104+
temperature=0.7,
105+
top_p=0.9,
106+
top_k=50,
107+
repetition_penalty=1.03,
108+
stop=None
109+
)
110+
generated_text += "\n" + additional_response.choices[0].message.content.strip()
111+
112+
return generated_text
68113
except Exception as e:
69114
print(f"An error occurred: {e}")
70115
await asyncio.sleep(60)
71-
return await generate_chunk(model, topic, current_word_count, language, is_new_chapter)
116+
return await generate_chunk(api, model, topic, current_word_count, language, is_new_chapter)
72117

73118
def create_pdf(content, title, language):
74119
buffer = io.BytesIO()
@@ -130,6 +175,7 @@ def playground():
130175

131176
@app.route('/generate', methods=['POST'])
132177
async def generate_book():
178+
api = request.form['api'] # 'openai' or 'together'
133179
model = request.form['model']
134180
topic = request.form['topic']
135181
language = request.form['language']
@@ -144,9 +190,9 @@ async def generate_book():
144190

145191
if is_new_chapter:
146192
chapter_count += 1
147-
task = asyncio.create_task(generate_chunk(model, topic, current_word_count, language, is_new_chapter=True))
193+
task = asyncio.create_task(generate_chunk(api, model, topic, current_word_count, language, is_new_chapter=True))
148194
else:
149-
task = asyncio.create_task(generate_chunk(model, topic, current_word_count, language))
195+
task = asyncio.create_task(generate_chunk(api, model, topic, current_word_count, language))
150196

151197
tasks.append(task)
152198
current_word_count += 500 # Approximate word count per chunk

pdfs.db

0 Bytes
Binary file not shown.

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ aiohttp
66
PyGithub==1.55
77
python-dotenv
88
flask[async]
9+
together
910

1.67 KB
Binary file not shown.
10 KB
Binary file not shown.
5.84 KB
Binary file not shown.
5.66 KB
Binary file not shown.
8.58 KB
Binary file not shown.

templates/hello.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,5 +1123,32 @@ <h2>Stay Updated</h2>
11231123
content.style.display = 'block';
11241124
}, 500);
11251125
});
1126+
document.getElementById('api').addEventListener('change', function() {
1127+
const modelSelect = document.getElementById('model');
1128+
const selectedApi = this.value;
1129+
1130+
// Clear existing options
1131+
modelSelect.innerHTML = '';
1132+
1133+
if (selectedApi === 'openai') {
1134+
// Add OpenAI models
1135+
const openAiModels = ['gpt-4o-mini', 'gpt-3.5-turbo', 'gpt-4-turbo', 'gpt-4o-mini-2024-07-18'];
1136+
openAiModels.forEach(model => {
1137+
const option = document.createElement('option');
1138+
option.value = model;
1139+
option.textContent = model;
1140+
modelSelect.appendChild(option);
1141+
});
1142+
} else if (selectedApi === 'together') {
1143+
// Add Together models
1144+
const togetherModels = ['meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo'];
1145+
togetherModels.forEach(model => {
1146+
const option = document.createElement('option');
1147+
option.value = model;
1148+
option.textContent = model;
1149+
modelSelect.appendChild(option);
1150+
});
1151+
}
1152+
});
11261153
</script>
11271154
</html>

templates/index.html

Lines changed: 54 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,6 @@
9696
<div class="flex justify-between items-center mb-6 lg:mb-10">
9797
<img src="https://raw.githubusercontent.com/Adarshagupta/BookAI/main/logo.png" alt="BookAI Logo"
9898
class="w-12 h-10">
99-
<h1 class="text-2xl lg:text-2xl font-bold text-gray-800 text-center">AI Book <span
100-
class="text-primary">Generator</span></h1>
10199
<button id="profile-button" class="text-gray-600 hover:text-gray-800 mr-4">
102100
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
103101
stroke="currentColor">
@@ -116,16 +114,32 @@ <h1 class="text-2xl lg:text-2xl font-bold text-gray-800 text-center">AI Book <sp
116114
</button>
117115
</div>
118116
<form id="book-form" class="space-y-4 lg:space-y-6 flex-grow">
117+
<div class="transition-all duration-300 hover:transform hover:scale-105">
118+
<label for="api" class="block mb-2 text-sm font-medium text-gray-700">API</label>
119+
<select id="api" name="api" required
120+
class="w-full p-3 text-sm text-gray-700 bg-gray-50 rounded-xl border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent transition-all duration-300">
121+
<option value="together">BookAI LLM (Fastest)</option>
122+
<option value="openai">OpenAI</option>
123+
</select>
124+
</div>
125+
119126
<div class="transition-all duration-300 hover:transform hover:scale-105">
120127
<label for="model" class="block mb-2 text-sm font-medium text-gray-700">Model</label>
121128
<select id="model" name="model" required
122129
class="w-full p-3 text-sm text-gray-700 bg-gray-50 rounded-xl border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent transition-all duration-300">
123-
<option value="gpt-4o-mini">GPT-4o Mini</option>
124-
<option value="gpt-3.5-turbo">GPT-3.5 Turbo</option>
125-
<option value="gpt-4-turbo">GPT-4-turbo</oSption>
126-
<option value="gpt-4o-mini-2024-07-18">GPT-4o Mini (2024-07-18)</option>
130+
<optgroup label="OpenAI Models" id="openai-models">
131+
<option value="gpt-4o-mini">GPT-4o Mini</option>
132+
<option value="gpt-3.5-turbo">GPT-3.5 Turbo</option>
133+
<option value="gpt-4-turbo">GPT-4-turbo</option>
134+
<option value="gpt-4o-mini-2024-07-18">GPT-4o Mini (2024-07-18)</option>
135+
</optgroup>
136+
<optgroup label="Together Models" id="together-models">
137+
<option value="meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo">BookAI-8B-Instruct-Turbo</option>
138+
<option value="meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo">BookAI-70B-Instruct-Turbo</option>
139+
</optgroup>
127140
</select>
128141
</div>
142+
129143
<div class="transition-all duration-300 hover:transform hover:scale-105">
130144
<label for="language" class="block mb-2 text-sm font-medium text-gray-700">Language</label>
131145
<select id="language" name="language" required
@@ -135,25 +149,26 @@ <h1 class="text-2xl lg:text-2xl font-bold text-gray-800 text-center">AI Book <sp
135149
<option value="spanish">Spanish</option>
136150
</select>
137151
</div>
138-
152+
139153
<div class="transition-all duration-300 hover:transform hover:scale-105">
140154
<label for="topic" class="block mb-2 text-sm font-medium text-gray-700">Book Topic</label>
141155
<input type="text" id="topic" name="topic" required
142156
class="w-full p-3 text-sm text-gray-700 bg-gray-50 rounded-xl border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent transition-all duration-300"
143157
placeholder="Enter your book topic...">
144158
</div>
159+
145160
<div class="transition-all duration-300 hover:transform hover:scale-105">
146-
<label for="word_count" class="block mb-2 text-sm font-medium text-gray-700">Target Word
147-
Count</label>
161+
<label for="word_count" class="block mb-2 text-sm font-medium text-gray-700">Target Word Count</label>
148162
<input type="number" id="word_count" name="word_count" value="10" required
149163
class="w-full p-3 text-sm text-gray-700 bg-gray-50 rounded-xl border border-gray-300 focus:ring-2 focus:ring-primary focus:border-transparent transition-all duration-300">
150164
</div>
151-
165+
152166
<button type="submit" id="generate-book"
153-
class="w-full bg-indigo-950 text-white py-3 rounded-xl hover:bg-indigo-950 -700 transition-all duration-300 font-medium transform hover:scale-105 hover:shadow-lg">
167+
class="w-full bg-indigo-950 text-white py-3 rounded-xl hover:bg-indigo-950-700 transition-all duration-300 font-medium transform hover:scale-105 hover:shadow-lg">
154168
Generate Book
155169
</button>
156170
</form>
171+
157172
<div id="progress" class="mt-4 lg:mt-6 text-gray-600 text-center text-sm"></div>
158173
<div id="error-message"
159174
class="mt-4 lg:mt-6 p-4 bg-red-100 text-red-700 rounded-xl text-center font-medium text-sm hidden">
@@ -1302,7 +1317,35 @@ <h3 class="text-lg font-semibold">ChatGPT</h3>
13021317
camera.updateProjectionMatrix();
13031318
renderer.setSize(window.innerWidth, window.innerHeight);
13041319
});
1320+
13051321
</script>
1322+
<script>
1323+
document.addEventListener('DOMContentLoaded', function() {
1324+
const apiSelect = document.getElementById('api');
1325+
const modelSelect = document.getElementById('model');
1326+
const openaiModels = document.getElementById('openai-models');
1327+
const togetherModels = document.getElementById('together-models');
1328+
1329+
function updateModelOptions() {
1330+
const selectedAPI = apiSelect.value;
1331+
1332+
if (selectedAPI === 'openai') {
1333+
openaiModels.style.display = '';
1334+
togetherModels.style.display = 'none';
1335+
modelSelect.value = openaiModels.querySelector('option').value;
1336+
} else if (selectedAPI === 'together') {
1337+
openaiModels.style.display = 'none';
1338+
togetherModels.style.display = '';
1339+
modelSelect.value = togetherModels.querySelector('option').value;
1340+
}
1341+
}
1342+
1343+
apiSelect.addEventListener('change', updateModelOptions);
1344+
1345+
// Initial call to set the correct options
1346+
updateModelOptions();
1347+
});
1348+
</script>
13061349
</body>
13071350

13081351
</html>

0 commit comments

Comments
 (0)