state.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import asyncio
  2. import reflex as rx
  3. from ..state import State
  4. # openai.api_key = os.environ["OPENAI_API_KEY"]
  5. # openai.api_base = os.getenv("OPENAI_API_BASE", "https://api.openai.com/v1")
  6. class QA(rx.Base):
  7. """A question and answer pair."""
  8. question: str
  9. answer: str
  10. DEFAULT_CHATS = {
  11. "Intros": [],
  12. }
  13. class State(State):
  14. """The app state."""
  15. # A dict from the chat name to the list of questions and answers.
  16. chats: dict[str, list[QA]] = DEFAULT_CHATS
  17. # The current chat name.
  18. current_chat = "Intros"
  19. # The current question.
  20. question: str
  21. # Whether we are processing the question.
  22. processing: bool = False
  23. # The name of the new chat.
  24. new_chat_name: str = ""
  25. # Whether the drawer is open.
  26. drawer_open: bool = False
  27. # Whether the modal is open.
  28. modal_open: bool = False
  29. def create_chat(self):
  30. """Create a new chat."""
  31. # Add the new chat to the list of chats.
  32. self.current_chat = self.new_chat_name
  33. self.chats[self.new_chat_name] = []
  34. # Toggle the modal.
  35. self.modal_open = False
  36. def toggle_modal(self):
  37. """Toggle the new chat modal."""
  38. self.modal_open = not self.modal_open
  39. def toggle_drawer(self):
  40. """Toggle the drawer."""
  41. self.drawer_open = not self.drawer_open
  42. def delete_chat(self):
  43. """Delete the current chat."""
  44. del self.chats[self.current_chat]
  45. if len(self.chats) == 0:
  46. self.chats = DEFAULT_CHATS
  47. self.current_chat = list(self.chats.keys())[0]
  48. self.toggle_drawer()
  49. def set_chat(self, chat_name: str):
  50. """Set the name of the current chat.
  51. Args:
  52. chat_name: The name of the chat.
  53. """
  54. self.current_chat = chat_name
  55. self.toggle_drawer()
  56. @rx.var
  57. def chat_titles(self) -> list[str]:
  58. """Get the list of chat titles.
  59. Returns:
  60. The list of chat names.
  61. """
  62. return list(self.chats.keys())
  63. async def process_question(self, form_data: dict[str, str]):
  64. """Get the response from the API.
  65. Args:
  66. form_data: A dict with the current question.
  67. Yields:
  68. The current question and the response.
  69. """
  70. # Check if the question is empty
  71. if self.question == "":
  72. return
  73. # Add the question to the list of questions.
  74. qa = QA(question=self.question, answer="")
  75. self.chats[self.current_chat].append(qa)
  76. # Clear the input and start the processing.
  77. self.processing = True
  78. self.question = ""
  79. yield
  80. # # Build the messages.
  81. # messages = [
  82. # {"role": "system", "content": "You are a friendly chatbot named Reflex."}
  83. # ]
  84. # for qa in self.chats[self.current_chat]:
  85. # messages.append({"role": "user", "content": qa.question})
  86. # messages.append({"role": "assistant", "content": qa.answer})
  87. # # Remove the last mock answer.
  88. # messages = messages[:-1]
  89. # Start a new session to answer the question.
  90. # session = openai.ChatCompletion.create(
  91. # model=os.getenv("OPENAI_MODEL", "gpt-3.5-turbo"),
  92. # messages=messages,
  93. # stream=True,
  94. # )
  95. # Stream the results, yielding after every word.
  96. # for item in session:
  97. answer = "I don't know! This Chatbot still needs to add in AI API keys!"
  98. for i in range(len(answer)):
  99. # Pause to show the streaming effect.
  100. await asyncio.sleep(0.1)
  101. # Add one letter at a time to the output.
  102. # if hasattr(item.choices[0].delta, "content"):
  103. # answer_text = item.choices[0].delta.content
  104. self.chats[self.current_chat][-1].answer += answer[i]
  105. self.chats = self.chats
  106. yield
  107. # Toggle the processing flag.
  108. self.processing = False