Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1 |
import os
|
2 |
import zipfile
|
|
|
3 |
from dotenv import load_dotenv
|
4 |
from groq import Groq
|
5 |
import chromadb
|
@@ -9,6 +10,7 @@ from sentence_transformers import CrossEncoder
|
|
9 |
import gradio as gr
|
10 |
from datetime import datetime
|
11 |
from huggingface_hub import hf_hub_download, HfApi
|
|
|
12 |
|
13 |
# Load environment variables and initialize clients
|
14 |
load_dotenv()
|
@@ -162,20 +164,55 @@ def get_context(message):
|
|
162 |
print(f"\nFinal context length: {total_chars} characters")
|
163 |
return context
|
164 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
def chat_response(message, history, model_name):
|
166 |
"""Chat response function for Gradio interface"""
|
167 |
try:
|
168 |
-
# Get context
|
169 |
context = get_context(message)
|
170 |
-
|
171 |
-
# Get current time and date
|
172 |
-
current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
173 |
|
174 |
# Build messages list
|
175 |
messages = [{
|
176 |
"role": "system",
|
177 |
"content": f"""You are an AI assistant for the British Antarctic Survey (BAS). Your responses should be based ONLY on the context provided below.
|
178 |
-
|
179 |
IMPORTANT INSTRUCTIONS:
|
180 |
1. ALWAYS thoroughly check the provided context before saying you don't have information
|
181 |
2. If you find ANY relevant information in the context, use it - even if it's not complete
|
@@ -183,18 +220,16 @@ IMPORTANT INSTRUCTIONS:
|
|
183 |
4. When citing sources, put them on a new line after the relevant information like this:
|
184 |
Here is some information about BAS.
|
185 |
Source: https://www.bas.ac.uk/example
|
186 |
-
|
187 |
5. Do not say things like:
|
188 |
- "I don't have access to real-time information"
|
189 |
- "I cannot browse the internet"
|
190 |
Instead, share what IS in the context, and only say "I don't have enough information" if you truly find nothing relevant to the users question.
|
191 |
-
|
192 |
6. Keep responses:
|
193 |
- With emojis where appropriate
|
194 |
- Without duplicate source citations
|
195 |
- Based strictly on the context below
|
196 |
|
197 |
-
Current Time: {
|
198 |
|
199 |
Context: {context}"""
|
200 |
}]
|
@@ -242,12 +277,11 @@ Context: {context}"""
|
|
242 |
# Create collapsible thinking section
|
243 |
if thinking_process:
|
244 |
final_response = f"""<details>
|
245 |
-
<summary>π€ Click
|
246 |
-
<hr>
|
247 |
<div style="font-size: 0.9em;">
|
248 |
-
<i>π{thinking_process}
|
249 |
</div>
|
250 |
-
<hr>
|
251 |
</details>
|
252 |
|
253 |
{final_response}"""
|
@@ -259,49 +293,64 @@ Context: {context}"""
|
|
259 |
else:
|
260 |
final_response += content
|
261 |
yield final_response
|
262 |
-
|
|
|
|
|
263 |
print("\n=== LLM Response End ===\n")
|
264 |
|
265 |
except Exception as e:
|
266 |
error_msg = f"An error occurred: {str(e)}"
|
267 |
print(f"\nERROR: {error_msg}")
|
|
|
|
|
|
|
268 |
yield error_msg
|
269 |
-
|
270 |
if __name__ == "__main__":
|
271 |
try:
|
272 |
print("\n=== Starting Application ===")
|
273 |
|
274 |
-
|
|
|
|
|
|
|
275 |
print("Initialising ChromaDB...")
|
276 |
chroma_client, collection, reranker = initialize_system()
|
277 |
print(f"Found {collection.count()} documents in collection")
|
278 |
|
279 |
print("\nCreating Gradio interface...")
|
280 |
|
281 |
-
|
282 |
demo = gr.Blocks()
|
283 |
|
284 |
with demo:
|
285 |
-
gr.Markdown("# British Antarctic Survey Website Chat Assistant
|
286 |
-
gr.Markdown("
|
287 |
-
# Add model selector
|
288 |
model_selector = gr.Dropdown(
|
289 |
choices=[
|
290 |
-
"llama-3.3-70b-versatile",
|
291 |
"llama-3.1-8b-instant",
|
|
|
|
|
292 |
"mixtral-8x7b-32768",
|
293 |
"deepseek-r1-distill-llama-70b"
|
294 |
],
|
295 |
-
value="llama-3.
|
296 |
-
label="Select AI Model π€",
|
297 |
-
info="Choose which AI model to use for responses -
|
298 |
)
|
299 |
|
300 |
-
chatbot = gr.Chatbot(height=
|
301 |
-
|
302 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
303 |
|
304 |
-
# Add example questions
|
305 |
gr.Examples(
|
306 |
examples=[
|
307 |
"What research stations does BAS operate in Antarctica? ποΈ",
|
@@ -324,11 +373,13 @@ if __name__ == "__main__":
|
|
324 |
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
|
325 |
bot, [chatbot, model_selector], chatbot
|
326 |
)
|
|
|
|
|
|
|
327 |
|
328 |
clear.click(lambda: None, None, chatbot, queue=False)
|
329 |
-
|
330 |
-
|
331 |
-
demo.queue()
|
332 |
demo.launch(
|
333 |
server_name="0.0.0.0",
|
334 |
server_port=7860,
|
|
|
1 |
import os
|
2 |
import zipfile
|
3 |
+
import json
|
4 |
from dotenv import load_dotenv
|
5 |
from groq import Groq
|
6 |
import chromadb
|
|
|
10 |
import gradio as gr
|
11 |
from datetime import datetime
|
12 |
from huggingface_hub import hf_hub_download, HfApi
|
13 |
+
from pathlib import Path
|
14 |
|
15 |
# Load environment variables and initialize clients
|
16 |
load_dotenv()
|
|
|
164 |
print(f"\nFinal context length: {total_chars} characters")
|
165 |
return context
|
166 |
|
167 |
+
def log_conversation(timestamp, user_message, assistant_response, model_name, context, error=None):
|
168 |
+
"""Log conversation details to a JSON file"""
|
169 |
+
log_dir = Path("logs")
|
170 |
+
log_dir.mkdir(exist_ok=True)
|
171 |
+
|
172 |
+
# Create a log entry
|
173 |
+
log_entry = {
|
174 |
+
"timestamp": timestamp,
|
175 |
+
"model_name": model_name,
|
176 |
+
"user_message": user_message,
|
177 |
+
"assistant_response": assistant_response,
|
178 |
+
"context": context,
|
179 |
+
"error": str(error) if error else None
|
180 |
+
}
|
181 |
+
|
182 |
+
# Use the current date for the log file name
|
183 |
+
current_date = datetime.now().strftime("%Y-%m-%d")
|
184 |
+
log_file = log_dir / f"conversation_log_{current_date}.json"
|
185 |
+
|
186 |
+
try:
|
187 |
+
# Load existing logs if file exists
|
188 |
+
if log_file.exists():
|
189 |
+
with open(log_file, 'r', encoding='utf-8') as f:
|
190 |
+
logs = json.load(f)
|
191 |
+
else:
|
192 |
+
logs = []
|
193 |
+
|
194 |
+
# Append new log entry
|
195 |
+
logs.append(log_entry)
|
196 |
+
|
197 |
+
# Write updated logs
|
198 |
+
with open(log_file, 'w', encoding='utf-8') as f:
|
199 |
+
json.dump(logs, f, ensure_ascii=False, indent=2)
|
200 |
+
|
201 |
+
print(f"\nβοΈ Logged conversation to {log_file}")
|
202 |
+
except Exception as e:
|
203 |
+
print(f"\nβ οΈ Error logging conversation: {str(e)}")
|
204 |
+
|
205 |
def chat_response(message, history, model_name):
|
206 |
"""Chat response function for Gradio interface"""
|
207 |
try:
|
208 |
+
# Get context and timestamp
|
209 |
context = get_context(message)
|
210 |
+
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
|
211 |
|
212 |
# Build messages list
|
213 |
messages = [{
|
214 |
"role": "system",
|
215 |
"content": f"""You are an AI assistant for the British Antarctic Survey (BAS). Your responses should be based ONLY on the context provided below.
|
|
|
216 |
IMPORTANT INSTRUCTIONS:
|
217 |
1. ALWAYS thoroughly check the provided context before saying you don't have information
|
218 |
2. If you find ANY relevant information in the context, use it - even if it's not complete
|
|
|
220 |
4. When citing sources, put them on a new line after the relevant information like this:
|
221 |
Here is some information about BAS.
|
222 |
Source: https://www.bas.ac.uk/example
|
|
|
223 |
5. Do not say things like:
|
224 |
- "I don't have access to real-time information"
|
225 |
- "I cannot browse the internet"
|
226 |
Instead, share what IS in the context, and only say "I don't have enough information" if you truly find nothing relevant to the users question.
|
|
|
227 |
6. Keep responses:
|
228 |
- With emojis where appropriate
|
229 |
- Without duplicate source citations
|
230 |
- Based strictly on the context below
|
231 |
|
232 |
+
Current Time: {timestamp}
|
233 |
|
234 |
Context: {context}"""
|
235 |
}]
|
|
|
277 |
# Create collapsible thinking section
|
278 |
if thinking_process:
|
279 |
final_response = f"""<details>
|
280 |
+
<summary>π€ <u>Click to see 'thinking' process</u></summary>
|
|
|
281 |
<div style="font-size: 0.9em;">
|
282 |
+
<i>π{thinking_process}π</i>
|
283 |
</div>
|
284 |
+
<hr style="margin: 0; height: 2px;">
|
285 |
</details>
|
286 |
|
287 |
{final_response}"""
|
|
|
293 |
else:
|
294 |
final_response += content
|
295 |
yield final_response
|
296 |
+
|
297 |
+
|
298 |
+
log_conversation(timestamp, message, final_response, model_name, context)
|
299 |
print("\n=== LLM Response End ===\n")
|
300 |
|
301 |
except Exception as e:
|
302 |
error_msg = f"An error occurred: {str(e)}"
|
303 |
print(f"\nERROR: {error_msg}")
|
304 |
+
|
305 |
+
log_conversation(datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
306 |
+
message, error_msg, model_name, context, error=e)
|
307 |
yield error_msg
|
308 |
+
|
309 |
if __name__ == "__main__":
|
310 |
try:
|
311 |
print("\n=== Starting Application ===")
|
312 |
|
313 |
+
|
314 |
+
Path("logs").mkdir(exist_ok=True)
|
315 |
+
|
316 |
+
|
317 |
print("Initialising ChromaDB...")
|
318 |
chroma_client, collection, reranker = initialize_system()
|
319 |
print(f"Found {collection.count()} documents in collection")
|
320 |
|
321 |
print("\nCreating Gradio interface...")
|
322 |
|
323 |
+
|
324 |
demo = gr.Blocks()
|
325 |
|
326 |
with demo:
|
327 |
+
gr.Markdown("# πβοΈBritish Antarctic Survey Website Chat Assistant π§π€")
|
328 |
+
gr.Markdown("Accesses text data from 11,982 unique BAS URLs (6GB [Vector Database](https://huggingface.co/datasets/Mr-Geo/chroma_db/tree/main/) π extracted 02/02/2025) | Created with open source technologies: [Gradio](https://gradio.app) for the interface π¨, [Groq](https://groq.com) API for rapid LLM processing β‘, and [Chroma](https://www.trychroma.com/) as the vector database π»π")
|
|
|
329 |
model_selector = gr.Dropdown(
|
330 |
choices=[
|
|
|
331 |
"llama-3.1-8b-instant",
|
332 |
+
"llama-3.3-70b-versatile",
|
333 |
+
"llama-3.3-70b-specdec",
|
334 |
"mixtral-8x7b-32768",
|
335 |
"deepseek-r1-distill-llama-70b"
|
336 |
],
|
337 |
+
value="llama-3.1-8b-instant",
|
338 |
+
label="Select AI Large Language Model π€",
|
339 |
+
info="Choose which AI model to use for responses - Select 'deepseek' for the 'thinking' AI search π"
|
340 |
)
|
341 |
|
342 |
+
chatbot = gr.Chatbot(height=550)
|
343 |
+
with gr.Row(equal_height=True):
|
344 |
+
msg = gr.Textbox(
|
345 |
+
placeholder="What would you like to know? Or choose an example question...β",
|
346 |
+
label="Your question",
|
347 |
+
show_label=True,
|
348 |
+
container=True,
|
349 |
+
scale=20
|
350 |
+
)
|
351 |
+
send = gr.Button("Send β¬οΈ", scale=1, min_width=50)
|
352 |
+
clear = gr.Button("Clear chat history π§Ή")
|
353 |
|
|
|
354 |
gr.Examples(
|
355 |
examples=[
|
356 |
"What research stations does BAS operate in Antarctica? ποΈ",
|
|
|
373 |
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
|
374 |
bot, [chatbot, model_selector], chatbot
|
375 |
)
|
376 |
+
send.click(user, [msg, chatbot], [msg, chatbot], queue=False).then(
|
377 |
+
bot, [chatbot, model_selector], chatbot
|
378 |
+
)
|
379 |
|
380 |
clear.click(lambda: None, None, chatbot, queue=False)
|
381 |
+
|
382 |
+
gr.Markdown("<footer style='text-align: center; margin-top: 5px;'>π€ AI-generated content; while the Chat Assistant strives for accuracy, errors may occur; please thoroughly check critical information π€<br>β οΈ <strong><u>Disclaimer: This system was not produced by the British Antarctic Survey (BAS) and AI generated output does not reflect the views or opinions of BAS</u></strong> β οΈ <br>(just a bit of fun :D)</footer>")
|
|
|
383 |
demo.launch(
|
384 |
server_name="0.0.0.0",
|
385 |
server_port=7860,
|