會議簡報產生器 是做什麼的?
輸入公司名稱(與選擇性聯絡人資訊)。透過 Tavily 研究該公司,再由 Gemini 整合為一頁式的會前摘要。可選擇儲存至 Notion。
重要規則: 請勿憑空捏造細節。簡報中的每一項事實、數字與主張都必須來自 Tavily 搜尋結果。若某區塊無搜尋資料,請標示「Limited public information found.」。切勿捏造募資金額、員工人數或產品細節。
步驟 1:環境檢查
確認必要的環境變數:
echo "TAVILY_API_KEY: ${TAVILY_API_KEY:+set}"
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+set}"
echo "NOTION_TOKEN: ${NOTION_TOKEN:-not set}"
echo "NOTION_DATABASE_ID: ${NOTION_DATABASE_ID:-not set}"
若缺少 TAVILY_API_KEY: 停止執行。告知使用者:「TAVILY_API_KEY 是必要的。請到 app.tavily.com 取得金鑰,並加到你的 .env 檔案中。」
若缺少 GEMINI_API_KEY: 停止執行。告知使用者:「GEMINI_API_KEY 是必要的。請到 aistudio.google.com 取得金鑰,並加到你的 .env 檔案中。」
若缺少 NOTION_TOKEN 或 NOTION_DATABASE_ID: 繼續執行。簡報將僅以純文字輸出,略過儲存至 Notion 的步驟。
確認輸入內容是否齊全。 使用者至少需提供公司名稱。若未提供,請詢問:「您正在與哪間公司開會?」
步驟 2:收集背景資訊
收集以下資訊。僅詢問缺少的項目。
必要項目:
- 公司名稱(或網域/URL,若有提供)
- 會議日期
選填項目(若缺少則不阻擋流程):
- 聯絡人姓名與職稱
- 會議類型(探索、產品展示、跟進、季度業務回顧)
- 使用者希望涵蓋的任何特定話題或目標
若使用者提供公司網址或網域,請用它來讓 Tavily 查詢更精準(例如在查詢中使用 site:example.com 或包含網域)。
步驟 3:使用 Tavily 進行研究
依序執行以下搜尋。每個搜尋針對簡報的一個區塊。儲存每個搜尋的前幾筆結果(標題、URL、內容片段、分數)。
僅保留分數 >= 0.5 的結果。若某搜尋未取得任何符合條件的結果,則將該區塊標示為「Limited public information found.」
搜尋 1:公司概覽
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" overview founded employees headquarters",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
搜尋 2:近期新聞(過去 30 天)
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" news announcement",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true,
"topic": "news",
"time_range": "month"
}'
搜尋 3:技術棧
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" technology stack engineering infrastructure tools",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
搜尋 4:產品與定價
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" product features pricing use case",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
搜尋 5:競爭對手
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" competitors alternatives vs",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
搜尋 6:資金與成長
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"COMPANY\" funding raised valuation growth",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
若有提供聯絡人姓名,則執行以下兩項搜尋:
搜尋 7:聯絡人資料
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"CONTACT_NAME\" \"COMPANY\" role title",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
搜尋 8:聯絡人背景
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "\"CONTACT_NAME\" background career LinkedIn",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
步驟 4:透過 Gemini 整合
完整閱讀 references/brief-format.md。閱讀 references/output-template.md 並使用該模板。
將 Gemini 請求寫入暫存檔:
cat > /tmp/meeting-brief-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "你是一位GTM研究分析師,正在為一場銷售或業務開發會議準備一份一頁式的會前摘要。規則:每一項主張都必須引用所提供研究中的來源網址。對於談話要點,請使用格式「因為[研究發現],請提及[要點]以達成[目標]」。不得使用虛構資料。若某區塊無研究資料,請寫「Limited public information found.」避免使用 em dash。不得使用禁用詞。總字數少於400字。摘要必須能在3分鐘內掃讀完畢。"
}]
},
"contents": [{
"parts": [{
"text": "RESEARCH_RESULTS_AND_INSTRUCTIONS_HERE"
}]
}],
"generationConfig": {
"temperature": 0.3,
"maxOutputTokens": 2500
}
}
ENDJSON
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/meeting-brief-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
將 RESEARCH_RESULTS_AND_INSTRUCTIONS_HERE 替換為:
- 所有 Tavily 搜尋結果(每個結果的標題、URL、內容片段)
- 來自 output-template.md 的簡報模板結構
- 公司名稱、聯絡人姓名(若有提供)、會議日期、會議類型(若有提供)
步驟 5:自我品質檢查
呈現前請檢查:
- 無虛構資料。每一項事實都有來自 Tavily 結果的來源網址。
- 談話要點使用「因為[研究發現],請提及[要點]以達成[目標]」格式
- 所有行中無 em dash
- 無禁用詞
- 簡報少於 400 字
- 若未提供聯絡人,決策者區塊顯示「Not specified」
- 無資料的區塊顯示「Limited public information found」而非猜測
- 開放式問題是針對此公司特定,而非通用問題
在呈現前修正任何違規事項。
步驟 6:輸出或儲存至 Notion
在一個程式碼區塊中呈現完整的簡報。
若 NOTION_TOKEN 與 NOTION_DATABASE_ID 都已設定,請詢問:「要將此簡報儲存至 Notion 嗎?」
確認後:
cat > /tmp/notion-brief-payload.json << 'ENDJSON'
{
"parent": { "database_id": "NOTION_DATABASE_ID_HERE" },
"properties": {
"Name": {
"title": [{ "text": { "content": "會議簡報:COMPANY, DATE" } }]
},
"Date": {
"date": { "start": "YYYY-MM-DD" }
}
},
"children": [
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [{ "type": "text", "text": { "content": "BRIEF_CONTENT_HERE" } }]
}
}
]
}
ENDJSON
curl -s -X POST "https://api.notion.com/v1/pages" \
-H "Authorization: Bearer $NOTION_TOKEN" \
-H "Content-Type: application/json" \
-H "Notion-Version: 2022-06-28" \
-d @/tmp/notion-brief-payload.json
儲存完成後顯示:「簡報已儲存至 Notion。請檢查你的資料庫。」
若未設定 Notion,則僅呈現簡報。請勿提及 Notion。