AI 助理免費安裝服務|十步安裝|從零到第一個 AI 回覆

進度 0%
這項免費安裝服務全程免費,不需要信用卡。 免費不等於無限量;Gemini、Apps Script 與 LINE 免費路徑都有 quota。超過限制時會回報限制、暫停或等待恢復,不會自動替你啟用 billing 或 Paid Tier。
這一頁怎麼用:由上往下一次做一步,依登入與授權畫面逐步完成。你看到的是五段成果進度;每一段裡仍保留原本的「開哪裡、按什麼、看到什麼」。 課文說明在 02/03/04,不讀也走得完;真的遇到問題開 05|AI Troubleshooter。
🔴 關於秘密,三個承諾:①這一頁不會把 Channel secret/API Key 送出去(斷網照常可用)②密鑰不寫入 localStorage、cookie、URL 或任何後端(頁面關閉即失)③密鑰的生成與貼入全程你親手在官方平台做。API Key 與 Channel secret 不要貼到聊天室、公開貼文、截圖、影片裡。這次交接只帶入非密的「小工作/真人接手」兩格,讀取後立即清除。
備開工前確認
你需要說明
你自己的 LINE 帳號手機上正在用的那個即可
你自己的 Google 帳號一般 Gmail 帳號即可
一支裝了 LINE 的手機最後測試要用它收第一個 AI 回覆
一段不被打斷的時間照著做一次到底;中斷也沒關係,平台上做完的都會留著
板安裝進度板

勾了會自動更新;進度只存在本頁開著的期間(刻意設計)。

1建立官方帳號
  1. 開 LINE 台灣的「免費開設帳號」頁(LINE 官方網站),按頁面中間綠色的「免費開設帳號」鍵。
  2. 接著會到「LINE Business ID」頁:還沒有的選「使用LINE帳號註冊」,用你手機 LINE 的帳號登入;已經有的選下方「登入」。(頁面可切繁體中文。)
  3. 填帳號名稱、行業別等基本資料,送出。若畫面提供「未認證帳號」選項,可先依畫面完成;帳號可用性、驗證與功能狀態以 LINE 當下顯示為準。
做完你應該看到:申請完成,你有了一個官方帳號。

已經有官方帳號的人,直接到步驟 2。

2啟用 Messaging API

這一步會把「能接程式的通道」打開。全程在中文介面。

  1. 開 LINE Official Account Manager,選你的帳號。
  2. 右上「設定」→ 左邊「Messaging API」。
  3. 按綠色「啟用Messaging API」。
  4. 「選擇服務提供者」:選「建立服務提供者」取個名(例:你的店名)→「同意」。已有的話選既有那個。
  5. 「隱私權政策及服務條款」兩欄都是選填,空著直接「確定」。
做完你應該看到:狀態變「使用中」,出現 Channel ID 等資訊,下方有一格「Webhook網址」。這一頁步驟 9 還會回來,記得路。
📷 對照圖|按下「啟用Messaging API」後的確認視窗(點圖可放大)
啟用確認視窗
📷 對照圖|選擇服務提供者+選填兩欄(兩張,點圖可放大)
選擇服務提供者隱私權政策兩欄選填
📷 對照圖|啟用完成:狀態「使用中」+Webhook網址欄(點圖可放大)
啟用完成:使用中
3複製 Channel ID 與 Channel secret

沿用剛才的 Messaging API 頁面,複製這個官方帳號的兩個設定。程式會自動向 LINE 取得短期權杖,不需要按 Issue。

  1. 在 LINE Manager 的「設定 → Messaging API」複製 Channel ID,貼進下方第一格。
  2. 複製同帳號的 Channel secret,貼進第二格。若 Manager 未顯示,從頁面連結進 LINE Developers,選同一個 channel 的 Basic settings;核對 Channel ID 後複製 Channel secret。
做完你應該看到:兩格都有值,而且來自同一個 Channel ID;不要重新發行 secret。
4取得 Gemini API Key
  1. 用你的 Google 帳號開 aistudio.google.com/apikey。
  2. 按右上「Create API key」。
  3. 幫金鑰取個名(隨意)、專案用它預設給的 →「Create key」。
  4. 「API key details」視窗出現金鑰——按複製鈕,貼進下面這格。
做完你應該看到:一串金鑰(外觀由 Google 當下的 API key 類型決定)。這項免費安裝服務全程免費,不需要信用卡。 走標準 Free Tier;免費不等於無限量,超過 Gemini、Apps Script 或 LINE 的 quota 時會回報限制、暫停或等待恢復,不會自動啟用 billing 或 Paid Tier。第三方顯示付款設定不是完成這項免費安裝服務的必要步驟,不要為了完成AI 助理免費安裝服務綁卡。
📷 對照圖|API Keys 頁 → 建立視窗 → 金鑰詳情(三張,點圖可放大)
API Keys 頁與 Create API key 按鈕Create a new key 視窗API key details(金鑰已遮蔽)
5開 GAS 專案,貼程式碼

