第 22 期 | 多模态输入:让客服机器人能够“看”图

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

🎯 本期学习目标

嘿,各位未来的 AI 大师们!欢迎来到《LangChain 全栈大师课》的第一期。我知道你们现在可能对 AI 的未来充满憧憬,但别急,罗马不是一天建成的,智能客服也不是一蹴而就的。本期,我们将直接触及智能客服系统的核心——它的“大脑”和“指令”。学完本期,你将:

  1. 透彻理解 LLM 在智能客服中的核心定位:明白大型语言模型如何成为我们客服小助手的智慧源泉。
  2. 掌握 LangChain 中 LLM 和 ChatModel 的基本调用:学会用最简洁的方式与最强大的模型对话。
  3. 精通 Prompt 工程的基础艺术:学会如何“发号施令”,让 LLM 真正按照我们的意图行事,成为一个合格的客服代表。
  4. 熟练运用 LangChain 的 PromptTemplate:告别硬编码,用模板化方式构建灵活、可复用的 Prompt。

📖 原理解析

好了,同学们,坐稳扶好!我们要开始深入 AI 的“神经中枢”了。

想象一下,我们的“智能客服知识库”项目,最终目的是让用户能通过自然语言提问,然后获得专业、准确、快速的答案。谁来提供这些答案?谁来理解用户稀奇古怪的问题?答案就是——大型语言模型(LLM)

LLM,全称 Large Language Model,是经过海量文本数据训练的深度学习模型。它们拥有惊人的文本生成、理解、总结、翻译能力。在我们的客服场景中,LLM 就是那个“无所不知”的大脑,它能:

  • 理解用户意图:用户问“我的订单什么时候到?”,它知道这是在查询物流。
  • 生成自然语言回复:它不会生硬地甩给你一串代码,而是用流畅、友好的语言回答。
  • 处理复杂情境:即使问题描述不清晰,它也能根据上下文进行推断。

但光有大脑还不够,你还得知道怎么“指挥”这个大脑。这就引出了我们的第二个主角——Prompt

Prompt,中文叫“提示词”或“指令”。它就像是给 LLM 下达的命令,告诉它“你是谁”、“你要做什么”、“你应该怎么做”。一个好的 Prompt,能让 LLM 的能力发挥得淋漓尽致;一个糟糕的 Prompt,则可能让它“胡言乱语”,甚至“答非所问”。

在 LangChain 的世界里,LLM 和 Prompt 的交互被优雅地抽象和封装。你不需要关心底层复杂的模型 API 调用,只需要通过 LangChain 提供的接口,就能轻松切换不同的模型(OpenAI 的 GPT 系列、Anthropic 的 Claude 系列,甚至是各种开源模型),并用结构化的方式构建你的 Prompt。

LangChain 中的 LLM 与 ChatModel

LangChain 主要提供了两种与语言模型交互的接口:

  1. LLM:主要用于文本补全(text completion)任务。你给它一段文本,它接着往下写。比如你给它“客服小助手应该如何...”,它会补全后续内容。
  2. ChatModel:这是我们智能客服项目的主力。它更适合多轮对话和角色扮演。它接收一系列“消息”(Messages),这些消息通常包含角色(系统、用户、助手),然后返回一系列消息。这正是我们客服场景最需要的。

PromptTemplate:让 Prompt 活起来

想象一下,我们每次都要为不同的用户问题手写一个完整的 Prompt,比如:

“你是一个专业的客服机器人。请帮助用户解决订单问题。用户的问题是:'我的订单#12345为什么还没发货?'”

如果订单号变了,或者问题类型变了,我们就要修改整个字符串。这效率太低了!

PromptTemplate 就是 LangChain 提供的解决方案。它允许你定义一个带有占位符的模板,然后动态地填充这些占位符。这样,你的 Prompt 结构保持不变,只有变量内容发生变化。这对于构建可复用、可维护的智能客服 Prompt 至关重要。

核心工作流图解

下面这个 Mermaid 图,清晰地展示了用户请求如何经过 Prompt 模板的“加持”,最终抵达 LLM 并获得回复的流程。这正是我们智能客服小助手的“第一次心跳”。

