ChatBot / app_Oct5_bak.py
Michael S. Trusov
November 3 commit to Hugging Face
58a86aa
Raw History Blame Contribute Delete
12.4 kB
#--------------------------------------------------------------------------------
#
# See Hugging Face from VSCode setup.txt for publishing instructions
#
#--------------------------------------------------------------------------------
import gradio as gr
import os
import random
import time
import numpy as np
import json
#--------------------------------------------------------------------------------
qs = {}
theme = gr.themes.Base(
primary_hue="gray",
secondary_hue="gray",
).set(
background_fill_primary_dark='*neutral_950',
background_fill_secondary_dark='*neutral_950'
)
import uuid
# Add a function to generate a unique session ID
def generate_session_id():
return str(uuid.uuid4())
from urllib.parse import parse_qs
def parse_query_params(query_string):
parsed_params = parse_qs(query_string)
simplified_params = {k: v[0] if len(v) == 1 else v for k, v in parsed_params.items()}
return simplified_params
def app_inits():
global qs
# The path to the QA text file
filename = 'images/qa_data.txt'
full_path = os.path.abspath(filename)
print("Loading responces from ", full_path)
# Open the file and load the object
with open(filename, 'r') as file:
qs = json.load(file)
print("Loaded Q & A")
#print(qs[0], '\n')
# Get all keys
keys = list(qs.keys())
# Print the keys
print("Keys:", keys)
# https://bumk766fall2023-chatbot.hf.space/?dw=0.02&dl=0.0001&ds=1
# print("CALL URL: http://127.0.0.1:7860/?dw=0.02&dl=0.0001")
# https://bumk766fall2023-chatbot.hf.space/?dw=0.02&dl=0.0001&ds=0.4
#print("CALL URL: http://127.0.0.1:7860/?dw=0.02&dl=0.0001&ds=0.4")
#print("CALL URL: http://127.0.0.1:7860/?dw=0.2&dl=0.000001&ds=0.000004")
print("CALL URL: http://127.0.0.1:7860/?dw=0.002&dl=0.02&ds=0.000004")
return
with gr.Blocks(theme = theme) as demo:
#chatbot = gr.Chatbot(value = [[None,'**How can I help you today?**']], elem_id="chatbot", layout = "panel", avatar_images=("images/user.jpg", "images/bot.jpg"),)
#chatbot = gr.Chatbot(elem_id="chatbot", layout = "panel", avatar_images=("images/user.jpg", "images/bot.jpg"),)
#chatbot = gr.Chatbot(elem_id="chatbot", layout = "panel", avatar_images=("images/user.jpg", "images/bot.jpg"),render_markdown=False)
chatbot = gr.Chatbot(elem_id="chatbot", layout = "panel", avatar_images=("images/user.jpg", "images/bot.jpg"),latex_delimiters=[],)
# height=800,
#def get_params(request: gr.Request, param_hiddentextbox):
def get_params(request: gr.Request):
headers = request.headers
host = request.client.host
user_agent = request.headers["user-agent"]
params = request.query_params
session_id = generate_session_id() # Generate a unique session ID
return str(params), session_id
#return {
# "ip": host,
# "user_agent": user_agent,
# "headers": headers,
# "URL_params": params,
#}
with gr.Row(equal_height=True):
msg = gr.Textbox(show_label=False, placeholder="Message ChatGPT...", max_lines = 5,container = False,)
#msg = gr.Textbox(value="Pre-filled value", show_label=False, placeholder="Message ChatGPT...", max_lines=5, container=False, interactive=False)
# USE FOR NOT EDITABLE VERSION
#msg = gr.Textbox(value="what's the best mexican food in Tucson", show_label=False, placeholder="what's the best mexican food in Tucson", max_lines = 5,container = False, interactive=False)
btn = gr.Button(value="", min_width=80, size = "lg", icon="images/button.jpg", scale= 0)
#param_hiddentextbox = gr.Textbox(show_label=False, visible=False, container = False,)
url_params = gr.State()
session_id = gr.State()
#demo.load(get_params, None, url_params, queue=False)
demo.load(get_params, None, [url_params, session_id], queue=False)
#demo.load(get_params, param_hiddentextbox, param_hiddentextbox, queue=False)
# --------------------------------------------------------------------------------------------
def user(user_message, history):
print("User prompted ", user_message)
return "", history + [[user_message, None]]
# --------------------------------------------------------------------------------------------
# --------------------------------------------------------------------------------------------
def bot( history, url_params, session_id):
global qs
DelayBetweenWords = 0.7
DelayBetweenLetters = 0.0001
DelayBetweenSentences = .6
QID15 = 0
QID16 = 0
# Go fast for debugging
DelayBetweenWords = 0.0001
DelayBetweenLetters = 0.0001
DelayBetweenSentences = .0001
#time.sleep(.02)
print("---------- url_params ------------ ")
print(url_params)
if url_params != "":
params = parse_query_params(url_params)
DelayBetweenWords = float(params.get("dw", DelayBetweenWords))
DelayBetweenLetters = float(params.get("dl", DelayBetweenLetters))
DelayBetweenSentences = float(params.get("ds", DelayBetweenSentences))
QID15 = int(params.get("QID15", QID15))
QID16 = int(params.get("QID16", QID16))
else:
print("No parameters provided. Using defaults")
print("dv=", DelayBetweenWords, "dl=", DelayBetweenLetters, "ds=", DelayBetweenSentences, "QID15=", QID15, "QID16=", QID16 )
# Get all keys
keywords = list(qs.keys())
# Print the keys
print("Keys:", keywords )
# String typed by user
text = history[-1][0]
print("User Input:", text)
if text != "":
search_keyword = find_best_keyword_match(keywords, text)
else:
search_keyword = "None"
log_message("-ENTRY- [query]: " + text + " [params]: " + url_params + " [keyword]: " + search_keyword, session_id)
if search_keyword == "None":
#bot_message = "Sorry, don't know any restaurants at this location..." + " [DEBUG (params: " + url_params + ")]"
bot_message = "Sorry, don't know any restaurants at this location..."
bot_message = "I'm sorry, but I can only provide information about Mexican restaurants in Tucson at the moment."
else:
output_text = qs.get(search_keyword, "Keyword identified. No information found.")
bot_message = output_text
if text == "debug":
bot_message = "[DEBUG (ver. 10/05/2024) params: " + url_params + "\nSentences Delay=" + str(DelayBetweenSentences) + " sec. Words Delay=" + str(DelayBetweenWords) + " sec. Letters Delay=" + str(DelayBetweenLetters) + " sec.) \nKeys:\n" + "\n".join(keywords) + "]"
# initialize new entry
history[-1][1] = ""
# output text letter-by-letter
for character in bot_message:
if character == "^":
history[-1][1] += " "
elif character == "@":
history[-1][1] += "<BR>"
elif character != "=":
history[-1][1] += character
# Delay between words
if character == " ":
time.sleep(DelayBetweenWords)
# Overall print speed
#elif character == "." or character == ",":
elif character == "=":
time.sleep(DelayBetweenSentences)
else:
time.sleep(DelayBetweenLetters)
yield history
log_message("-EXIT - [query]: " + text + " [params]: " + url_params + " [keyword]: " + search_keyword, session_id)
# --------------------------------------------------------------------------------------------
# Events handling
btn.click(user, [msg, chatbot], [msg, chatbot], queue=False, show_progress=False).then(
bot, [chatbot, url_params, session_id], chatbot, concurrency_limit=50
)
# btn.click(user, [msg, chatbot], [msg, chatbot], queue=False, show_progress=False).then(
# bot, [chatbot, url_params, session_id], chatbot, concurrency_limit=50
# ).then(
# lambda: "what's the best mexican food in Tucson", None, msg
# )
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False, show_progress=False).then(
bot, [chatbot, url_params, session_id], chatbot, concurrency_limit=50
)
# btn.click(user, [msg, chatbot], [msg, chatbot], queue=False, show_progress=False).then(
# bot, [chatbot, url_params], chatbot, concurrency_limit=50
# )
# msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False, show_progress=False).then(
# bot, [chatbot, url_params], chatbot, concurrency_limit=50
# )
# --------------------------------------------------------------------------------------------
def normalize(s):
"""Lowercase and strip the string to normalize it."""
return s.lower().strip()
def levenshtein_distance(s1, s2):
"""Calculate the Levenshtein distance between two strings."""
if len(s1) < len(s2):
return levenshtein_distance(s2, s1)
if len(s2) == 0:
return len(s1)
previous_row = range(len(s2) + 1)
for i, c1 in enumerate(s1):
current_row = [i + 1]
for j, c2 in enumerate(s2):
insertions = previous_row[j + 1] + 1
deletions = current_row[j] + 1
substitutions = previous_row[j] + (c1 != c2)
current_row.append(min(insertions, deletions, substitutions))
previous_row = current_row
return previous_row[-1]
def find_best_keyword_match(keywords, text, max_distance=3):
"""Find the best keyword match in the text, allowing for some misspelling."""
text_normalized = normalize(text)
best_match = None
lowest_distance = float('inf')
for keyword in keywords:
keyword_normalized = normalize(keyword)
# Calculate the Levenshtein distance for composite keywords by comparing against slices of the text
if ' ' in keyword_normalized:
slice_length = len(keyword_normalized)
for i in range(len(text_normalized) - slice_length + 1):
text_slice = text_normalized[i:i+slice_length]
distance = levenshtein_distance(text_slice, keyword_normalized)
if distance < lowest_distance:
best_match = keyword
lowest_distance = distance
else:
# For single words, compare against each word in the text
for word in text_normalized.split():
distance = levenshtein_distance(word, keyword_normalized)
if distance < lowest_distance:
best_match = keyword
lowest_distance = distance
if lowest_distance <= max_distance:
return best_match
return "None"
from datetime import datetime
import threading
# Initialize a global threading lock
log_lock = threading.Lock()
# The path to the log file
filename = 'images/log_data.txt'
def log_message(param, session_id):
# Get current timestamp
timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
# Define the log file name based on session ID
#filename = f'{session_id}_log_data.txt'
session_id_text = f'{session_id}'
# Prepare log message
log_msg = f'{session_id_text}: {timestamp}: : {param}\n'
# Open the log file, append the message, and ensure the file is closed properly
# Use the lock to ensure that only one thread writes to the file at a time
with log_lock:
with open(filename, 'a') as log_file:
log_file.write(log_msg)
# Get the absolute path of the log file
abs_path = os.path.abspath(filename)
# Print the absolute path for debugging purposes
print(f'Writing to Log file: {abs_path}')
# --------------------------------------------------------------------------------------------
# Launching
# --------------------------------------------------------------------------------------------
app_inits()
demo.queue()
demo.launch(allowed_paths=["."], max_threads=40)