SiennaClarke commited on
Commit
f9fbe82
·
verified ·
1 Parent(s): 19b8d9f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +76 -125
app.py CHANGED
@@ -2,138 +2,89 @@ import streamlit as st
2
  from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
3
  from threading import Thread
4
  import torch
5
- import time
6
 
7
- # 1. Advanced CSS: Branding, Animations, and Split-Pane Artifacts
8
- st.set_page_config(page_title="Claude", page_icon="☁️", layout="wide")
9
 
10
- # Claude's exact 2026 color palette
11
- CLAUDE_ORANGE = "#d97757"
12
- CLAUDE_PAPER = "#f9f9f8"
13
-
14
- st.markdown(f"""
15
- <style>
16
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
17
-
18
- .stApp {{ background-color: #ffffff; font-family: 'Inter', sans-serif; }}
19
-
20
- /* Sidebar: warm paper texture */
21
- [data-testid="stSidebar"] {{
22
- background-color: {CLAUDE_PAPER} !important;
23
- border-right: 1px solid #e5e5e5 !important;
24
- }}
25
-
26
- /* The "Living Avatar" Animation - Moving Lines Effect */
27
- @keyframes breathe {{
28
- 0% {{ transform: scale(1); opacity: 0.8; }}
29
- 50% {{ transform: scale(1.05); opacity: 1; }}
30
- 100% {{ transform: scale(1); opacity: 0.8; }}
31
- }}
32
-
33
- [data-testid="chatAvatarAssistant"] {{
34
- background-color: {CLAUDE_ORANGE} !important;
35
- border-radius: 8px !important;
36
- animation: breathe 3s infinite ease-in-out;
37
- box-shadow: 0 0 15px rgba(217, 119, 87, 0.2);
38
- }}
39
-
40
- /* Artifacts Window Styling */
41
- .artifact-container {{
42
- background-color: #fcfcfb;
43
- border: 1px solid #e5e5e5;
44
- border-radius: 12px;
45
- padding: 20px;
46
- height: 80vh;
47
- overflow-y: auto;
48
- box-shadow: inset 0 0 10px rgba(0,0,0,0.02);
49
- }}
50
-
51
- /* Floating Input Bar */
52
- .stChatInputContainer {{
53
- border: 1px solid #d1d1d1 !important;
54
- border-radius: 16px !important;
55
- box-shadow: 0 8px 32px rgba(0,0,0,0.06) !important;
56
- max-width: 800px !important;
57
- margin: 0 auto 20px auto !important;
58
- }}
59
-
60
- header, footer {{ visibility: hidden; }}
61
- </style>
62
- """, unsafe_allow_html=True)
63
-
64
- # 2. Model Initialization
65
  @st.cache_resource
66
- def load_llm():
67
- model_id = "Qwen/Qwen2.5-3B-Instruct" # Highest 2026 performance/efficiency ratio
68
  tokenizer = AutoTokenizer.from_pretrained(model_id)
69
- model = AutoModelForCausalLM.from_pretrained(model_id, torch_dtype=torch.bfloat16, device_map="auto")
70
- return model, tokenizer
71
-
72
- model, tokenizer = load_llm()
73
-
74
- # 3. Sidebar: Context & Settings
75
- with st.sidebar:
76
- st.markdown(f"<h2 style='color: #1a1a1a; font-size: 1.25rem;'>Claude 3.5 Sonnet</h2>", unsafe_allow_html=True)
77
- if st.button("+ Start New Chat", use_container_width=True):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  st.session_state.messages = []
79
- st.session_state.artifact_content = ""
80
  st.rerun()
81
-
82
- st.divider()
83
- st.caption("CAPABILITIES")
84
- show_artifacts = st.toggle("Artifacts (Preview)", value=True)
85
- st.caption("Recent Artifacts")
86
- if st.session_state.get("artifact_content"):
87
- st.info("📄 current_code_snippet.py")
88
-
89
- # 4. Layout Definition (Chat vs Artifacts)
90
- if show_artifacts and st.session_state.get("artifact_content"):
91
- col_chat, col_art = st.columns([1, 1], gap="large")
92
- else:
93
- col_chat = st.container()
94
- col_art = None
95
-
96
- # 5. Chat Logic
97
- if "messages" not in st.session_state: st.session_state.messages = []
98
- if "artifact_content" not in st.session_state: st.session_state.artifact_content = ""
99
-
100
- with col_chat:
101
- # Landing View
102
- if not st.session_state.messages:
103
- st.markdown("<div style='height: 10vh;'></div>", unsafe_allow_html=True)
104
- st.markdown("<h1 style='text-align: center; font-weight: 500;'>How can I help you today?</h1>", unsafe_allow_html=True)
105
 
106
- for m in st.session_state.messages:
107
- with st.chat_message(m["role"]):
108
- st.markdown(m["content"])
109
 
110
- if prompt := st.chat_input("Ask Claude..."):
111
- st.session_state.messages.append({"role": "user", "content": prompt})
112
- with st.chat_message("user"): st.markdown(prompt)
113
 
