forked from patchy631/ai-engineering-hub
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
121 lines (102 loc) · 4.35 KB
/
Copy pathapp.py
File metadata and controls
121 lines (102 loc) · 4.35 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import re
import base64
import streamlit as st
from ollama import chat
# Set Streamlit page configuration (optional)
st.set_page_config(page_title="Ollama Streaming Chat", layout="centered")
def format_reasoning_response(thinking_content):
"""Format assistant content by removing think tags."""
return (
thinking_content.replace("<think>\n\n</think>", "")
.replace("<think>", "")
.replace("</think>", "")
)
def display_message(message):
"""Display a single message in the chat interface."""
role = "user" if message["role"] == "user" else "assistant"
with st.chat_message(role):
if role == "assistant":
display_assistant_message(message["content"])
else:
st.markdown(message["content"])
def display_assistant_message(content):
"""Display assistant message with thinking content if present."""
pattern = r"<think>(.*?)</think>"
think_match = re.search(pattern, content, re.DOTALL)
if think_match:
think_content = think_match.group(0)
response_content = content.replace(think_content, "")
think_content = format_reasoning_response(think_content)
with st.expander("Thinking complete!"):
st.markdown(think_content)
st.markdown(response_content)
else:
st.markdown(content)
def display_chat_history():
"""Display all previous messages in the chat history."""
for message in st.session_state["messages"]:
if message["role"] != "system": # Skip system messages
display_message(message)
def process_thinking_phase(stream):
"""Process the thinking phase of the assistant's response."""
thinking_content = ""
with st.status("Thinking...", expanded=True) as status:
think_placeholder = st.empty()
for chunk in stream:
content = chunk["message"]["content"] or ""
thinking_content += content
if "<think>" in content:
continue
if "</think>" in content:
content = content.replace("</think>", "")
status.update(label="Thinking complete!", state="complete", expanded=False)
break
think_placeholder.markdown(format_reasoning_response(thinking_content))
return thinking_content
def process_response_phase(stream):
"""Process the response phase of the assistant's response."""
response_placeholder = st.empty()
response_content = ""
for chunk in stream:
content = chunk["message"]["content"] or ""
response_content += content
response_placeholder.markdown(response_content)
return response_content
@st.cache_resource
def get_chat_model():
"""Get a cached instance of the chat model."""
return lambda messages: chat(
model="qwen3:4b",
messages=messages,
stream=True,
)
def handle_user_input():
"""Handle new user input and generate assistant response."""
if user_input := st.chat_input("Type your message here..."):
st.session_state["messages"].append({"role": "user", "content": user_input})
with st.chat_message("user"):
st.markdown(user_input)
with st.chat_message("assistant"):
chat_model = get_chat_model()
stream = chat_model(st.session_state["messages"])
thinking_content = process_thinking_phase(stream)
response_content = process_response_phase(stream)
# Save the complete response
st.session_state["messages"].append(
{"role": "assistant", "content": thinking_content + response_content}
)
def main():
"""Main function to handle the chat interface and streaming responses."""
st.markdown("""
# Mini ChatGPT powered by <img src="data:image/png;base64,{}" width="170" style="vertical-align: -20px;">
""".format(base64.b64encode(open("assets/logo_qwen3.png", "rb").read()).decode()), unsafe_allow_html=True)
st.markdown("<h4 style='text-align: center;'>With thinking UI! 💡</h4>", unsafe_allow_html=True)
display_chat_history()
handle_user_input()
if __name__ == "__main__":
# Initialize session state
if "messages" not in st.session_state:
st.session_state["messages"] = [
{"role": "system", "content": "You are a helpful assistant."}
]
main()