LangChain 實戰教學:打造你的第一個 AI 應用

從零開始學習 LangChain 框架,涵蓋 Chain、Agent、Memory 三大核心概念,附完整程式碼範例。

AI Academy 編輯部2025年11月22日

LangChain 實戰教學:打造你的第一個 AI 應用

什麼是 LangChain?

LangChain 是一個用於開發 LLM 應用程式的開源框架。它提供了標準化的介面和豐富的工具,讓你能快速建構複雜的 AI 應用。

為什麼選擇 LangChain?

  • 統一介面:支援 OpenAI、Anthropic、Cohere 等多種模型
  • 模組化設計:Chain、Agent、Memory 可靈活組合
  • 豐富生態系:大量預建的工具和整合
  • 生產就緒:LangSmith 提供監控和評估

環境設定

安裝

pip install langchain langchain-openai python-dotenv

設定 API Key

# .env
OPENAI_API_KEY=sk-your-api-key
# main.py
from dotenv import load_dotenv
load_dotenv()

核心概念一:LLM 與 Chat Models

基本使用

from langchain_openai import ChatOpenAI

# 建立 Chat Model
llm = ChatOpenAI(
    model="gpt-4o-mini",
    temperature=0.7
)

# 簡單對話
response = llm.invoke("用一句話解釋什麼是機器學習")
print(response.content)

使用 Messages

from langchain_core.messages import HumanMessage, SystemMessage

messages = [
    SystemMessage(content="你是一位友善的 Python 教學助教"),
    HumanMessage(content="什麼是 list comprehension?")
]

response = llm.invoke(messages)
print(response.content)

核心概念二:Prompt Templates

基本模板

from langchain_core.prompts import ChatPromptTemplate

# 建立模板
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一位 {role},用{style}的方式回答問題。"),
    ("human", "{question}")
])

# 填入變數
messages = prompt.invoke({
    "role": "資深工程師",
    "style": "簡潔專業",
    "question": "什麼是 API?"
})

response = llm.invoke(messages)

使用 Partial Variables

from datetime import datetime

prompt = ChatPromptTemplate.from_messages([
    ("system", "今天是 {date}。你是一位新聞編輯。"),
    ("human", "幫我寫一則關於 {topic} 的新聞標題")
])

# 預先填入部分變數
prompt = prompt.partial(date=datetime.now().strftime("%Y-%m-%d"))

# 使用時只需填入剩餘變數
messages = prompt.invoke({"topic": "AI 發展"})

核心概念三:Chains

Chain 是 LangChain 的核心,用於串連多個元件。

使用 LCEL(LangChain Expression Language)

from langchain_core.output_parsers import StrOutputParser

# 建立 Chain:Prompt -> LLM -> Output Parser
chain = prompt | llm | StrOutputParser()

# 執行
result = chain.invoke({
    "role": "技術作家",
    "style": "深入淺出",
    "question": "解釋 RESTful API"
})
print(result)

串連多個 Chain

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

# Chain 1: 生成大綱
outline_prompt = ChatPromptTemplate.from_template(
    "為主題「{topic}」生成一個 3 點的文章大綱,只輸出大綱。"
)
outline_chain = outline_prompt | llm | StrOutputParser()

# Chain 2: 根據大綱寫文章
article_prompt = ChatPromptTemplate.from_template(
    "根據以下大綱撰寫一篇短文:\n{outline}"
)
article_chain = article_prompt | llm | StrOutputParser()

# 組合 Chain
full_chain = (
    {"outline": outline_chain, "topic": lambda x: x["topic"]}
    | article_chain
)

result = full_chain.invoke({"topic": "遠端工作的優缺點"})

核心概念四:Memory

讓 AI 記住對話歷史。

對話記憶

from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

# 建立記憶儲存
store = {}

def get_session_history(session_id: str):
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

# 建立帶記憶的 Chain
prompt = ChatPromptTemplate.from_messages([
    ("system", "你是一位友善的助教。"),
    ("placeholder", "{history}"),
    ("human", "{input}")
])

chain = prompt | llm

chain_with_history = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="history"
)

# 使用(同一個 session_id 會記住對話)
config = {"configurable": {"session_id": "user_123"}}

response1 = chain_with_history.invoke(
    {"input": "我叫小明"},
    config=config
)
print(response1.content)

