"""kwest.dev is a saas tool to craft stories for your ideas.""" import os from typing import Union import requests import streamlit as st API_URL = os.getenv("API_URL", None) AUTH_TOKEN = os.getenv("AUTH_TOKEN", None) RECIPES = ["sell", "motivate", "convince", "connect", "explain", "lead", "impress"] VALID_EMOJIS = {"yes": "✅", "no": "❌"} if not API_URL or not AUTH_TOKEN: raise ValueError("API_URL and AUTH_TOKEN secrets must be set in the environment variables.") def check_if_input_is_valid(input_str: str) -> Union[dict[str, str], None]: """Check if the input string is valid for the API.""" response = requests.post( f"{API_URL}input-check", headers={"Authorization": f"{AUTH_TOKEN}", "Accept": "application/json"}, json={"input": input_str}, ) if response.status_code == 200: return response.json()["output"] else: return None def get_recipe_choices(input_str: str) -> Union[dict[str, str], None]: """Get the recipe choices for the input string.""" response = requests.post( f"{API_URL}recipe-choice", headers={"Authorization": f"{AUTH_TOKEN}", "Accept": "application/json"}, json={"input": input_str}, ) if response.status_code == 200: return response.json()["output"] else: return None def craft_story_from_recipe(input_str: str, recipe: str) -> None: """Craft a story from the input string and recipe.""" response = requests.post( f"{API_URL}craft-from-recipe", headers={"Authorization": f"{AUTH_TOKEN}", "Accept": "application/json"}, json={"input": input_str, "recipe": recipe}, ) if response.status_code == 200: st.session_state.story = response.json()["output"]["story"] else: raise ValueError("An error occurred while crafting the story.") # UI st.title("kwest.dev") st.subheader("Leverage the power of storytelling for any idea. 💡") with st.expander(label="How to present your idea to get the best story 👇", expanded=True): st.markdown( """ - 🎯 Explain the **main objective** of your idea. What is the **main goal** you are trying to achieve? - 📝 Give as much **context** as possible. For example, what is the problem you are trying to solve? If you have a good name for your idea, share it. - 👤 What is the **audience** for your idea? Who are the people that should be interested in it? Once you have shared this information, we will propose 2 recipes for your story. Choose the one you like the most between the two. The different recipes available are: `sell`, `motivate`, `convince`, `connect`, `explain`, `lead`, `impress` If you aren't satisfied with the recipes proposed, you can choose a different one below. __Examples of good and bad inputs:__ ✅ `I need a pitch for a new app that helps people find the best restaurants in town. I will present it to angel investors. The name of the app is "Foodie".` ❌ `I need a pitch for a new app. It's cool.` """ ) input_col, btn_col = st.columns([3, 1], vertical_alignment="bottom") with input_col: input_str = st.text_area("Your idea that needs a story", "", placeholder="I need a pitch for ...") with btn_col: check_input = st.button(label="▶️", key="check_input", help="Check if the input is valid") if check_input: input_is_valid = check_if_input_is_valid(input_str) if input_is_valid is None: st.error("An error occurred while checking the input. Please try again.") st.stop() else: st.write( f"Objective: {VALID_EMOJIS[input_is_valid['objective']]} | " f"Context: {VALID_EMOJIS[input_is_valid['context']]} | " f"Audience: {VALID_EMOJIS[input_is_valid['audience']]}" ) if input_is_valid["objective"] == "yes" and input_is_valid["context"] == "yes" and input_is_valid["audience"] == "yes": recipe_choices = get_recipe_choices(input_str) st.write("Choose the recipe you want to use for your story.") choice_1, choice_2 = st.columns(2) other_choices = st.columns(5) with choice_1: recipe_1 = st.button( recipe_choices["recipe"], on_click=lambda: craft_story_from_recipe(input_str, recipe_choices["recipe"]) ) with choice_2: recipe_2 = st.button( recipe_choices["second_recipe"], on_click=lambda: craft_story_from_recipe(input_str, recipe_choices["second_recipe"]) ) for idx, recipe in enumerate(RECIPES - [recipe_choices["recipe"], recipe_choices["second_recipe"]]): with other_choices[idx]: other_recipe = st.button( recipe, on_click=lambda: craft_story_from_recipe(input_str, recipe) ) if "story" in st.session_state: st.markdown(st.session_state.story) del st.session_state.story