owned this note
owned this note
Published
Linked with GitHub
# 第三堂:前後端整合:募資文案智能寫作
## Whisper 語音轉文字
### NPM 介紹
* multer:處理上傳檔案
* FormData:包裝成 FormData 請求送出給 OpenAI
* axios:發出網路請求
### 儲存在記憶體跟實體空間的差異
| 項目 | 記憶體儲存 (MemoryStorage) | 實體硬碟儲存 (DiskStorage) |
|------------------|--------------------------------------------------------------------|--------------------------------------------------------------------------|
| **儲存位置** | 將檔案暫存在伺服器記憶體 (RAM) 中 | 將檔案寫入伺服器硬碟或指定的實體路徑 |
| **使用情境** | 適合即時處理、小型檔案處理、多數情況不需長期保存 | 適合需要暫留或後續再處理的檔案、大量或較大檔案上傳 |
| **效能** | I/O 速度快,無須讀寫硬碟,對小檔案較有效率 | 需要硬碟 I/O,速度可能稍慢,但對大檔案或長期保存更實用 |
| **記憶體壓力** | 檔案全存於記憶體,若並發或檔案過大,可能導致 Out Of Memory | 不會耗用過多 RAM,但在硬碟空間不足時也可能引發其他問題 |
| **保留時間** | 只要程式結束或記憶體被釋放,檔案即消失 | 儲存在硬碟上,可持續保存,除非自行刪除或重新部署 |
| **部署/權限** | 部署較方便,不需考慮硬碟路徑、讀寫權限 | 需設定讀寫路徑與權限,若在 Serverless 或限制多的環境需特別注意 |
| **後續操作** | 資料只在記憶體內,若需要多階段處理必須先轉存 | 可直接存檔後續再加工、分析,可多人或多服務存取同一檔案 |
| **除錯與追蹤** | 處理完後即釋放,檔案不留存,事後較難復原檢查 | 上傳後會有實際檔案,可以做後續的除錯或檢視 |
| **清理管理** | 不需額外清理檔案,使用後自動釋放 | 需要手動或透過機制定期刪除不再使用的檔案 |

