fracapuano/transcript2notes
0
1from openai import OpenAI2from dotenv import load_dotenv3from typing import List, Optional4from tqdm import tqdm5 6load_dotenv()7client = OpenAI()8 9def extract_topics(meeting_transcript):10 prompt_text = f"""11 ## Transcript12 <transcript>13 {meeting_transcript}14 </transcript>15 16 You are a topic extractor whose main task is to identify and list the top 5 most important topics discussed17 in a meeting, to whom you have access thanks to the provided meeting transcript.18 Provided the transcript available under the <transcript> tags, analyze it and extract the main topics discussed. 19 Format your output as a list of skills I could iterate on.20 21 An ideal output for a meeting covering budgeting budget concers, project handling and staffing looks like22 [Budgeting, Project Deadlines, Staffing, New Policies, Client Feedback]23 """24 25 response = client.chat.completions.create(26 model="gpt-4-turbo",27 messages=[{"role": "user", "content": prompt_text}],28 max_tokens=100, # short list of topics discussed29 temperature=0.0,30 stop=["\n", "]"] # Stops to help ensure the list format is respected31 )32 33 topics = response.choices[0].message.content.strip('][').split(', ') # Processing the string output into a Python list34 return topics35 36def generate_bullet_point_summary(topic, meeting_transcript):37 prompt_text = f"""38 <topic>39 {topic}40 </topic>41 <transcript>42 {meeting_transcript}43 </transcript>44 45 You are an AI assistant tasked with assisting in summarizing meeting discussions. 46 Below is the transcript of a meeting, and a specific topic to focus on.47 Please provide a summary of all the discussions related to this topic in bullet points. Be very48 concise and to the point. Each bullet point must contain one concept only.49 """50 51 response = client.chat.completions.create(52 model="gpt-4-turbo",53 messages=[{"role": "user", "content": prompt_text}],54 max_tokens=400, # Increase if more detailed summaries are needed55 stop=["\n\n"] # A double newline to signify the end of the summary list56 )57 summary = response.choices[0].message.content.strip()58 return summary59 60def summarize_topics(topics, meeting_transcript):61 # Generate summaries for each topic62 summaries = {}63 for topic in topics:64 summaries[topic] = generate_bullet_point_summary(topic, meeting_transcript)65 66 return summaries67 68def extract_actionable_items(meeting_transcript):69 prompt_text = f"""70 Please carefully analyze the following meeting transcript, which will be provided between XML tags:71 72 <meeting_transcript>73 {meeting_transcript}74 </meeting_transcript>75 76 First, identify each unique speaker who participated in the meeting.77 78 Then, for each speaker you identified, carefully extract any concrete action items, tasks, or next79 steps that were assigned to them during the meeting. Use the full context of the meeting to80 determine what the key next steps are for each person.81 82 Format your response as a bulleted list, with each speaker's full name followed by a sublist of the83 specific action items you identified for them. Here is an example of the desired format:84 85 ## John Smith:86 - Follow up with the client by next Wednesday.87 - Prepare a detailed budget proposal for the next meeting.88 - Jane Doe:89 - Coordinate with the marketing team to draft the new campaign outline.90 - Send updated staffing requirements to HR by Friday.91 92 Omit any speakers for whom no clear action items or next steps were specified in the meeting. Focus93 on extracting the most concrete and actionable items for each speaker.94 95 Write your full list of speakers and action items inside <result> tags.96 If you are unable to identify the speakers' names, please write "Speaker 1", "Speaker 2", etc.97 """98 response = client.chat.completions.create(99 model="gpt-4-turbo",100 messages=[{"role": "user", "content": prompt_text}],101 stop=["\n\n"] # A double newline to signify the end of the list102 )103 action_items = response.choices[0].message.content.strip()104 return action_items105 106def cleanup_meeting_notes(meeting_notes, speakers_list=None):107 prompt_text = f"""108 <meeting_notes_draft>109 {meeting_notes}110 </meeting_notes_draft>111 <speakers_list>112 {speakers_list if speakers_list else "No speakers list provided"}113 </speakers_list>114 115 You are a meeting notes editor who has been tasked with cleaning up the draft of a meeting notes document.116 You must not modify the content you receive in any way or form, your task is simply to reformat the text to make it adhere to117 the following guidelines:118 - Production-ready meeting notes are always formatted in markdown. Ensure that the text is properly formatted in markdown.119 - Production-ready meeting notes always have 3 sections: "Speakers", "Meeting Summary", "Action Items". These sections are always H1 in markdown (#Speakers, #Meeting Summary, #Action Items).120 - Production-ready meeting notes always have a horizontal rule (---) between each section.121 - Production-ready meeting notes always present the topics discussed in the #Meeting Summary section, with each topic being a toggle subheading (> ##Topic).122 - Production-ready meeting notes always present the bullet points under each topic as markdown bullet points points.123 - Production-ready meeting notes always have each speaker's name in bold.124 - Production-ready meeting notes always have the action items in a bulleted list.125 - Production-ready meeting notes always have the action items grouped by the speaker who is responsible for them.126 - Production-ready meetings always presents speakers mapped to the name in the <speakers_list> tag, if available, in the same order. This means that for ["Francesco", "Carlo", "Antonio"]127 you would have that "Francesco" is the "Speaker 0", "Carlo" is the "Speaker 1", and "Antonio" is the "Speaker 2".128 129 Your output must exactly match the format described above. You must not modify the content of the meeting notes in any way, only the formatting. You will be 130 penalized if you change the content of the meeting notes.131 An example template for the meeting notes is as follows:132 # Speakers133 - **Speaker 0**134 - **Speaker 1**135 ...136 137 ---138 # Meeting Summary139 > ## Topic 1140 - Bullet point 1141 - Bullet point 2142 ...143 > ## Topic 2144 - Bullet point 1145 - Bullet point 2146 ...147 148 ---149 # Action Items150 ## <Speaker 0's name> to own151 - Action item 1152 - Action item 2153 ## <Speaker 1's name> to own154 - Action item 1155 - Action item 2156 """157 158 response = client.chat.completions.create(159 model="gpt-4-turbo",160 messages=[{"role": "user", "content": prompt_text}]161 )162 return response.choices[0].message.content163 164def transcript_to_notes(meeting_transcript: str, speakers_list:Optional[List[str]]=None) -> str:165 """Converts a meeting transcript into formatted meeting notes.166 167 Args:168 meeting_transcript (str): The text of the meeting transcript169 speakers_list (Optional[List[str]]): A list of speakers in the meeting170 171 Returns:172 str: The formatted meeting notes173 """174 pbar = tqdm(total=3)175 topics = extract_topics(meeting_transcript)176 pbar.update(1)177 by_topic_summaries = summarize_topics(topics, meeting_transcript)178 pbar.update(1)179 actions_by_speaker = extract_actionable_items(meeting_transcript)180 pbar.update(1)181 182 draft_notes = f"""183 topics: {topics}184 summaries: {by_topic_summaries}185 actions: {actions_by_speaker}186 """187 188 meeting_notes = cleanup_meeting_notes(draft_notes, speakers_list)189 return meeting_notes190 191# Example usage192if __name__ == "__main__":193 with open("tanguy-off-boarding-meeting.txt", "r") as file:194 meeting_transcript = file.read()195 196 speakers_list = ["Tanguy", "Francesco"]197 198 notes = transcript_to_notes(meeting_transcript, speakers_list)199 with open("meeting_notes.md", "w") as file:200 file.write(notes)201 202 print("Meeting notes generated successfully!")