這項免費安裝服務全程免費,不需要信用卡。 Google Apps Script(GAS)是 Google 的腳本執行服務,可以讓一小段程式有自己的網址;consumer 帳戶有官方 quota 與限制,超過時會停止執行或回報服務不可用,不會因此自動付款。本包只用它承接你自己的小工作;免費不等於無限量。

  1. 用你的 Google 帳號開 script.google.com → 按「新專案」。
  2. 編輯區全選(Ctrl+A)→ Delete 全部刪掉。
  3. 按下面「複製整段程式碼」→ 貼進空白編輯區 → Ctrl+S 儲存。要整段貼:從第一行 /** 到最後一個 }。

已複製 ✓

/** 愛智理- AI 助理免費安裝服務:LINE × Gemini 十步教學 */
function cfg_(name) {
  return PropertiesService.getScriptProperties().getProperty(name);
}

/** 秘密只留在自己的指令碼屬性,不寫進程式碼或執行紀錄。 */
function importSetup_() {
  var props = PropertiesService.getScriptProperties();
  var raw = props.getProperty('SETUP_INPUT');
  if (!raw) return;
  var data;
  try { data = JSON.parse(raw); } catch (_) { throw new Error('設定格式不完整:回第6步重新複製整份設定'); }
  if (!data || typeof data !== 'object' || Array.isArray(data)) throw new Error('設定格式錯誤');
  var required = ['LINE_CHANNEL_ID', 'LINE_CHANNEL_SECRET', 'GEMINI_API_KEY', 'KNOWLEDGE'];
  var allowed = required.concat(['PROMPT', 'GEMINI_MODEL']);
  if (Object.keys(data).some(function(k) { return allowed.indexOf(k) < 0; })) throw new Error('設定含未知欄位');
  required.forEach(function(k) {
    if (typeof data[k] !== 'string' || !data[k].trim()) throw new Error('缺少設定:' + k);
  });
  if (!/^\d+$/.test(data.LINE_CHANNEL_ID.trim())) throw new Error('Channel ID 應只有數字');
  var clean = {};
  allowed.forEach(function(k) {
    if (data[k] !== undefined && typeof data[k] !== 'string') throw new Error('設定型態錯誤:' + k);
    clean[k] = (data[k] || '').trim();
  });
  props.setProperties(clean, false);
  props.deleteProperty('SETUP_INPUT');
  console.log('設定已匯入;暫存設定已清除');
}

/** 只快取到到期前60秒。快取遺失時重發,不沿用失效憑證。 */
function lineToken_() {
  var id = cfg_('LINE_CHANNEL_ID');
  var secret = cfg_('LINE_CHANNEL_SECRET');
  if (!id || !secret) throw new Error('LINE 設定缺少 Channel ID 或 Channel secret');
  var digest = Utilities.computeDigest(Utilities.DigestAlgorithm.SHA_256, id + '\n' + secret);
  var key = 'fs_line_' + Utilities.base64EncodeWebSafe(digest);
  var cache = CacheService.getScriptCache();
  var token = cache.get(key);
  if (token) return token;
  var res;
  try {
    res = UrlFetchApp.fetch('https://api.line.me/oauth2/v3/token', {
      method: 'post', contentType: 'application/x-www-form-urlencoded',
      payload: { grant_type: 'client_credentials', client_id: id, client_secret: secret },
      muteHttpExceptions: true
    });
  } catch (_) { throw new Error('LINE 權杖連線失敗'); }
  if (res.getResponseCode() !== 200) throw new Error('LINE 權杖 HTTP ' + res.getResponseCode());
  var data;
  try { data = JSON.parse(res.getContentText()); } catch (_) { throw new Error('LINE 權杖回應格式錯誤'); }
  if (!data.access_token || typeof data.access_token !== 'string' || !isFinite(data.expires_in) || Number(data.expires_in) <= 60)
    throw new Error('LINE 權杖回應不完整');
  cache.put(key, data.access_token, Math.min(840, Math.floor(Number(data.expires_in) - 60)));
  return data.access_token;
}

function ok_() {
  return ContentService.createTextOutput(JSON.stringify({ ok: true })).setMimeType(ContentService.MimeType.JSON);
}

function doPost(e) {
  try {
    if (!e || !e.postData || !e.postData.contents) return ok_();
    var body;
    try { body = JSON.parse(e.postData.contents); } catch (_) { throw new Error('Webhook 內容格式錯誤'); }
    var events = body.events || [];
    if (!Array.isArray(events)) throw new Error('Webhook events 格式錯誤');
    events.forEach(function(ev) {
      if (ev.type !== 'message' || !ev.message || ev.message.type !== 'text' || !ev.replyToken) return;
      var answer;
      try { answer = askGemini_(ev.message.text); }
      catch (err) {
        console.error('Gemini 失敗:' + err.message);
        answer = '抱歉,我這邊暫時有點問題,請稍等一下由真人回覆你。';
      }
      replyToLine_(ev.replyToken, answer);
    });
  } catch (err) { console.error('doPost 失敗:' + err.message); }
  return ok_();
}

