第 26 期 | 本地模型替身:结合 Ollama 与 Llama3

⏱ 预计阅读 20 分钟 更新于 2026/5/7
💡 进群学习加 wx: agentupdate
(申请发送: agentupdate)

本期副标题:从 LangChain 架构到第一个智能客服问答机器人

同学们,欢迎来到《LangChain 全栈大师课:从零基础到生产级 AI 应用》的第一期!我是你们的导师,一个在 AI 领域摸爬滚打十年,对技术和教育都充满热情的“老兵”。今天,我们将一起踏上征途,揭开 LangChain 这把“AI 应用开发瑞士军刀”的神秘面纱,并亲手打造我们智能客服小助手的第一个“大脑”!

🎯 本期学习目标

经过本期的洗礼,你将能够:

  1. 洞悉 LangChain 的核心价值与设计哲学:理解为什么 LangChain 会成为构建 LLM 应用的事实标准,它解决了哪些痛点。
  2. 掌握 LangChain 的基础架构与关键模块:对 LangChain 的组件有一个清晰的认知,知道它们各自扮演的角色。
  3. 亲手搭建一个简单的智能客服问答机器人:从零开始,利用 LangChain 快速实现一个基于大模型的问答功能。
  4. 初步理解 LangChain 在智能客服项目中的应用:明确本期所学知识如何奠定我们“智能客服知识库”项目的基石。

📖 原理解析

LangChain:AI 应用开发的瑞士军刀,真的不夸张!

你可能会问,我们有了 OpenAI、Anthropic 这样强大的 LLM,为什么还需要 LangChain?这就像你有了最顶级的发动机,但你还需要一套完整的车架、传动系统、刹车和方向盘才能造出一辆真正的汽车。

LLM 固然强大,但它本身只是一个“黑箱”式的文本生成器。在实际的 AI 应用中,我们需要的远不止是简单的问答。想象一下我们的“智能客服知识库”项目:

  • 它需要从海量文档中检索信息。
  • 它需要理解用户的复杂意图。
  • 它需要记住用户的历史对话。
  • 它需要调用外部工具(比如查询订单状态、重置密码接口)。
  • 它还需要将这些复杂的步骤有逻辑地串联起来。

如果每次都从头开始构建这些逻辑,那简直是重复造轮子的噩梦!LangChain 应运而生,它提供了一套标准化的、模块化的、可组合的工具集,极大地简化了 LLM 应用的开发流程。它就像一把瑞士军刀,把各种实用的工具(模块)集成在一起,让你能够高效地处理各种复杂的任务。

LangChain 的核心理念:模块化与可组合性

LangChain 的设计哲学非常清晰:将构建 LLM 应用所需的各种能力抽象成独立的模块,然后通过“链 (Chain)”的机制将这些模块灵活地组合起来,以完成更复杂的任务。

它的主要模块包括:

  • LLMs (Language Models):这是 LangChain 的“心脏”,负责与各种大模型(OpenAI, Google Gemini, Anthropic Claude 等)进行交互。它提供统一的接口,让你轻松切换不同的模型。
  • Prompt Templates (提示词模板):这是 LangChain 的“大脑皮层”,负责生成结构化的、针对特定任务的提示词。好的提示词是 LLM 应用成功的关键,LangChain 让提示词的管理和复用变得异常简单。
  • Chains (链):这是 LangChain 的“神经系统”,负责将多个 LLM 调用或其他工具按顺序或逻辑组合起来。它定义了信息流的走向和处理逻辑。
  • Retrievers (检索器):这是 LangChain 的“记忆库”,负责从外部知识源(如向量数据库、文档)中检索相关信息,以增强 LLM 的知识。
  • Agents (智能体):这是 LangChain 的“决策者”,赋予 LLM 使用工具的能力。Agent 能够根据用户的输入,自主决定需要执行哪些步骤、调用哪些工具来解决问题。
  • Memory (记忆):这是 LangChain 的“短期记忆”,让 LLM 能够记住对话历史,从而实现多轮对话的连贯性。
  • Document Loaders (文档加载器):这是 LangChain 的“资料员”,负责从各种格式(PDF, CSV, HTML 等)加载数据。
  • Vector Stores (向量数据库):这是 LangChain 的“长期记忆”,用于存储和检索向量化的文本数据,常与检索器配合使用。

