Demo Upload - First Commit
Browse files- README.md +5 -1
- app.py +369 -4
- icons/CT.svg +46 -0
- icons/GP.svg +41 -0
- icons/GS.svg +39 -0
- icons/M.svg +58 -0
- icons/P.svg +41 -0
- requierements.txt +2 -0
- styles.css +199 -0
README.md
CHANGED
|
@@ -7,7 +7,11 @@ sdk: gradio
|
|
| 7 |
sdk_version: 4.38.1
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
-
license:
|
| 11 |
---
|
| 12 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
|
| 7 |
sdk_version: 4.38.1
|
| 8 |
app_file: app.py
|
| 9 |
pinned: false
|
| 10 |
+
license: other
|
| 11 |
---
|
| 12 |
|
| 13 |
+
All rights reserved to Traceflow Ltd.
|
| 14 |
+
Visit https://blankstate.ai
|
| 15 |
+
Contact us contact@blankstate.ai
|
| 16 |
+
|
| 17 |
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
CHANGED
|
@@ -1,7 +1,372 @@
|
|
| 1 |
import gradio as gr
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
|
| 3 |
-
|
| 4 |
-
return "Hello " + name + "!!"
|
| 5 |
|
| 6 |
-
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import gradio as gr
|
| 2 |
+
import time
|
| 3 |
+
import random
|
| 4 |
+
import os
|
| 5 |
+
import base64
|
| 6 |
+
import json
|
| 7 |
+
import requests
|
| 8 |
+
import redis
|
| 9 |
|
| 10 |
+
#from huggingface_hub import login
|
|
|
|
| 11 |
|
| 12 |
+
# Global variables
|
| 13 |
+
picked_blueprint_js = None
|
| 14 |
+
protocol_scores = {}
|
| 15 |
+
protocol_markdown = None
|
| 16 |
+
DEFAULT_BLUEPRINT_INDEX = 0
|
| 17 |
+
DEFAULT_CONVERSATION_TYPE = "Banking"
|
| 18 |
+
|
| 19 |
+
HF_TOKEN = os.environ.get('PRIVATE_TOKEN')
|
| 20 |
+
|
| 21 |
+
COGN_API_URL = os.environ.get('BLANK_API_ENDPOINT')
|
| 22 |
+
|
| 23 |
+
headers = {
|
| 24 |
+
"Authorization": f"Bearer {HF_TOKEN}",
|
| 25 |
+
"Content-Type": "application/json",
|
| 26 |
+
}
|
| 27 |
+
|
| 28 |
+
R_PWD = os.environ['REDIS_CRED']
|
| 29 |
+
R_HOST = os.environ['REDIS_HOST']
|
| 30 |
+
r = redis.Redis(
|
| 31 |
+
host=R_HOST,
|
| 32 |
+
port=13508,
|
| 33 |
+
password=R_PWD)
|
| 34 |
+
|
| 35 |
+
# Predefined conversation examples
|
| 36 |
+
conversations = {
|
| 37 |
+
"Banking": [
|
| 38 |
+
("Banker", "Hello, welcome to our bank. How may I assist you today?"),
|
| 39 |
+
("Client", "Good afternoon, I am looking to apply for a personal loan to cover some unexpected expenses."),
|
| 40 |
+
("Banker", "Certainly, can you please provide us with some details about your income, expenses, and the amount you are looking to borrow?"),
|
| 41 |
+
("Client", "Yes, my monthly income is around $4,500, and my expenses are roughly $3,500. I'm looking to borrow $5,000 for a period of 2 years."),
|
| 42 |
+
("Banker", "Based on your income and expenses, we can offer you a loan with an interest rate of 5.5% per annum, with monthly repayments of $272. Would that be acceptable to you?"),
|
| 43 |
+
("Client", "Yes, that's reasonable. Can you please provide me with the necessary paperwork to complete the application process?"),
|
| 44 |
+
("Banker", "Absolutely, I will have a loan application form for you to fill out, as well as some documents to verify your income and identity. Once we have all the required information, we can process your loan application and get back to you as soon as possible."),
|
| 45 |
+
("Client", "Thank you very much, I appreciate your help. I look forward to doing business with your bank."),
|
| 46 |
+
("Banker", "It's been my pleasure, and we're confident that we can provide you with the financial solutions you need. Don't hesitate to reach out if you have any further questions or concerns."),
|
| 47 |
+
("Client", "Thank you, I'll be in touch. Goodbye for now."),
|
| 48 |
+
("Banker", "Goodbye, have a great day!")
|
| 49 |
+
],
|
| 50 |
+
"Unhappy Customer": [
|
| 51 |
+
("Customer Service", "Thank you for contacting customer service. I understand you're having an issue. Could you please explain what's wrong?"),
|
| 52 |
+
("Customer", "I'm very unhappy with the service I received. My order arrived damaged and the support I received was not helpful."),
|
| 53 |
+
("Customer Service", "I'm really sorry to hear that. Could you provide me with your order number so I can look into this for you?"),
|
| 54 |
+
("Customer", "Sure, it's 12345."),
|
| 55 |
+
("Customer Service", "Thank you. I'll check the details and see what we can do to resolve this issue for you."),
|
| 56 |
+
("Customer", "Thank you."),
|
| 57 |
+
("Customer Service", "I've checked your order and see the issue. We'll send you a replacement immediately and offer a discount on your next purchase."),
|
| 58 |
+
("Customer", "I appreciate that. Thank you for your help."),
|
| 59 |
+
("Customer Service", "You're welcome. Is there anything else I can assist you with?"),
|
| 60 |
+
("Customer", "No, that's all. Thank you."),
|
| 61 |
+
("Customer Service", "Have a great day!")
|
| 62 |
+
],
|
| 63 |
+
"Internal": [
|
| 64 |
+
("Employee 1", "Hey colleague, do you have a minute to discuss the new project?"),
|
| 65 |
+
("Employee 2", "Sure, what's up?"),
|
| 66 |
+
("Employee 1", "I think we need to re-evaluate our timeline. The client has requested some changes that will impact our deadlines."),
|
| 67 |
+
("Employee 2", "I agree. Let's set up a meeting with the team to discuss the adjustments and update our schedule."),
|
| 68 |
+
("Employee 1", "Sounds good. I'll send out a meeting invite for tomorrow."),
|
| 69 |
+
("Employee 2", "Great, thanks for coordinating this."),
|
| 70 |
+
("Employee 1", "No problem. See you at the meeting."),
|
| 71 |
+
("Employee 2", "See you!")
|
| 72 |
+
]
|
| 73 |
+
}
|
| 74 |
+
|
| 75 |
+
# Load blueprints and protocols
|
| 76 |
+
def load_blueprints_and_protocols():
|
| 77 |
+
try:
|
| 78 |
+
data = r.json().get("bp_patterns_seeker")
|
| 79 |
+
except redis.exceptions.ResponseError as e:
|
| 80 |
+
return ("Error:", e)
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
|
| 84 |
+
blueprints = [blueprint["name"] for blueprint in data["blueprints"]]
|
| 85 |
+
protocols = {blueprint["name"]: {ptype: [] for ptype in ["CT", "GS", "GP", "P", "M"]} for blueprint in data["blueprints"]}
|
| 86 |
+
default_protocols = {}
|
| 87 |
+
|
| 88 |
+
for blueprint in data["blueprints"]:
|
| 89 |
+
for metamarker in blueprint["metamarkers"]:
|
| 90 |
+
protocol_type = metamarker.get("Type")
|
| 91 |
+
if protocol_type in protocols[blueprint["name"]]:
|
| 92 |
+
protocol_name = list(metamarker.keys())[0]
|
| 93 |
+
protocols[blueprint["name"]][protocol_type].append(protocol_name)
|
| 94 |
+
|
| 95 |
+
if blueprints.index(blueprint["name"]) == DEFAULT_BLUEPRINT_INDEX:
|
| 96 |
+
if protocol_type not in default_protocols:
|
| 97 |
+
default_protocols[protocol_type] = []
|
| 98 |
+
default_protocols[protocol_type].append(protocol_name)
|
| 99 |
+
|
| 100 |
+
return blueprints, protocols, data, default_protocols
|
| 101 |
+
|
| 102 |
+
blueprints, protocols, data, default_protocols = load_blueprints_and_protocols()
|
| 103 |
+
|
| 104 |
+
# Initialize protocol_scores
|
| 105 |
+
def initialize_scores():
|
| 106 |
+
global protocol_scores
|
| 107 |
+
protocol_scores = {protocol: 0 for blueprint in protocols
|
| 108 |
+
for category in protocols[blueprint]
|
| 109 |
+
for protocol in protocols[blueprint][category]}
|
| 110 |
+
|
| 111 |
+
initialize_scores()
|
| 112 |
+
|
| 113 |
+
# Initialize picked_blueprint_js with the default blueprint
|
| 114 |
+
picked_blueprint_js = data["blueprints"][DEFAULT_BLUEPRINT_INDEX]
|
| 115 |
+
|
| 116 |
+
def update_scores(message):
|
| 117 |
+
global protocol_scores, picked_blueprint_js
|
| 118 |
+
|
| 119 |
+
details = True
|
| 120 |
+
local = True
|
| 121 |
+
|
| 122 |
+
blueprint = picked_blueprint_js
|
| 123 |
+
print(f"Blueprint to API:", blueprint)
|
| 124 |
+
|
| 125 |
+
payload = {
|
| 126 |
+
"inputs": message,
|
| 127 |
+
"blueprint": [blueprint, 'BlueprintScore'],
|
| 128 |
+
"parameters": [{"details": details}, {"local": local}]
|
| 129 |
+
}
|
| 130 |
+
|
| 131 |
+
try:
|
| 132 |
+
response = requests.post(COGN_API_URL, headers=headers, json=payload)
|
| 133 |
+
|
| 134 |
+
if response.status_code == 200:
|
| 135 |
+
api_data = response.json()
|
| 136 |
+
|
| 137 |
+
if 'mw_score' in api_data[1]:
|
| 138 |
+
for protocol, score in api_data[1]['mw_score'].items():
|
| 139 |
+
if protocol in protocol_scores:
|
| 140 |
+
protocol_scores[protocol] = int(score * 100)
|
| 141 |
+
else:
|
| 142 |
+
print(f"Protocol '{protocol}' not found in protocol_scores")
|
| 143 |
+
else:
|
| 144 |
+
print(f"API request failed with status code {response.status_code}")
|
| 145 |
+
return {"error": "API request failed"}
|
| 146 |
+
|
| 147 |
+
except Exception as e:
|
| 148 |
+
print(f"API request failed: {str(e)}")
|
| 149 |
+
return {"error": "API request failed"}
|
| 150 |
+
|
| 151 |
+
return {"success": "Protocol scores updated successfully"}
|
| 152 |
+
|
| 153 |
+
def update_protocols(blueprint_name):
|
| 154 |
+
global protocol_scores, picked_blueprint_js
|
| 155 |
+
|
| 156 |
+
# Find the correct blueprint object
|
| 157 |
+
for blueprint in data["blueprints"]:
|
| 158 |
+
if blueprint["name"] == blueprint_name:
|
| 159 |
+
picked_blueprint_js = blueprint
|
| 160 |
+
break
|
| 161 |
+
|
| 162 |
+
if blueprint_name not in protocols:
|
| 163 |
+
return gr.update(value="")
|
| 164 |
+
|
| 165 |
+
css = """
|
| 166 |
+
<style>
|
| 167 |
+
.protocol-item {
|
| 168 |
+
display: flex;
|
| 169 |
+
align-items: center;
|
| 170 |
+
margin-bottom: 10px;
|
| 171 |
+
width: 100%;
|
| 172 |
+
}
|
| 173 |
+
.protocol-icon {
|
| 174 |
+
width: 24px;
|
| 175 |
+
height: 24px;
|
| 176 |
+
margin-right: 10px;
|
| 177 |
+
flex-shrink: 0;
|
| 178 |
+
}
|
| 179 |
+
.protocol-details {
|
| 180 |
+
display: flex;
|
| 181 |
+
align-items: center;
|
| 182 |
+
flex-grow: 1;
|
| 183 |
+
margin-right: 20px;
|
| 184 |
+
}
|
| 185 |
+
.protocol-name {
|
| 186 |
+
font-weight: bold;
|
| 187 |
+
margin-right: 10px;
|
| 188 |
+
}
|
| 189 |
+
.protocol-score {
|
| 190 |
+
font-size: 0.9em;
|
| 191 |
+
color: #666;
|
| 192 |
+
}
|
| 193 |
+
.progress-container {
|
| 194 |
+
width: 40px;
|
| 195 |
+
height: 40px;
|
| 196 |
+
position: relative;
|
| 197 |
+
flex-shrink: 0;
|
| 198 |
+
}
|
| 199 |
+
.progress-bar {
|
| 200 |
+
width: 100%;
|
| 201 |
+
height: 100%;
|
| 202 |
+
border-radius: 50%;
|
| 203 |
+
background: conic-gradient(#0014FF calc(var(--value) * 3.6deg), #ddd 0deg);
|
| 204 |
+
display: flex;
|
| 205 |
+
align-items: center;
|
| 206 |
+
justify-content: center;
|
| 207 |
+
}
|
| 208 |
+
.progress-bar::before {
|
| 209 |
+
content: "";
|
| 210 |
+
position: absolute;
|
| 211 |
+
inset: 5px;
|
| 212 |
+
background: white;
|
| 213 |
+
border-radius: 50%;
|
| 214 |
+
}
|
| 215 |
+
.progress-text {
|
| 216 |
+
position: absolute;
|
| 217 |
+
top: 50%;
|
| 218 |
+
left: 50%;
|
| 219 |
+
transform: translate(-50%, -50%);
|
| 220 |
+
font-size: 12px;
|
| 221 |
+
color: #333;
|
| 222 |
+
}
|
| 223 |
+
</style>
|
| 224 |
+
"""
|
| 225 |
+
html_output = css
|
| 226 |
+
for title, categories in [("Advice", ["CT", "GP", "GS"]), ("Compliance", ["P"]), ("Insight", ["M"])]:
|
| 227 |
+
all_protocols = [(category, protocol) for category in categories for protocol in protocols[blueprint_name].get(category, [])]
|
| 228 |
+
if all_protocols:
|
| 229 |
+
html_output += f"<h3>{title}</h3>"
|
| 230 |
+
for category, protocol in all_protocols:
|
| 231 |
+
score = protocol_scores[protocol]
|
| 232 |
+
icon = load_svg_icon(category)
|
| 233 |
+
html_output += f'''
|
| 234 |
+
<div class="protocol-item">
|
| 235 |
+
<img src="{icon}" alt="{category}" class="protocol-icon" />
|
| 236 |
+
<div class="protocol-details">
|
| 237 |
+
<span class="protocol-name">{protocol}</span>
|
| 238 |
+
</div>
|
| 239 |
+
<div class="progress-container">
|
| 240 |
+
<div class="progress-bar" style="--value:{score};"></div>
|
| 241 |
+
<div class="progress-text">{score}</div>
|
| 242 |
+
</div>
|
| 243 |
+
</div>
|
| 244 |
+
'''
|
| 245 |
+
return gr.update(value=html_output)
|
| 246 |
+
|
| 247 |
+
def load_svg_icon(icon_type):
|
| 248 |
+
icon_cache = {}
|
| 249 |
+
if icon_type in icon_cache:
|
| 250 |
+
return icon_cache[icon_type]
|
| 251 |
+
icon_path = os.path.join("icons", f"{icon_type}.svg")
|
| 252 |
+
if os.path.exists(icon_path):
|
| 253 |
+
with open(icon_path, "rb") as f:
|
| 254 |
+
svg_content = f.read()
|
| 255 |
+
base64_icon = base64.b64encode(svg_content).decode("utf-8")
|
| 256 |
+
icon_cache[icon_type] = f'data:image/svg+xml;base64,{base64_icon}'
|
| 257 |
+
return icon_cache[icon_type]
|
| 258 |
+
return ""
|
| 259 |
+
|
| 260 |
+
def create_app():
|
| 261 |
+
global protocol_markdown, picked_blueprint_js
|
| 262 |
+
blueprints, protocols, data, default_protocols = load_blueprints_and_protocols()
|
| 263 |
+
initialize_scores()
|
| 264 |
+
picked_blueprint_js = data["blueprints"][DEFAULT_BLUEPRINT_INDEX]
|
| 265 |
+
|
| 266 |
+
is_running = False
|
| 267 |
+
history = []
|
| 268 |
+
conversation = []
|
| 269 |
+
message_index = 0
|
| 270 |
+
|
| 271 |
+
with gr.Blocks(theme=gr.themes.Base(), css="style.css") as app:
|
| 272 |
+
|
| 273 |
+
with gr.Row():
|
| 274 |
+
with gr.Column(scale=3):
|
| 275 |
+
blueprint_radio = gr.Radio(label="", choices=blueprints, type="index", value=DEFAULT_BLUEPRINT_INDEX, elem_classes="gr-radio-row")
|
| 276 |
+
protocol_markdown = gr.HTML(label="Associated Protocols:", value="")
|
| 277 |
+
with gr.Column(scale=0.1):
|
| 278 |
+
gr.HTML("")
|
| 279 |
+
with gr.Column(scale=3):
|
| 280 |
+
conversation_type = gr.Radio(choices=list(conversations.keys()), label="", value=DEFAULT_CONVERSATION_TYPE, elem_classes="gr-radio-row")
|
| 281 |
+
chat_display = gr.HTML()
|
| 282 |
+
with gr.Row():
|
| 283 |
+
start_button = gr.Button("▶")
|
| 284 |
+
pause_button = gr.Button("Pause")
|
| 285 |
+
resume_button = gr.Button("Resume")
|
| 286 |
+
stop_button = gr.Button("Stop")
|
| 287 |
+
num_messages = gr.Slider(minimum=2, maximum=20, value=10, step=1, label="Number of messages", visible=False)
|
| 288 |
+
|
| 289 |
+
# Helper functions to update chat and protocols
|
| 290 |
+
def conversation_type_change_handler(conversation_type):
|
| 291 |
+
stop_conversation()
|
| 292 |
+
return ""
|
| 293 |
+
|
| 294 |
+
def blueprint_change_handler(selected_index):
|
| 295 |
+
global picked_blueprint_js
|
| 296 |
+
blueprint_name = blueprints[selected_index]
|
| 297 |
+
return update_protocols(blueprint_name)
|
| 298 |
+
|
| 299 |
+
# Logic to handle the conversation loop
|
| 300 |
+
def run_conversation(conversation_type, num_messages):
|
| 301 |
+
nonlocal is_running, history, conversation, message_index
|
| 302 |
+
|
| 303 |
+
is_running = True # Start running the conversation
|
| 304 |
+
history = []
|
| 305 |
+
conversation = conversations[conversation_type][:num_messages]
|
| 306 |
+
message_index = 0
|
| 307 |
+
|
| 308 |
+
while is_running and message_index < len(conversation):
|
| 309 |
+
speaker, message = conversation[message_index]
|
| 310 |
+
history.append((speaker, message))
|
| 311 |
+
update_scores(message)
|
| 312 |
+
updated_protocols = update_protocols(picked_blueprint_js["name"])
|
| 313 |
+
message_index += 1
|
| 314 |
+
yield generate_chat_html(), updated_protocols
|
| 315 |
+
time.sleep(0.5) # Introduce a slight delay between messages
|
| 316 |
+
|
| 317 |
+
is_running = False # Reset after conversation completes
|
| 318 |
+
|
| 319 |
+
def generate_chat_html():
|
| 320 |
+
nonlocal history
|
| 321 |
+
chat_html = "<div class='chat-container'>"
|
| 322 |
+
for speaker, message in history:
|
| 323 |
+
chat_html += f"<div class='message {speaker.lower().replace(' ', '-')}'>"
|
| 324 |
+
chat_html += f"<strong>{speaker}:</strong> {message}"
|
| 325 |
+
chat_html += "</div>"
|
| 326 |
+
chat_html += "</div>"
|
| 327 |
+
return chat_html
|
| 328 |
+
|
| 329 |
+
def pause_conversation():
|
| 330 |
+
nonlocal is_running
|
| 331 |
+
is_running = False
|
| 332 |
+
return generate_chat_html(), protocol_markdown.value
|
| 333 |
+
|
| 334 |
+
def resume_conversation():
|
| 335 |
+
nonlocal is_running
|
| 336 |
+
if not is_running:
|
| 337 |
+
is_running = True
|
| 338 |
+
return generate_chat_html(), protocol_markdown.value
|
| 339 |
+
|
| 340 |
+
def stop_conversation():
|
| 341 |
+
nonlocal is_running, history
|
| 342 |
+
is_running = False
|
| 343 |
+
history = []
|
| 344 |
+
return "", protocol_markdown.value
|
| 345 |
+
|
| 346 |
+
# Gradio elements and events
|
| 347 |
+
blueprint_radio.change(
|
| 348 |
+
blueprint_change_handler,
|
| 349 |
+
inputs=[blueprint_radio],
|
| 350 |
+
outputs=[protocol_markdown]
|
| 351 |
+
)
|
| 352 |
+
conversation_type.change(
|
| 353 |
+
conversation_type_change_handler,
|
| 354 |
+
inputs=[conversation_type],
|
| 355 |
+
outputs=[chat_display]
|
| 356 |
+
)
|
| 357 |
+
|
| 358 |
+
start_button.click(
|
| 359 |
+
run_conversation,
|
| 360 |
+
inputs=[conversation_type, num_messages],
|
| 361 |
+
outputs=[chat_display, protocol_markdown]
|
| 362 |
+
)
|
| 363 |
+
|
| 364 |
+
pause_button.click(pause_conversation, outputs=[chat_display, protocol_markdown])
|
| 365 |
+
resume_button.click(resume_conversation, outputs=[chat_display, protocol_markdown])
|
| 366 |
+
stop_button.click(stop_conversation, outputs=[chat_display, protocol_markdown])
|
| 367 |
+
|
| 368 |
+
return app
|
| 369 |
+
|
| 370 |
+
if __name__ == "__main__":
|
| 371 |
+
app = create_app()
|
| 372 |
+
app.launch()
|
icons/CT.svg
ADDED
|
|
icons/GP.svg
ADDED
|
|
icons/GS.svg
ADDED
|
|
icons/M.svg
ADDED
|
|
icons/P.svg
ADDED
|
|
requierements.txt
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#huggingface_hub==0.22.2
|
| 2 |
+
redis==4.5.4
|
styles.css
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
/* Import Poppins font */
|
| 2 |
+
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
|
| 3 |
+
|
| 4 |
+
/* Apply Poppins font to all elements */
|
| 5 |
+
* {
|
| 6 |
+
font-family: 'Poppins', sans-serif !important;
|
| 7 |
+
}
|
| 8 |
+
|
| 9 |
+
/* Button Styles */
|
| 10 |
+
button.svelte-cmf5ev {
|
| 11 |
+
background-color: #356EFF !important;
|
| 12 |
+
border-radius: 25px !important;
|
| 13 |
+
color: white !important;
|
| 14 |
+
}
|
| 15 |
+
|
| 16 |
+
button.svelte-cmf5ev:hover {
|
| 17 |
+
background-color: #0010CC !important;
|
| 18 |
+
}
|
| 19 |
+
|
| 20 |
+
/* Radio Button Styles */
|
| 21 |
+
.gr-radio-row {
|
| 22 |
+
display: flex !important;
|
| 23 |
+
flex-wrap: wrap !important;
|
| 24 |
+
gap: 10px !important;
|
| 25 |
+
}
|
| 26 |
+
|
| 27 |
+
.gr-radio-row input[type="radio"] {
|
| 28 |
+
display: none !important;
|
| 29 |
+
}
|
| 30 |
+
|
| 31 |
+
.gr-radio-row label {
|
| 32 |
+
display: inline-block !important;
|
| 33 |
+
padding: 10px 20px !important;
|
| 34 |
+
background-color: #ffffff !important;
|
| 35 |
+
border: 2px solid #0010CC !important;
|
| 36 |
+
border-radius: 25px !important;
|
| 37 |
+
cursor: pointer !important;
|
| 38 |
+
transition: all 0.3s ease !important;
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
/* Hover State */
|
| 42 |
+
.gr-radio-row label:hover {
|
| 43 |
+
background-color: #0010CC !important;
|
| 44 |
+
color: white !important;
|
| 45 |
+
}
|
| 46 |
+
|
| 47 |
+
.gr-radio-row input[type="radio"]:checked + label {
|
| 48 |
+
background-color: #0010CC !important;
|
| 49 |
+
border-color: #356EFF !important;
|
| 50 |
+
color: white !important;
|
| 51 |
+
}
|
| 52 |
+
|
| 53 |
+
/* Existing styles */
|
| 54 |
+
.gradio-group {
|
| 55 |
+
margin-bottom: 15px;
|
| 56 |
+
}
|
| 57 |
+
|
| 58 |
+
.gradio-slider {
|
| 59 |
+
width: 200px;
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
+
/* Protocol Display */
|
| 63 |
+
div.protocol-item {
|
| 64 |
+
display: inline-flex !important;
|
| 65 |
+
align-items: center;
|
| 66 |
+
margin-bottom: 10px;
|
| 67 |
+
width: 100%;
|
| 68 |
+
}
|
| 69 |
+
|
| 70 |
+
.protocol-icon {
|
| 71 |
+
width: 24px;
|
| 72 |
+
height: 24px;
|
| 73 |
+
margin-right: 10px;
|
| 74 |
+
flex-shrink: 0;
|
| 75 |
+
}
|
| 76 |
+
|
| 77 |
+
.protocol-details {
|
| 78 |
+
display: flex;
|
| 79 |
+
align-items: center;
|
| 80 |
+
flex-grow: 1;
|
| 81 |
+
margin-right: 20px;
|
| 82 |
+
}
|
| 83 |
+
|
| 84 |
+
.protocol-name {
|
| 85 |
+
font-weight: bold;
|
| 86 |
+
margin-right: 10px;
|
| 87 |
+
}
|
| 88 |
+
|
| 89 |
+
.protocol-score {
|
| 90 |
+
font-size: 0.8em;
|
| 91 |
+
color: #666;
|
| 92 |
+
}
|
| 93 |
+
|
| 94 |
+
/* Circular Progress Bar */
|
| 95 |
+
.progress-container {
|
| 96 |
+
width: 40px;
|
| 97 |
+
height: 40px;
|
| 98 |
+
position: relative;
|
| 99 |
+
flex-shrink: 0;
|
| 100 |
+
}
|
| 101 |
+
|
| 102 |
+
.progress-bar {
|
| 103 |
+
width: 100%;
|
| 104 |
+
height: 100%;
|
| 105 |
+
border-radius: 50%;
|
| 106 |
+
background: conic-gradient(#0014FF calc(var(--value) * 3.6deg), #ddd 0deg);
|
| 107 |
+
display: flex;
|
| 108 |
+
align-items: center;
|
| 109 |
+
justify-content: center;
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
.progress-bar::before {
|
| 113 |
+
content: "";
|
| 114 |
+
position: absolute;
|
| 115 |
+
inset: 5px;
|
| 116 |
+
background: white;
|
| 117 |
+
border-radius: 50%;
|
| 118 |
+
}
|
| 119 |
+
|
| 120 |
+
.progress-text {
|
| 121 |
+
position: absolute;
|
| 122 |
+
top: 50%;
|
| 123 |
+
left: 50%;
|
| 124 |
+
transform: translate(-50%, -50%);
|
| 125 |
+
font-size: 12px;
|
| 126 |
+
color: #333;
|
| 127 |
+
}
|
| 128 |
+
|
| 129 |
+
/* Chat Container Styles */
|
| 130 |
+
.chat-container {
|
| 131 |
+
height: 400px;
|
| 132 |
+
overflow-y: auto;
|
| 133 |
+
border: 1px solid #ccc;
|
| 134 |
+
border-radius: 10px;
|
| 135 |
+
padding: 15px;
|
| 136 |
+
margin-bottom: 20px;
|
| 137 |
+
background-color: #f9f9f9;
|
| 138 |
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
| 139 |
+
}
|
| 140 |
+
|
| 141 |
+
/* Ensure the chat section has an initial size */
|
| 142 |
+
#chat_display {
|
| 143 |
+
min-height: 400px;
|
| 144 |
+
width: 100%;
|
| 145 |
+
display: block !important;
|
| 146 |
+
}
|
| 147 |
+
|
| 148 |
+
/* Message Styles */
|
| 149 |
+
.message {
|
| 150 |
+
margin-bottom: 15px;
|
| 151 |
+
padding: 10px 15px;
|
| 152 |
+
border-radius: 18px;
|
| 153 |
+
max-width: 80%;
|
| 154 |
+
position: relative;
|
| 155 |
+
clear: both;
|
| 156 |
+
}
|
| 157 |
+
|
| 158 |
+
.banker, .customer-service, .employee-1 {
|
| 159 |
+
background-color: #E3F2FD;
|
| 160 |
+
color: #1565C0;
|
| 161 |
+
float: left;
|
| 162 |
+
border-bottom-left-radius: 5px;
|
| 163 |
+
}
|
| 164 |
+
|
| 165 |
+
.client, .customer, .employee-2 {
|
| 166 |
+
background-color: #E8EAF6;
|
| 167 |
+
color: #3F51B5;
|
| 168 |
+
float: right;
|
| 169 |
+
border-bottom-right-radius: 5px;
|
| 170 |
+
}
|
| 171 |
+
|
| 172 |
+
/* Add a subtle shadow to messages for depth */
|
| 173 |
+
.message::after {
|
| 174 |
+
content: '';
|
| 175 |
+
position: absolute;
|
| 176 |
+
bottom: 0;
|
| 177 |
+
width: 0;
|
| 178 |
+
height: 0;
|
| 179 |
+
border: 8px solid transparent;
|
| 180 |
+
}
|
| 181 |
+
|
| 182 |
+
.banker::after, .customer-service::after, .employee-1::after {
|
| 183 |
+
left: -8px;
|
| 184 |
+
border-right-color: #E3F2FD;
|
| 185 |
+
border-bottom-color: #E3F2FD;
|
| 186 |
+
}
|
| 187 |
+
|
| 188 |
+
.client::after, .customer::after, .employee-2::after {
|
| 189 |
+
right: -8px;
|
| 190 |
+
border-left-color: #E8EAF6;
|
| 191 |
+
border-bottom-color: #E8EAF6;
|
| 192 |
+
}
|
| 193 |
+
|
| 194 |
+
/* Style for the sender's name */
|
| 195 |
+
.message strong {
|
| 196 |
+
display: block;
|
| 197 |
+
margin-bottom: 5px;
|
| 198 |
+
font-weight: 600;
|
| 199 |
+
}
|