### 範例程式碼
```=javascript
const express = require("express");
const multer = require("multer");
const axios = require("axios");
const FormData = require("form-data");
require("dotenv").config();
// 初始化 Express 應用程式
const app = express();
const PORT = 3000;
// 中間件設定
app.use(express.json());
app.use(express.static("public"));
// 設定檔案上傳 - 使用記憶體儲存
const upload = multer({
storage: multer.memoryStorage(), // 使用記憶體儲存
limits: { fileSize: 25 * 1024 * 1024 }, // 25MB 限制
fileFilter: (req, file, cb) => {
// 只允許音訊檔案
if (file.mimetype.startsWith("audio/")) {
cb(null, true);
} else {
cb(new Error("請上傳音訊檔案"));
}
},
});
// 音訊轉文字函式 - 使用記憶體緩衝區
async function transcribeAudio(audioBuffer, mimeType, originalFilename) {
try {
// 取得副檔名
const extension = originalFilename.split(".").pop() || "mp3";
// 創建 FormData
const form = new FormData();
form.append("model", "whisper-1");
form.append("language", "zh");
// 直接將緩衝區添加到 FormData
form.append("file", audioBuffer, {
filename: `audio.${extension}`,
contentType: mimeType,
});
// 使用 axios 發送請求到 OpenAI API
const response = await axios.post(
"https://api.openai.com/v1/audio/transcriptions",
form,
{
headers: {
...form.getHeaders(),
Authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
},
}
);
return {
success: true,
text: response.data.text,
};
} catch (error) {
return {
success: false,
error: error.response?.data?.error?.message || error.message,
};
}
}
// API 端點 - 音訊轉文字
app.post("/api/transcribe", upload.single("audio"), async (req, res) => {
if (!req.file) {
return res.status(400).json({ error: "請上傳音訊檔案" });
}
console.log(
`收到音訊檔案: ${req.file.originalname}, 大小: ${req.file.size} bytes`
);
// 使用緩衝區而非檔案路徑
const result = await transcribeAudio(
req.file.buffer,
req.file.mimetype,
req.file.originalname
);
if (result.success) {
res.json(result);
} else {
res.status(500).json(result);
}
});
// 啟動伺服器
app.listen(PORT, () => {
console.log(`伺服器運行在 http://localhost:${PORT}`);
});
```
## 募資文案優化重點
1. 提升文案效率
2. 法規跟敏感詞彙檢查
### 募資文案 API 流程圖


### 沒問題的範例
```=javascript
{
"project_name": "智能環保水壺",
"target_fund": "NT$500,000",
"start_date": "2023-12-01",
"end_date": "2024-01-31",
"product_type": "智能硬體",
"brand_background": "由一群環保工程師和設計師組成的團隊,致力於減少一次性塑料使用",
"core_features": "溫度監控、水質檢測、飲水提醒、可替換濾芯、環保材質",
"target_audience": "注重健康和環保的年輕專業人士和戶外愛好者",
"tone_style": "專業但友善,強調環保和科技創新"
}
```
### 會出事的範例 XD
```=JavaScript
{
"project_name": "黃金投資致富計畫",
"target_fund": "NT$2,000,000",
"start_date": "2024-01-01",
"end_date": "2024-02-28",
"product_type": "貴金屬投資",
"brand_background": "由一群具有10年以上金融市場經驗的專業投資顧問組成,我們的團隊成員曾在國際知名金融機構工作,擁有豐富的貴金屬交易經驗。",
"core_features": "保證獲利的黃金投資方案、零風險投資組合、100%回報保證、獨家市場預測系統、政府立案的投資顧問團隊、絕對保密的VIP客戶服務",
"target_audience": "想要快速致富的投資者、退休規劃人士、尋求穩定高回報的保守型投資者",
"tone_style": "專業權威,強調獨特性和絕對優勢"
}
```
```=javascript
/**
* 生成募資文案
* @param {Object} projectData - 專案資料
* @returns {Promise<string>} - 生成的文案
*/
async function generateFundraisingCopy(projectData) {
try {
console.log(`生成募資文案: ${projectData.project_name}`);
// 構建結構化的提示
const prompt = `
你是一位專業的文案撰寫專家,以下是專案資訊:
專案名稱:${projectData.project_name}
募資目標金額:${projectData.target_fund}
開始/結束日期:${projectData.start_date} ~ ${projectData.end_date}
產品類型:${projectData.product_type}
團隊背景:${projectData.brand_background}
核心特色:${projectData.core_features}
目標客群:${projectData.target_audience}
希望文案風格:${projectData.tone_style}
請根據以上資訊,創建一個完整的募資頁面文案,包含以下部分:
1. 引人注目的標題
2. 簡短有力的專案摘要
3. 專案背景與故事
4. 產品/服務特色與優勢[可以有多個區塊,不需要只有一個]
5. 團隊介紹
6. 資金用途說明
7. 回饋方案建議
8. 時程規劃
9. 結尾呼籲行動
使用繁體中文,並根據指定的文案風格撰寫。
`;
const response = await openai.responses.create({
model: "gpt-4o",
instructions:
"你是一位專業的募資文案撰寫專家,擅長撰寫吸引人的眾籌專案文案。",
input: [{ role: "user", content: prompt }],
temperature: 0.7,
});
return response.output_text;
} catch (error) {
console.error("生成募資文案時出錯:", error);
throw error;
}
}
/**
* 檢測敏感詞
* @param {string} content - 要檢測的文案內容
* @returns {Promise<Object>} - 檢測結果
*/
async function detectSensitiveContent(content) {
try {
console.log("進行敏感詞檢測");
const sensitiveWordsList = `毒品,海洛因,大麻,槍械,武器,彈藥,炸彈,爆炸物,賭博,賭場,偽造,人口販賣,
保證致富,永遠有效,無副作用,100%有效,立刻見效,史上最強,絕無僅有,獨一無二,前所未有,終極解決方案,
台獨,港獨,藏獨,納粹,三K黨,伊斯蘭國,ISIS,基地組織,恐怖分子,極端主義,聖戰,
黑鬼,支那,小日本,台巴子,基佬,人妖,娘炮,婊子,智障,殘廢,
色情,A片,淫穢,性交,口交,強姦,兒童色情,血腥,屠殺,虐殺,謀殺,
治癒癌症,包治百病,奇蹟療效,立即見效,無副作用,藥到病除,根治,永不復發,醫生推薦,權威認證,
快速致富,一夜致富,穩賺不賠,高收益,零風險,保證回報,利潤翻倍,一本萬利,傳銷,老鼠會`;
// 定義函式
const tools = [
{
type: "function",
name: "sensitive_content_analysis",
description: "分析文案中的敏感內容並提供結果",
parameters: {
type: "object",
properties: {
hasSensitiveContent: {
type: "boolean",
description: "是否發現敏感內容",
},
sensitiveWords: {
type: "array",
items: {
type: "string",
},
description: "發現的敏感詞列表",
},
issues: {
type: "array",
items: {
type: "object",
properties: {
category: {
type: "string",
description: "問題類別,如政治敏感、歧視性語言等",
},
description: {
type: "string",
description: "問題說明",
},
suggestion: {
type: "string",
description: "修改建議",
},
},
},
description: "敏感內容問題列表",
},
summary: {
type: "string",
description: "敏感內容分析總結",
},
},
required: [
"hasSensitiveContent",
"sensitiveWords",
"issues",
"summary",
],
},
},
];
const response = await openai.responses.create({
model: "gpt-4o",
instructions: `你是一位內容審核專家,負責檢測文案中可能存在的敏感詞或不適當內容。
請特別檢查以下敏感詞列表中的詞語是否出現在文案中:
${sensitiveWordsList}
此外,也請檢查以下類別的敏感內容:
1. 政治敏感詞
2. 歧視性語言
3. 違法或灰色地帶內容
4. 誇大不實的宣傳
5. 侵犯智慧財產權的內容
6. 違反平台規範的內容
請使用 sensitive_content_analysis 函式回傳分析結果,提供詳細的敏感詞檢測報告。`,
input: [{ role: "user", content: content }],
tools: tools,
tool_choice: "auto",
temperature: 0.3,
});
// 解析函式呼叫結果
if (response.output && response.output.length > 0) {
const functionCall = response.output.find(
(item) =>
item.type === "function_call" &&
item.name === "sensitive_content_analysis"
);
if (functionCall) {
const result = JSON.parse(functionCall.arguments);
// 添加原始分析文本
const analysisText = `敏感詞檢測結果:
是否發現敏感內容:${result.hasSensitiveContent ? "是" : "否"}
${
result.hasSensitiveContent
? `發現的敏感詞:${result.sensitiveWords.join("、")}`
: "未發現敏感詞"
}
問題詳情:
${result.issues
.map(
(issue) =>
`- ${issue.category}:${issue.description}\n 建議:${issue.suggestion}`
)
.join("\n\n")}
總結:${result.summary}`;
return {
...result,
analysis: analysisText,
};
}
}
// 如果函式呼叫失敗,回傳預設結果
return {
hasSensitiveContent: false,
sensitiveWords: [],
issues: [],
summary: "無法進行敏感詞分析",
analysis: "無法進行敏感詞分析,請稍後再試。",
};
} catch (error) {
console.error("檢測敏感詞時出錯:", error);
throw error;
}
}
/**
* 進行法規檢測
* @param {string} content - 要檢測的文案內容
* @param {Object} projectData - 專案資料
* @returns {Promise<Object>} - 檢測結果
*/
async function regulatoryCompliance(content, projectData) {
try {
console.log("進行法規檢測");
const checkList = `一、交易/集資類(4 大常見違規重點)
1. 保證獲利、零風險、穩賺不賠(如「穩賺不賠」「保證本金」);可能違反《公平交易法》虛偽廣告、金管會廣告辦法、銀行法非法吸金等。
2. 誇大收益、高額回報(如「短期翻倍」「年化收益率XX%」);可能違反《公平交易法》虛偽不實、銀行法第29條之1非法吸收資金。
3. 冒用官方或第三方背書(如「政府立案」「金管會核准」「官方保證」);可能違反《公平交易法》誤導表示、相關刑法偽造文書規範。
4. 未揭露風險或限制(只談好處、不提風險,或警語極小字);可能違反《消費者保護法》重要資訊揭露、《公平交易法》誤導宣傳。
二、功能性產品(智慧裝置、AI 工具等)
1. 使用最高級、絕對化詞彙(如「全球唯一」「第一品牌」「無失誤」);恐違反《公平交易法》第21條誇大不實。
2. 暗示醫療功效或醫療級(如「治療失眠」「舒緩關節疼痛」「醫生背書」);恐違反《藥事法》《醫療器材管理法》等。
3. 虛假專利或官方認證(如「NASA技術」「軍規測試」「FDA核可」);恐違反《公平交易法》或《專利法》。
三、營養保健食品(膠原蛋白、益生菌、魚油等)
1. 宣稱醫療功效(如「治療糖尿病」「預防感冒」「降血壓、抗癌」);違反《食品安全衛生管理法》第28條(不得標榜療效)。
2. 誇大瘦身或速效(如「免運動就能瘦」「3天見效」「一週瘦10公斤」);違反食安法誇大宣傳,亦涉《公平交易法》虛偽不實。
3. 偽專業背書或不實認證(如「衛福部小綠人認證」「FDA核可」「名醫推薦」);違反食安法及《公平交易法》虛假廣告。
四、美容保健產品(瘦身、美白、抗老化等)
1. 不實速效、永久功效(如「瞬間美白」「一週逆齡」「永不復發」);違反《化粧品衛生安全管理法》第10條、亦涉《公平交易法》。
2. 醫藥療效宣稱(如「治療粉刺」「醫療級除皺」「根治痘痘」);超出化粧品範疇,違反化粧品法及《藥事法》。
3. 誇大成分作用(如「幹細胞再生技術」「醫美級玻尿酸」);無科學依據或專利說明則違反《化粧品衛生安全管理法》《公平交易法》。`;
// 定義函式
const tools = [
{
type: "function",
name: "regulatory_compliance_analysis",
description: "分析文案是否符合法規並提供結果",
parameters: {
type: "object",
properties: {
hasRegulatoryIssues: {
type: "boolean",
description: "是否發現法規問題",
},
violations: {
type: "array",
items: {
type: "object",
properties: {
category: {
type: "string",
description: "違規類別",
},
content: {
type: "string",
description: "違規內容",
},
law: {
type: "string",
description: "相關法規",
},
suggestion: {
type: "string",
description: "修正建議",
},
},
},
description: "法規違規列表",
},
missingElements: {
type: "array",
items: {
type: "string",
},
description: "缺少的必要元素(如風險揭露、退款政策等)",
},
summary: {
type: "string",
description: "法規檢測總結",
},
},
required: [
"hasRegulatoryIssues",
"violations",
"missingElements",
"summary",
],
},
},
];
const response = await openai.responses.create({
model: "gpt-4o",
instructions: `你是一位募資平台法規專家,負責檢查募資文案是否符合相關法規。
請特別檢查以下法規清單中提到的違規情況是否出現在文案中:
${checkList}
此外,也請檢查以下方面:
1. 消費者保護法相關規範
2. 廣告法規遵循
3. 募資平台特定規範
4. 產品安全與責任聲明
5. 智慧財產權聲明
6. 退款與交付政策
請使用 regulatory_compliance_analysis 函式回傳分析結果,提供詳細的法規檢測報告。`,
input: [
{
role: "user",
content: `專案資料: ${JSON.stringify(
projectData
)}\n\n文案內容: ${content}`,
},
],
tools: tools,
tool_choice: "auto",
temperature: 0.3,
});
// 解析函式呼叫結果
if (response.output && response.output.length > 0) {
const functionCall = response.output.find(
(item) =>
item.type === "function_call" &&
item.name === "regulatory_compliance_analysis"
);
if (functionCall) {
const result = JSON.parse(functionCall.arguments);
// 添加原始分析文本
const analysisText = `法規檢測結果:
是否發現法規問題:${result.hasRegulatoryIssues ? "是" : "否"}
${result.hasRegulatoryIssues ? "違規項目:" : ""}
${result.violations
.map(
(v) =>
`- ${v.category}:${v.content}\n 相關法規:${v.law}\n 建議:${v.suggestion}`
)
.join("\n\n")}
${result.missingElements.length > 0 ? "缺少的必要元素:" : ""}
${result.missingElements.map((e) => `- ${e}`).join("\n")}
總結:${result.summary}`;
return {
...result,
analysis: analysisText,
};
}
}
// 如果函式呼叫失敗,回傳預設結果
return {
hasRegulatoryIssues: false,
violations: [],
missingElements: [],
summary: "無法進行法規檢測",
analysis: "無法進行法規檢測,請稍後再試。",
};
} catch (error) {
console.error("進行法規檢測時出錯:", error);
throw error;
}
}
/**
* 生成總結回饋
* @param {Object} results - 各階段結果
* @returns {Promise<string>} - 總結回饋
*/
async function generateFeedback(results) {
try {
console.log("生成總結回饋");
const response = await openai.responses.create({
model: "gpt-4o",
instructions: `你是一位募資顧問專家,負責提供專業的募資文案回饋。
根據文案生成、敏感詞檢測和法規檢測的結果,提供全面的總結回饋。
包含以下方面:
1. 文案整體評價
2. 敏感內容處理建議
3. 法規合規性建議
4. 改進方向
5. 募資成功要點提示
使用繁體中文,提供專業、實用且具體的建議。`,
input: [{ role: "user", content: JSON.stringify(results) }],
temperature: 0.5,
});
return response.output_text;
} catch (error) {
console.error("生成總結回饋時出錯:", error);
throw error;
}
}
/**
* 處理募資文案生成
* @param {Object} projectData - 專案資料
* @returns {Promise<Object>} - 生成的文案
*/
async function processFundraisingCopy(projectData) {
try {
console.log(`生成募資文案: "${projectData.project_name}"`);
const copyContent = await generateFundraisingCopy(projectData);
return {
projectData,
copyContent,
};
} catch (error) {
console.error("處理募資文案生成時出錯:", error);
throw error;
}
}
/**
* 處理文案檢測流程
* @param {Object} data - 包含文案內容和專案資料
* @returns {Promise<Object>} - 檢測結果
*/
async function processCopyCheck(data) {
try {
const { copyContent, projectData } = data;
// 第一階段:敏感詞檢測
console.log("第一階段:敏感詞檢測");
const sensitiveCheck = await detectSensitiveContent(copyContent);
// 第二階段:法規檢測
console.log("第二階段:法規檢測");
const regulatoryCheck = await regulatoryCompliance(
copyContent,
projectData
);
// 生成總結回饋
const results = {
projectData,
copyContent,
sensitiveCheck,
regulatoryCheck,
};
const feedback = await generateFeedback(results);
return {
sensitiveCheck,
regulatoryCheck,
feedback,
};
} catch (error) {
console.error("處理文案檢測時出錯:", error);
throw error;
}
}
// API 端點 - 處理募資文案生成
app.post("/api/fundraising/generate", async (req, res) => {
try {
const projectData = req.body;
// 檢查必要欄位
if (!projectData.project_name) {
return res.status(400).json({ error: "請提供專案名稱" });
}
// 設定預設值
const processedData = {
project_name: projectData.project_name,
target_fund: projectData.target_fund || "未指定",
start_date: projectData.start_date || "未指定",
end_date: projectData.end_date || "未指定",
product_type: projectData.product_type || "未指定",
brand_background: projectData.brand_background || "未指定",
core_features: projectData.core_features || "未指定",
target_audience: projectData.target_audience || "未指定",
tone_style: projectData.tone_style || "專業友善",
};
console.log(`收到募資文案生成請求: "${processedData.project_name}"`);
const result = await processFundraisingCopy(processedData);
res.json(result);
} catch (error) {
console.error("處理募資文案生成時出錯:", error);
res.status(500).json({ error: error.message || "處理請求時發生錯誤" });
}
});
// API 端點 - 處理文案檢測
app.post("/api/fundraising/check", async (req, res) => {
try {
const { copyContent, projectData } = req.body;
// 檢查必要欄位
if (!copyContent) {
return res.status(400).json({ error: "請提供文案內容" });
}
if (!projectData || !projectData.project_name) {
return res.status(400).json({ error: "請提供完整的專案資料" });
}
console.log(`收到文案檢測請求: "${projectData.project_name}"`);
const result = await processCopyCheck({ copyContent, projectData });
res.json(result);
} catch (error) {
console.error("處理文案檢測時出錯:", error);
res.status(500).json({ error: error.message || "處理請求時發生錯誤" });
}
});
```