response2 = chain_with_history.invoke(
    {"input": "我叫什麼名字?"},
    config=config
)
print(response2.content)  # 會記得叫小明

核心概念五:Output Parsers

結構化 AI 的輸出。

JSON 輸出

from langchain_core.output_parsers import JsonOutputParser
from pydantic import BaseModel, Field

# 定義輸出結構
class MovieReview(BaseModel):
    title: str = Field(description="電影名稱")
    rating: int = Field(description="評分 1-10")
    summary: str = Field(description="一句話評論")

parser = JsonOutputParser(pydantic_object=MovieReview)

prompt = ChatPromptTemplate.from_messages([
    ("system", "分析用戶的電影評論,以 JSON 格式輸出。\n{format_instructions}"),
    ("human", "{review}")
])

chain = prompt | llm | parser

result = chain.invoke({
    "review": "乍看之下是英雄片,但阿凡達其實有深刻的環保意涵,視覺效果令人驚艷,推薦!",
    "format_instructions": parser.get_format_instructions()
})

print(result)
# {'title': '阿凡達', 'rating': 9, 'summary': '視覺震撼的環保史詩'}

實戰專案:FAQ 問答機器人

整合所有概念,建立一個有記憶的問答機器人:

from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory

# 1. 設定 LLM
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0.7)

# 2. 定義 FAQ 知識庫
FAQ_KNOWLEDGE = """
Q: 如何退費?
A: 請在購買後 7 天內,至會員中心申請退費,我們會在 3-5 個工作天處理。

Q: 課程可以看多久?
A: 購買後可永久觀看,不限次數。

Q: 有提供發票嗎?
A: 有的,購買後會自動寄送電子發票到您的信箱。
"""

# 3. 建立 Prompt
prompt = ChatPromptTemplate.from_messages([
    ("system", """你是 AI Academy 的客服助理。請根據以下 FAQ 回答問題。
如果問題不在 FAQ 中,請禮貌地表示無法回答,並建議聯繫客服。

FAQ 知識庫:
{faq}

回答規則:
- 使用友善親切的語氣
- 回答要簡潔明瞭
- 可以適當使用 emoji"""),
    ("placeholder", "{history}"),
    ("human", "{input}")
])

# 4. 建立 Chain
chain = prompt | llm | StrOutputParser()

# 5. 加入記憶
store = {}

def get_session_history(session_id: str):
    if session_id not in store:
        store[session_id] = ChatMessageHistory()
    return store[session_id]

chain_with_memory = RunnableWithMessageHistory(
    chain,
    get_session_history,
    input_messages_key="input",
    history_messages_key="history"
)

# 6. 使用
def chat(user_input: str, session_id: str = "default"):
    response = chain_with_memory.invoke(
        {"input": user_input, "faq": FAQ_KNOWLEDGE},
        config={"configurable": {"session_id": session_id}}
    )
    return response

# 測試
print(chat("課程買了可以看多久?"))
print(chat("那如果要退費呢?"))
print(chat("我想買 iPhone"))  # 不在 FAQ 中

除錯技巧

開啟 Verbose 模式

import langchain
langchain.debug = True  # 顯示詳細執行過程

使用 LangSmith

# .env
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=your-api-key
LANGCHAIN_PROJECT=my-project

常見問題

Q: Chain invoke 和 stream 的差異?

# invoke: 等待完整回應
result = chain.invoke({"input": "Hello"})

# stream: 串流輸出(適合長回應)
for chunk in chain.stream({"input": "Hello"}):
    print(chunk, end="", flush=True)

Q: 如何處理 Rate Limit?

from langchain_openai import ChatOpenAI

llm = ChatOpenAI(
    model="gpt-4o-mini",
    max_retries=3,  # 自動重試
    request_timeout=30
)

延伸學習

主題說明
RAG結合向量資料庫做知識問答
Agents讓 AI 使用工具完成複雜任務
Callbacks監控和記錄 Chain 執行

總結

LangChain 的核心概念:

  1. LLM/Chat Models:與 AI 模型互動的基礎
  2. Prompt Templates:可重用的提示模板
  3. Chains:串連多個元件的管道
  4. Memory:記住對話歷史
  5. Output Parsers:結構化輸出

下一步行動

  1. 安裝 LangChain 並執行範例程式碼
  2. 建立一個簡單的對話機器人
  3. 嘗試加入 Memory 功能
  4. 探索 RAG 應用

相關文章

參考資源