Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -6,7 +6,6 @@ from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, ServiceCon
|
|
| 6 |
from llama_index.llms.openai import OpenAI as LlamaOpenAI
|
| 7 |
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 8 |
from llama_index.core.prompts import PromptTemplate
|
| 9 |
-
import textwrap
|
| 10 |
|
| 11 |
# ---------- AI Instructions & Prompts ----------
|
| 12 |
SYSTEM_INSTRUCTION = """You are an elite marketing copywriter and TrustLogic expert assistant.
|
|
@@ -116,91 +115,21 @@ client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
|
|
| 116 |
|
| 117 |
# ---------- Chainlit Hooks ----------
|
| 118 |
|
| 119 |
-
|
| 120 |
@cl.on_chat_start
|
| 121 |
async def start():
|
| 122 |
-
"""Initialize chat session
|
| 123 |
-
welcome_message = "How can I assist you today?"
|
| 124 |
-
|
| 125 |
-
# HTML snippet to inject CSS/JS that hides attachment and stop button selectors
|
| 126 |
-
# and provides a small helper to show an indeterminate loading bar.
|
| 127 |
-
injected_ui = textwrap.dedent("""
|
| 128 |
-
<div id="trustlogic-ui-inject" style="display:none;">
|
| 129 |
-
<style>
|
| 130 |
-
/* Hide file upload / attachment button */
|
| 131 |
-
.cl-file-input, .cl-upload, input[type="file"], button[aria-label="Upload file"] {
|
| 132 |
-
display: none !important;
|
| 133 |
-
visibility: hidden !important;
|
| 134 |
-
}
|
| 135 |
-
/* Hide stop/abort buttons commonly used in UIs */
|
| 136 |
-
button[aria-label="Stop"], .cl-stop-button, .stop-btn, button[data-testid="stop-button"] {
|
| 137 |
-
display: none !important;
|
| 138 |
-
visibility: hidden !important;
|
| 139 |
-
}
|
| 140 |
-
|
| 141 |
-
/* Simple loading bar container (hidden by default) */
|
| 142 |
-
#trustlogic-loading {
|
| 143 |
-
width: 100%;
|
| 144 |
-
max-width: 780px;
|
| 145 |
-
margin: 8px 0;
|
| 146 |
-
height: 10px;
|
| 147 |
-
background: rgba(0,0,0,0.06);
|
| 148 |
-
border-radius: 6px;
|
| 149 |
-
overflow: hidden;
|
| 150 |
-
display: none;
|
| 151 |
-
}
|
| 152 |
-
#trustlogic-loading .bar {
|
| 153 |
-
width: 0%;
|
| 154 |
-
height: 100%;
|
| 155 |
-
background: linear-gradient(90deg, rgba(0,0,0,0.12), rgba(0,0,0,0.24));
|
| 156 |
-
animation: indeterminate 1.2s infinite linear;
|
| 157 |
-
}
|
| 158 |
-
@keyframes indeterminate {
|
| 159 |
-
0% { transform: translateX(-100%); width: 40%; }
|
| 160 |
-
50% { transform: translateX(0%); width: 60%; }
|
| 161 |
-
100% { transform: translateX(100%); width: 40%; }
|
| 162 |
-
}
|
| 163 |
-
</style>
|
| 164 |
-
|
| 165 |
-
<div id="trustlogic-loading">
|
| 166 |
-
<div class="bar"></div>
|
| 167 |
-
</div>
|
| 168 |
-
|
| 169 |
-
<script>
|
| 170 |
-
// expose helpers to show/hide the loading bar from incoming messages
|
| 171 |
-
window.chainlitHelpers = window.chainlitHelpers || {};
|
| 172 |
-
window.chainlitHelpers.showLoading = function() {
|
| 173 |
-
var el = document.getElementById('trustlogic-loading');
|
| 174 |
-
if (el) el.style.display = 'block';
|
| 175 |
-
}
|
| 176 |
-
window.chainlitHelpers.hideLoading = function() {
|
| 177 |
-
var el = document.getElementById('trustlogic-loading');
|
| 178 |
-
if (el) el.style.display = 'none';
|
| 179 |
-
}
|
| 180 |
-
|
| 181 |
-
// best-effort hide for other variants: try again after a small delay (some UI renders later)
|
| 182 |
-
setTimeout(function() {
|
| 183 |
-
document.querySelectorAll('.cl-file-input, .cl-upload, button[aria-label="Upload file"], button[aria-label="Stop"], .cl-stop-button, .stop-btn').forEach(n => {
|
| 184 |
-
n.style.display = 'none';
|
| 185 |
-
n.style.visibility = 'hidden';
|
| 186 |
-
});
|
| 187 |
-
}, 600);
|
| 188 |
-
</script>
|
| 189 |
-
</div>
|
| 190 |
-
""")
|
| 191 |
-
|
| 192 |
-
# send welcome and injection; mark as HTML so it renders client-side
|
| 193 |
await cl.Message(content=welcome_message).send()
|
| 194 |
-
await cl.Message(content=injected_ui, content_type="html").send()
|
| 195 |
|
| 196 |
@cl.on_message
|
| 197 |
async def main(message: cl.Message):
|
| 198 |
"""Process incoming messages"""
|
| 199 |
query = message.content.strip()
|
| 200 |
|
| 201 |
-
#
|
| 202 |
-
|
| 203 |
-
await
|
| 204 |
|
| 205 |
# Check knowledge base first
|
| 206 |
kb_query_engine = index.as_query_engine(
|
|
@@ -225,25 +154,22 @@ Decision criteria:
|
|
| 225 |
Reply with only: USE_KB or USE_WEB"""
|
| 226 |
|
| 227 |
decision = client.chat.completions.create(
|
| 228 |
-
model="gpt-
|
| 229 |
messages=[{"role": "user", "content": decision_prompt}],
|
| 230 |
)
|
| 231 |
|
| 232 |
decision_text = decision.choices[0].message.content.strip()
|
| 233 |
|
| 234 |
-
# Remove loading message
|
| 235 |
-
await loading_msg.remove()
|
| 236 |
-
|
| 237 |
-
# Create response message
|
| 238 |
-
msg = cl.Message(content="")
|
| 239 |
-
|
| 240 |
# --- Use Knowledge Base ---
|
| 241 |
if "USE_KB" in decision_text:
|
| 242 |
response_text = str(kb_response) + FOOTER_MESSAGE
|
| 243 |
|
| 244 |
# Stream the response
|
| 245 |
-
for char in response_text:
|
| 246 |
await msg.stream_token(char)
|
|
|
|
|
|
|
|
|
|
| 247 |
|
| 248 |
await msg.update()
|
| 249 |
return
|
|
@@ -298,4 +224,9 @@ Reply with only: USE_KB or USE_WEB"""
|
|
| 298 |
@cl.on_chat_end
|
| 299 |
async def end():
|
| 300 |
"""Handle chat end"""
|
| 301 |
-
print("Chat session ended")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
from llama_index.llms.openai import OpenAI as LlamaOpenAI
|
| 7 |
from llama_index.embeddings.openai import OpenAIEmbedding
|
| 8 |
from llama_index.core.prompts import PromptTemplate
|
|
|
|
| 9 |
|
| 10 |
# ---------- AI Instructions & Prompts ----------
|
| 11 |
SYSTEM_INSTRUCTION = """You are an elite marketing copywriter and TrustLogic expert assistant.
|
|
|
|
| 115 |
|
| 116 |
# ---------- Chainlit Hooks ----------
|
| 117 |
|
|
|
|
| 118 |
@cl.on_chat_start
|
| 119 |
async def start():
|
| 120 |
+
"""Initialize chat session with a welcoming message"""
|
| 121 |
+
welcome_message = """How can I assist you today?"""
|
| 122 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
await cl.Message(content=welcome_message).send()
|
|
|
|
| 124 |
|
| 125 |
@cl.on_message
|
| 126 |
async def main(message: cl.Message):
|
| 127 |
"""Process incoming messages"""
|
| 128 |
query = message.content.strip()
|
| 129 |
|
| 130 |
+
# Create streaming message
|
| 131 |
+
msg = cl.Message(content="")
|
| 132 |
+
await msg.send()
|
| 133 |
|
| 134 |
# Check knowledge base first
|
| 135 |
kb_query_engine = index.as_query_engine(
|
|
|
|
| 154 |
Reply with only: USE_KB or USE_WEB"""
|
| 155 |
|
| 156 |
decision = client.chat.completions.create(
|
| 157 |
+
model="gpt-5",
|
| 158 |
messages=[{"role": "user", "content": decision_prompt}],
|
| 159 |
)
|
| 160 |
|
| 161 |
decision_text = decision.choices[0].message.content.strip()
|
| 162 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
# --- Use Knowledge Base ---
|
| 164 |
if "USE_KB" in decision_text:
|
| 165 |
response_text = str(kb_response) + FOOTER_MESSAGE
|
| 166 |
|
| 167 |
# Stream the response
|
| 168 |
+
for i, char in enumerate(response_text):
|
| 169 |
await msg.stream_token(char)
|
| 170 |
+
# Add small delay for better UX (optional)
|
| 171 |
+
if i % 50 == 0:
|
| 172 |
+
await cl.sleep(0.01)
|
| 173 |
|
| 174 |
await msg.update()
|
| 175 |
return
|
|
|
|
| 224 |
@cl.on_chat_end
|
| 225 |
async def end():
|
| 226 |
"""Handle chat end"""
|
| 227 |
+
print("Chat session ended")
|
| 228 |
+
|
| 229 |
+
@cl.on_stop
|
| 230 |
+
async def stop():
|
| 231 |
+
"""Handle stop button"""
|
| 232 |
+
await cl.Message(content="⏹️ Task stopped by user.").send()
|