graph TD
    A[用户查询: "我的订单怎么了?"] --> B{LangChain PromptTemplate}
    B -- 注入上下文 --> C[完整Prompt: "你是一个专业的客服...用户问题是'我的订单怎么了?'"]
    C --> D[LangChain ChatModel (e.g., GPT-4)]
    D -- 生成回复 --> E[LLM回复: "请提供订单号,我来帮您查询。"]
    E --> F[智能客服小助手]
    F --> G[返回用户]

    subgraph LangChain 内部
        B
        C
        D
    end

图解说明:

  1. 用户查询:这是我们客服小助手收到的一切输入的起点。
  2. LangChain PromptTemplate:根据我们预设的模板,将用户查询和其他必要信息(例如,系统角色设定、历史对话、从知识库检索到的信息等)填充进去。
  3. 完整 Prompt:一个结构化、包含所有必要指令和上下文的提示词,准备发送给 LLM。
  4. LangChain ChatModel:通过 LangChain 提供的接口,调用底层的大型语言模型(例如 OpenAI 的 GPT-4)。
  5. LLM 回复:LLM 根据 Prompt 的指令,生成符合预期的自然语言回复。
  6. 智能客服小助手:我们的应用接收到 LLM 的回复。
  7. 返回用户:最终,用户在界面上看到客服小助手的回复。

这个流程看起来简单,但每一步都至关重要。PromptTemplate 的设计决定了 LLM 的表现上限,而 ChatModel 的选择则决定了其智能程度和成本。

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

好了,原理讲得再多,不如撸起袖子干一场!我们现在就来为我们的智能客服小助手,搭建它的“大脑”和“指令系统”。

我们将使用 Python 和 LangChain 来实现。确保你已经安装了必要的库:pip install langchain langchain-openai python-dotenv

第一步:环境配置与模型初始化

为了安全和方便,我们会把 API Key 放在 .env 文件中。

创建一个 .env 文件,内容如下(请替换为你的真实 API Key):

OPENAI_API_KEY="sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

然后是 Python 代码:

import os
from dotenv import load_dotenv

# 导入 LangChain 核心组件
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, SystemMessagePromptTemplate, HumanMessagePromptTemplate
from langchain_core.messages import HumanMessage, SystemMessage

# 加载环境变量
load_dotenv()

# 获取 OpenAI API Key
openai_api_key = os.getenv("OPENAI_API_KEY")
if not openai_api_key:
    raise ValueError("请在 .env 文件中设置 OPENAI_API_KEY")

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

# 1. 初始化 ChatModel
# 我们选择 ChatOpenAI,因为它对多轮对话和角色扮演支持最好。
# temperature 参数控制生成文本的随机性。0.0 表示更确定性,1.0 表示更有创造性。
# 对于客服场景,我们通常希望回复准确且稳定,所以会设置一个较低的值。
chat_model = ChatOpenAI(
    api_key=openai_api_key,
    model="gpt-3.5-turbo", # 也可以尝试 "gpt-4o" 或其他模型
    temperature=0.3 # 客服场景,我们希望模型回答更稳定和准确
)
print(f"ChatModel 初始化完成,使用模型: {chat_model.model_name}")

# --- 模拟客服场景 ---

# 场景一:直接调用 ChatModel - 简单提问
print("\n--- 场景一:直接调用 ChatModel ---")
# ChatModel 接收的是消息列表,每条消息都有一个角色(System, Human, AI)
messages_direct = [
    HumanMessage(content="我的订单#12345为什么还没发货?")
]
response_direct = chat_model.invoke(messages_direct)
print("用户: 我的订单#12345为什么还没发货?")
print(f"小助手 (直接调用): {response_direct.content}")
# 思考:这样的回复够专业吗?没有明确的角色设定,模型可能自由发挥。

# 场景二:引入 SystemMessage - 设定角色
print("\n--- 场景二:引入 SystemMessage - 设定角色 ---")
# SystemMessage 告诉模型它的角色和行为规范
messages_with_system = [
    SystemMessage(content="你是一个专业的电商客服助手,以友好、耐心、准确的语气回答用户问题。如果信息不足以回答,请礼貌地要求用户提供更多细节。"),
    HumanMessage(content="我的订单#67890什么时候能收到?")
]
response_with_system = chat_model.invoke(messages_with_system)
print("用户: 我的订单#67890什么时候能收到?")
print(f"小助手 (设定角色): {response_with_system.content}")
# 思考:有了角色设定,回复是不是更像一个客服了?

# 场景三:使用 PromptTemplate - 动态生成Prompt
print("\n--- 场景三:使用 PromptTemplate - 动态生成Prompt ---")

# 定义一个 ChatPromptTemplate
# from_messages 接收一个消息模板列表
# SystemMessagePromptTemplate 用于设定系统角色
# HumanMessagePromptTemplate 用于接收用户输入,并可以包含变量
customer_service_prompt = ChatPromptTemplate.from_messages(
    [
        SystemMessagePromptTemplate.from_template(
            "你是一个专业的电商客服助手,以友好、耐心、准确的语气回答用户问题。 "
            "如果信息不足以回答,请礼貌地要求用户提供更多细节。 "
            "当前时间是 {current_time}。" # 我们可以加入动态的系统信息
        ),
        HumanMessagePromptTemplate.from_template("用户的问题是:{user_query}")
    ]
)

# 动态填充 Prompt 变量
from datetime import datetime
current_time = datetime.now().strftime("%Y年%m月%d日 %H:%M")

# 准备用户查询
user_question_1 = "我的订单#ABCDE发货了吗?"
user_question_2 = "我收到的商品有损坏,该怎么办?"

# 使用 .invoke() 方法,传入变量字典
formatted_prompt_1 = customer_service_prompt.invoke({"current_time": current_time, "user_query": user_question_1})
response_template_1 = chat_model.invoke(formatted_prompt_1)

print(f"\n用户: {user_question_1}")
print(f"小助手 (PromptTemplate): {response_template_1.content}")

formatted_prompt_2 = customer_service_prompt.invoke({"current_time": current_time, "user_query": user_question_2})
response_template_2 = chat_model.invoke(formatted_prompt_2)

print(f"\n用户: {user_question_2}")
print(f"小助手 (PromptTemplate): {response_template_2.content}")

print("\n------ 智能客服小助手演示结束 ------")

代码解析:

  1. load_dotenv(): 从 .env 文件加载环境变量,确保 API Key 不直接暴露在代码中,这是生产环境的最佳实践。
  2. ChatOpenAI: 初始化一个基于 OpenAI API 的聊天模型。model 参数指定我们使用的模型版本(例如 gpt-3.5-turbogpt-4o)。temperature 参数非常重要,它控制模型输出的随机性。对于客服这种需要严谨和准确的场景,我们通常会设置一个较低的值(如 0.3),以减少“幻觉”或不确定性。
  3. 直接调用 chat_model.invoke(): 最简单的调用方式,直接传入一个 HumanMessage 列表。你会发现,模型虽然能回答,但可能缺乏“客服”的专业口吻。
  4. 引入 SystemMessage: 这是 Prompt 工程的关键一步。通过 SystemMessage(content="..."),我们给模型设定了明确的角色和行为规范。这就像给一个新员工提供入职培训手册,告诉他“你是谁,该怎么说话,该做什么”。你会明显感受到回复风格的变化。
  5. ChatPromptTemplateSystemMessagePromptTemplate, HumanMessagePromptTemplate:
    • ChatPromptTemplate.from_messages() 允许我们构建一个结构化的 Prompt 模板,它接收一个消息模板列表。
    • SystemMessagePromptTemplate.from_template() 用于定义系统级别的指令模板,可以包含 {} 占位符。
    • HumanMessagePromptTemplate.from_template() 用于定义用户输入的消息模板,同样可以包含 {} 占位符。
    • 通过 .invoke() 方法,我们传入一个字典,字典的键对应模板中的占位符,值则是我们要填充的动态数据。这样,我们就能轻松地复用同一个客服 Prompt 结构,只是改变用户查询、当前时间等变量。

通过这三个场景的演练,你应该能直观感受到,从简单的模型调用到引入 SystemMessage 设定角色,再到使用 PromptTemplate 实现动态 Prompt,每一步都让我们的智能客服小助手变得更加专业、灵活和强大。

坑与避坑指南

作为一名资深的老兵,我见过太多新手在这里栽跟头。别怕,我来给你指明前方的“雷区”:

  1. Prompt 模糊性导致模型“跑偏”
    • :你可能觉得你的 Prompt 已经很清楚了,但 LLM 毕竟不是人,它会严格按照你给的词语去理解。比如你只说“回答用户问题”,它可能用很随意的语气,甚至跑题。
    • 避坑具体化,具体化,再具体化! 设定明确的角色(“你是一个专业的电商客服”),指定语气(“友好、耐心、准确”),规定行为(“如果信息不足,请礼貌要求更多细节”),甚至可以给出输出格式要求。就像给一个刚入职的实习生写工作手册,越详细越好。
  2. API Key 安全问题
    • :直接把 API Key 写死在代码里,或者上传到公共代码库(如 GitHub)。这等于把你的银行卡密码贴在额头上。
    • 避坑永远使用环境变量! 如本期所示,将 OPENAI_API_KEY 存储在 .env 文件中,并确保 .env.gitignore 忽略。在部署到服务器时,通过系统环境变量注入。
  3. Token 成本与模型选择
    • :盲目追求最新最强的模型(如 GPT-4o),但每次调用都会消耗大量 Token,导致成本飙升。
    • 避坑根据场景选择合适的模型。 对于简单的问答或信息提取,gpt-3.5-turbo 通常就足够了,且速度更快、成本更低。只有在需要处理非常复杂、需要高度推理或创造性的任务时,才考虑更强大的模型。时刻关注 LangChain 对开源模型的支持,未来可能会有更经济的选择。
  4. 上下文窗口限制(为未来埋伏笔)
    • :随着对话轮次增加,Prompt 可能会变得越来越长,最终超出 LLM 的上下文窗口限制。模型会“失忆”或者直接报错。
    • 避坑:虽然本期我们还没深入到多轮对话,但要提前有这个意识。在后续课程中,我们将学习如何通过**记忆(Memory)管理、检索增强生成(RAG)**等技术,智能地管理上下文,只把最相关的信息喂给 LLM。
  5. “幻觉”问题
    • :LLM 可能会生成听起来非常合理但实际上是错误或捏造的信息(我们称之为“幻觉”)。这在客服场景中是致命的。
    • 避坑
      • 降低 temperature:如代码所示,将温度设置在 0.3 左右,可以有效降低模型的“创造性”,使其输出更趋于确定性。
      • 明确指令:在 SystemMessage 中强调“只根据提供的信息回答,不进行猜测”。
      • 引入知识库:这是我们整个项目的核心!通过将 LLM 与我们自己的客服知识库结合(RAG),强制它从可信赖的源头获取信息,大大减少幻觉。这正是我们后续课程的重点。

记住,这些“坑”不是为了吓唬你,而是让你能以更专业的视角去思考和设计你的 AI 应用。

📝 本期小结

恭喜你,迈出了成为 LangChain 大师的第一步!

在本期中,我们深入理解了 LLM 如何作为智能客服的“大脑”,以及 Prompt 如何成为我们指挥这个大脑的“指令”。我们通过实战代码,学习了如何在 LangChain 中初始化并调用 ChatModel,并通过 SystemMessage 设定角色,最终掌握了使用 PromptTemplate 构建灵活、可复用的动态 Prompt 的艺术。

你现在应该对如何让一个 AI 模型开口说话,并按照你的意图行事有了一个清晰的认识。这个基础至关重要,它将贯穿我们后续所有更复杂的模块。

下一期,我们将继续深入,探讨如何让我们的客服小助手拥有“记忆”,记住之前的对话内容,从而实现更连贯、更智能的多轮对话。敬请期待!