Ashhar
commited on
Commit
•
e2d2e30
1
Parent(s):
be41821
button feature
Browse files- Kommuneity.png +0 -0
- app.py +105 -40
Kommuneity.png
CHANGED
app.py
CHANGED
@@ -2,6 +2,9 @@ import streamlit as st
|
|
2 |
import os
|
3 |
import datetime as DT
|
4 |
import pytz
|
|
|
|
|
|
|
5 |
from transformers import AutoTokenizer
|
6 |
|
7 |
from dotenv import load_dotenv
|
@@ -12,7 +15,10 @@ from groq import Groq
|
|
12 |
client = Groq(
|
13 |
api_key=os.environ.get("GROQ_API_KEY"),
|
14 |
)
|
|
|
15 |
MODEL = "llama-3.1-70b-versatile"
|
|
|
|
|
16 |
|
17 |
tokenizer = AutoTokenizer.from_pretrained("Xenova/Meta-Llama-3.1-Tokenizer")
|
18 |
|
@@ -24,9 +30,18 @@ def countTokens(text):
|
|
24 |
return len(tokens)
|
25 |
|
26 |
|
27 |
-
SYSTEM_MSG = """
|
28 |
You're an storytelling assistant who guides users through four phases of narrative development, helping them craft compelling personal or professional stories. The story created should be in simple language, yet evoke great emotions.
|
29 |
Ask one question at a time, give the options in a well formatted manner in different lines
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
# Tier 1: Story Creation
|
32 |
You initiate the storytelling process through a series of engaging prompts:
|
@@ -61,13 +76,13 @@ How we're different: A marketing story
|
|
61 |
|
62 |
Guided Storytelling Framework:
|
63 |
You then lead users through a structured narrative development via the following prompts:
|
64 |
-
Describe the day it happened
|
65 |
-
What was the Call to Action / Invitation
|
66 |
-
Describing the obstacles (up to three) in 4 lines
|
67 |
-
Exploring emotions/fears experienced during the incident
|
68 |
-
Recognize the helpers / any objects of help in the incident
|
69 |
-
Detailing the resolution / Reaching the final goal
|
70 |
-
Reflecting on personal growth or lessons learned (What did you do that changed your life forever?)
|
71 |
|
72 |
Now, show the story created so far, and ask for confirmation before proceeding to the next tier.
|
73 |
|
@@ -99,11 +114,13 @@ Tips for maximising emotional resonance and memorability
|
|
99 |
By guiding users through these three tiers, you aim to cater to novice storytellers, offering a comprehensive platform for narrative skill development through its adaptive approach.
|
100 |
You end it with the final story and seeking any suggestions from the user to refine the story further.
|
101 |
Once the user confirms, you congratulate them with emojis on completing the story and provide the final story in a beatifully formatted manner.
|
|
|
102 |
|
103 |
"""
|
104 |
|
105 |
USER_ICON = "man.png"
|
106 |
AI_ICON = "Kommuneity.png"
|
|
|
107 |
|
108 |
st.set_page_config(
|
109 |
page_title="Kommuneity Story Creator",
|
@@ -113,7 +130,7 @@ st.set_page_config(
|
|
113 |
ipAddress = st.context.headers.get("x-forwarded-for")
|
114 |
|
115 |
|
116 |
-
def __nowInIST():
|
117 |
return DT.datetime.now(pytz.timezone("Asia/Kolkata"))
|
118 |
|
119 |
|
@@ -126,6 +143,32 @@ def pprint(log: str):
|
|
126 |
pprint("\n")
|
127 |
|
128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
def predict(prompt):
|
130 |
historyFormatted = [{"role": "system", "content": SYSTEM_MSG}]
|
131 |
historyFormatted.extend(st.session_state.messages)
|
@@ -149,31 +192,9 @@ def predict(prompt):
|
|
149 |
yield chunkContent
|
150 |
|
151 |
|
152 |
-
st.title("
|
153 |
-
|
154 |
-
st.
|
155 |
-
|
156 |
-
# st.markdown(
|
157 |
-
# """
|
158 |
-
# <style>
|
159 |
-
# :root {
|
160 |
-
# --bg-color: white;
|
161 |
-
# --text-color: black;
|
162 |
-
# }
|
163 |
-
|
164 |
-
# .main {
|
165 |
-
# background-color: var(--bg-color);
|
166 |
-
# color: var(--text-color);
|
167 |
-
# transition: background-color 0.3s, color 0.3s;
|
168 |
-
# }
|
169 |
-
# </style>
|
170 |
-
# """,
|
171 |
-
# unsafe_allow_html=True
|
172 |
-
# )
|
173 |
-
|
174 |
-
if "messages" not in st.session_state:
|
175 |
-
st.session_state.messages = []
|
176 |
-
|
177 |
|
178 |
for message in st.session_state.messages:
|
179 |
role = message["role"]
|
@@ -182,17 +203,61 @@ for message in st.session_state.messages:
|
|
182 |
with st.chat_message(role, avatar=avatar):
|
183 |
st.markdown(content)
|
184 |
|
185 |
-
if prompt := st.chat_input():
|
|
|
|
|
|
|
186 |
with st.chat_message("user", avatar=USER_ICON):
|
187 |
st.markdown(prompt)
|
188 |
pprint(f"{prompt=}")
|
189 |
st.session_state.messages.append({"role": "user", "content": prompt })
|
190 |
|
191 |
with st.chat_message("assistant", avatar=AI_ICON):
|
192 |
-
|
193 |
-
|
194 |
-
|
|
|
195 |
responseGenerator = predict(prompt)
|
196 |
-
|
197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
st.session_state.messages.append({"role": "assistant", "content": response})
|
|
|
2 |
import os
|
3 |
import datetime as DT
|
4 |
import pytz
|
5 |
+
import time
|
6 |
+
import json
|
7 |
+
import re
|
8 |
from transformers import AutoTokenizer
|
9 |
|
10 |
from dotenv import load_dotenv
|
|
|
15 |
client = Groq(
|
16 |
api_key=os.environ.get("GROQ_API_KEY"),
|
17 |
)
|
18 |
+
|
19 |
MODEL = "llama-3.1-70b-versatile"
|
20 |
+
JSON_SEPARATOR = ">>>>"
|
21 |
+
|
22 |
|
23 |
tokenizer = AutoTokenizer.from_pretrained("Xenova/Meta-Llama-3.1-Tokenizer")
|
24 |
|
|
|
30 |
return len(tokens)
|
31 |
|
32 |
|
33 |
+
SYSTEM_MSG = f"""
|
34 |
You're an storytelling assistant who guides users through four phases of narrative development, helping them craft compelling personal or professional stories. The story created should be in simple language, yet evoke great emotions.
|
35 |
Ask one question at a time, give the options in a well formatted manner in different lines
|
36 |
+
If your response has number of options to choose from, only then append your final response with this exact keyword "{JSON_SEPARATOR}", and only after this, append with the JSON of options to choose from. The JSON should be of the format:
|
37 |
+
{{
|
38 |
+
"options": [
|
39 |
+
{{ "id": "1", "label": "Option 1"}},
|
40 |
+
{{ "id": "2", "label": "Option 2"}},
|
41 |
+
]
|
42 |
+
}}
|
43 |
+
Do not write "Choose one of the options below:"
|
44 |
+
Keep options to less than 9
|
45 |
|
46 |
# Tier 1: Story Creation
|
47 |
You initiate the storytelling process through a series of engaging prompts:
|
|
|
76 |
|
77 |
Guided Storytelling Framework:
|
78 |
You then lead users through a structured narrative development via the following prompts:
|
79 |
+
- Describe the day it happened
|
80 |
+
- What was the Call to Action / Invitation
|
81 |
+
- Describing the obstacles (up to three) in 4 lines
|
82 |
+
- Exploring emotions/fears experienced during the incident
|
83 |
+
- Recognize the helpers / any objects of help in the incident
|
84 |
+
- Detailing the resolution / Reaching the final goal
|
85 |
+
- Reflecting on personal growth or lessons learned (What did you do that changed your life forever?)
|
86 |
|
87 |
Now, show the story created so far, and ask for confirmation before proceeding to the next tier.
|
88 |
|
|
|
114 |
By guiding users through these three tiers, you aim to cater to novice storytellers, offering a comprehensive platform for narrative skill development through its adaptive approach.
|
115 |
You end it with the final story and seeking any suggestions from the user to refine the story further.
|
116 |
Once the user confirms, you congratulate them with emojis on completing the story and provide the final story in a beatifully formatted manner.
|
117 |
+
Note that the final story should include twist, turns and events that make it really engaging and enjoyable to read.
|
118 |
|
119 |
"""
|
120 |
|
121 |
USER_ICON = "man.png"
|
122 |
AI_ICON = "Kommuneity.png"
|
123 |
+
START_MSG = "I want to create a story 😊"
|
124 |
|
125 |
st.set_page_config(
|
126 |
page_title="Kommuneity Story Creator",
|
|
|
130 |
ipAddress = st.context.headers.get("x-forwarded-for")
|
131 |
|
132 |
|
133 |
+
def __nowInIST() -> DT.datetime:
|
134 |
return DT.datetime.now(pytz.timezone("Asia/Kolkata"))
|
135 |
|
136 |
|
|
|
143 |
pprint("\n")
|
144 |
|
145 |
|
146 |
+
def __isInvalidResponse(response: str):
|
147 |
+
if len(re.findall(r'\n[a-z]', response)) > 3:
|
148 |
+
return True
|
149 |
+
|
150 |
+
if ('\n{\n "options"' in response) and (JSON_SEPARATOR not in response):
|
151 |
+
return True
|
152 |
+
|
153 |
+
|
154 |
+
def __resetButtonState():
|
155 |
+
st.session_state["buttonValue"] = ""
|
156 |
+
|
157 |
+
|
158 |
+
def __setStartMsg(msg):
|
159 |
+
st.session_state.startMsg = msg
|
160 |
+
|
161 |
+
|
162 |
+
if "messages" not in st.session_state:
|
163 |
+
st.session_state.messages = []
|
164 |
+
|
165 |
+
if "buttonValue" not in st.session_state:
|
166 |
+
__resetButtonState()
|
167 |
+
|
168 |
+
if "startMsg" not in st.session_state:
|
169 |
+
st.session_state.startMsg = ""
|
170 |
+
|
171 |
+
|
172 |
def predict(prompt):
|
173 |
historyFormatted = [{"role": "system", "content": SYSTEM_MSG}]
|
174 |
historyFormatted.extend(st.session_state.messages)
|
|
|
192 |
yield chunkContent
|
193 |
|
194 |
|
195 |
+
st.title("Kommuneity Story Creator 📖")
|
196 |
+
if not st.session_state.startMsg:
|
197 |
+
st.button(START_MSG, on_click=lambda: __setStartMsg(START_MSG))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
for message in st.session_state.messages:
|
200 |
role = message["role"]
|
|
|
203 |
with st.chat_message(role, avatar=avatar):
|
204 |
st.markdown(content)
|
205 |
|
206 |
+
if prompt := (st.chat_input() or st.session_state["buttonValue"] or st.session_state.startMsg):
|
207 |
+
__resetButtonState()
|
208 |
+
__setStartMsg("")
|
209 |
+
|
210 |
with st.chat_message("user", avatar=USER_ICON):
|
211 |
st.markdown(prompt)
|
212 |
pprint(f"{prompt=}")
|
213 |
st.session_state.messages.append({"role": "user", "content": prompt })
|
214 |
|
215 |
with st.chat_message("assistant", avatar=AI_ICON):
|
216 |
+
placeholder = st.empty()
|
217 |
+
|
218 |
+
def getResponse():
|
219 |
+
response = ""
|
220 |
responseGenerator = predict(prompt)
|
221 |
+
|
222 |
+
for chunk in responseGenerator:
|
223 |
+
response += chunk
|
224 |
+
if __isInvalidResponse(response):
|
225 |
+
return
|
226 |
+
|
227 |
+
if JSON_SEPARATOR not in response:
|
228 |
+
placeholder.markdown(response)
|
229 |
+
|
230 |
+
return response
|
231 |
+
|
232 |
+
response = getResponse()
|
233 |
+
while not response:
|
234 |
+
pprint("Empty response. Retrying..")
|
235 |
+
time.sleep(0.5)
|
236 |
+
response = getResponse()
|
237 |
+
|
238 |
+
pprint(f"{response=}")
|
239 |
+
|
240 |
+
def selectButton(optionLabel):
|
241 |
+
st.session_state["buttonValue"] = optionLabel
|
242 |
+
pprint(f"Selected: {optionLabel}")
|
243 |
+
|
244 |
+
responseParts = response.split(JSON_SEPARATOR)
|
245 |
+
if len(responseParts) > 1:
|
246 |
+
[response, jsonStr] = responseParts
|
247 |
+
|
248 |
+
try:
|
249 |
+
json.loads(jsonStr)
|
250 |
+
jsonObj = json.loads(jsonStr)
|
251 |
+
options = jsonObj["options"]
|
252 |
+
|
253 |
+
for option in options:
|
254 |
+
st.button(
|
255 |
+
option["label"],
|
256 |
+
key=option["id"],
|
257 |
+
on_click=lambda label=option["label"]: selectButton(label)
|
258 |
+
)
|
259 |
+
# st.code(jsonStr, language="json")
|
260 |
+
except Exception as e:
|
261 |
+
pprint(e)
|
262 |
+
|
263 |
st.session_state.messages.append({"role": "assistant", "content": response})
|