diff --git a/frontend/components/hint.py b/frontend/components/hint.py index b7a7aa0..705e585 100644 --- a/frontend/components/hint.py +++ b/frontend/components/hint.py @@ -16,7 +16,7 @@ def hint( rx.text(text), side=side, align=align, - class_name="flex justify-center items-center bg-slate-11 px-1.5 py-0.5 rounded-lg text-[#FFFFFF] text-sm", + class_name="flex justify-center items-center bg-slate-11 px-1.5 py-0.5 rounded-lg text-slate-1 text-sm", ), class_name=class_name, default_open=active, diff --git a/frontend/frontend.py b/frontend/frontend.py index 0d661d4..71a0def 100644 --- a/frontend/frontend.py +++ b/frontend/frontend.py @@ -21,7 +21,7 @@ def index() -> rx.Component: rx.box( reset(), settings_icon(), - class_name="top-4 right-4 absolute flex flex-row items-center gap-3.5", + class_name="top-4 right-4 z-50 absolute flex flex-row items-center gap-3.5", ), # Main content rx.box( @@ -31,7 +31,7 @@ def index() -> rx.Component: chat(), # Action bar action_bar(), - class_name="relative flex flex-col justify-between gap-20 mx-auto px-6 pt-16 lg:pt-6 pb-6 max-w-4xl h-screen", + class_name="relative flex flex-col justify-between gap-10 lg:gap-20 mx-auto px-6 pt-16 lg:pt-6 pb-6 max-w-4xl h-screen", ), accent_color=SettingsState.color, ) diff --git a/frontend/state.py b/frontend/state.py index 31c8950..0980094 100644 --- a/frontend/state.py +++ b/frontend/state.py @@ -2,10 +2,9 @@ import json import os import uuid - import httpx import reflex as rx -from openai import AsyncOpenAI + class SettingsState(rx.State): # The accent color for the app @@ -16,8 +15,6 @@ class SettingsState(rx.State): class State(rx.State): - # The current question being asked. - question: str # Whether the app is processing a question. processing: bool = False @@ -27,7 +24,15 @@ class State(rx.State): user_id: str = str(uuid.uuid4()) - async def answer(self): + async def answer(self, payload: dict[str, str]): + + # Add the question to the chat history + question = payload["question"] + + # If empty return + if question == "": + return + # Set the processing state to True. self.processing = True yield @@ -42,16 +47,10 @@ async def answer(self): {"role": "assistant", "content": chat_history_tuple[1]} ) - self.chat_history.append((self.question, "")) - - # Clear the question input. - question = self.question - self.question = "" + self.chat_history.append((question, "")) # Yield here to clear the frontend input before continuing. yield - - client = httpx.AsyncClient() # call the agentic workflow @@ -77,33 +76,9 @@ async def answer(self): answer[: i + 1], ) yield - - - # Add to the answer as the chatbot responds. - answer = "" - yield - - async for item in session: - if hasattr(item.choices[0].delta, "content"): - if item.choices[0].delta.content is None: - break - answer += item.choices[0].delta.content - self.chat_history[-1] = (self.chat_history[-1][0], answer) - yield - - # Ensure the final answer is added to chat history - if answer: - self.chat_history[-1] = (self.chat_history[-1][0], answer) - yield - # Set the processing state to False. self.processing = False - async def handle_key_down(self, key: str): - if key == "Enter": - async for t in self.answer(): - yield t - def clear_chat(self): # Reset the chat history and processing state self.chat_history = [] diff --git a/frontend/views/chat.py b/frontend/views/chat.py index 853901a..d723b5c 100644 --- a/frontend/views/chat.py +++ b/frontend/views/chat.py @@ -56,12 +56,11 @@ def chat() -> rx.Component: def action_bar() -> rx.Component: return rx.box( - rx.box( + rx.form( rx.el.input( placeholder="Ask anything", - on_blur=State.set_question, - id="input1", - class_name="box-border bg-slate-3 px-4 py-2 pr-14 rounded-full w-full outline-none focus:outline-accent-10 h-[48px] text-slate-12 placeholder:text-slate-9", + name="question", + class_name="box-border bg-slate-3 px-4 py-2 pr-14 rounded-full w-full outline-none focus:outline-accent-10 h-[48px] text-slate-12 placeholder:text-slate-9 peer", ), rx.el.button( rx.cond( @@ -74,13 +73,12 @@ def action_bar() -> rx.Component: ), rx.icon(tag="arrow-up", size=19, color="white"), ), - on_click=[State.answer, rx.set_value("input1", "")], - class_name="top-1/2 right-4 absolute bg-accent-9 hover:bg-accent-10 disabled:hover:bg-accent-9 opacity-65 disabled:opacity-50 p-1.5 rounded-full transition-colors -translate-y-1/2 cursor-pointer disabled:cursor-default", - disabled=rx.cond( - State.processing | (State.question == ""), True, False - ), + class_name="top-1/2 right-4 absolute bg-accent-9 hover:bg-accent-10 disabled:hover:bg-accent-9 opacity-65 disabled:opacity-50 peer-placeholder-shown:opacity-50 p-1.5 rounded-full transition-colors -translate-y-1/2 cursor-pointer disabled:cursor-default peer-placeholder-shown:cursor-default", + disabled=rx.cond(State.processing, True, False), ), + on_submit=State.answer, class_name="relative w-full", + reset_on_submit=True, ), # Made with Reflex link made_with_reflex(), diff --git a/frontend/views/templates.py b/frontend/views/templates.py index 70e4167..8330253 100644 --- a/frontend/views/templates.py +++ b/frontend/views/templates.py @@ -8,7 +8,7 @@ def template_card(icon: str, title: str, description: str, color: str) -> rx.Com rx.text(title, class_name="font-medium text-slate-11 text-sm"), rx.text(description, class_name="text-slate-10 text-xs"), class_name="relative align-top flex flex-col gap-2 border-slate-4 bg-slate-1 hover:bg-slate-3 shadow-sm px-3 pt-3 pb-4 border rounded-2xl text-[15px] text-start transition-colors", - on_click=[State.set_question(description), State.answer], + on_click=State.answer({"question": description}), ) @@ -45,7 +45,7 @@ def templates() -> rx.Component: ), class_name="gap-4 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 w-full", ), - class_name="top-1/3 left-1/2 absolute flex flex-col justify-center items-center gap-10 w-full max-w-4xl transform -translate-x-1/2 -translate-y-1/2 px-6 z-50", + class_name="top-1/2 lg:top-1/3 left-1/2 z-50 absolute flex flex-col justify-center items-center gap-10 px-6 w-full max-w-4xl transform -translate-x-1/2 -translate-y-1/2", style={ "animation": "reveal 0.35s ease-out", "@keyframes reveal": {"0%": {"opacity": "0"}, "100%": {"opacity": "1"}},