from markdown_it import MarkdownIt from mdit_py_plugins import front_matter from reactpy import component, html from reactpy.core.hooks import use_ref from utils import wait_message def markdown_to_html(markdown_text): md = ( MarkdownIt("commonmark", {"breaks": True, "html": True}) .use(front_matter.front_matter_plugin) ) return md.render(markdown_text) @component def MarkdownRenderer(content): html_content = markdown_to_html(content) return html.div( { "style": { "fontFamily": "Arial", "color": "#49454F", "fontSize": "14px", }, "dangerouslySetInnerHTML": {"__html": html_content} } ) @component def ExamplePrompts(examples, send_example, first_turn): example_questions = [example.strip() for example in examples.split(";")] if examples else [] def create_prompt_button(question): return html.button( { "style": { "backgroundColor": "#FFFFFF", "borderWidth": "1px", "borderColor": "#65558F", "borderRadius": "20px", "padding": "5px 7px", "margin": "5px", "cursor": "pointer", "color": "#21005D", "fontSize": "13px", }, "type": "button", "onClick": lambda _: send_example(question), }, question ) examples_ref = use_ref(None) if examples_ref.current is None: examples_ref.current = html.div( { "style": { "display": "flex", "transform": "translate(4%, 100%)", "flexDirection": "column", "justifyContent": "center", "width": "90%", } }, html.p( { "style": { "fontSize": "16px", "fontFamily": "Arial", "color": "#49454F", "marginBottom": "5px", "transform": "translateX(3%)", "textAlign": "left", } }, "Queries to try:" ), html.div( { "style": { "display": "flex", "flexWrap": "wrap", "justifyContent": "center", } }, *[create_prompt_button(q) for q in example_questions] ) ) if first_turn: return examples_ref.current return None @component def ChatMessage(user, message): return html.div( { "style": { "display": "flex", "width": "75%", "transform": "translateX(20%)", "justifyContent": "flex-end" if user == "human" else "flex-start", "margin": "20px 0px 10px 0px" } }, html.div( { "style": { "maxWidth": "50%", "padding": "0px 15px 0px 10px", "borderRadius": "15px", "backgroundColor": "#E8DEF8" if user == "human" else "#ECE6F0", "color": "#000000", } }, MarkdownRenderer(message) ) ) @component def Logs(messages, log_entries, show_logs, set_show_logs, show_logs_button): if (len(messages) > 0) and (len(log_entries) > 0) and (messages[-1]["message"] != wait_message) and (show_logs_button): if not show_logs: return html.div( { "style": { "display": "flex", "transform": "translateX(75%)", "width": "20%", "margin": "0px", } }, html.button( { "style": { "position": "flex", "background": "none", "color": "#757575", "border": "none", "cursor": "pointer", "fontFamily": "Arial", "fontSize": "14px", }, "type": "button", "onClick": lambda _: set_show_logs(True) }, "Show Logs" ) ) else: return html.div( { "style": { "display": "flex", "transform": "translateX(20%)", "border": "2px solid #e2dfdf", "borderRadius": "10px", "width": "75%", } }, html.div( [ html.p( { "style": { "fontSize": "14px", "marginLeft": "10px", } }, entry ) for entry in log_entries ], html.button( { "style": { "position": "flex", "background": "none", "color": "#757575", "border": "none", "cursor": "pointer", "fontFamily": "Arial", "fontSize": "14px", "marginBottom": "10px", "marginLeft": "5px", }, "type": "button", "onClick": lambda _: set_show_logs(False) }, "Hide Logs" ) ) ) return None @component def ChatUI(messages, first_turn, examples, send_example, log_entries, show_logs, set_show_logs, show_logs_button, collapsed): def render_chat_content(): if first_turn: return ExamplePrompts(examples, send_example, first_turn) else: return [ChatMessage(msg["user"], msg["message"]) for msg in messages] return html.div( { "style": { "display": "flex", "flexDirection": "column", "padding": "10px", "backgroundColor": "#F4F1F4", "overflowY": "auto", "height": f"calc(100vh - {265 if collapsed else 335}px)", "marginBottom": "15px", "paddingBottom": "15px", }, }, render_chat_content(), Logs(messages, log_entries, show_logs, set_show_logs, show_logs_button) )