# chatbot.py
import openai
import streamlit as st
import wandb
from set_env import set_env
import weave
_ = set_env("OPENAI_API_KEY")
_ = set_env("WANDB_API_KEY")
wandb.login()
weave_client = weave.init("feedback-example")
oai_client = openai.OpenAI()
def init_states():
"""Configurer les clés session_state si elles n'existent pas encore."""
if "messages" not in st.session_state:
st.session_state["messages"] = []
if "calls" not in st.session_state:
st.session_state["calls"] = []
if "session_id" not in st.session_state:
st.session_state["session_id"] = "123abc"
@weave.op
def chat_response(full_history):
"""
Appelle l'API OpenAI en mode streaming en tenant compte de l'intégralité de l'historique de conversation jusqu'à présent.
full_history est une liste de dicts : [{"role":"user"|"assistant","content":...}, ...]
"""
stream = oai_client.chat.completions.create(
model="gpt-4", messages=full_history, stream=True
)
response_text = st.write_stream(stream)
return {"response": response_text}
def render_feedback_buttons(call_idx):
"""Affiche les boutons pouce haut/bas et le feedback textuel pour l'appel."""
col1, col2, col3 = st.columns([1, 1, 4])
# Bouton pouce haut
with col1:
if st.button("👍", key=f"thumbs_up_{call_idx}"):
st.session_state.calls[call_idx].feedback.add_reaction("👍")
st.success("Thanks for the feedback!")
# Bouton pouce bas
with col2:
if st.button("👎", key=f"thumbs_down_{call_idx}"):
st.session_state.calls[call_idx].feedback.add_reaction("👎")
st.success("Thanks for the feedback!")
# Feedback textuel
with col3:
feedback_text = st.text_input("Feedback", key=f"feedback_input_{call_idx}")
if (
st.button("Submit Feedback", key=f"submit_feedback_{call_idx}")
and feedback_text
):
st.session_state.calls[call_idx].feedback.add_note(feedback_text)
st.success("Feedback submitted!")
def display_old_messages():
"""Affiche la conversation stockée dans st.session_state.messages avec les boutons de feedback"""
for idx, message in enumerate(st.session_state.messages):
with st.chat_message(message["role"]):
st.markdown(message["content"])
# S'il s'agit d'un message de l'assistant, afficher le formulaire de feedback
if message["role"] == "assistant":
# Déterminer l'index de ce message de l'assistant dans st.session_state.calls
assistant_idx = (
len(
[
m
for m in st.session_state.messages[: idx + 1]
if m["role"] == "assistant"
]
)
- 1
)
# Afficher les boutons pouce haut/bas et le feedback textuel
if assistant_idx < len(st.session_state.calls):
render_feedback_buttons(assistant_idx)
def display_chat_prompt():
"""Affiche la zone de saisie du prompt de chat."""
if prompt := st.chat_input("Ask me anything!"):
# Afficher immédiatement le nouveau message de l'utilisateur
with st.chat_message("user"):
st.markdown(prompt)
# Enregistrer le message de l'utilisateur dans la session
st.session_state.messages.append({"role": "user", "content": prompt})
# Préparer l'historique de chat pour l'API
full_history = [
{"role": msg["role"], "content": msg["content"]}
for msg in st.session_state.messages
]
with st.chat_message("assistant"):
# Associer les attributs Weave pour le suivi des instances de conversation
with weave.attributes(
{"session": st.session_state["session_id"], "env": "prod"}
):
# Appeler l'API OpenAI (stream)
result, call = chat_response.call(full_history)
# Stocker le message de l'assistant
st.session_state.messages.append(
{"role": "assistant", "content": result["response"]}
)
# Stocker l'objet d'appel Weave pour associer le feedback à la réponse concernée
st.session_state.calls.append(call)
# Afficher les boutons de feedback pour le nouveau message
new_assistant_idx = (
len(
[
m
for m in st.session_state.messages
if m["role"] == "assistant"
]
)
- 1
)
# Afficher les boutons de feedback
if new_assistant_idx < len(st.session_state.calls):
render_feedback_buttons(new_assistant_idx)
def main():
st.title("Chatbot with immediate feedback forms")
init_states()
display_old_messages()
display_chat_prompt()
if __name__ == "__main__":
main()