iT邦幫忙

2025 iThome 鐵人賽

DAY 14
0
生成式 AI

打造基於 MCP 協議與 n8n 工作流的會議處理 Agent系列 第 14

Day 14 打造參與者辨識核心 - Notion 成員資料庫建置與配對邏輯原型

  • 分享至 

  • xImage
  •  

昨天我們完成了智慧日期解析功能,讓 AI 能自動辨認會議中的時間表達並標準化處理,接下來會議記錄中經常出現「小明負責處理這個功能」、「請阿志下週二提交報告」這類的任務指派。

今天的目標是建立一個「成員知識庫」,讓 AI 知道我們團隊有哪些成員,並在分析會議紀錄時,能從中辨識出參與者與被指派任務的對象。

今天的目標與挑戰

  • 更新 Notion 的「會議記錄」資料庫,新增「參與夥伴」與「任務指派」的人員欄位
  • 在「GIGI工作室」建立「人員資料庫」作為 AI 的知識基礎
  • 新增「載入成員列表」與「格式化成員列表」等節點,建立初步的成員匹配邏輯
  • 將 AI 辨識的成員名稱,與 Notion 資料庫中的成員 ID 進行比對,以便自動填入

Step 1:更新 Notion 資料庫結構

我們需要先在「會議記錄」和「GIGI 工作室」中進行一些準備

1-1 在「會議記錄」資料庫新增欄位

進入您的「會議記錄」資料庫,新增以下兩個「人員 (Person)」屬性的欄位:

  1. 參與夥伴
    • 屬性人員 (Person)
    • 設定:允許多人選擇
    • 用途:記錄本次會議的所有參與成員
  2. 任務指派
    • 屬性人員 (Person)
    • 設定:允許多人選擇
    • 用途:記錄所有被指派任務的成員

1-2 建立人員資料庫

步驟 1:建立新的資料庫

在「GIGI 工作室」裡建立資料庫,並將資料庫標題命名為「人員資料庫

步驟 2:設計資料庫欄位結構

我們需要建立以下欄位來支援完整的參與者識別功能:

欄位名稱 屬性類型 設定說明 用途說明
姓名 標題 預設欄位,不需修改 正式姓名,作為主要辨認依據
暱稱 文字 單行文字 會議中常用的暱稱,用頓號分隔多個暱稱
職位 文字 單行文字 職位稱呼,例如「PM」、「技術主管」
部門 選取 單選選項 所屬部門
Notion 成員 人員 單人選擇 連結到實際的 Notion 工作區成員帳號
電子郵件 電子郵件 標準電子郵件格式 聯絡用電子郵件
狀態 選取 單選選項 建立「啟用」、「停用」兩個選項

步驟 3:加入人員資料

建立一些人員資料來做測試

步驟 4:開啟授權給M2A Agent

  1. 我們點擊資料庫右上角的「...」選單
  2. 選擇「連接」
  3. 搜尋「M2A Agent」
  4. 確認連接「M2A Agent」
    連接M2A Agent

這樣我們就完成人員資料庫的建立了!


Step 2:新增「載入成員列表」節點

資料庫準備好後,在「格式化專案列表」節點後,新增 2 個處理成員資訊的節點。

2-1 新增「載入成員列表」節點

  1. 在「格式化專案列表」節點後新增一個 Notion Database Query 節點
  2. 將節點重新命名為「載入成員列表
  3. 設定以下參數:
    • Resource:Database Page
    • Operation:Get Many
    • Database:選擇成員資料庫
    • Return All:啟用
    • Simplify:啟用

2-2 新增「格式化成員列表」節點

在「載入成員列表」節點後新增一個 Code 節點,將載入的原始資料,整理成 AI 更容易理解的格式。

  1. 將節點重新命名為「格式化成員列表
  2. 在節點裡撰寫以下程式
// 從人員資料庫載入完整的成員資訊
const membersData = $input.all();

// 支援多種分隔符號的函式
function splitByMultipleDelimiters(text) {
  if (!text) return [];
  
  // 支援頓號、逗號、分號等多種分隔符號
  return text.split(/[、,;,]/).map(item => item.trim()).filter(item => item);
}

// 建立成員資訊陣列
const memberList = membersData.map(member => {
  const memberData = member.json;
  
  // 處理姓名
  const name = memberData.properties?.姓名?.title?.[^0]?.plain_text || '未知姓名';
  
  // 處理電子郵件
  const email = memberData.properties?.電子郵件?.email || '';
  
  // 處理暱稱(支援多種分隔符號)
  const nicknameText = memberData.properties?.暱稱?.rich_text?.[^0]?.plain_text || '';
  const nicknames = splitByMultipleDelimiters(nicknameText);
  
  // 處理職位(支援多種分隔符號)
  const positionText = memberData.properties?.職位?.rich_text?.[^0]?.plain_text || '';
  const positions = splitByMultipleDelimiters(positionText);
  
  // 處理部門
  const department = memberData.properties?.部門?.select?.name || '';
  
  // 處理 Notion 成員連結
  const notionUserField = memberData.properties?.['Notion 成員']?.people?.[^0];
  
  // 只有當 Notion 成員連結存在時,才將此成員加入清單
  if (!notionUserField || !notionUserField.id) {
    return null; // 回傳 null
  }
  
  const notionUserId = notionUserField.id;
  
  // 處理狀態
  const status = memberData.properties?.狀態?.select?.name || '啟用';
  
  // 建立完整的關鍵字清單
  const allKeywords = [
    name, // 正式姓名
    ...nicknames, // 所有暱稱
    ...positions, // 所有職位
    department, // 部門
    email ? email.split('@')[^0] : '' // 電子郵件帳號部分
  ].filter(k => k && k.trim() !== '');
  
  return {
    id: memberData.id,
    name: name,
    nicknames: nicknames,
    positions: positions,
    department: department,
    email: email,
    notion_user_id: notionUserId, // 實際要用來填入 Person 欄位的 ID
    status: status,
    keywords: [...new Set(allKeywords)] // 關鍵字陣列
  };
}).filter(member => member !== null && member.status === '啟用' && member.name !== '未知姓名'); // 過濾掉無效成員

