Queer European MD passionate about IT

Mission903Solutions.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. from openai import OpenAI
  2. import tiktoken
  3. import json
  4. from datetime import datetime
  5. import os
  6. import streamlit as st
  7. api_key = os.environ["OPENAI_API_KEY"]
  8. class ConversationManager:
  9. def __init__(self, api_key, base_url="https://api.openai.com/v1", history_file=None, default_model="gpt-3.5-turbo", default_temperature=0.7, default_max_tokens=150, token_budget=4096):
  10. self.client = OpenAI(api_key=api_key)
  11. self.base_url = base_url
  12. if history_file is None:
  13. timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
  14. self.history_file = f"conversation_history_{timestamp}.json"
  15. else:
  16. self.history_file = history_file
  17. self.default_model = default_model
  18. self.default_temperature = default_temperature
  19. self.default_max_tokens = default_max_tokens
  20. self.token_budget = token_budget
  21. self.system_messages = {
  22. "sassy_assistant": "You are a sassy assistant that is fed up with answering questions.",
  23. "angry_assistant": "You are an angry assistant that likes yelling in all caps.",
  24. "thoughtful_assistant": "You are a thoughtful assistant, always ready to dig deeper. You ask clarifying questions to ensure understanding and approach problems with a step-by-step methodology.",
  25. "custom": "Enter your custom system message here."
  26. }
  27. self.system_message = self.system_messages["sassy_assistant"] # Default persona
  28. self.load_conversation_history()
  29. def count_tokens(self, text):
  30. try:
  31. encoding = tiktoken.encoding_for_model(self.default_model)
  32. except KeyError:
  33. print(f"Warning: Model '{self.default_model}' not found. Using 'gpt-3.5-turbo' encoding as default.")
  34. encoding = tiktoken.encoding_for_model("gpt-3.5-turbo")
  35. tokens = encoding.encode(text)
  36. return len(tokens)
  37. def total_tokens_used(self):
  38. try:
  39. return sum(self.count_tokens(message['content']) for message in self.conversation_history)
  40. except Exception as e:
  41. print(f"An unexpected error occurred while calculating the total tokens used: {e}")
  42. return None
  43. def enforce_token_budget(self):
  44. try:
  45. while self.total_tokens_used() > self.token_budget:
  46. if len(self.conversation_history) <= 1:
  47. break
  48. self.conversation_history.pop(1)
  49. except Exception as e:
  50. print(f"An unexpected error occurred while enforcing the token budget: {e}")
  51. def set_persona(self, persona):
  52. if persona in self.system_messages:
  53. self.system_message = self.system_messages[persona]
  54. self.update_system_message_in_history()
  55. else:
  56. raise ValueError(f"Unknown persona: {persona}. Available personas are: {list(self.system_messages.keys())}")
  57. def set_custom_system_message(self, custom_message):
  58. if not custom_message:
  59. raise ValueError("Custom message cannot be empty.")
  60. self.system_messages['custom'] = custom_message
  61. self.set_persona('custom')
  62. def update_system_message_in_history(self):
  63. try:
  64. if self.conversation_history and self.conversation_history[0]["role"] == "system":
  65. self.conversation_history[0]["content"] = self.system_message
  66. else:
  67. self.conversation_history.insert(0, {"role": "system", "content": self.system_message})
  68. except Exception as e:
  69. print(f"An unexpected error occurred while updating the system message in the conversation history: {e}")
  70. def chat_completion(self, prompt, temperature=None, max_tokens=None, model=None):
  71. temperature = temperature if temperature is not None else self.default_temperature
  72. max_tokens = max_tokens if max_tokens is not None else self.default_max_tokens
  73. model = model if model is not None else self.default_model
  74. self.conversation_history.append({"role": "user", "content": prompt})
  75. self.enforce_token_budget()
  76. try:
  77. response = self.client.chat.completions.create(
  78. model=model,
  79. messages=self.conversation_history,
  80. temperature=temperature,
  81. max_tokens=max_tokens,
  82. )
  83. except Exception as e:
  84. print(f"An error occurred while generating a response: {e}")
  85. return None
  86. ai_response = response.choices[0].message.content
  87. self.conversation_history.append({"role": "assistant", "content": ai_response})
  88. self.save_conversation_history()
  89. return ai_response
  90. def load_conversation_history(self):
  91. try:
  92. with open(self.history_file, "r") as file:
  93. self.conversation_history = json.load(file)
  94. except FileNotFoundError:
  95. self.conversation_history = [{"role": "system", "content": self.system_message}]
  96. except json.JSONDecodeError:
  97. print("Error reading the conversation history file. Starting with an empty history.")
  98. self.conversation_history = [{"role": "system", "content": self.system_message}]
  99. def save_conversation_history(self):
  100. try:
  101. with open(self.history_file, "w") as file:
  102. json.dump(self.conversation_history, file, indent=4)
  103. except IOError as e:
  104. print(f"An I/O error occurred while saving the conversation history: {e}")
  105. except Exception as e:
  106. print(f"An unexpected error occurred while saving the conversation history: {e}")
  107. def reset_conversation_history(self):
  108. self.conversation_history = [{"role": "system", "content": self.system_message}]
  109. try:
  110. self.save_conversation_history() # Attempt to save the reset history to the file
  111. except Exception as e:
  112. print(f"An unexpected error occurred while resetting the conversation history: {e}")
  113. ### Streamlit code ###
  114. st.title("Sassy Chatbot :face_with_rolling_eyes:")
  115. # Sidebar
  116. st.sidebar.header("Options")
  117. # Initialize the ConversationManager object
  118. if 'chat_manager' not in st.session_state:
  119. st.session_state['chat_manager'] = ConversationManager(api_key)
  120. chat_manager = st.session_state['chat_manager']
  121. # Set the token budget, max tokens per message, and temperature with sliders
  122. max_tokens_per_message = st.sidebar.slider("Max Tokens Per Message", min_value=10, max_value=500, value=50)
  123. temperature = st.sidebar.slider("Temperature", min_value=0.0, max_value=1.0, value=0.7, step=0.01)
  124. # Select and set system message with a selectbox
  125. system_message = st.sidebar.selectbox("System message", ['Sassy', 'Angry', 'Thoughtful', 'Custom'])
  126. if system_message == 'Sassy':
  127. chat_manager.set_persona('sassy_assistant')
  128. elif system_message == 'Angry':
  129. chat_manager.set_persona('angry_assistant')
  130. elif system_message == 'Thoughtful':
  131. chat_manager.set_persona('thoughtful_assistant')
  132. # Open text area for custom system message if "Custom" is selected
  133. elif system_message == 'Custom':
  134. custom_message = st.sidebar.text_area("Custom system message")
  135. if st.sidebar.button("Set custom system message"):
  136. chat_manager.set_custom_system_message(custom_message)
  137. if st.sidebar.button("Reset conversation history", on_click=chat_manager.reset_conversation_history):
  138. st.session_state['conversation_history'] = chat_manager.conversation_history
  139. if 'conversation_history' not in st.session_state:
  140. st.session_state['conversation_history'] = chat_manager.conversation_history
  141. conversation_history = st.session_state['conversation_history']
  142. # Chat input from the user
  143. user_input = st.chat_input("Write a message")
  144. # Call the chat manager to get a response from the AI. Uses settings from the sidebar.
  145. if user_input:
  146. response = chat_manager.chat_completion(user_input, temperature=temperature, max_tokens=max_tokens_per_message)
  147. # Display the conversation history
  148. for message in conversation_history:
  149. if message["role"] != "system":
  150. with st.chat_message(message["role"]):
  151. st.write(message["content"])