Created
February 18, 2025 23:11
-
-
Save cpsievert/8ab4b904beacda691e9a5bcba53074ac to your computer and use it in GitHub Desktop.
A real example of py-shiny's MarkdownStream() + chatlas
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from chatlas import ChatAnthropic | |
from faicons import icon_svg | |
from shiny import reactive | |
from shiny.express import input, render, ui | |
chat_model = ChatAnthropic( | |
system_prompt=""" | |
You are a helpful AI fitness coach. | |
Give detailed workout plans to users based on their fitness goals and experience level. | |
Before getting into details, give a brief introduction to the workout plan. | |
Keep the overall tone encouraging and professional yet friendly. | |
Generate the response in Markdown format and avoid using h1, h2, or h3. | |
""", | |
) | |
ui.page_opts(title="Personalized Workout Plan Generator") | |
with ui.sidebar(open={"mobile": "always-above"}): | |
ui.input_select( | |
"goal", | |
"Fitness Goal", | |
["Strength", "Cardio", "Flexibility", "General Fitness"], | |
) | |
ui.input_selectize( | |
"equipment", | |
"Available Equipment", | |
["Dumbbells", "Barbell", "Resistance Bands", "Bodyweight"], | |
multiple=True, | |
selected=["Bodyweight", "Barbell"], | |
) | |
ui.input_slider("experience", "Experience Level", min=1, max=10, value=5) | |
ui.input_slider("duration", "Duration (mins)", min=15, max=90, step=5, value=45) | |
ui.input_select( | |
"daysPerWeek", | |
"Days per Week", | |
[str(i) for i in range(1, 8)], | |
selected="3", | |
) | |
ui.input_task_button("generate", "Get Workout", icon=icon_svg("person-running")) | |
@render.express | |
def download_ui(): | |
if not workout_plan(): | |
return | |
@render.download(filename="workout_plan.md", label="Download Workout") | |
def download(): | |
yield workout_plan() | |
# Create a Markdown stream to display the workout plan | |
md_stream = ui.MarkdownStream("response_stream") | |
md_stream.ui( | |
content=""" | |
Hi there! π I'm your AI fitness coach. πͺ | |
Fill out the form in the sidebar to get started. π ποΈββ οΈ | |
""", | |
) | |
# When the user clicks the "Generate Workout" button, generate a workout plan | |
@reactive.effect | |
@reactive.event(input.generate) | |
async def _(): | |
prompt = f""" | |
Generate a {input.duration()}-minute workout plan for a {input.goal()} fitness goal. | |
On a scale of 1-10, I have a level {input.experience()} experience, | |
works out {input.daysPerWeek()} days per week, and have access to: | |
{", ".join(input.equipment()) if input.equipment() else "no equipment"}. | |
Format the response in Markdown. | |
""" | |
stream = await md_stream.stream(await chat_model.stream_async(prompt)) | |
current_stream.set(stream) | |
current_stream = reactive.value(None) | |
@reactive.calc | |
def workout_plan(): | |
if not current_stream(): | |
return None | |
stream = current_stream() | |
return stream.result() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment