Spaces:
Running
Running
Refactor chat functionality and update dependencies
Browse files- Replaced the client initialization with a direct call to claude_llm.
- Enhanced chat function to stream responses from the LLM.
- Updated AWS region in the client configuration.
- Added user loading utility and user data CSV.
- Introduced custom CSS for UI styling.
- Added logo image for branding.
- app.py +52 -33
- bedrock_client.py +15 -2
- requirements.txt +2 -1
- static/deval.css +28 -0
- static/logo.png +0 -0
- user.csv +3 -0
- utils.py +10 -0
app.py
CHANGED
@@ -1,42 +1,61 @@
|
|
1 |
import gradio as gr
|
2 |
-
import
|
3 |
-
from
|
4 |
|
5 |
-
|
6 |
-
client = get_anthropic_client()
|
7 |
|
8 |
-
# Streaming chat handler
|
9 |
-
async def chat(user_message, history):
|
10 |
-
messages = history.copy()
|
11 |
-
messages.append({"role": "user", "content": user_message})
|
12 |
|
13 |
-
|
|
|
|
|
14 |
|
15 |
-
|
16 |
-
|
17 |
-
|
|
|
|
|
|
|
|
|
|
|
18 |
|
19 |
-
|
20 |
-
|
21 |
-
yield messages + [{"role": "assistant", "content": full_response}]
|
22 |
-
|
23 |
-
# Append full assistant response to history
|
24 |
-
messages.append({"role": "assistant", "content": full_response})
|
25 |
yield messages
|
26 |
|
27 |
-
# Gradio UI
|
28 |
-
with gr.Blocks() as demo:
|
29 |
-
gr.Markdown("# π€ DevalBot")
|
30 |
-
chatbot = gr.Chatbot(label="Claude v2.1", type="messages")
|
31 |
-
msg = gr.Textbox(placeholder="Ask Claude anything...", show_label=False)
|
32 |
-
state = gr.State([]) # chat history
|
33 |
-
clear = gr.Button("π§Ή Clear Chat")
|
34 |
-
|
35 |
-
def clear_chat():
|
36 |
-
return [], []
|
37 |
-
|
38 |
-
msg.submit(chat, [msg, state], chatbot, queue=True)
|
39 |
-
msg.submit(lambda: "", None, msg) # clear input
|
40 |
-
clear.click(clear_chat, None, [chatbot, state])
|
41 |
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
import gradio as gr
|
2 |
+
from bedrock_client import claude_llm
|
3 |
+
from utils import load_users
|
4 |
|
5 |
+
AUTHS = load_users('user.csv')
|
|
|
6 |
|
|
|
|
|
|
|
|
|
7 |
|
8 |
+
def chat(user_message, history):
|
9 |
+
# append the user message
|
10 |
+
messages = history + [{"role":"user","content":user_message}]
|
11 |
|
12 |
+
# pick the right LLM
|
13 |
+
llm = claude_llm
|
14 |
+
full = ""
|
15 |
+
# stream tokens as they arrive
|
16 |
+
for token in llm.stream(user_message):
|
17 |
+
full += token
|
18 |
+
# yield an updated history snapshot
|
19 |
+
yield messages + [{"role":"assistant","content": full}]
|
20 |
|
21 |
+
# final history
|
22 |
+
messages.append({"role":"assistant","content":full})
|
|
|
|
|
|
|
|
|
23 |
yield messages
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
+
with gr.Blocks(css_paths=["static/deval.css"],theme = gr.themes.Default(primary_hue="blue", secondary_hue="yellow"),) as demo:
|
27 |
+
# ββ Logo + Header + Logout ββββββββββββββββββββββββββββββββ
|
28 |
+
|
29 |
+
gr.Image(
|
30 |
+
value="static/logo.png",
|
31 |
+
show_label=False,
|
32 |
+
interactive=False,
|
33 |
+
show_download_button=False,
|
34 |
+
show_fullscreen_button=False,
|
35 |
+
elem_id="logo-primary", # matches the CSS above
|
36 |
+
)
|
37 |
+
|
38 |
+
#logout_btn = gr.Button("Logout", elem_id="logout-btn")
|
39 |
+
# inject auto-reload script
|
40 |
+
gr.HTML(
|
41 |
+
"""
|
42 |
+
<script>
|
43 |
+
// Reload the page after 1 minutes (300β000 ms)
|
44 |
+
setTimeout(() => {
|
45 |
+
window.location.reload();
|
46 |
+
}, 1000);
|
47 |
+
</script>
|
48 |
+
"""
|
49 |
+
)
|
50 |
+
gr.ChatInterface(
|
51 |
+
chat,
|
52 |
+
type="messages",
|
53 |
+
editable=True,
|
54 |
+
concurrency_limit=200,
|
55 |
+
save_history=True,
|
56 |
+
)
|
57 |
+
|
58 |
+
|
59 |
+
|
60 |
+
demo.queue() \
|
61 |
+
.launch(auth=AUTHS)
|
bedrock_client.py
CHANGED
@@ -1,11 +1,12 @@
|
|
1 |
from anthropic import AnthropicBedrock
|
|
|
2 |
import os
|
3 |
|
4 |
def get_anthropic_client():
|
5 |
return AnthropicBedrock(
|
6 |
aws_access_key=os.environ["AWS_ACCESS_KEY_ID"],
|
7 |
aws_secret_key=os.environ["AWS_SECRET_ACCESS_KEY"],
|
8 |
-
aws_region=os.environ.get("AWS_DEFAULT_REGION", "
|
9 |
)
|
10 |
|
11 |
def claude_stream_response(messages, client):
|
@@ -22,4 +23,16 @@ def claude_stream_response(messages, client):
|
|
22 |
if event.type == "content_block_delta":
|
23 |
text = getattr(event.delta, "text", None)
|
24 |
if text:
|
25 |
-
yield text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from anthropic import AnthropicBedrock
|
2 |
+
from langchain_aws.llms.bedrock import BedrockLLM
|
3 |
import os
|
4 |
|
5 |
def get_anthropic_client():
|
6 |
return AnthropicBedrock(
|
7 |
aws_access_key=os.environ["AWS_ACCESS_KEY_ID"],
|
8 |
aws_secret_key=os.environ["AWS_SECRET_ACCESS_KEY"],
|
9 |
+
aws_region=os.environ.get("AWS_DEFAULT_REGION", "eu-central-1")
|
10 |
)
|
11 |
|
12 |
def claude_stream_response(messages, client):
|
|
|
23 |
if event.type == "content_block_delta":
|
24 |
text = getattr(event.delta, "text", None)
|
25 |
if text:
|
26 |
+
yield text
|
27 |
+
|
28 |
+
|
29 |
+
|
30 |
+
claude_llm = BedrockLLM(
|
31 |
+
aws_access_key_id = os.environ["AWS_ACCESS_KEY_ID"],
|
32 |
+
aws_secret_access_key = os.environ["AWS_SECRET_ACCESS_KEY"],
|
33 |
+
region_name = "eu-central-1",
|
34 |
+
provider = "anthropic",
|
35 |
+
model_id = "anthropic.claude-v2:1",
|
36 |
+
streaming = True,
|
37 |
+
model_kwargs = {"temperature": 0.7},
|
38 |
+
)
|
requirements.txt
CHANGED
@@ -4,4 +4,5 @@ botocore
|
|
4 |
fastapi
|
5 |
uvicorn
|
6 |
aiofiles
|
7 |
-
anthropic
|
|
|
|
4 |
fastapi
|
5 |
uvicorn
|
6 |
aiofiles
|
7 |
+
anthropic[bedrock]>=0.50.0
|
8 |
+
langchain-aws>=0.2.17
|
static/deval.css
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* ββ Brand overrides βββββββββββββββββββββββββββββββββββββββββββ */
|
2 |
+
:root {
|
3 |
+
--color-brand-primary: #E7AB12;
|
4 |
+
--color-brand-secondary: #0D456C;
|
5 |
+
}
|
6 |
+
|
7 |
+
|
8 |
+
/* ββ Page background βββββββββββββββββββββββββββββ */
|
9 |
+
body, .gradio-container {
|
10 |
+
background-color: #F2F6F8 !important; /* your desired page bg */
|
11 |
+
}
|
12 |
+
|
13 |
+
/* ββ All buttons βββββββββββββββββββββββββββββββββ */
|
14 |
+
button.gr-button {
|
15 |
+
background-color: #0D456C !important; /* your desired button bg */
|
16 |
+
color: #F2F6F8 !important; /* button text color */
|
17 |
+
}
|
18 |
+
|
19 |
+
/* optional: hover state */
|
20 |
+
button.gr-button:hover {
|
21 |
+
background-color: #0056b3 !important;
|
22 |
+
}
|
23 |
+
|
24 |
+
/* ββ Global button look ββββββββββββββββββββββββββββββββββββββββ */
|
25 |
+
button.gr-button {
|
26 |
+
background-color: #0D456C !important;
|
27 |
+
color: #E7AB12 !important;
|
28 |
+
}
|
static/logo.png
ADDED
![]() |
user.csv
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
users,passwords
|
2 |
+
alice,pw1
|
3 |
+
bob,pw2
|
utils.py
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import csv
|
2 |
+
|
3 |
+
def load_users(path):
|
4 |
+
"""
|
5 |
+
Reads a CSV with header 'users,passwords'
|
6 |
+
and returns a list of (user, password) tuples.
|
7 |
+
"""
|
8 |
+
with open(path, newline="", encoding="utf-8") as f:
|
9 |
+
reader = csv.DictReader(f)
|
10 |
+
return [(row["users"], row["passwords"]) for row in reader]
|