在本期,我们先聚焦最核心的几个模块:LLMs、Prompt Templates 和 Chain,来构建我们智能客服的第一个简单问答功能。

智能客服的“大脑”雏形:问答工作流解析

设想一下,我们的智能客服小助手,最基本的能力是什么?不就是用户问一个问题,它能给出一个合理的答案吗?

这个过程在 LangChain 中,可以简化为以下工作流:

  1. 用户输入问题:比如“如何重置我的密码?”
  2. 提示词模板加工:将用户的问题嵌入到一个预设的模板中,给 LLM 明确的指示,例如“你是一个专业的客服助手,请用简洁友好的语言回答用户的问题:[用户问题]”。
  3. 调用大型语言模型 (LLM):将加工后的提示词发送给大模型。
  4. 模型生成答案:LLM 根据提示词和其内部知识生成回复。
  5. 输出答案:将 LLM 的回复呈现给用户。

这个工作流,就是我们智能客服的“大脑”雏形。它虽然简单,但却是所有复杂功能的基础。

graph TD
    A[用户] --> B{输入问题};
    B --> C[PromptTemplate: 构造指令];
    C --> D[LLM: 大语言模型];
    D --> E[输出解析器 (可选): 格式化回答];
    E --> F[智能客服小助手];
    F --> G[回复用户];

    subgraph LangChain 核心流程
        C --- D --- E
    end

    style A fill:#f9f,stroke:#333,stroke-width:2px;
    style B fill:#bbf,stroke:#333,stroke-width:2px;
    style C fill:#ccf,stroke:#333,stroke-width:2px;
    style D fill:#ddf,stroke:#333,stroke-width:2px;
    style E fill:#eef,stroke:#333,stroke-width:2px;
    style F fill:#fcf,stroke:#333,stroke-width:2px;
    style G fill:#9f9,stroke:#333,stroke-width:2px;

上图清晰地展示了从用户提问到智能客服回复的简化流程。LangChain 在其中扮演了连接各个模块、串联逻辑的核心角色。

💻 实战代码演练 (客服项目中的具体应用)

好了,原理讲明白了,是时候撸起袖子干活了!我们将用 LangChain 来实现上述的简单问答流程,让我们的智能客服小助手能够回答一些通用问题。

准备工作

首先,我们需要安装 LangChain 库和 OpenAI 相关的集成库。我们选择 OpenAI 作为本期的 LLM 提供方,因为它目前是行业标杆,且接入方便。

# Python 环境
pip install langchain langchain-openai python-dotenv

# TypeScript / JavaScript 环境
npm install langchain @langchain/openai dotenv

然后,为了安全管理 API Key,我们通常使用 .env 文件。在项目根目录下创建一个名为 .env 的文件,并填入你的 OpenAI API Key:

OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Python 实战代码

让我们用 Python 来构建第一个智能客服问答机器人。

import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableSequence

# 1. 加载环境变量
# 这一步是读取 .env 文件中的 OPENAI_API_KEY
load_dotenv()

# 检查 API Key 是否已加载
if not os.getenv("OPENAI_API_KEY"):
    raise ValueError("OPENAI_API_KEY not found in environment variables. Please set it in a .env file.")

print("--- 智能客服小助手启动中 ---")

# 2. 初始化大语言模型 (LLM)
# 我们使用 ChatOpenAI,它封装了 OpenAI 的聊天模型接口
# temperature 参数控制模型的创造性,0 表示更确定性,1 表示更有创造性
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0.7)
print(f"✅ 已连接到大模型: {llm.model_name}")

