iT邦幫忙

2025 iThome 鐵人賽

DAY 8
0
生成式 AI

用 Node.js 打造生成式 AI 應用:從 Prompt 到 Agent 開發實戰系列 第 8

Day 08 - LangChain 快速上手:從零開始建立 LLM 應用程式

  • 分享至 

  • xImage
  •  

昨天我們初步認識了 LangChain,了解到它是一個專為 LLM 應用程式設計的框架,能幫助我們用模組化的方式組合大型語言模型應用。

今天我們要動手實作,從零開始建立一個最小可行的 LangChain 專案,並透過範例快速體驗它的基本用法。

實作:使用 LangChain 建立 CLI 聊天機器人

今天的目標改寫先前的 CLI 聊天機器人,我們將使用 LangChain 串接 ChatOpenAI 模型,打造一個可進行多輪對話的聊天機器人。完成後,你可以將這個版本與先前直接使用 openai 套件呼叫 API 的版本相比較,觀察在程式結構、可讀性與擴充性上的差異。

在開始之前,請先初始化一個新的專案,命名為 llm-chatbot,我們將在這個專案中完成實作內容。

Note:如果你對 Node.js 專案初始化流程還不熟悉,可以先回顧 Day 01 中「建立 Node.js 專案與 TypeScript 開發環境」的內容。

安裝依賴套件

建立專案環境後,請在專案根目錄中執行以下指令,安裝所需依賴套件:

npm install @langchain/core @langchain/openai dotenv
  • @langchain/core:LangChain 的核心模組,提供所有開發元件的共通介面與執行邏輯。
  • @langchain/openai:LangChain 提供的 OpenAI 模型整合套件。
  • dotenv:用來讀取 .env 檔案中的環境變數,例如 API 金鑰。

設定 API 金鑰

為了讓程式能成功呼叫 OpenAI API,我們需要在專案根目錄建立一個 .env 檔案,並填入你的 OpenAI API 金鑰:

OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

@langchain/openai 預設會從 process.env.OPENAI_API_KEY 讀取金鑰。如果你使用 .env 搭配 dotenv,在程式啟動時就會自動載入並生效。若你希望使用不同的變數名稱,也可以在建立 OpenAI client 時,手動指定 apiKey

建立 CLI 主程式

接下來,我們撰寫一個互動式命令列程式,讓使用者可以在終端機中輸入訊息並即時獲得 GPT 回覆。這次我們將使用 @langchain/openaiChatOpenAI 來取代原生 OpenAI SDK,為後續整合 LangChain 功能鋪路。

請打開 src/index.ts 並輸入以下程式碼:

// src/index.ts
import 'dotenv/config';
import readline from 'readline';
import { ChatOpenAI } from '@langchain/openai';

async function main() {
  const llm = new ChatOpenAI({
    model: 'gpt-4o-mini',
  });

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  console.log('LLM Chatbot 已啟動,輸入訊息開始對話(按 Ctrl+C 離開)。\n');
  rl.setPrompt('> ');
  rl.prompt();

  rl.on('line', async (input) => {
    try {
      const response = await llm.invoke(input);
      console.log(`\n${response.content}\n`);
    } catch (err) {
      console.error(err);
    }

    rl.prompt();
  });
}

main();

在上述程式中,我們主要完成了以下工作:

  1. 使用 ChatOpenAI 建立 LangChain 封裝的 OpenAI 模型實例,並指定使用 gpt-4o-mini
  2. 透過 Node.js 的 readline 模組建立互動式命令列介面,持續接收使用者輸入並顯示輸出。
  3. 每當使用者輸入訊息時,呼叫 llm.invoke(input) 將內容傳遞給模型,並取得回覆。
  4. 將模型回覆透過 response.content 即時輸出到終端機。
  5. 在回覆後重新顯示提示符,形成持續對話的互動流程。

這樣我們就完成了一個最簡單的 LangChain 版 CLI 聊天機器人,能即時與 OpenAI GPT 模型互動。

測試執行結果

完成程式後,就可以來測試看看效果了。在專案根目錄下執行以下指令啟動程式:

npm run dev

終端機會顯示以下訊息,代表聊天機器人已經啟動成功:

LLM Chatbot 已啟動,輸入訊息開始對話(按 Ctrl+C 離開)。

> Hello!

Hello! How can I assist you today?

此時你可以在 > 後面輸入任何訊息,例如提問或聊天,GPT 都會即時回覆你。程式會持續等待輸入,直到你按下 Ctrl+C 才會中止。

打造支援多輪對話的聊天機器人

上一步我們已經完成了單輪對話的 CLI Chatbot。接下來要進一步升級,讓它能記住對話歷程,實現多輪對話。這需要在程式中額外維護一個 messages 陣列,用來保存使用者與 AI 的所有訊息。

在使用原生 OpenAI SDK 時,訊息通常是以簡單物件的方式存在,例如:

[
  { role: 'system', content: '你是一個樂於助人的 AI 助理。' },
  { role: 'user', content: '你好!' }
]

而在 LangChain 中,則提供了清楚的訊息類別:

  • SystemMessage:設定 AI 的角色或行為。
  • HumanMessage:代表使用者輸入。
  • AIMessage:代表模型回覆。

