Skip to content

Commit a6162bd

Browse files
author
reidliu41
committed
[doc] add streamlit integration
Signed-off-by: reidliu41 <[email protected]>
1 parent 26bc4bb commit a6162bd

File tree

3 files changed

+200
-0
lines changed

3 files changed

+200
-0
lines changed
Loading

docs/source/deployment/frameworks/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@ lws
1212
modal
1313
open-webui
1414
skypilot
15+
streamlit
1516
triton
1617
:::
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
(deployment-streamlit)=
2+
3+
# Streamlit
4+
5+
[Streamlit](https://github.com/streamlit/streamlit) lets you transform Python scripts into interactive web apps in minutes, instead of weeks. Build dashboards, generate reports, or create chat apps.
6+
7+
## Prerequisites
8+
9+
- Setup vLLM environment
10+
11+
## Deploy
12+
13+
- Start the vLLM server with the supported chat completion model, e.g.
14+
15+
```console
16+
vllm serve qwen/Qwen1.5-0.5B-Chat
17+
```
18+
19+
- Install streamlit and openai:
20+
21+
```console
22+
pip install streamlit openai
23+
```
24+
25+
- Create python file(streamlit-ui-app.py) and copy the below code into it:
26+
27+
```console
28+
import streamlit as st
29+
from openai import OpenAI
30+
from datetime import datetime
31+
import os
32+
33+
# Get command line arguments from environment variables
34+
openai_api_key = os.getenv('VLLM_API_KEY', "EMPTY")
35+
openai_api_base = os.getenv('VLLM_API_BASE', "http://localhost:8000/v1")
36+
37+
# Initialize session states for managing chat sessions
38+
if "sessions" not in st.session_state:
39+
st.session_state.sessions = {}
40+
41+
if "current_session" not in st.session_state:
42+
st.session_state.current_session = None
43+
44+
if "messages" not in st.session_state:
45+
st.session_state.messages = []
46+
47+
if "active_session" not in st.session_state:
48+
st.session_state.active_session = None
49+
50+
# Initialize session state for API base URL
51+
if "api_base_url" not in st.session_state:
52+
st.session_state.api_base_url = openai_api_base
53+
54+
def create_new_chat_session():
55+
"""Create a new chat session with timestamp as ID"""
56+
session_id = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
57+
st.session_state.sessions[session_id] = []
58+
st.session_state.current_session = session_id
59+
st.session_state.active_session = session_id
60+
st.session_state.messages = []
61+
62+
def switch_to_chat_session(session_id):
63+
"""Switch to a different chat session"""
64+
st.session_state.current_session = session_id
65+
st.session_state.active_session = session_id
66+
st.session_state.messages = st.session_state.sessions[session_id]
67+
68+
def get_llm_response(messages, model):
69+
"""Get streaming response from llm
70+
71+
Args:
72+
messages: List of message dictionaries
73+
model: Name of model
74+
75+
Returns:
76+
Streaming response object or error message string
77+
"""
78+
try:
79+
response = client.chat.completions.create(
80+
model=model,
81+
messages=messages,
82+
stream=True
83+
)
84+
return response
85+
except Exception as e:
86+
st.error(f"Error details: {str(e)}")
87+
return f"Error: {str(e)}"
88+
89+
# Sidebar - API Settings first
90+
st.sidebar.title("API Settings")
91+
new_api_base = st.sidebar.text_input("API Base URL:", value=st.session_state.api_base_url)
92+
if new_api_base != st.session_state.api_base_url:
93+
st.session_state.api_base_url = new_api_base
94+
st.rerun()
95+
96+
st.sidebar.divider()
97+
98+
# Sidebar - Session Management
99+
st.sidebar.title("Chat Sessions")
100+
if st.sidebar.button("New Session"):
101+
create_new_chat_session()
102+
103+
# Display all sessions in reverse chronological order
104+
for session_id in sorted(st.session_state.sessions.keys(), reverse=True):
105+
# Mark the active session with a pinned button
106+
if session_id == st.session_state.active_session:
107+
st.sidebar.button(
108+
f"📍 {session_id}",
109+
key=session_id,
110+
type="primary",
111+
on_click=switch_to_chat_session,
112+
args=(session_id,)
113+
)
114+
else:
115+
st.sidebar.button(
116+
f"Session {session_id}",
117+
key=session_id,
118+
on_click=switch_to_chat_session,
119+
args=(session_id,)
120+
)
121+
122+
# Main interface
123+
st.title("vLLM Chat Assistant")
124+
125+
# Initialize OpenAI client with API settings
126+
client = OpenAI(
127+
api_key=openai_api_key,
128+
base_url=st.session_state.api_base_url
129+
)
130+
131+
# Get and display current model id
132+
models = client.models.list()
133+
model = models.data[0].id
134+
st.markdown(f"**Model**: {model}")
135+
136+
# Initialize first session if none exists
137+
if st.session_state.current_session is None:
138+
create_new_chat_session()
139+
st.session_state.active_session = st.session_state.current_session
140+
141+
# Display chat history for current session
142+
for message in st.session_state.messages:
143+
with st.chat_message(message["role"]):
144+
st.write(message["content"])
145+
146+
# Handle user input and generate llm response
147+
if prompt := st.chat_input("Type your message here..."):
148+
# Save user message to session
149+
st.session_state.messages.append({"role": "user", "content": prompt})
150+
st.session_state.sessions[st.session_state.current_session] = st.session_state.messages
151+
152+
# Display user message
153+
with st.chat_message("user"):
154+
st.write(prompt)
155+
156+
# Prepare messages for llm
157+
messages_for_llm = [
158+
{"role": m["role"], "content": m["content"]}
159+
for m in st.session_state.messages
160+
]
161+
162+
# Generate and display llm response
163+
with st.chat_message("assistant"):
164+
message_placeholder = st.empty()
165+
full_response = ""
166+
167+
# Get streaming response from llm
168+
response = get_llm_response(messages_for_llm, model)
169+
if isinstance(response, str):
170+
message_placeholder.markdown(response)
171+
full_response = response
172+
else:
173+
for chunk in response:
174+
if hasattr(chunk.choices[0].delta, "content"):
175+
content = chunk.choices[0].delta.content
176+
if content:
177+
full_response += content
178+
message_placeholder.markdown(full_response + "▌")
179+
180+
message_placeholder.markdown(full_response)
181+
182+
# Save llm response to session history
183+
st.session_state.messages.append({"role": "assistant", "content": full_response})
184+
```
185+
186+
- Start the streamlit web UI and start to chat:
187+
188+
```console
189+
streamlit run streamlit-ui-app.py
190+
191+
# or specify the VLLM_API_BASE or VLLM_API_KEY
192+
VLLM_API_BASE="http://vllm-server-host:vllm-server-port/v1" streamlit run streamlit-ui-app.py
193+
194+
# start with debug mode to view more details
195+
streamlit run streamlit-ui-app.py --logger.level=debug
196+
```
197+
198+
:::{image} /assets/deployment/streamlit-chat.png
199+
:::

0 commit comments

Comments
 (0)