114
- with st.chat_message("assistant"):
115
- streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
116
- msgs = [{"role": "system", "content": "You are Claude. If the user asks for code, provide it clearly."}] + st.session_state.messages[-6:]
117
- inputs = tokenizer.apply_chat_template(msgs, tokenize=True, add_generation_prompt=True, return_tensors="pt").to(model.device)
118
-
119
- thread = Thread(target=model.generate, kwargs=dict(input_ids=inputs, streamer=streamer, max_new_tokens=1024))
120
- thread.start()
121
-
122
- full_response = st.write_stream(streamer)
123
-
124
- # Detect if response contains code to trigger "Artifact"
125
- if "```" in full_response:
126
- code_content = full_response.split("```")[1]
127
- st.session_state.artifact_content = code_content
128
- st.rerun()
129
 
130
- st.session_state.messages.append({"role": "assistant", "content": full_response})
131
-
132
- # 6. Artifact Display (Right Panel)
133
- if col_art and st.session_state.artifact_content:
134
- with col_art:
135
- st.markdown("<p style='font-size: 0.8rem; color: #6e6e6e; margin-bottom: 5px;'>ARTIFACT</p>", unsafe_allow_html=True)
136
- with st.container(border=True):
137
- st.code(st.session_state.artifact_content, language="python")
138
- if st.button("Copy to Clipboard"):
139
- st.toast("Code copied!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
3
  from threading import Thread
4
  import torch
 
5
 
6
+ # App Configuration
7
+ st.set_page_config(page_title="Qwen3 Turbo", page_icon="")
8
 
9
+ # 1. Load Qwen3 (Cached for efficiency)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  @st.cache_resource
11
+ def load_qwen3():
12
+ model_id = "Qwen/Qwen3-1.7B-Instruct"
13
  tokenizer = AutoTokenizer.from_pretrained(model_id)
14
+ model = AutoModelForCausalLM.from_pretrained(
15
+ model_id,
16
+ torch_dtype="auto",
17
+ device_map="auto"
18
+ )
19
+ return tokenizer, model
20
+
21
+ tokenizer, model = load_qwen3()
22
+
23
+ # 2. System Prompt Selection (Main UI, No Sidebar)
24
+ st.title("⚡ Qwen3-1.7B Local Chat")
25
+
26
+ system_options = {
27
+ "General Assistant": "You are a helpful and concise assistant.",
28
+ "Python Expert": "You are an expert Python developer. Provide clean, efficient code with brief explanations.",
29
+ "Creative Storyteller": "You are a creative writer. Use vivid imagery and engaging narrative styles."
30
+ }
31
+
32
+ # Horizontal layout for the selector and a clear button
33
+ col1, col2 = st.columns([3, 1])
34
+ with col1:
35
+ selected_role = st.selectbox("Choose AI Personality:", list(system_options.keys()))
36
+ with col2:
37
+ if st.button("Clear History", use_container_width=True):
38
  st.session_state.messages = []
 
39
  st.rerun()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
+ system_prompt = system_options[selected_role]
 
 
42
 
43
+ # 3. Setup Session State
44
+ if "messages" not in st.session_state:
45
+ st.session_state.messages = []
46
 
47
+ # Display Chat History
48
+ for message in st.session_state.messages:
49
+ if message["role"] != "system": # Hide system prompt from UI
50
+ with st.chat_message(message["role"]):
51
+ st.markdown(message["content"])
 
 
 
 
 
 
 
 
 
 
52
 
53
+ # 4. Chat Input & Streaming
54
+ if prompt := st.chat_input("Message Qwen3..."):
55
+ # Insert system prompt if history is empty
56
+ if len(st.session_state.messages) == 0:
57
+ st.session_state.messages.append({"role": "system", "content": system_prompt})
58
+
59
+ # Add User Message
60
+ st.session_state.messages.append({"role": "user", "content": prompt})
61
+ with st.chat_message("user"):
62
+ st.markdown(prompt)
63
+
64
+ # Generate Assistant Response
65
+ with st.chat_message("assistant"):
66
+ # Prepare input with chat template
67
+ input_ids = tokenizer.apply_chat_template(
68
+ st.session_state.messages,
69
+ tokenize=True,
70
+ add_generation_prompt=True,
71
+ return_tensors="pt"
72
+ ).to(model.device)
73
+
74
+ streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
75
+
76
+ generation_kwargs = dict(
77
+ input_ids=input_ids,
78
+ streamer=streamer,
79
+ max_new_tokens=1024,
80
+ temperature=0.7
81
+ )
82
+
83
+ # Threaded generation for real-time streaming
84
+ thread = Thread(target=model.generate, kwargs=generation_kwargs)
85
+ thread.start()
86
+
87
+ # Stream the output
88
+ full_response = st.write_stream(streamer)
89
+
90
+ st.session_state.messages.append({"role": "assistant", "content": full_response})