# 3. 定义提示词模板 (Prompt Template)
# 这是我们给 LLM 的指令,告诉它如何扮演角色和回答问题
# {question} 是一个占位符,用户的问题会填充到这里
prompt_template = ChatPromptTemplate.from_messages(
    [
        ("system", "你是一个友好的智能客服助手,你的任务是简洁、准确地回答用户的问题。"),
        ("human", "{question}"),
    ]
)
print("✅ 已定义智能客服的提示词模板。")

# 4. 构建链 (Chain)
# LangChain Expression Language (LCEL) 是构建链的现代化方式,简洁且强大
# 这里的链表示:用户问题 -> 提示词模板 -> LLM -> 字符串解析器
# StrOutputParser 将 LLM 的输出(通常是 AIMessage 对象)转换为纯字符串
qa_chain = RunnableSequence(prompt_template | llm | StrOutputParser())
print("✅ 已构建问答链。")

# 5. 模拟智能客服问答
print("\n--- 开始模拟问答 ---")

# 场景1: 用户询问如何重置密码 (客服常见问题)
user_question_1 = "我忘记了我的账户密码,请问如何重置?"
print(f"\n🙋‍♂️ 用户提问: {user_question_1}")
# 调用链来获取答案
response_1 = qa_chain.invoke({"question": user_question_1})
print(f"🤖 智能客服: {response_1}")

# 场景2: 用户询问产品功能 (客服常见问题)
user_question_2 = "你们的产品支持哪些文件格式的上传?"
print(f"\n🙋‍♂️ 用户提问: {user_question_2}")
response_2 = qa_chain.invoke({"question": user_question_2})
print(f"🤖 智能客服: {response_2}")

# 场景3: 用户询问一个通用知识 (LLM 的通识能力)
user_question_3 = "请简要解释一下人工智能是什么?"
print(f"\n🙋‍♂️ 用户提问: {user_question_3}")
response_3 = qa_chain.invoke({"question": user_question_3})
print(f"🤖 智能客服: {response_3}")

print("\n--- 模拟问答结束 ---")
print("🎉 恭喜,你的第一个智能客服问答机器人已成功运行!")

代码解析:

  1. load_dotenv(): 从 .env 文件加载环境变量,确保你的 API Key 不会硬编码在代码中,这是生产级应用的基本要求。
  2. ChatOpenAI: 初始化一个聊天模型实例。我们指定了 gpt-3.5-turbo 模型。temperature 参数很重要,它控制了模型回复的“随机性”或“创造性”。对于客服场景,我们通常希望回复更稳定、更确定,所以 0.7 是一个比较折中的选择。
  3. ChatPromptTemplate.from_messages(): 定义了我们与 LLM 沟通的“剧本”。
    • ("system", ...):系统消息,用于设定 LLM 的角色和行为准则。在这里,我们让它扮演一个“友好的智能客服助手”。这是进行提示词工程(Prompt Engineering)的关键一环。
    • ("human", "{question}"):用户消息,{question} 是一个占位符,LangChain 会自动将我们传入的实际问题替换进去。
  4. RunnableSequence (LCEL): 这是 LangChain 0.1.0+ 版本推荐的链式调用方式,非常简洁直观。
    • prompt_template | llm | StrOutputParser():这表示一个管道操作。用户输入首先经过 prompt_template 加工成完整的提示词,然后这个提示词被发送给 llm,LLM 返回的结果再经过 StrOutputParser 转换为纯文本字符串。
  5. qa_chain.invoke(): 调用我们构建好的链,传入一个字典,其中 question 的值就是用户实际的问题。

通过这段代码,我们的智能客服小助手就拥有了初步的问答能力。它能理解用户的问题,并基于 OpenAI 模型的通用知识和我们设定的“客服助手”角色,给出相应的回复。

TypeScript 实战代码

对于前端或 Node.js 开发者,我们也提供 TypeScript 版本的实现。

import * as dotenv from 'dotenv';
import { ChatOpenAI } from '@langchain/openai';
import { ChatPromptTemplate } from '@langchain/core/prompts';
import { StringOutputParser } from '@langchain/core/output_parsers';
import { RunnableSequence } from '@langchain/core/runnables';

// 1. 加载环境变量
// 这一步是读取 .env 文件中的 OPENAI_API_KEY
dotenv.config();

// 检查 API Key 是否已加载
if (!process.env.OPENAI_API_KEY) {
    throw new Error("OPENAI_API_KEY not found in environment variables. Please set it in a .env file.");
}

console.log("--- 智能客服小助手启动中 ---");

// 2. 初始化大语言模型 (LLM)
// 我们使用 ChatOpenAI,它封装了 OpenAI 的聊天模型接口
// temperature 参数控制模型的创造性,0 表示更确定性,1 表示更有创造性
const llm = new ChatOpenAI({
    model: "gpt-3.5-turbo",
    temperature: 0.7,
});
console.log(`✅ 已连接到大模型: ${llm.modelName}`);

// 3. 定义提示词模板 (Prompt Template)
// 这是我们给 LLM 的指令,告诉它如何扮演角色和回答问题
// {question} 是一个占位符,用户的问题会填充到这里
const promptTemplate = ChatPromptTemplate.fromMessages([
    ["system", "你是一个友好的智能客服助手,你的任务是简洁、准确地回答用户的问题。"],
    ["human", "{question}"],
]);
console.log("✅ 已定义智能客服的提示词模板。");

// 4. 构建链 (Chain)
// LangChain Expression Language (LCEL) 是构建链的现代化方式,简洁且强大
// 这里的链表示:用户问题 -> 提示词模板 -> LLM -> 字符串解析器
// StringOutputParser 将 LLM 的输出(通常是 AIMessage 对象)转换为纯字符串
const qaChain = RunnableSequence.from([
    promptTemplate,
    llm,
    new StringOutputParser(),
]);
console.log("✅ 已构建问答链。");

// 5. 模拟智能客服问答
async function runDemo() {
    console.log("\n--- 开始模拟问答 ---");

    // 场景1: 用户询问如何重置密码 (客服常见问题)
    const userQuestion1 = "我忘记了我的账户密码,请问如何重置?";
    console.log(`\n🙋‍♂️ 用户提问: ${userQuestion1}`);
    // 调用链来获取答案
    const response1 = await qaChain.invoke({ question: userQuestion1 });
    console.log(`🤖 智能客服: ${response1}`);

    // 场景2: 用户询问产品功能 (客服常见问题)
    const userQuestion2 = "你们的产品支持哪些文件格式的上传?";
    console.log(`\n🙋‍♂️ 用户提问: ${userQuestion2}`);
    const response2 = await qaChain.invoke({ question: userQuestion2 });
    console.log(`🤖 智能客服: ${response2}`);

    // 场景3: 用户询问一个通用知识 (LLM 的通识能力)
    const userQuestion3 = "请简要解释一下人工智能是什么?";
    console.log(`\n🙋‍♂️ 用户提问: ${userQuestion3}`);
    const response3 = await qaChain.invoke({ question: userQuestion3 });
    console.log(`🤖 智能客服: ${response3}`);

    console.log("\n--- 模拟问答结束 ---");
    console.log("🎉 恭喜,你的第一个智能客服问答机器人已成功运行!");
}

runDemo();

TypeScript 代码解析:

与 Python 版本逻辑完全一致,只是语法上有所区别:

  1. dotenv.config(): 加载 .env 文件。
  2. new ChatOpenAI(): 初始化聊天模型。
  3. ChatPromptTemplate.fromMessages(): 定义提示词模板,这里同样使用 [string, string] 的数组形式表示消息。
  4. RunnableSequence.from([...]): 构建链,同样通过数组顺序定义管道。
  5. await qaChain.invoke({ question: userQuestion }): 调用链是异步的,所以需要使用 await

至此,我们的智能客服小助手已经具备了最基础的问答能力。它能够接收用户的问题,并利用大模型的通用知识和我们设定的角色进行回复。虽然它还不能访问我们公司内部的知识库,但这是一个坚实的第一步!

