DrishtiSharma commited on
Commit
6b1586f
·
verified ·
1 Parent(s): 5de1a56

Create multilingual_word_limit_issue_fixed_v2.py

Browse files
lab/multilingual_word_limit_issue_fixed_v2.py ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from graph import EssayWriter, RouteQuery, GraphState
3
+ from crew import *
4
+ import os
5
+ import traceback
6
+ import base64
7
+
8
+ # Install Graphviz if not found
9
+ if os.system("which dot") != 0:
10
+ os.system("apt-get update && apt-get install -y graphviz")
11
+
12
+ st.markdown(
13
+ """
14
+ <h1 style="text-align: center; white-space: nowrap; font-size: 2.5em;">
15
+ Multi-Agent Essay Writing Assistant
16
+ </h1>
17
+ """,
18
+ unsafe_allow_html=True
19
+ )
20
+
21
+ # Ensure session state variables are initialized properly
22
+ if "messages" not in st.session_state:
23
+ st.session_state["messages"] = [{"role": "assistant", "content": "Hello! How can I assist you today?"}]
24
+
25
+ if "app" not in st.session_state:
26
+ st.session_state["app"] = None
27
+
28
+ if "chat_active" not in st.session_state:
29
+ st.session_state["chat_active"] = True
30
+
31
+ # Sidebar with essay settings and user-defined length
32
+ # Sidebar with essay settings and user-defined length
33
+ with st.sidebar:
34
+ st.subheader("About:")
35
+ st.info(
36
+ "\n\n 1. This app uses the 'gpt-4o-mini-2024-07-18' model."
37
+ "\n\n 2. Writing essays may take some time, approximately 1-2 minutes."
38
+ )
39
+
40
+ # API Key Retrieval
41
+ openai_key = st.secrets.get("OPENAI_API_KEY", "")
42
+
43
+ st.divider()
44
+
45
+ # User-defined essay length selection
46
+ st.subheader("📝 Configure Essay Settings:")
47
+ essay_length = st.number_input(
48
+ "Select Essay Length (words):",
49
+ min_value=150,
50
+ max_value=500,
51
+ value=250,
52
+ step=50
53
+ )
54
+
55
+ #st.divider()
56
+
57
+ #Language Selection
58
+ #st.subheader("🌍 Select Language:")
59
+ language_options = {
60
+ "Arabic (العربية)": "Arabic",
61
+ "Bengali (বাংলা)": "Bengali",
62
+ "Bulgarian (Български)": "Bulgarian",
63
+ "Chinese (中文, Simplified)": "Chinese (Simplified)",
64
+ "Chinese (繁體, Traditional)": "Chinese (Traditional)",
65
+ "Croatian (Hrvatski)": "Croatian",
66
+ "Czech (Čeština)": "Czech",
67
+ "Danish (Dansk)": "Danish",
68
+ "Dutch (Nederlands)": "Dutch",
69
+ "English": "English",
70
+ "Filipino (Tagalog)": "Filipino",
71
+ "Finnish (Suomi)": "Finnish",
72
+ "French (Français)": "French",
73
+ "German (Deutsch)": "German",
74
+ "Greek (Ελληνικά)": "Greek",
75
+ "Gujarati (ગુજરાતી)": "Gujarati",
76
+ "Hebrew (עברית)": "Hebrew",
77
+ "Hindi (हिन्दी)": "Hindi",
78
+ "Hungarian (Magyar)": "Hungarian",
79
+ "Indonesian (Bahasa Indonesia)": "Indonesian",
80
+ "Italian (Italiano)": "Italian",
81
+ "Japanese (日本語)": "Japanese",
82
+ "Korean (한국어)": "Korean",
83
+ "Malay (Bahasa Melayu)": "Malay",
84
+ "Malayalam (മലയാളം)": "Malayalam",
85
+ "Marathi (मराठी)": "Marathi",
86
+ "Nepali (नेपाली)": "Nepali",
87
+ "Norwegian (Norsk)": "Norwegian",
88
+ "Persian (فارسی)": "Persian",
89
+ "Polish (Polski)": "Polish",
90
+ "Portuguese (Português)": "Portuguese",
91
+ "Punjabi (ਪੰਜਾਬੀ)": "Punjabi",
92
+ "Romanian (Română)": "Romanian",
93
+ "Russian (Русский)": "Russian",
94
+ "Serbian (Српски)": "Serbian",
95
+ "Sinhala (සිංහල)": "Sinhala",
96
+ "Slovak (Slovenčina)": "Slovak",
97
+ "Spanish (Español)": "Spanish",
98
+ "Swahili (Kiswahili)": "Swahili",
99
+ "Swedish (Svenska)": "Swedish",
100
+ "Tamil (தமிழ்)": "Tamil",
101
+ "Telugu (తెలుగు)": "Telugu",
102
+ "Thai (ไทย)": "Thai",
103
+ "Turkish (Türkçe)": "Turkish",
104
+ "Ukrainian (Українська)": "Ukrainian",
105
+ "Urdu (اردو)": "Urdu",
106
+ "Vietnamese (Tiếng Việt)": "Vietnamese"
107
+ }
108
+
109
+ selected_language = st.selectbox("Choose Language:", sorted(language_options.keys()), index=list(language_options.keys()).index("English"))
110
+
111
+ st.divider()
112
+
113
+ # Reference section
114
+ st.subheader("📖 References:")
115
+ st.markdown(
116
+ "[1. Multi-Agent System with CrewAI and LangChain](https://discuss.streamlit.io/t/new-project-i-have-build-a-multi-agent-system-with-crewai-and-langchain/84002)",
117
+ unsafe_allow_html=True
118
+ )
119
+
120
+
121
+ # Initialize agents function
122
+ def initialize_agents():
123
+ if not openai_key:
124
+ st.error("⚠️ OpenAI API key is missing! Please provide a valid key through Hugging Face Secrets.")
125
+ st.session_state["chat_active"] = True
126
+ return None
127
+
128
+ os.environ["OPENAI_API_KEY"] = openai_key
129
+ try:
130
+ # Prevent re-initialization
131
+ if "app" in st.session_state and st.session_state["app"] is not None:
132
+ return st.session_state["app"]
133
+
134
+ # Initialize the full EssayWriter instance
135
+ essay_writer = EssayWriter() # Store the full instance
136
+ st.session_state["app"] = essay_writer # Now contains `graph`
137
+ st.session_state["chat_active"] = False # Enable chat after successful initialization
138
+
139
+ return essay_writer
140
+ except Exception as e:
141
+ st.error(f"❌ Error initializing agents: {e}")
142
+ st.session_state["chat_active"] = True
143
+ return None
144
+
145
+
146
+ # Automatically initialize agents on app load
147
+ if st.session_state["app"] is None:
148
+ st.session_state["app"] = initialize_agents()
149
+
150
+ if st.session_state["app"] is None:
151
+ st.error("⚠️ Failed to initialize agents. Please check your API key and restart the app.")
152
+
153
+ app = st.session_state["app"]
154
+
155
+ # Function to invoke the agent and generate a response
156
+ def generate_response(topic, length, selected_language):
157
+ if not app or not hasattr(app, "graph"):
158
+ st.error("⚠️ Agents are not initialized. Please check the system or restart the app.")
159
+ return {"response": "Error: Agents not initialized."}
160
+
161
+ # Define section allocations dynamically based on length
162
+ if length <= 300:
163
+ intro_limit = length // 5 # Shorter intro (~20% of total)
164
+ body_limit = length // 2 # 2-3 key sections only (~50% of total)
165
+ conclusion_limit = length // 5 # Brief closing (~20% of total)
166
+ num_sections = 2 # Fewer key points
167
+ elif length <= 400:
168
+ intro_limit = length // 6 # Slightly shorter intro (~17% of total)
169
+ body_limit = length // 1.8 # Allows more depth (~55% of total)
170
+ conclusion_limit = length // 6 # Balanced closing (~17% of total)
171
+ num_sections = 3 # More sections
172
+ else:
173
+ intro_limit = length // 7 # Even shorter intro (~15% of total)
174
+ body_limit = length // 1.7 # More depth in body (~60% of total)
175
+ conclusion_limit = length // 7 # Shorter but strong closing (~15% of total)
176
+ num_sections = 4 # Maximum sections for deeper discussion
177
+
178
+ # Adjusted structured prompt with language enforcement
179
+ refined_prompt = f"""
180
+ Write a well-structured, engaging, and informative essay on "{topic}" in **{selected_language}** with **EXACTLY {length} words**.
181
+ ### **Structure:**
182
+ - **Title**: A compelling, creative title (max 10 words).
183
+ - **Introduction** ({intro_limit} words max):
184
+ - Define the topic & its importance concisely.
185
+ - Provide a strong thesis statement.
186
+ - Briefly mention key themes.
187
+ - **Main Body** ({body_limit} words max):
188
+ - Cover **{num_sections} key aspects only**.
189
+ - Each section must have:
190
+ - A clear **subheading**.
191
+ - A **topic sentence** & supporting details.
192
+ - **Examples, statistics, or historical references** (if relevant).
193
+ - Ensure logical transitions between sections.
194
+ - **Conclusion** ({conclusion_limit} words max):
195
+ - Summarize key insights concisely.
196
+ - Reinforce thesis based on discussion.
197
+ - End with a **thought-provoking** final statement (question, reflection, or call to action).
198
+ ### **Important Rules:**
199
+ - 🚫 **DO NOT exceed {length} words**.
200
+ - ✅ **Avoid redundancy & filler sentences**.
201
+ - 🔄 **Merge similar ideas** to keep flow natural.
202
+ - ✂ **Use precise, impactful language**.
203
+ - 🎯 **Ensure balanced coverage** (not too broad or too specific).
204
+ - **STOP when {length} words are reached**.
205
+ - Write in **{selected_language}** ONLY.
206
+ """
207
+
208
+ # Invoke AI model with controlled word limit
209
+ response = app.graph.invoke(input={
210
+ "topic": topic,
211
+ "length": length,
212
+ "prompt": refined_prompt,
213
+ "max_tokens": length * 1.2 # Ensures generation doesn’t exceed limit
214
+ })
215
+
216
+ return response
217
+
218
+
219
+ # Define Tabs
220
+ tab1, tab2 = st.tabs(["📜 Essay Generation", "📊 Workflow Viz"])
221
+
222
+ # 📜 Tab 1: Essay Generation
223
+ with tab1:
224
+ # Display chat messages from the session
225
+ if "messages" not in st.session_state:
226
+ st.session_state["messages"] = [{"role": "assistant", "content": "Hello! How can I assist you today?"}]
227
+
228
+ for message in st.session_state["messages"]:
229
+ with st.chat_message(message["role"]):
230
+ st.markdown(message["content"], unsafe_allow_html=True)
231
+
232
+ # Input
233
+ topic = st.text_input("📝 Provide an essay topic:", value="Write an essay on the cultural diversity of India")
234
+
235
+ # Add spacing
236
+ st.write("")
237
+
238
+ # Generate button
239
+ if st.button("🚀 Generate Essay"):
240
+ if topic and topic.strip(): # Ensure it's not empty
241
+ # Store user message only if it's not already stored
242
+ if not any(msg["content"] == topic for msg in st.session_state["messages"]):
243
+ st.session_state["messages"].append({"role": "user", "content": topic})
244
+
245
+ with st.spinner("⏳ Generating your essay..."):
246
+ response = None
247
+ if app:
248
+ response = app.write_essay({"topic": topic})
249
+ else:
250
+ st.error("⚠️ Agents are not initialized. Please check the system or restart the app.")
251
+
252
+ # Store and display assistant response
253
+ if response and "essay" in response:
254
+ essay = response["essay"]
255
+
256
+ assistant_response = f"Here is your {essay_length}-word essay preview and the download link."
257
+ st.session_state["messages"].append({"role": "assistant", "content": assistant_response})
258
+
259
+ st.chat_message("assistant").markdown(assistant_response)
260
+
261
+ # Create Two-Column Layout
262
+ col1, col2 = st.columns(2)
263
+
264
+ with col1:
265
+ st.markdown(f"### 📝 Essay Preview ({essay_length} words)")
266
+ st.markdown(f"#### {essay['header']}")
267
+ st.markdown(essay["entry"])
268
+
269
+ for para in essay["paragraphs"]:
270
+ st.markdown(f"**{para['sub_header']}**")
271
+ st.markdown(para["paragraph"])
272
+
273
+ st.markdown("**🖊️ Conclusion:**")
274
+ st.markdown(essay["conclusion"])
275
+
276
+ with col2:
277
+ st.markdown("### ✍️ Edit Your Essay:")
278
+
279
+ # Combine all parts of the essay into one editable text field
280
+ full_essay_text = f"## {essay['header']}\n\n{essay['entry']}\n\n"
281
+ for para in essay["paragraphs"]:
282
+ full_essay_text += f"### {para['sub_header']}\n{para['paragraph']}\n\n"
283
+ full_essay_text += f"**Conclusion:**\n{essay['conclusion']}"
284
+
285
+ # Editable text area for the user
286
+ edited_essay = st.text_area("Edit Here:", value=full_essay_text, height=300)
287
+
288
+ # Save and Download buttons
289
+ save_col1, save_col2 = st.columns(2)
290
+
291
+ with save_col1:
292
+ if st.button("💾 Save as TXT"):
293
+ with open("edited_essay.txt", "w", encoding="utf-8") as file:
294
+ file.write(edited_essay)
295
+ with open("edited_essay.txt", "rb") as file:
296
+ st.download_button(label="⬇️ Download TXT", data=file, file_name="edited_essay.txt", mime="text/plain")
297
+
298
+ with save_col2:
299
+ if st.button("📄 Save as PDF"):
300
+ from fpdf import FPDF
301
+
302
+ pdf = FPDF()
303
+ pdf.set_auto_page_break(auto=True, margin=15)
304
+ pdf.add_page()
305
+ pdf.set_font("Arial", size=12)
306
+
307
+ for line in edited_essay.split("\n"):
308
+ pdf.cell(200, 10, txt=line, ln=True, align='L')
309
+
310
+ pdf.output("edited_essay.pdf")
311
+
312
+ with open("edited_essay.pdf", "rb") as file:
313
+ st.download_button(label="⬇️ Download PDF", data=file, file_name="edited_essay.pdf", mime="application/pdf")
314
+
315
+ # Provide download link for the original PDF
316
+ pdf_name = response.get("pdf_name")
317
+ if pdf_name and os.path.exists(pdf_name):
318
+ with open(pdf_name, "rb") as pdf_file:
319
+ b64 = base64.b64encode(pdf_file.read()).decode()
320
+ href = f"<a href='data:application/octet-stream;base64,{b64}' download='{pdf_name}'>📄 Click here to download the original PDF</a>"
321
+ st.markdown(href, unsafe_allow_html=True)
322
+
323
+ # Save response in session state
324
+ st.session_state["messages"].append(
325
+ {"role": "assistant", "content": f"Here is your {essay_length}-word essay preview and the download link."}
326
+ )
327
+ elif response:
328
+ st.markdown(response["response"])
329
+ st.session_state["messages"].append({"role": "assistant", "content": response["response"]})
330
+ else:
331
+ st.error("⚠️ No response received. Please try again.")
332
+
333
+
334
+
335
+ # 📊 Tab 2: Workflow Visualization
336
+ with tab2:
337
+ #st.subheader("📊 Multi-Agent Essay Writer Workflow Viz")
338
+
339
+ try:
340
+ graph_path = "/tmp/graph.png"
341
+ if os.path.exists(graph_path):
342
+ st.image(graph_path, caption="Multi-Agent Essay Writer Workflow Visualization", use_container_width=True)
343
+ else:
344
+ st.warning("⚠️ Workflow graph not found. Please run `graph.py` to regenerate `graph.png`.")
345
+
346
+ except Exception as e:
347
+ st.error("❌ An error occurred while generating the workflow visualization.")
348
+ st.text_area("Error Details:", traceback.format_exc(), height=500)
349
+
350
+
351
+ # Acknowledgement Section
352
+ st.markdown(
353
+ """
354
+ <div style="text-align: center; font-size: 14px; color: #555; padding-top: 200px; margin-top: 200px;">
355
+ <strong>Acknowledgement:</strong> This app is based on Mesut Duman's work:
356
+ <a href="https://github.com/mesutdmn/Autonomous-Multi-Agent-Systems-with-CrewAI-Essay-Writer/tree/main"
357
+ target="_blank" style="color: #007BFF; text-decoration: none;">
358
+ CrewAI Essay Writer
359
+ </a>
360
+ </div>
361
+ """,
362
+ unsafe_allow_html=True,
363
+ )