function askGemini_(userText) {
  var key = cfg_('GEMINI_API_KEY');
  if (!key) throw new Error('Gemini 設定缺少 API Key');
  var model = cfg_('GEMINI_MODEL') || 'gemini-3.5-flash-lite';
  var persona = cfg_('PROMPT') || '你是這家店的客服助理。用繁體中文,簡短、有禮貌地回答。';
  var facts = cfg_('KNOWLEDGE') || '';
  var systemText = '【你可以依據的資料】\n' + (facts || '(目前沒有提供資料)') +
    '\n\n【預設風格;下面你的身分可以修改風格】\n回答控制在三句話以內。\n' +
    '\n【你的身分與說話方式】\n' + persona +
    '\n\n【安全底線;請最優先遵守】\n' +
    '1. 只根據上面的資料回答;資料裡沒有的,就說你不知道。\n' +
    '2. 遇到價格變動、退款、客訴,或你不確定的事,回答「這部分我幫你轉給真人確認」。\n' +
    '3. 不要承諾我們做不到的事。';
  var res;
  try {
    res = UrlFetchApp.fetch('https://generativelanguage.googleapis.com/v1beta/models/' + encodeURIComponent(model) + ':generateContent', {
      method: 'post', contentType: 'application/json', headers: { 'x-goog-api-key': key },
      payload: JSON.stringify({systemInstruction: {parts: [{text: systemText}]},
        contents: [{role: 'user', parts: [{text: userText}]}], generationConfig: {maxOutputTokens: 1024}}),
      muteHttpExceptions: true
    });
  } catch (_) { throw new Error('Gemini 連線失敗'); }
  if (res.getResponseCode() !== 200) throw new Error('Gemini HTTP ' + res.getResponseCode());
  var data;
  try { data = JSON.parse(res.getContentText()); } catch (_) { throw new Error('Gemini 回應格式錯誤'); }
  var parts = data.candidates && data.candidates[0] && data.candidates[0].content && data.candidates[0].content.parts;
  var out = parts && parts.filter(function(p) { return p.text && !p.thought; }).map(function(p) { return p.text; }).join('');
  if (!out) throw new Error('Gemini 沒有文字回覆:請檢查模型與安全限制');
  return out;
}

function replyToLine_(replyToken, text) {
  var res;
  var token = lineToken_();
  try {
    res = UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', {
      method: 'post', contentType: 'application/json', headers: {Authorization: 'Bearer ' + token},
      payload: JSON.stringify({replyToken: replyToken, messages: [{type: 'text', text: String(text).slice(0, 4900)}]}),
      muteHttpExceptions: true
    });
  } catch (_) { throw new Error('LINE 回覆連線失敗'); }
  if (res.getResponseCode() !== 200) throw new Error('LINE 回覆 HTTP ' + res.getResponseCode());
}

/** 先檢查設定,再驗證 LINE 與 Gemini;失敗即停,不印秘密或模型回覆。 */
function checkSetup() {
  importSetup_();
  ['LINE_CHANNEL_ID', 'LINE_CHANNEL_SECRET', 'GEMINI_API_KEY', 'KNOWLEDGE'].forEach(function(k) {
    if (!cfg_(k)) throw new Error('缺少設定:' + k + ',回第6步');
  });
  console.log('設定:完整');
  var token = lineToken_();
  var res;
  try {
    res = UrlFetchApp.fetch('https://api.line.me/v2/bot/info', {headers: {Authorization: 'Bearer ' + token}, muteHttpExceptions: true});
  } catch (_) { throw new Error('LINE 帳號檢查連線失敗'); }
  if (res.getResponseCode() !== 200) throw new Error('LINE 帳號檢查 HTTP ' + res.getResponseCode());
  console.log('LINE:連線成功');
  askGemini_('請問你們幾點開?');
  console.log('Gemini:連線成功');
  console.log('下一步:部署並用手機收第一個 AI 回覆;本檢查尚未驗證 Webhook 回程');
}
做完你應該看到:編輯區是上面這段,上方出現「已儲存」。
📷 對照圖|「新專案」按鈕+貼好儲存後的編輯器(點圖可放大)
GAS 編輯器貼好程式碼
6一次貼入設定

這頁把 ID、secret、API Key 和工作資料合成一份設定。只貼一列,避免逐格拼名稱。秘密保存在你自己的 Apps Script;第 7 步會自動拆開並刪掉暫存列。

