Add services configured, add Streamlit client for interactive chatbot
This commit is contained in:
+30
-13
@@ -6,6 +6,7 @@ function App() {
|
||||
const [messages, setMessages] = useState([]);
|
||||
const [input, setInput] = useState("");
|
||||
const messagesEndRef = useRef(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const sendMessage = async () => {
|
||||
if (!input.trim()) return;
|
||||
@@ -13,16 +14,21 @@ function App() {
|
||||
const userMessage = { role: "user", content: input };
|
||||
setMessages(prev => [...prev, userMessage]);
|
||||
setInput("");
|
||||
setLoading(true); // 🚀 show loader
|
||||
|
||||
const res = await fetch("/chat", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ user_id: "user1", message: input })
|
||||
});
|
||||
try {
|
||||
const res = await fetch("/chat", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ user_id: "user1", message: input })
|
||||
});
|
||||
|
||||
const data = await res.json();
|
||||
const botMessage = { role: "assistant", content: data.response };
|
||||
setMessages(prev => [...prev, botMessage]);
|
||||
const data = await res.json();
|
||||
const botMessage = { role: "assistant", content: data.response };
|
||||
setMessages(prev => [...prev, botMessage]);
|
||||
} finally {
|
||||
setLoading(false); // ✅ hide loader
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -37,11 +43,22 @@ function App() {
|
||||
</div>
|
||||
</header>
|
||||
<div className="chat-box">
|
||||
{messages.map((msg, i) => (
|
||||
<div key={i} className={`p-2 rounded ${msg.role === "user" ? "bg-blue-100 text-right" : "bg-gray-200 text-left"}`}>
|
||||
<ReactMarkdown>{msg.content}</ReactMarkdown>
|
||||
</div>
|
||||
))}
|
||||
{loading && (
|
||||
<div className="d-flex justify-content-start p-2">
|
||||
<div className="spinner-border text-secondary" role="status" style={{width: "1.5rem", height: "1.5rem"}}>
|
||||
<span className="visually-hidden">Thinking...</span>
|
||||
</div>
|
||||
<span className="ms-2 text-muted">The model is processing...</span>
|
||||
</div>
|
||||
)}
|
||||
{messages.map((msg, i) => (
|
||||
<div key={i} className={`d-flex mb-2 ${msg.role === "user" ? "justify-content-end" : "justify-content-start"}`}>
|
||||
<div className={`p-2 rounded shadow-sm ${msg.role === "user" ? "bg-primary text-white" : "bg-light text-dark border" }`} style={{ maxWidth: "75%" }}>
|
||||
<ReactMarkdown>{msg.content}</ReactMarkdown>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div ref={messagesEndRef} />
|
||||
</div>
|
||||
<div className="input-bar d-flex justify-content-center p-3 bg-light border-top">
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
[Unit]
|
||||
Description=LM Studio proxy Python Backend Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=samuele
|
||||
WorkingDirectory=/home/samuele/lm-chat-app/backend
|
||||
ExecStart=/usr/bin/env uvicorn main:app --host 0.0.0.0 --port 8000 --reload
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=LM Studio proxy Node Frontend Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=samuele
|
||||
WorkingDirectory=/home/samuele/lm-chat-app/frontend
|
||||
ExecStart=/home/samuele/lm-chat-app/start-frontend.sh
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=Streamlit LM Studio Chatbot proxy Service
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=samuele
|
||||
WorkingDirectory=/home/samuele/lm-chat-app/streamlit
|
||||
ExecStart=/home/samuele/lm-chat-app/start-streamlit.sh
|
||||
Restart=always
|
||||
RestartSec=1
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
cd /home/samuele/lm-chat-app/streamlit
|
||||
streamlit run app.py
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
## Streamlit chatbot client
|
||||
|
||||
Client Chatbot con update realtime che sfrutta le API di openAI per connettersi a LM Studio locale
|
||||
|
||||
esempio tratto inizialmente da qui:
|
||||
|
||||
https://github.com/ingridstevens/AI-projects/tree/main/streamlit-streaming-langchain
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
####
|
||||
#### Streamlit Streaming using LM Studio as OpenAI Standin
|
||||
#### run with `streamlit run app.py`
|
||||
|
||||
# !pip install pypdf langchain langchain_openai
|
||||
|
||||
import streamlit as st
|
||||
from langchain_core.messages import AIMessage, HumanMessage
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_core.output_parsers import StrOutputParser
|
||||
from langchain_core.prompts import ChatPromptTemplate
|
||||
|
||||
# app config
|
||||
st.set_page_config(page_title="Egalware Chatbot", page_icon="🤖")
|
||||
st.title("Egalware's Streaming Chatbot")
|
||||
|
||||
def get_response(user_query, chat_history):
|
||||
|
||||
template = """
|
||||
You are a helpful assistant. Answer the following questions considering the history of the conversation:
|
||||
|
||||
Chat history: {chat_history}
|
||||
|
||||
User question: {user_question}
|
||||
"""
|
||||
|
||||
prompt = ChatPromptTemplate.from_template(template)
|
||||
|
||||
# Using LM Studio Local Inference Server
|
||||
llm = ChatOpenAI(base_url="http://10.74.83.100:1234/v1",api_key="lm-studio", model="qwen/qwen3-4b-2507")
|
||||
|
||||
chain = prompt | llm | StrOutputParser()
|
||||
|
||||
return chain.stream({
|
||||
"chat_history": chat_history,
|
||||
"user_question": user_query,
|
||||
})
|
||||
|
||||
# session state
|
||||
if "chat_history" not in st.session_state:
|
||||
st.session_state.chat_history = [
|
||||
AIMessage(content="Hello, I am a bot. How can I help you?"),
|
||||
]
|
||||
|
||||
|
||||
# conversation
|
||||
for message in st.session_state.chat_history:
|
||||
if isinstance(message, AIMessage):
|
||||
with st.chat_message("AI"):
|
||||
st.write(message.content)
|
||||
elif isinstance(message, HumanMessage):
|
||||
with st.chat_message("Human"):
|
||||
st.write(message.content)
|
||||
|
||||
# user input
|
||||
user_query = st.chat_input("Type your message here...")
|
||||
if user_query is not None and user_query != "":
|
||||
st.session_state.chat_history.append(HumanMessage(content=user_query))
|
||||
|
||||
with st.chat_message("Human"):
|
||||
st.markdown(user_query)
|
||||
|
||||
with st.chat_message("AI"):
|
||||
response = st.write_stream(get_response(user_query, st.session_state.chat_history))
|
||||
|
||||
st.session_state.chat_history.append(AIMessage(content=response))
|
||||
Reference in New Issue
Block a user