Engineering6 min read

From Meeting Notes to Notion Tasks: AI Project Manager

Lost in a sea of meeting notes? Struggling to keep track of project tasks? There’s a better way.

Tega Adeyemi
Tega Adeyemi
From Meeting Notes to Notion Tasks: AI Project Manager

Introducing our latest project: a Meeting Transcript Processor that seamlessly integrates with Notion for managing project tasks. If you've ever felt overwhelmed trying to organize project management tasks discussed during meetings, this project is for you. Imagine converting the chaos of meeting notes into structured project management tasks, automatically updated in Notion – all with just a few clicks.

📈 Introducing Our Meeting Transcript Processor

What's the idea behind this project? We've built a smart tool that uses AI to transform meeting transcripts into well-defined project management tasks in Notion, allowing teams to keep track of ongoing projects efficiently and collaboratively. Here’s what it can do:

From Meeting Notes to Notion Tasks: AI Project Manager — Tega Adeyemi | Cohorte
Initial state of the ‘Tasks’ table
From Meeting Notes to Notion Tasks: AI Project Manager — Tega Adeyemi | Cohorte
Next, we feed the meeting transcript into the app
From Meeting Notes to Notion Tasks: AI Project Manager — Tega Adeyemi | Cohorte
‘Tasks’ are automatically updated and new tasks are added after processing the meeting transcript

💡 How Does It Work?

Under the hood, this tool leverages:

🚀 Let's Dive into the Features

Setting Up the App with Streamlit

We're using Streamlit to make the app visually appealing and easy to use. When you open the app, you’ll find a simple form where you can enter your meeting transcript and process it with a click of a button.

import streamlit as st

st.title("Meeting Transcript Processor")

Providing the API Keys

We’ve added a sidebar in the app for entering the OpenAI API Key and Notion API Token, ensuring your information is safe and the setup is straightforward. The keys are stored securely in session state, which keeps the process simple for recurring use.

st.sidebar.title("API Key Configuration")
openai_api_key = st.sidebar.text_input("Enter your OpenAI API Key", type="password")
notion_token = st.sidebar.text_input("Enter your Notion connection token", type="password")
database_id = st.sidebar.text_input("Enter your Notion database ID", type="password")

Extracting Tasks from Transcripts

The real magic happens when you enter your meeting transcript. By using OpenAI's language model, our app analyzes the transcript, extracts the relevant tasks, and converts them into a structured format that Notion can use.

Here’s a step-by-step breakdown of the process:

1. Transcription Input:

Users enter the meeting transcript in a simple text area provided by Streamlit.

# Text area for meeting transcript input
with st.form(key='transcript_form'):
    transcript = st.text_area("Enter Meeting Transcript")
    submit_button = st.form_submit_button(label='Process Transcript')
2. AI-Powered Task Extraction:

Once the form is submitted, the app sends the transcript to OpenAI's language model for processing. The AI uses the context of the meeting to generate structured tasks that include details like the task name, assignee, status, user story, and any helpful information.

client = OpenAI(api_key=openai_api_key)
response = client.beta.chat.completions.parse(
    messages=[
        {"role": "system", "content": "You are an assistant that extracts tasks from meeting transcripts. Please return the tasks in JSON format as a list of dictionaries with the following keys: name, assignee (if available), status, user_story, helpful_info, ticket_number (if available)."},
        {"role": "user", "content": transcript}
    ],
    model="gpt-4o-mini",
    response_format=ExtractTasksResponse
)

extracted_tasks = response.choices[0].message.parsed.tasks

Once you hit the "Process Transcript" button, the app works behind the scenes to parse the transcript and extract tasks. We use a structured response format to ensure consistency—meaning every task will have all the information it needs, such as task name, status, assignee, user story, and helpful info.

Displaying Extracted Tasks

To make sure you see exactly what the AI extracts, we present the tasks in a clean table format before sending them to Notion.

st.write("Extracted Tasks (Parsed Response):")
st.table([task.dict() for task in extracted_tasks])

Adding and Updating Tasks in Notion

The tool isn't just about extracting tasks; it also checks whether the task already exists in Notion using a unique ticket number. If it finds the task, it updates the relevant information like status or assignee. If the task doesn’t exist, it creates a new one, assigning it the next available ticket number.

Here’s how this part works:

1. Checking Existing Tasks:

After extracting the tasks, the app compares each extracted task with the current tasks in Notion. It uses the ticket number (a unique identifier for each task) to determine if a task already exists.

existing_task = next((t for t in current_tasks if t["ticket_number"] == ticket_number), None) if ticket_number else None
2. Updating Tasks:

If a task already exists, the app will update only the necessary fields. For example, if the status or assignee has changed, it will update those specific properties while leaving others unchanged.

if existing_task:
    update_properties = {}
    if status.lower() != existing_task["status"].lower():
        update_properties["Status"] = {"status": {"name": status}}
    if assignee and assignee.lower() != "unassigned" and assignee.lower() != existing_task["assignee"].lower():
        update_properties["Assignee"] = {"multi_select": [{"name": assignee}]}

    if update_properties:
        notion.pages.update(
            page_id=existing_task["page_id"],
            properties=update_properties
        )
        st.write(f"Updated task: {task_name}")
    else:
        st.write(f"No changes detected for task: {task_name}")
3. Creating New Tasks:

If the task doesn’t exist, the app creates a new entry in Notion. It assigns the next available ticket number to ensure uniqueness and organizes the task with all relevant information.

else:
    new_ticket_number = str(max_ticket_number + 1)
    max_ticket_number += 1
    create_properties = {
        "Name": {"title": [{"text": {"content": task_name}}]},
        "Status": {"status": {"name": status}},
        "User Story": {"rich_text": [{"text": {"content": user_story}}]},
        "Helpful Info": {"rich_text": [{"text": {"content": helpful_info}}]},
        "Ticket Number": {"rich_text": [{"text": {"content": new_ticket_number}}]}
    }
    if assignee and assignee.lower() != "unassigned":
        create_properties["Assignee"] = {"multi_select": [{"name": assignee}]}

    notion.pages.create(
        parent={"database_id": database_id},
        properties=create_properties
    )
    st.write(f"Created new task: {task_name} with Ticket Number: {new_ticket_number}")

Here's how the update or create logic works:

  1. Checking Existing Tasks: It uses the ticket number as an identifier to see if a task already exists in Notion.
  2. Updating or Creating: If the task exists, it updates only those fields that have changed. Otherwise, it creates a brand-new entry in Notion.
existing_task = next((t for t in current_tasks if t["ticket_number"] == ticket_number), None) if ticket_number else None
if existing_task:
    # Update the task in Notion
else:
    # Create a new task in Notion

💪 Why This Tool Is a Game Changer

Use Cases

This Meeting Transcript Processor is ideal for:

Behind the Scenes: The Technology Stack

Wrapping Up

We’re really excited about what this tool can do for meeting productivity. It’s a game changer for teams looking to stay organized without spending hours documenting action items. Our AI Meeting Transcript Processor will streamline your task management workflow, ensuring nothing gets lost in translation from meeting discussions to actionable tasks.

Author

Harshad Suryawanshi

October 24, 2024

From Meeting Notes to Notion Tasks: AI Project Manager — Tega Adeyemi | Cohorte