From 182ae741d8b5ea096c639aa78bc613aa33231f3f Mon Sep 17 00:00:00 2001 From: LUIS NOVO Date: Wed, 13 Nov 2024 17:02:48 -0300 Subject: [PATCH] cleanup podcast --- open_notebook/plugins/podcasts.py | 102 ++++++------------------------ pages/5_🎙️_Podcasts.py | 41 +++++++----- 2 files changed, 45 insertions(+), 98 deletions(-) diff --git a/open_notebook/plugins/podcasts.py b/open_notebook/plugins/podcasts.py index ce92ff3..39adec9 100644 --- a/open_notebook/plugins/podcasts.py +++ b/open_notebook/plugins/podcasts.py @@ -2,7 +2,7 @@ from typing import ClassVar, List, Optional from loguru import logger from podcastfy.client import generate_podcast -from pydantic import Field, field_validator +from pydantic import Field, field_validator, model_validator from open_notebook.config import DATA_FOLDER from open_notebook.domain.notebook import ObjectModel @@ -23,8 +23,8 @@ class PodcastConfig(ObjectModel): podcast_name: str podcast_tagline: str output_language: str = Field(default="English") - person1_role: str - person2_role: str + person1_role: List[str] + person2_role: List[str] conversation_style: List[str] engagement_technique: List[str] dialogue_structure: List[str] @@ -35,10 +35,24 @@ class PodcastConfig(ObjectModel): wordcount: int = Field(ge=400, le=10000) creativity: float = Field(ge=0, le=1) provider: str = Field(default="openai") - voice1: Optional[str] = None - voice2: Optional[str] = None + voice1: str + voice2: str model: str + # Backwards compatibility + @field_validator("person1_role", "person2_role", mode="before") + @classmethod + def split_string_to_list(cls, value): + if isinstance(value, str): + return [item.strip() for item in value.split(",")] + return value + + @model_validator(mode="after") + def validate_voices(self) -> "PodcastConfig": + if not self.voice1 or not self.voice2: + raise ValueError("Both voice1 and voice2 must be provided") + return self + def generate_episode(self, episode_name, text, instructions=None): self.user_instructions = ( instructions if instructions else self.user_instructions @@ -140,13 +154,8 @@ conversation_styles = [ "Debate-style", "Interview-style", "Storytelling", - "Reflective", - "Narrative", "Satirical", "Educational", - "Conversational", - "Critical", - "Empathetic", "Philosophical", "Speculative", "Motivational", @@ -156,25 +165,15 @@ conversation_styles = [ "Serious", "Investigative", "Debunking", - "Collaborative", "Didactic", "Thought-provoking", "Controversial", - "Skeptical", - "Optimistic", - "Pessimistic", - "Objective", - "Subjective", "Sarcastic", "Emotional", "Exploratory", - "Friendly", "Fast-paced", "Slow-paced", "Introspective", - "Open-ended", - "Affirmative", - "Dissenting", ] # Dialogue Structures @@ -191,15 +190,10 @@ dialogue_structures = [ "Pro Arguments", "Con Arguments", "Cross-examination", - "Rebuttal", "Expert Interviews", - "Panel Discussion", "Case Studies", "Myth Busting", - "Debunking Misconceptions", - "Audience Questions", "Q&A Session", - "Listener Feedback", "Rapid-fire Questions", "Summary of Key Points", "Recap", @@ -207,29 +201,11 @@ dialogue_structures = [ "Actionable Tips", "Call to Action", "Future Outlook", - "Teaser for Next Episode", "Closing Remarks", - "Thank You and Credits", - "Outtakes or Bloopers", - "Sponsor Messages", - "Social Media Shout-outs", "Resource Recommendations", - "Feedback Request", - "Lightning Round", - "Behind-the-Scenes Insights", - "Ethical Considerations", - "Fact-checking Segment", "Trending Topics", "Closing Inspirational Quote", "Final Reflections", - "Debrief", - "Farewell Messages", - "Next Episode Preview", - "Live Reactions", - "Call-in Segment", - "Acknowledgements", - "Transition Segments", - "Break Segments", ] # Podcast Participant Roles @@ -265,15 +241,7 @@ participant_roles = [ "Researcher", "Reporter", "Advocate", - "Influencer", - "Observer", - "Listener", - "Facilitator", - "Innovator", "Debater", - "Educator", - "Motivator", - "Narrator", "Explorer", "Opponent", "Proponent", @@ -289,49 +257,17 @@ participant_roles = [ "Author", "Journalist", "Activist", - "Challenger", - "Supporter", - "Mentor", - "Mentee", "Panelist", - "Audience Representative", - "Case Study Presenter", "Data Analyst", - "Ethicist", - "Cultural Critic", - "Technologist", - "Environmentalist", - "Legal Expert", - "Healthcare Professional", - "Financial Advisor", - "Policy Maker", - "Sociologist", - "Anthropologist", "Myth Buster", "Trend Analyst", "Futurist", - "Negotiator", - "Community Leader", "Voice of Reason", - "Conflict Resolver", - "Emotional Support", "Pragmatist", "Idealist", "Realist", "Satirist", - "Story Analyst", - "Language Expert", - "Historical Witness", - "Survivor", - "Inspirational Figure", - "Cultural Ambassador", - "Digital Nomad", - "Remote Correspondent", "Field Reporter", - "Data Scientist", - "Gamer", - "Musician", - "Filmmaker", ] # Engagement Techniques diff --git a/pages/5_🎙️_Podcasts.py b/pages/5_🎙️_Podcasts.py index 040d76d..40ede27 100644 --- a/pages/5_🎙️_Podcasts.py +++ b/pages/5_🎙️_Podcasts.py @@ -82,19 +82,26 @@ with templates_tab: "User Instructions", help="Any additional intructions to pass to the LLM that will generate the transcript", ) - pd_cfg["person1_role"] = st.text_input("Person 1 role") + pd_cfg["person1_role"] = st_tags( + [], participant_roles, "Person 1 roles", key="person1_roles" + ) st.caption(f"Suggestions:{', '.join(participant_roles)}") - pd_cfg["person2_role"] = st.text_input("Person 2 role") + pd_cfg["person2_role"] = st_tags( + [], participant_roles, "Person 2 roles", key="person2_roles" + ) pd_cfg["conversation_style"] = st_tags( - [], conversation_styles, "Conversation Style" + [], conversation_styles, "Conversation Style", key="conversation_styles" ) st.caption(f"Suggestions:{', '.join(conversation_styles)}") pd_cfg["engagement_technique"] = st_tags( - [], engagement_techniques, "Engagement Techniques" + [], + engagement_techniques, + "Engagement Techniques", + key="engagement_techniques", ) st.caption(f"Suggestions:{', '.join(engagement_techniques)}") pd_cfg["dialogue_structure"] = st_tags( - [], dialogue_structures, "Dialogue Structure" + [], dialogue_structures, "Dialogue Structure", key="dialogue_structures" ) st.caption(f"Suggestions:{', '.join(dialogue_structures)}") pd_cfg["wordcount"] = st.slider( @@ -126,6 +133,8 @@ with templates_tab: pd_cfg["voice1"] = st.text_input( "Voice 1", help="You can use Elevenlabs voice ID" ) + st.caption("Voice names are case sensitive. Be sure to add the exact name.") + st.markdown( "[Open AI voices](https://platform.openai.com/docs/guides/text-to-speech)" ) @@ -142,10 +151,8 @@ with templates_tab: pd = PodcastConfig(**pd_cfg) pd_cfg = {} pd.save() - st.rerun() except Exception as e: st.error(e) - st.exception(e) for pd_config in PodcastConfig.get_all(order_by="created desc"): with st.expander(pd_config.name): @@ -174,17 +181,20 @@ with templates_tab: value=pd_config.output_language, key=f"output_language_{pd_config.id}", ) - pd_config.person1_role = st.text_input( - "Person 1 role", - value=pd_config.person1_role, - key=f"person1_role_{pd_config.id}", + pd_config.person1_role = st_tags( + pd_config.person1_role, + conversation_styles, + "Person 1 Roles", + key=f"person_1_roles_{pd_config.id}", ) st.caption(f"Suggestions:{', '.join(participant_roles)}") - pd_config.person2_role = st.text_input( - "Person 2 role", - value=pd_config.person2_role, - key=f"person2_role_{pd_config.id}", + pd_config.person2_role = st_tags( + pd_config.person2_role, + conversation_styles, + "Person 2 Roles", + key=f"person_2_roles_{pd_config.id}", ) + pd_config.conversation_style = st_tags( pd_config.conversation_style, conversation_styles, @@ -293,6 +303,7 @@ with templates_tab: key=f"voice1_{pd_config.id}", help="You can use Elevenlabs voice ID", ) + st.caption("Voice names are case sensitive. Be sure to add the exact name.") st.markdown( "[Open AI voices](https://platform.openai.com/docs/guides/text-to-speech)" )