坑与避坑指南

作为一名资深开发者,我见过太多的坑,也总结了一些避坑经验,今天就先分享几个初学者常犯的错误和注意事项:

  1. API Key 安全性:
    • 坑: 直接把 OPENAI_API_KEY 硬编码在代码里,或者上传到公共仓库(如 GitHub)。这等于把你的银行卡密码贴在脸上!
    • 避坑指南: 永远使用环境变量(如 .env 文件配合 python-dotenvdotenv)来管理敏感信息。在部署到生产环境时,也要确保这些变量是通过安全的方式(如 Kubernetes Secrets, AWS Secrets Manager, Vault 等)注入的。
  2. 提示词工程 (Prompt Engineering) 的重要性:
    • 坑: 觉得 LLM 无所不能,随便给个问题就能得到完美答案。或者提示词模糊不清,导致模型“胡言乱语”(Hallucination)。
    • 避坑指南: “Garbage in, garbage out” 在 LLM 世界里尤其适用。本期我们用的 system 消息就是最基础的提示词工程。请记住,清晰、明确、有上下文的指令,比你花几小时调参可能都管用。多尝试不同的措辞,限定模型的回复格式、长度、语气等。
  3. LLM 的“幻觉” (Hallucination):
    • 坑: 过于信任 LLM 的回答,认为它说的都是真理。
    • 避坑指南: 现阶段的 LLM 并不是一个严谨的知识库,它可能会生成听起来合理但实际上是错误或虚构的信息。在我们的智能客服项目中,这意味着它可能会“编造”公司政策或产品功能。这是这个简单问答模型的最大局限性。未来我们将通过 RAG(检索增强生成)等技术来解决这个问题,让 LLM 能够基于我们提供的真实知识进行回答。
  4. 成本管理与模型选择:
    • 坑: 不加思索地使用最新最强的模型(如 gpt-4),导致账单爆炸。
    • 避坑指南: 不同的模型有不同的价格和性能。对于简单的问答或测试,gpt-3.5-turbo 通常是性价比最高的选择。只有在确实需要更高级推理能力时,才考虑使用更昂贵的模型。LangChain 的统一接口让你切换模型变得轻而易举,善用这个特性。
  5. 异步操作 (Async) 与并发:
    • 坑: 在处理大量请求时,同步调用 LLM 导致性能瓶颈。
    • 避坑指南: LangChain 的许多方法都提供了异步版本(如 ainvoke)。在生产环境中,尤其是在 Web 服务中,务必利用异步编程来提升并发处理能力和响应速度。我们本期为了简化,使用了同步调用,但心中要有这根弦。

📝 本期小结

恭喜你,同学们!通过本期的学习,我们不仅深入理解了 LangChain 作为 AI 应用开发“瑞士军刀”的核心价值和模块化设计理念,更亲手搭建了我们“智能客服知识库”项目的第一个里程碑——一个基于大模型的简单问答机器人。

我们学会了如何:

  • 初始化并连接到 OpenAI 大模型。
  • 利用 ChatPromptTemplate 进行基础的提示词工程,赋予模型角色。
  • 通过 LangChain Expression Language (LCEL) 构建简洁高效的问答链。
  • 在实际项目中,让智能客服小助手能够响应用户的通用问题。

虽然这个小助手还很“稚嫩”,它的知识仅限于 LLM 的通用训练数据,无法访问我们公司的内部文档,但这正是 LangChain 的魅力所在——它为我们后续扩展功能打下了坚实的基础。

在接下来的课程中,我们将逐步解锁 LangChain 更强大的能力,比如如何让我们的智能客服能够“阅读”公司的产品手册和 FAQ 文档,如何记住用户的多轮对话,甚至如何调用外部 API 来执行具体操作。

下期预告:我们将深入探索 LangChain 的 Document LoadersText Splitters,学习如何将海量的非结构化文档转化为 LLM 可以理解的知识片段,为我们的智能客服构建专属的“记忆库”!

加油,AI 架构师们,我们的征途才刚刚开始!