<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:media="http://search.yahoo.com/mrss/">
  <channel>
    <title>ngrok｜林鼎淵 Dean Lin</title>
    <link>https://deanlin.net/tags/ngrok/</link>
    <image><url>https://deanlin.net/images/author_hu_aa256fc934e9a932.jpg</url><title>ngrok｜林鼎淵 Dean Lin</title><link>https://deanlin.net/tags/ngrok/</link><width>144</width><height>144</height></image>
    <description>林鼎淵（Dean Lin）的部落格：生成式 AI 企業內訓講師、外商資安公司軟體專家、7 本書作者。400 多篇文章用白話分享生成式 AI 實戰、Claude Code 與 Vibe Coding 教學、團隊合作與職場成長。</description>
    <generator>Hugo</generator>
    <language>zh-tw</language>
    <copyright>© 2020–2026 林鼎淵 Dean Lin</copyright>
    <lastBuildDate>Wed, 25 Jan 2023 15:24:33 +0800</lastBuildDate>
    <atom:link href="https://deanlin.net/tags/ngrok/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>靠問 ChatGPT 寫程式，能完成 OpenAI &amp; Linebot 的 Side Project 嗎？（下）</title>
      <link>https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/</link>
      <pubDate>Wed, 25 Jan 2023 15:24:33 +0800</pubDate>
      <guid>https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/</guid>
      <dc:creator>林鼎淵</dc:creator>
      <category>AI 實戰</category>
      <description>在這篇文章中，我們要來設定 Line 的 webhook，並測試 ChatGPT 寫的程式是否可以正確執行；並告訴讀者遇到問題時，我們可以從哪些面向來思考、解決；最後於文末給想用 ChatGPT 寫程式、學程式的朋友一些建議。</description>
      <media:content url="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-og_hu_b00ae86497f1183.jpg" medium="image" type="image/jpeg" width="1200" height="675" />
      <content:encoded><![CDATA[<p>在<a href="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-1/">上一篇文章</a>中，我們好不容易請 ChatGPT 完成 OpenAI-Linebot 的專案，並順利啟動。</p>
<p>在這篇文章中，我們要來設定 Line 的 webhook，並測試 ChatGPT 寫的程式是否可以正確執行；並告訴讀者遇到問題時，我們可以從哪些面向來思考、解決；最後於文末給想用 ChatGPT 寫程式、學程式的朋友一些建議。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-01.webp" width="1260" height="689" alt="靠問 ChatGPT 寫程式，能完成 OpenAI &amp; Linebot 的 Side Project 嗎？（下）（圖 1）" fetchpriority="high" decoding="async"></p>
<pre tabindex="0"><code>大綱

▋ 在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）
▋ 設定 Line 的 webhook
▋ 測試功能＆痛苦的 Debug 之路
▋ 結論：給想用 ChatGPT 寫程式、學程式的朋友一些建議
</code></pre><h2 id="在-local-建立一個可以讓-line-訪問的-http-serverngrok">在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）<a class="h-anchor" href="#%e5%9c%a8-local-%e5%bb%ba%e7%ab%8b%e4%b8%80%e5%80%8b%e5%8f%af%e4%bb%a5%e8%ae%93-line-%e8%a8%aa%e5%95%8f%e7%9a%84-http-serverngrok" aria-label="這個段落的連結"></a></h2>
<p>上一篇文章中，專案是在本地啟動的，因此他的網址是 <a href="http://localhost:3000">http://localhost:3000</a> ，而 Line 的 webhook 是無法接受本地網址的。</p>
<p>為了方便 Debug，我這邊選擇在 local 建立一個可以讓 Line 訪問的 HTTP server，具體的方案我們來詢問一下 ChatGPT。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-02.webp" width="1077" height="537" alt="在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）（圖 2）" loading="lazy" decoding="async"></p>
<p>這邊我選用「ngrok」的方案，並在指定「作業系統」的狀態下，請 ChatGPT 告訴我接下來該怎麼做。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-03.webp" width="1086" height="705" alt="在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）（圖 3）" loading="lazy" decoding="async"></p>
<p>接下來我們就按造建議的步驟來實作看看。</p>
<p><strong>SETP 1</strong>：先到 ngrok 的官網下載 ngrok 的 Mac 版本： <a href="https://ngrok.com/download">https://ngrok.com/download</a> 。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-04.webp" width="1400" height="1296" alt="在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）（圖 4）" loading="lazy" decoding="async"></p>
<blockquote>
<p>提醒讀者，要先確認自己 mac 的處理器是 Intel 還是 Apple Silicon 喔！</p>
</blockquote>
<p><strong>SETP 2</strong>：解壓縮下載的檔案，並將 ngrok 放入您的 PATH 中 (例如: /usr/local/bin)</p>
<p>解壓縮檔案後，你會得到一個 ngrok 的值行檔，其實你就算放在 download 的資料夾也能執行，不過放到 bin 的資料夾下可以在任何位置執行。</p>
<p>下面說明一下 mac 進入 bin 資料夾的步驟：「到 mac 桌面」or「點擊 Finder」➝ 「前往」➝ 「前往資料夾」➝ 輸入「/usr/local/bin」➝ 把「ngrok 值行檔」丟進去。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-05.webp" width="1108" height="892" alt="在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）（圖 5）" loading="lazy" decoding="async"></p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-06.webp" width="956" height="456" alt="在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）（圖 6）" loading="lazy" decoding="async"></p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-07.webp" width="1400" height="670" alt="在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）（圖 7）" loading="lazy" decoding="async"></p>
<p><strong>SETP 3</strong>：打開終端機，輸入 <code>ngrok http 3000</code> (3000 是您的本地環境的 HTTP Server 的通訊埠)，啟動 ngrok。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-08.webp" width="1400" height="486" alt="在 local 建立一個可以讓 Line 訪問的 HTTP server（ngrok）（圖 8）" loading="lazy" decoding="async"></p>
<p><strong>SETP 4</strong>：ngrok 將會顯示一個可供外部訪問的 URL（上圖紅框處 <code>https://xxxx.ngrok.io</code>），您可以在 LINE 的 Developer Console 中設定 webhook 的 URL。</p>
<blockquote>
<p><strong>小提醒</strong>：Session 2 小時後會過期，到時再重新執行一次 <code>ngrok http 3000</code> 就好了，然後別忘記把新的 URL 設定到 Line 的 webhook。</p>
</blockquote>
<hr>
<h2 id="-設定-line-的-webhook">設定 Line 的 webhook<a class="h-anchor" href="#-%e8%a8%ad%e5%ae%9a-line-%e7%9a%84-webhook" aria-label="這個段落的連結"></a></h2>
<p>因為設定步驟很簡單，我就不特別問 ChatGPT 了。</p>
<p><strong>SETP 1</strong>：在 Messaging API 的 WebhookURL 貼上剛剛的的網址，並於後面加上 <code>/webhook</code>（那是我們程式設定的 API 路徑）。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-09.webp" width="1077" height="563" alt="設定 Line 的 webhook（圖 9）" loading="lazy" decoding="async"></p>
<p><strong>SETP 2</strong>：按下「Verify」後得到 Success 就代表有成功聯通嚕！</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-10.webp" width="1000" height="397" alt="設定 Line 的 webhook（圖 10）" loading="lazy" decoding="async"></p>
<p><strong>SETP 3</strong>：在 Messaging API 取得 Linebot 的 LineID，並把他加入好友。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-11.webp" width="739" height="332" alt="設定 Line 的 webhook（圖 11）" loading="lazy" decoding="async"></p>
<p>加入好友後，他會跟你打招呼。</p>
<p>但當你很興奮的傳訊息給他時，他的回覆語氣一點都不像是 ChatGPT。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-12.webp" width="1382" height="1006" alt="設定 Line 的 webhook（圖 12）" loading="lazy" decoding="async"></p>
<p>雖然到這裡我們已經知道出事了，但還是先把下面的步驟做完吧。</p>
<p><strong>SETP 4</strong>：在 Messaging API 關閉自動回覆（Auto-reply messages）與打招呼（Greeting messages）。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-13.webp" width="1300" height="588" alt="設定 Line 的 webhook（圖 13）" loading="lazy" decoding="async"></p>
<blockquote>
<p>因為自動回覆（Auto-reply messages）會干擾 Debug 所以建議關閉，至於打招呼（Greeting messages）要不要關閉就看你自己。</p>
</blockquote>
<hr>
<h2 id="測試功能痛苦的-debug-之路">測試功能＆痛苦的 Debug 之路<a class="h-anchor" href="#%e6%b8%ac%e8%a9%a6%e5%8a%9f%e8%83%bd%e7%97%9b%e8%8b%a6%e7%9a%84-debug-%e4%b9%8b%e8%b7%af" aria-label="這個段落的連結"></a></h2>
<p>上面 Webhook URL 的 Verify 得到 200 只是證明這條路有打通，如果把畫面切到 ngrok，會發現許多 500 的錯誤訊息。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-14.webp" width="1400" height="708" alt="測試功能＆痛苦的 Debug 之路（圖 14）" loading="lazy" decoding="async"></p>
<h3 id="-上一篇-chatgpt-給的程式有哪些錯誤">上一篇 ChatGPT 給的程式有哪些錯誤？<a class="h-anchor" href="#-%e4%b8%8a%e4%b8%80%e7%af%87-chatgpt-%e7%b5%a6%e7%9a%84%e7%a8%8b%e5%bc%8f%e6%9c%89%e5%93%aa%e4%ba%9b%e9%8c%af%e8%aa%a4" aria-label="這個段落的連結"></a></h3>
<p>回到程式，你會發現有「TypeError: Cannot read properties of undefined (reading ‘events’)」的錯誤。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-15.webp" width="1400" height="384" alt="上一篇 ChatGPT 給的程式有哪些錯誤？（圖 15）" loading="lazy" decoding="async"></p>
<p>如果你把這個問題拿去詢問 ChatGPT，會收到一大堆鬼打牆的回覆。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-16.webp" width="1067" height="728" alt="上一篇 ChatGPT 給的程式有哪些錯誤？（圖 16）" loading="lazy" decoding="async"></p>
<p>這邊筆者就直接告訴大家為什麼會有各式各樣的錯誤：</p>
<ul>
<li>「@line/bot-sdk」套件使用方式錯誤</li>
<li>「openai」套件使用方式錯誤</li>
</ul>
<p>你沒看錯，要實作的兩個套件，ChatGPT 的使用方式都是有問題的。</p>
<h3 id="-讓-chatgpt-擔任程式專家改用英文詢問">讓 ChatGPT 擔任程式專家，改用英文詢問<a class="h-anchor" href="#-%e8%ae%93-chatgpt-%e6%93%94%e4%bb%bb%e7%a8%8b%e5%bc%8f%e5%b0%88%e5%ae%b6%e6%94%b9%e7%94%a8%e8%8b%b1%e6%96%87%e8%a9%a2%e5%95%8f" aria-label="這個段落的連結"></a></h3>
<p>為了避免冤枉好人，我這次改成用英文詢問，並讓 ChatGPT 擔任程式專家來撰寫，這是他給出的新回覆：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">const</span> line <span style="color:#ff7b72;font-weight:bold">=</span> require(<span style="color:#a5d6ff">&#39;@line/bot-sdk&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> express <span style="color:#ff7b72;font-weight:bold">=</span> require(<span style="color:#a5d6ff">&#39;express&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> openai <span style="color:#ff7b72;font-weight:bold">=</span> require(<span style="color:#a5d6ff">&#39;openai&#39;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>openai.apiKey <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#a5d6ff">&#34;YOUR_API_KEY&#34;</span>;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> config <span style="color:#ff7b72;font-weight:bold">=</span> {
</span></span><span style="display:flex;"><span>  channelAccessToken<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#39;YOUR_CHANNEL_ACCESS_TOKEN&#39;</span>,
</span></span><span style="display:flex;"><span>  channelSecret<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#39;YOUR_CHANNEL_SECRET&#39;</span>
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> client <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">new</span> line.Client(config);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> app <span style="color:#ff7b72;font-weight:bold">=</span> express();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app.post(<span style="color:#a5d6ff">&#39;/webhook&#39;</span>, line.middleware(config), (req, res) =&gt; {
</span></span><span style="display:flex;"><span>  Promise
</span></span><span style="display:flex;"><span>    .all(req.body.events.map(handleEvent))
</span></span><span style="display:flex;"><span>    .then((result) =&gt; res.json(result))
</span></span><span style="display:flex;"><span>    .<span style="color:#ff7b72">catch</span>((err) =&gt; {
</span></span><span style="display:flex;"><span>      console.error(err);
</span></span><span style="display:flex;"><span>      res.status(<span style="color:#a5d6ff">500</span>).end();
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">function</span> handleEvent (event) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (event.type <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#a5d6ff">&#39;message&#39;</span> <span style="color:#ff7b72;font-weight:bold">||</span> event.message.type <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#a5d6ff">&#39;text&#39;</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">return</span> Promise.resolve(<span style="color:#79c0ff">null</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">return</span> openai
</span></span><span style="display:flex;"><span>    .engines
</span></span><span style="display:flex;"><span>    .completions
</span></span><span style="display:flex;"><span>    .create({
</span></span><span style="display:flex;"><span>      prompt<span style="color:#ff7b72;font-weight:bold">:</span> event.message.text,
</span></span><span style="display:flex;"><span>      engine<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;text-davinci-002&#34;</span>,
</span></span><span style="display:flex;"><span>      maxTokens<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">100</span>
</span></span><span style="display:flex;"><span>    })
</span></span><span style="display:flex;"><span>    .then((completions) =&gt; {
</span></span><span style="display:flex;"><span>      <span style="color:#ff7b72">const</span> message <span style="color:#ff7b72;font-weight:bold">=</span> completions.choices[<span style="color:#a5d6ff">0</span>].text;
</span></span><span style="display:flex;"><span>      <span style="color:#ff7b72">return</span> client.replyMessage(event.replyToken, {
</span></span><span style="display:flex;"><span>        type<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#39;text&#39;</span>,
</span></span><span style="display:flex;"><span>        text<span style="color:#ff7b72;font-weight:bold">:</span> message
</span></span><span style="display:flex;"><span>      });
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app.listen(<span style="color:#a5d6ff">3000</span>);
</span></span><span style="display:flex;"><span>console.log(<span style="color:#a5d6ff">&#39;Linebot is running on 3000 port&#39;</span>);
</span></span></code></pre></div><p>果然專家就是比較厲害，錯誤訊息變得不一樣了！</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-17.webp" width="1400" height="292" alt="讓 ChatGPT 擔任程式專家，改用英文詢問（圖 17）" loading="lazy" decoding="async"></p>
<p>但這個錯誤並沒有辦法靠詢問 ChatGPT 解決（他會再次鬼打牆）。</p>
<p><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-18.webp" width="1083" height="665" alt="讓 ChatGPT 擔任程式專家，改用英文詢問（圖 18）" loading="lazy" decoding="async"></p>
<h3 id="-好吧最後還是得靠自己處理">好吧…最後還是得靠自己處理<a class="h-anchor" href="#-%e5%a5%bd%e5%90%a7%e6%9c%80%e5%be%8c%e9%82%84%e6%98%af%e5%be%97%e9%9d%a0%e8%87%aa%e5%b7%b1%e8%99%95%e7%90%86" aria-label="這個段落的連結"></a></h3>
<p>因為我看錯誤的源頭出在 openai 套件，所以我就去官網研究了一下：<a href="https://www.npmjs.com/package/openai">https://www.npmjs.com/package/openai</a></p>
<p>先給大家看一下官網給的範例程式：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span><span style="color:#ff7b72">const</span> { Configuration, OpenAIApi } <span style="color:#ff7b72;font-weight:bold">=</span> require(<span style="color:#a5d6ff">&#34;openai&#34;</span>);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> configuration <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">new</span> Configuration({
</span></span><span style="display:flex;"><span>  apiKey<span style="color:#ff7b72;font-weight:bold">:</span> process.env.OPENAI_API_KEY,
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> openai <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">new</span> OpenAIApi(configuration);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> completion <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">await</span> openai.createCompletion({
</span></span><span style="display:flex;"><span>  model<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;text-davinci-002&#34;</span>,
</span></span><span style="display:flex;"><span>  prompt<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;Hello world&#34;</span>,
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>console.log(completion.data.choices[<span style="color:#a5d6ff">0</span>].text);
</span></span></code></pre></div><p><strong>如果把他跟 ChatGPT 給的程式做比對，會發現 ChatGPT 的使用方式根本是錯的</strong>，下面筆者就直接把修改好的程式放上來，調整過的部分有在旁邊用註解說明：</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-javascript" data-lang="javascript"><span style="display:flex;"><span>require(<span style="color:#a5d6ff">&#39;dotenv&#39;</span>).config(); <span style="color:#8b949e;font-style:italic">// 皆採用 .env 讀取
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> line <span style="color:#ff7b72;font-weight:bold">=</span> require(<span style="color:#a5d6ff">&#39;@line/bot-sdk&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> express <span style="color:#ff7b72;font-weight:bold">=</span> require(<span style="color:#a5d6ff">&#39;express&#39;</span>);
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> { Configuration, OpenAIApi } <span style="color:#ff7b72;font-weight:bold">=</span> require(<span style="color:#a5d6ff">&#34;openai&#34;</span>); <span style="color:#8b949e;font-style:italic">// 他套件使用方式錯誤，我直接改掉
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> configuration <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">new</span> Configuration({
</span></span><span style="display:flex;"><span>  apiKey<span style="color:#ff7b72;font-weight:bold">:</span> process.env.OPENAI_API_KEY,
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> openai <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">new</span> OpenAIApi(configuration);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> config <span style="color:#ff7b72;font-weight:bold">=</span> {
</span></span><span style="display:flex;"><span>  channelAccessToken<span style="color:#ff7b72;font-weight:bold">:</span> process.env.CHANNEL_ACCESS_TOKEN,
</span></span><span style="display:flex;"><span>  channelSecret<span style="color:#ff7b72;font-weight:bold">:</span> process.env.CHANNEL_SECRET,
</span></span><span style="display:flex;"><span>};
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> client <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">new</span> line.Client(config);
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">const</span> app <span style="color:#ff7b72;font-weight:bold">=</span> express();
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app.post(<span style="color:#a5d6ff">&#39;/webhook&#39;</span>, line.middleware(config), (req, res) =&gt; {
</span></span><span style="display:flex;"><span>  Promise
</span></span><span style="display:flex;"><span>    .all(req.body.events.map(handleEvent))
</span></span><span style="display:flex;"><span>    .then((result) =&gt; res.json(result))
</span></span><span style="display:flex;"><span>    .<span style="color:#ff7b72">catch</span>((err) =&gt; {
</span></span><span style="display:flex;"><span>      console.error(err);
</span></span><span style="display:flex;"><span>      res.status(<span style="color:#a5d6ff">500</span>).end();
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>});
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">function</span> handleEvent (event) {
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">if</span> (event.type <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#a5d6ff">&#39;message&#39;</span> <span style="color:#ff7b72;font-weight:bold">||</span> event.message.type <span style="color:#ff7b72;font-weight:bold">!==</span> <span style="color:#a5d6ff">&#39;text&#39;</span>) {
</span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">return</span> Promise.resolve(<span style="color:#79c0ff">null</span>);
</span></span><span style="display:flex;"><span>  }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#ff7b72">return</span> openai.createCompletion({ <span style="color:#8b949e;font-style:italic">// 方法用錯修正
</span></span></span><span style="display:flex;"><span>    prompt<span style="color:#ff7b72;font-weight:bold">:</span> event.message.text,
</span></span><span style="display:flex;"><span>    model<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#34;text-davinci-003&#34;</span>, <span style="color:#8b949e;font-style:italic">// 使用 model 而非 engine
</span></span></span><span style="display:flex;"><span>    max_tokens<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">1000</span> <span style="color:#8b949e;font-style:italic">// 應用 max_tokens 而非 maxTokens
</span></span></span><span style="display:flex;"><span>  }).then((completions) =&gt; {
</span></span><span style="display:flex;"><span>    <span style="color:#8b949e;font-style:italic">// 少了 data 這層結構，並要加上 trim() 去除空白
</span></span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">const</span> message <span style="color:#ff7b72;font-weight:bold">=</span> completions.data.choices[<span style="color:#a5d6ff">0</span>].text.trim();
</span></span><span style="display:flex;"><span>    <span style="color:#ff7b72">return</span> client.replyMessage(event.replyToken, {
</span></span><span style="display:flex;"><span>      type<span style="color:#ff7b72;font-weight:bold">:</span> <span style="color:#a5d6ff">&#39;text&#39;</span>,
</span></span><span style="display:flex;"><span>      text<span style="color:#ff7b72;font-weight:bold">:</span> message
</span></span><span style="display:flex;"><span>    });
</span></span><span style="display:flex;"><span>  });
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>app.listen(<span style="color:#a5d6ff">3000</span>);
</span></span><span style="display:flex;"><span>console.log(<span style="color:#a5d6ff">&#39;Linebot is running on 3000 port&#39;</span>);
</span></span></code></pre></div><p>最後再給大家看看順利溝通時的畫面：</p>
<div class="gallery-row cols-2">

<figure class="figure"><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-19.webp" width="744" height="970" alt="好吧…最後還是得靠自己處理（圖 19）" loading="lazy" decoding="async">
</figure>

<figure class="figure"><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-20.webp" width="742" height="972" alt="好吧…最後還是得靠自己處理（圖 20）" loading="lazy" decoding="async">
</figure>


</div>

<p>看到成功溝通的畫面時，筆者真的感動到快哭了，這是個能與你溝通的 AI 機器人喔！</p>
<blockquote>
<p>不過操作下來我覺得回答穩定度沒有比 ChatGPT 高，有時會出現一些奇怪的程式碼，讀者有興趣可以再做優化，本篇文章僅為參考範例。</p>
</blockquote>
<hr>
<h2 id="結論給想用-chatgpt-寫程式學程式的朋友一些建議">結論：給想用 ChatGPT 寫程式、學程式的朋友一些建議<a class="h-anchor" href="#%e7%b5%90%e8%ab%96%e7%b5%a6%e6%83%b3%e7%94%a8-chatgpt-%e5%af%ab%e7%a8%8b%e5%bc%8f%e5%ad%b8%e7%a8%8b%e5%bc%8f%e7%9a%84%e6%9c%8b%e5%8f%8b%e4%b8%80%e4%ba%9b%e5%bb%ba%e8%ad%b0" aria-label="這個段落的連結"></a></h2>
<p>可能是我運氣比較好，剛好測試到 ChatGPT 的許多 Bug，下面筆者彙整了一些遇到的「坑」給讀者參考：</p>
<ol>
<li><strong>ChatGPT 沒有最新資料</strong>：筆者在使用 ChatGPT 時，他的資料是在 2021 年截止的，也就是說他不認識新推出的套件，當套件有更新時他也無法第一時間知道。</li>
<li><strong>有些問題 ChatGPT 真的回答不出來</strong>：如果是程式邏輯問題，ChatGPT 有機會給出解答，但如果是套件相關問題，可能真的給不出解答；你一直問他也只是鬼打牆。</li>
<li><strong>似是而非的答案最可怕</strong>：ChatGPT 在上一篇（中文）跟這一篇（英文）給的答案，如果只看「邏輯」，那是正確的；但實際跑起來卻有一堆問題，不去看官方網站查證真的無法解決。</li>
</ol>
<p>會有上述問題，我覺得是因為 ChatGPT 還在學習、以及資料不夠即時；相信在未來推出新版時，能給出更正確的解答。</p>
<p>至於如何透過 ChatGPT 學程式，我的建議如下：</p>
<ol>
<li>要學習的<strong>程式語言、工具要有一定的年紀</strong>。</li>
<li>使用套件遇到錯誤時，<strong>先去官網看說明文件</strong>。</li>
<li>如果完全沒基礎，<strong>強烈建議先從書籍、課程開始學習</strong>。</li>
</ol>
<p>目前筆者把 ChatGPT 的定位放在「輔助」，適合給你方向、關鍵字、優化的建議；像是這次使用下來，雖然程式有些許錯誤，但是在「步驟、關鍵字、指令」方面的建議都是很不錯的。</p>
<p>未來筆者會出一系列使用 ChatGPT、openAI 的文章，如果你對這個議題感興趣，可以持續關注我的文章！</p>
<a class="linkcard" href="https://deanlin.net/categories/ai/">
  <span class="lc-body">
    <span class="lc-title">AI 實戰</span>
    <span class="lc-desc">實測生成式 AI 工具、Vibe Coding 與自動化流程的第一手心得，把 AI 變成每天都用得上的即戰力。</span>
    <span class="lc-site"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false"><path d="M5 12h14M13 6l6 6-6 6"/></svg>林鼎淵 Dean Lin</span>
  </span>
</a>

<p><strong>想將 AI 導入自己的職場與生活嗎？歡迎<a href="https://www.books.com.tw/products/0011004216">購買筆者出版的新書</a></strong>，幫助您<strong>在 AI 的浪潮中站穩腳步，並在未來的職場競爭中佔據優勢！</strong></p>
<figure class="figure"><img src="https://deanlin.net/blog/202301/chatgpt-line-bot-side-project-part-2/images/chatgpt-line-bot-side-project-part-2-21.webp" width="1400" height="319" alt="林鼎淵著作《ChatGPT 與 AI 繪圖效率大師（新增 Copilot、Gamma、Runway、Suno）》" loading="lazy" decoding="async">
  <figcaption><a href="https://www.books.com.tw/products/0011004216">https://www.books.com.tw/products/0011004216</a></figcaption>
</figure>

<p><strong>參考資料</strong>：</p>
<ol>
<li>用英文溝通 ChatGPT 得到的回覆：<a href="https://github.com/dean9703111/linebot-openai-chatgpt/blob/master/bug2-index.js">Github</a></li>
<li>筆者自己優化得到的解答：<a href="https://github.com/dean9703111/linebot-openai-chatgpt/blob/master/index.js">Github</a></li>
</ol>
]]></content:encoded>
    </item>
  </channel>
</rss>