// 建立給 AI 用的成員清單字串(包含所有可能的稱呼)
const memberListString = memberList.map(member => {
  let memberInfo = `${member.name}`;
  
  // 加入暱稱
  if (member.nicknames.length > 0) {
    memberInfo += ` (別名: ${member.nicknames.join('、')})`;
  }
  
  // 加入職位
  if (member.positions.length > 0) {
    memberInfo += ` [職位: ${member.positions.join('、')}]`;
  }
  
  // 加入部門
  if (member.department) {
    memberInfo += ` {${member.department}}`;
  }
  
  // 加入電子郵件
  if (member.email) {
    memberInfo += ` [${member.email}]`;
  }
  
  return memberInfo;
}).join('\n');

return [{
  json: {
    member_list: memberListString,
    member_data: memberList,
    total_members: memberList.length
  }
}];

2-3 新增「成員 ID 處理」節點

在「AI 摘要與任務提取」節點後新增一個 Code 節點,專門用來處理 AI 回傳的成員名稱,並轉換為 Notion API 需要的 ID 格式。

  1. 將節點重新命名為「成員 ID 處理
  2. 在節點裡撰寫以下程式
// 從「AI 摘要與任務提取」拿處理結果
const aiResult = $input.first().json;
const meetingInfo = aiResult.meeting_info;

// 加入保護檢查,確保欄位存在且為陣列
const participantIds = meetingInfo.participant_ids || [];
const assignedMemberIds = meetingInfo.assigned_member_ids || [];

// 直接使用 ID 字串陣列,不包裝成物件
const participantPersons = participantIds;
const assignedPersons = assignedMemberIds;

// 回傳結果
return [{
  json: {
    ...aiResult,
    meeting_info: {
      ...meetingInfo,
      participant_persons: participantPersons,
      assigned_persons: assignedPersons
    }
  }
}];

Step 3:更新寫入會議紀錄節點

現在要在兩個「寫入會議紀錄」節點中新增人員相關欄位。

3-1 修改 True 分支的寫入節點

  1. 開啟「寫入會議紀錄」節點(True 分支,有專案關聯的那個)
  2. Properties 區域新增以下欄位:
    • 參與夥伴{{ $('使用者 ID 處理').first().json.meeting_info.participant_persons }}
    • 任務指派{{ $('使用者 ID 處理').first().json.meeting_info.assigned_persons }}

3-2 修改 False 分支的寫入節點

  1. 開啟「寫入會議紀錄」節點(False 分支,沒有專案關聯的那個)
  2. 新增相同的欄位:
    • 參與夥伴{{ $('使用者 ID 處理').first().json.meeting_info.participant_persons }}
    • 任務指派{{ $('使用者 ID 處理').first().json.meeting_info.assigned_persons }}

Step 4:測試與驗證

4-1 準備測試音訊

建立包含參與者和任務指派資訊的測試內容。

4-2 執行測試

  1. 開啟 Gradio 前端介面
  2. 上傳測試音訊
  3. 在處理指令中輸入:請分析會議內容,特別注意參與者和任務指派
  4. 點擊「開始處理」

4-3 驗證結果

檢查 Notion「會議記錄」資料庫中的結果

  1. 參與夥伴:應顯示參與此次會議的夥伴
  2. 任務指派:應顯示被指派任務的人員

今天的成果總結

完成項目

  • 在「會議記錄」資料庫中新增了「參與夥伴」和「任務指派」兩個欄位
  • 建立了「人員資料庫」為後續打下了辨識人員相關的基礎
  • 建立了人員比對的初步邏輯

尚待改善

  • 會議摘要與任務提取精準度下降
  • 參與夥伴被設為人員資料庫裡的所有成員
  • AI 在指派任務時,仍然會出現張冠李戴的情況,邏輯需要強化。
  • 行動任務提取一樣失去了精準度產生了偏差,例如指派錯誤成員
  • 任務包含多個不同的截止日期時,目前的邏輯無法有效處理。

心得

今天的開發我們成功地搭建了成員辨識的骨架,雖然沒有達到完美的結果,甚至在摘要、任務提取的品質上有所倒退,但這個成功的原型為我們指明了接下來強化的方向。挫折感還是有的,但看到成員頭貼出現在會議記錄欄位的那一刻,還是相當振奮人心的!

🎯 明天計劃
為摘要、任務提取、成員辨識等各設計專用的Prompt,強化指派邏輯精準度,修正分析品質偏差。


上一篇
Day 13 Prompt 架構升級 — 智慧日期解析與模組化設計
下一篇
Day 15 強化解析架構 — 設計多工 Prompt 與指派邏輯強化
系列文
打造基於 MCP 協議與 n8n 工作流的會議處理 Agent17
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言