選填:語氣與模型
  1. Apps Script 左邊「專案設定」(齒輪)→「指令碼屬性」→「新增指令碼屬性」。
  2. 按「複製設定名稱」,貼到名稱欄;按「複製整份設定」,貼到值欄。
  3. 按「儲存指令碼屬性」。

已複製 ✓

這份設定含秘密,只能貼在自己的專案設定值欄;不要貼進程式碼、聊天或截圖。貼好後複製其他文字覆蓋剪貼簿,並清除剪貼簿歷史中的秘密。

做完你應該看到:只有一列 SETUP_INPUT,值是一整份設定。不要自行拆開或修改。
📷 對照圖|指令碼屬性只有一列 SETUP_INPUT(點圖可放大;值已遮蔽)
指令碼屬性只有一列 SETUP_INPUT(值已遮蔽)
7執行 checkSetup 驗證連線
  1. 回編輯畫面,上方下拉選單選「checkSetup」→ 按「執行」。
  2. 第一次執行會跳授權:「審查權限」→ 選你的 Google 帳號 → 確認專案名稱就是你剛建立的專案;若出現「這個應用程式未經 Google 驗證」(這程式就是你自己剛貼的)→ 點「進階」→「前往(你的專案名稱)(不安全)」→「繼續/允許」。
做完你應該看到:「設定:完整」「LINE:連線成功」「Gemini:連線成功」。失敗會指出層級,先修那一層再繼續。這次 Gemini 檢查會使用一次免費額度;尚未驗證手機回程。

只授權你剛建立的自己的程式。若帳戶政策禁止授權,不要改建 OAuth 應用;先停止這條路徑並確認帳戶政策。

📷 對照圖|「未經 Google 驗證」授權:進階→前往→繼續(兩張,點圖可放大)
進階→前往專案授權同意畫面
8部署,拿到網址
  1. 右上「部署」→「新增部署作業」。
  2. 「選取類型」旁的齒輪 → 選「網頁應用程式」。
  3. 兩格設定:「執行身分」=「我(你的 email)」;「誰可以存取」=「所有人」。
  4. 按「部署」。
  5. 完成視窗最下面「網頁應用程式」的網址按「複製」。
做完你應該看到:一串 https://script.google.com/macros/s/… 網址已複製。可以順手貼進下面這格備用。
交給 LINE 的網址必須是 /exec 結尾——結尾不是 /exec(例如網址裡有 library)=複製到別格了,回完成視窗拿「網頁應用程式」那串。
📷 對照圖|選類型 → 兩格設定 → 完成視窗(三張,點圖可放大)
選取類型:網頁應用程式執行身分=我+所有人部署完成視窗(網址位置)
9回 Manager 接上線
  1. 回步驟 2 那頁(Manager → 設定 → Messaging API)。
  2. 把剛複製的網址貼進「Webhook網址」那格 → 按「儲存」。
  3. 左邊「回應設定」→ 把「Webhook」開成綠色。
做完你應該看到:Webhook 開關是綠的。設定完成——最後做步驟 10 傳一句話實測,收到 AI 回覆才算上線。

同頁的「自動回應訊息」「加入好友的歡迎訊息」「聊天」開不開由你決定——它們跟機器人回覆不衝突(2026-08 實測)。想讓客人只收到 AI 的回答,就把自動回應關掉。注意:自動回應開著時,你測試收到的可能是罐頭回應而非 AI——測試時以回覆內容判斷。

📷 對照圖|Webhook網址貼好儲存+回應設定 Webhook 綠色(兩張,點圖可放大)
Webhook網址貼好儲存(值已遮蔽)回應設定 Webhook 綠色
10手機實測:收你的第一個 AI 回覆

用手機把自己的官方帳號加好友(Manager 的「加入好友工具」可取得 QR code),照順序傳兩句。第一次測試先用步驟 6 的範例四行,通了再換自己的內容。

請問你們幾點開?
應該看到:回覆裡有你 KNOWLEDGE 第一行寫的營業時間。
我星期日想過去,順便問一下改期要怎麼弄?
應該看到:同一則回覆同時講到「星期日不營業」和「改期轉真人」——它把兩行資料自己湊起來了,不是背稿。
兩格都勾=AI 助理免費安裝服務完成。你現在有一個真的會回客人的 AI 工作入口,跑在你自己的帳號上,密鑰從頭到尾沒離開你的環境。想讓它更懂:回步驟 6 在 KNOWLEDGE 多寫幾行。下一步見 06。

已複製 ✓

Google/LINE 的介面、配額與政策可能變動;使用自己的帳號逐步確認。完成判定以手機實際收到 AI 回覆為準。

直接體驗 MVP 版 AI 經理人

MVP 專用官方 LINE;裝之前/裝之後都能點

國國生活國際商行|統一編號 80070191