另外還有 FunctionMessageToolMessage 等進階訊息型別,用來處理工具調用。

以下是修改後的程式碼:

// src/index.ts
import 'dotenv/config';
import readline from 'readline';
import { ChatOpenAI } from '@langchain/openai';
import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';

async function main() {
  const llm = new ChatOpenAI({
    model: 'gpt-4o-mini',
  });

  const messages: BaseMessage[] = [
    new SystemMessage('你是一個樂於助人的 AI 助理。'),
  ];

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  console.log('LLM Chatbot 已啟動,輸入訊息開始對話(按 Ctrl+C 離開)。\n');
  rl.setPrompt('> ');
  rl.prompt();

  rl.on('line', async (input) => {
    messages.push(new HumanMessage(input));

    try {
      const response = await llm.invoke(messages);
      console.log(`\n${response.content}\n`);

      messages.push(new AIMessage(response));
    } catch (err) {
      console.error(err);
    }

    rl.prompt();
  });
}

main();

在上述程式中,我們主要完成了以下工作:

  1. 使用 ChatOpenAI 建立 LangChain 封裝的 OpenAI 模型實例,並指定使用 gpt-4o-mini
  2. 透過 SystemMessage 設定助理角色,並以 messages 陣列保存完整對話歷程。
  3. 當使用者輸入訊息時,將其轉換為 HumanMessage 並加入 messages
  4. 呼叫 llm.invoke(messages),將完整的對話上下文傳遞給模型,以產生回覆。
  5. 取得回覆後,將其輸出到終端機,並以 AIMessage 的形式存回 messages,持續累積對話狀態。
  6. 最後重新顯示提示符,讓聊天能以多輪方式持續進行。

這樣一來,我們就成功讓 CLI Chatbot 具備多輪對話的能力,而不再是單次問答。

使用串流模式提升對話體驗

目前的實作雖然能夠進行多輪對話,但每次輸入訊息後,都要等模型完整生成回覆才會一次性輸出。若我們想模擬更接近「即時打字」的效果,就可以改用 串流模式(Streaming)

在 LangChain 中,我們可以透過 stream() 方法來逐步接收模型的輸出,並即時將文字輸出到終端機。

以下是修改後的範例:

import 'dotenv/config';
import readline from 'readline';
import { ChatOpenAI } from '@langchain/openai';
import { AIMessage, BaseMessage, HumanMessage, SystemMessage } from '@langchain/core/messages';

async function main() {
  const llm = new ChatOpenAI({
    model: 'gpt-4o-mini',
  });

  const messages: BaseMessage[] = [
    new SystemMessage('你是一個樂於助人的 AI 助理。'),
  ];

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  console.log('LLM Chatbot 已啟動,輸入訊息開始對話(按 Ctrl+C 離開)。\n');
  rl.setPrompt('> ');
  rl.prompt();

  rl.on('line', async (input) => {
    messages.push(new HumanMessage(input));

    try {
      const stream = await llm.stream(messages);

      let aiMessage = '';

      process.stdout.write('\n');
      for await (const chunk of stream) {
        const content = chunk?.content ?? '';
        process.stdout.write(content.toString());
        aiMessage += content;
      }
      process.stdout.write('\n\n');

      messages.push(new AIMessage(aiMessage));
    } catch (err) {
      console.error(err);
    }

    rl.prompt();
  });
}

main();

在上述程式中,我們主要完成了以下工作:

  1. 使用 ChatOpenAI 建立 LangChain 封裝的 OpenAI 模型實例,並指定使用 gpt-4o-mini
  2. 透過 SystemMessage 設定助理的角色,並以 messages 陣列保存完整的對話上下文。
  3. 當使用者輸入訊息時,將其轉換為 HumanMessage 並加入 messages
  4. 使用 llm.stream(messages) 以串流模式呼叫模型,逐步接收回覆。
  5. 透過 for await...of 即時輸出模型回應,同時將逐字輸出的內容累積為完整的 aiMessage
  6. 回覆完成後,將 aiMessage 封裝為 AIMessage 加入 messages,確保後續對話能持續保持上下文。
  7. 每輪互動結束後,重新顯示提示符,讓使用者能不斷與聊天機器人進行多輪交流。

這樣一來,當使用者輸入問題時,模型的回覆會邊生成邊顯示,互動體驗更加自然。

小結

今天我們實作了一個 LangChain 版 CLI 聊天機器人,從零開始快速體驗 LangChain 的核心用法:

  • 透過 ChatOpenAI 建立模型實例,並在 CLI 中接收使用者輸入、回傳 GPT 模型回應。
  • 引入 SystemMessageHumanMessageAIMessage,維護 messages 陣列,讓對話能具備上下文,實現多輪互動。
  • 使用 stream() 方法改寫呼叫流程,實現逐字輸出的串流模式,讓回覆更即時自然。

這只是起點,接下來我們將深入探索 LangChain 的進階元件與整合能力,打造更具擴充性與可維護性的 LLM 應用。


上一篇
Day 07 - 認識 LangChain:打造生成式 AI 應用的 LLM 框架
下一篇
Day 09 - 提示模板設計:掌握 LangChain Prompt Templates 用法
系列文
用 Node.js 打造生成式 AI 應用:從 Prompt 到 Agent 開發實戰14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言