第 21 期 | 外部 API 集成:使用 OpenAPI 查询天气与汇率
(申请发送: agentupdate)
🎯 本期学习目标
嘿,各位未来的 AI 大师们!欢迎来到《LangChain 全栈大师课》的第五站。前几期我们已经对 LangChain 有了初步的认识,但要真正让你的智能客服活起来,我们必须深入它的“大脑”——那些强大到令人惊叹的大语言模型(LLM)。本期,我们将告别黑盒,彻底掌握 LangChain 如何与这些模型高效、优雅地对话。
学完本期,你将:
- 透彻理解 LangChain 中
LLM和ChatModel的核心区别与最佳应用场景,不再混淆,精准选择。 - 掌握如何在 LangChain 中配置、调用主流大语言模型(如 OpenAI 的 GPT 系列),为你的智能客服注入强大的语言理解和生成能力。
- 学会通过 LangChain 的统一接口,灵活切换不同的大模型提供商,让你的应用拥有更高的可移植性和弹性。
- 洞察模型参数(如
temperature和max_tokens)对生成结果的关键影响,成为一名真正的模型调优师。
📖 原理解析
好了,伙计们,系好安全带!我们要进入 LangChain 的“发动机舱”了。
想象一下,你是个顶级厨师,而大语言模型(LLM)就是你厨房里的各种先进设备:有能烤面包的烤箱,有能切菜的料理机,还有能调味的高精度电子秤。这些设备功能强大,但它们的说明书、操作界面、电源插座可能都不一样。直接操作,你得学一堆不同的接口和协议,这多麻烦!
LangChain 的 LLM 和 ChatModel 就是你的“通用操作面板”或者“智能中央控制器”。它们提供了一套标准化的接口,让你无论面对哪个品牌的烤箱(OpenAI)、料理机(Anthropic)还是电子秤(Hugging Face),都能用一套统一的指令来操作。
LLM vs. ChatModel:不仅仅是名称不同
BaseLLM(文本补全模型):- 核心功能:接收一段文本(
string),然后返回一段补全的文本(string)。 - 工作模式:它更像是你在一个文本框里写了一半话,然后模型帮你把剩下的内容“预测”出来、补全。
- 典型场景:早期的大模型(如 GPT-3 的
text-davinci-003)主要就是这种模式。适用于简单的文本生成、摘要、翻译等,不涉及多轮对话或角色扮演。 - 客服项目中的应用:如果你只是想让客服小助手对用户的一句话进行快速总结,或者从一段文本中提取关键词,
LLM就能胜任。
- 核心功能:接收一段文本(
BaseChatModel(聊天模型):- 核心功能:接收一个消息列表(
List[BaseMessage]),然后返回一个消息对象(BaseMessage)。 - 工作模式:这是现代大模型(如 GPT-3.5-turbo, GPT-4, Claude)的主流接口。它更理解“对话”的概念,能区分系统指令(
SystemMessage)、用户提问(HumanMessage)和 AI 回复(AIMessage)。这使得模型能够更好地理解上下文,进行多轮对话,并扮演特定角色。 - 典型场景:几乎所有需要“智能对话”的场景。多轮问答、角色扮演、内容创作、代码生成等。
- 客服项目中的应用:这才是我们智能客服小助手的大脑核心!它能记住之前的对话,理解用户意图,扮演“专业客服”角色,并根据系统给定的知识库信息进行回复。
- 核心功能:接收一个消息列表(
为什么 ChatModel 越来越重要?
因为现代大模型的设计哲学变了。它们不再仅仅是“文本补全器”,而是“对话引擎”。通过明确的 SystemMessage,我们可以给模型设定“人格”和“行为准则”,比如“你是一个友善且专业的客服,请用中文简洁回答。”这对于我们的智能客服来说,是实现个性化、专业化服务的基石。
LangChain 的抽象层级
LangChain 的设计哲学就是“抽象化”。它将不同提供商(OpenAI, Anthropic, Hugging Face 等)和不同模型类型(LLM, ChatModel)的复杂性封装起来,暴露一个统一的接口。
graph TD
subgraph LangChain 统一接口
A[调用 LangChain LLM/ChatModel] --> B{选择模型接口}
end
B -- LLM 类型 --> C[BaseLLM 接口]
B -- ChatModel 类型 --> D[BaseChatModel 接口]
C --> C1(OpenAI LLM)
C --> C2(HuggingFace LLM)
C --> C3(Google Palm LLM)
D --> D1(ChatOpenAI)
D --> D2(ChatAnthropic)
D --> D3(ChatGoogleGenerativeAI)
D --> D4(ChatHuggingFace)
subgraph 外部大模型服务
C1 --> E1(OpenAI API)
C2 --> E2(HuggingFace Transformers)
C3 --> E3(Google Palm API)
D1 --> E1
D2 --> E4(Anthropic API)
D3 --> E5(Google Generative AI API)
D4 --> E2
end
E1 -- 文本/消息 --> F[大模型响应]
E2 -- 文本/消息 --> F
E3 -- 文本/消息 --> F
E4 -- 文本/消息 --> F
E5 -- 文本/消息 --> F
F --> A图解:LangChain LLM/ChatModel 抽象层
这张图清晰地展示了 LangChain 如何在你的应用和各种大模型之间搭建了一座桥梁。你只需要和 LangChain 的 BaseLLM 或 BaseChatModel 接口打交道,至于底层是 OpenAI 还是 Anthropic,LangChain 会帮你处理好一切。这极大地降低了开发难度,并提升了应用的可扩展性。
💻 实战代码演练 (客服项目中的具体应用)
好了,理论说完了,是时候撸起袖子,让我们的智能客服小助手真正开口说话了!
首先,确保你的环境已经安装了必要的库。我们以 OpenAI 为例,因为它目前依然是业界标杆。
pip install langchain langchain-openai python-dotenv
# 或者对于 TypeScript/JavaScript
# npm install langchain @langchain/openai dotenv
别忘了设置你的 API 密钥。最安全的方式是使用环境变量。创建一个 .env 文件,内容如下:
OPENAI_API_KEY="sk-YOUR_OPENAI_API_KEY_HERE"
然后,在你的代码中加载它。
1. 使用 ChatModel (Python)
我们直接从 ChatModel 开始,因为它更强大,也更符合现代大模型的应用场景。我们的智能客服小助手就是基于 ChatModel 来进行多轮对话和角色扮演的。
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.messages import HumanMessage, SystemMessage, AIMessage
# 1. 加载环境变量
load_dotenv()
# 确保 OPENAI_API_KEY 已设置
if not os.getenv("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY 环境变量未设置。请在 .env 文件中配置。")
print("--- LangChain ChatModel 实战:智能客服小助手初体验 ---")
# 2. 初始化 ChatModel
# model_name 可以是 "gpt-3.5-turbo", "gpt-4", "gpt-4o" 等
# temperature 控制生成文本的随机性。0.0 表示确定性最高,1.0 表示创造性最高。
# 对于客服场景,我们通常希望回复准确、一致,所以温度会设置得较低。
chat_model = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.2)
# 3. 模拟客服对话:单轮提问
print("\n--- 场景一:客服小助手处理单轮用户提问 ---")
user_query_1 = "我的鼠标突然不动了,应该怎么排查?"
messages_1 = [
SystemMessage(content="你是一个专业的电脑硬件客服助手,请提供简洁有效的排查步骤。"), # 设定系统角色和指令
HumanMessage(content=user_query_1) # 用户提问
]
print(f"用户提问: {user_query_1}")
response_1 = chat_model.invoke(messages_1)
print(f"客服小助手回复: {response_1.content}")
# 预期输出可能包含:检查连接、更换电池、重启电脑、更新驱动等。
# 4. 模拟客服对话:多轮追问 (ChatModel 的强大之处)
print("\n--- 场景二:客服小助手进行多轮对话 ---")
user_query_2_part1 = "我按照你的方法试了,还是不行,是不是鼠标坏了?"
messages_2 = [
SystemMessage(content="你是一个专业的电脑硬件客服助手,请提供简洁有效的排查步骤。"),
HumanMessage(content=user_query_1), # 第一次用户提问
AIMessage(content=response_1.content), # 小助手第一次回复
HumanMessage(content=user_query_2_part1) # 用户追问
]
print(f"用户追问: {user_query_2_part1}")
response_2 = chat_model.invoke(messages_2)
print(f"客服小助手回复: {response_2.content}")
# 预期输出会基于之前的对话上下文,更深入地排查或建议送修。
# 5. 探索模型参数:temperature 的影响
print("\n--- 场景三:调整 temperature 观察模型回复风格 ---")
# 降低温度,让回答更严谨、事实性强
chat_model_strict = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.0)
messages_strict = [
SystemMessage(content="你是一个严谨的科学研究员,请客观描述地球是圆的还是平的。"),
HumanMessage(content="地球是什么形状?")
]
response_strict = chat_model_strict.invoke(messages_strict)
print(f"严谨模式 (temperature=0.0): {response_strict.content}")
# 提高温度,让回答更具创造性、发散性
chat_model_creative = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.8)
messages_creative = [
SystemMessage(content="你是一个充满想象力的诗人,请用诗歌描述地球的形状。"),
HumanMessage(content="地球是什么形状?")
]
response_creative = chat_model_creative.invoke(messages_creative)
print(f"创意模式 (temperature=0.8): {response_creative.content}")
print("\n--- 恭喜,你已初步掌握 LangChain ChatModel 的核心用法! ---")
1. 使用 ChatModel (TypeScript)
import { config } from 'dotenv';
import { ChatOpenAI } from '@langchain/openai';
import { HumanMessage, SystemMessage, AIMessage } from '@langchain/core/messages';
// 1. 加载环境变量
config();
// 确保 OPENAI_API_KEY 已设置
if (!process.env.OPENAI_API_KEY) {
throw new Error("OPENAI_API_KEY 环境变量未设置。请在 .env 文件中配置。");
}
console.log("--- LangChain ChatModel 实战:智能客服小助手初体验 ---");
async function runChatModelDemo() {
// 2. 初始化 ChatModel
// modelName 可以是 "gpt-3.5-turbo", "gpt-4", "gpt-4o" 等
// temperature 控制生成文本的随机性。0.0 表示确定性最高,1.0 表示创造性最高。
// 对于客服场景,我们通常希望回复准确、一致,所以温度会设置得较低。
const chatModel = new ChatOpenAI({
modelName: "gpt-3.5-turbo",
temperature: 0.2,
});
// 3. 模拟客服对话:单轮提问
console.log("\n--- 场景一:客服小助手处理单轮用户提问 ---");
const userQuery1 = "我的鼠标突然不动了,应该怎么排查?";
const messages1 = [
new SystemMessage("你是一个专业的电脑硬件客服助手,请提供简洁有效的排查步骤。"), // 设定系统角色和指令
new HumanMessage(userQuery1) // 用户提问
];
console.log(`用户提问: ${userQuery1}`);
const response1 = await chatModel.invoke(messages1);
console.log(`客服小助手回复: ${response1.content}`);
// 预期输出可能包含:检查连接、更换电池、重启电脑、更新驱动等。
// 4. 模拟客服对话:多轮追问 (ChatModel 的强大之处)
console.log("\n--- 场景二:客服小助手进行多轮对话 ---");
const userQuery2Part1 = "我按照你的方法试了,还是不行,是不是鼠标坏了?";
const messages2 = [
new SystemMessage("你是一个专业的电脑硬件客服助手,请提供简洁有效的排查步骤。"),
new HumanMessage(userQuery1), // 第一次用户提问
new AIMessage(response1.content as string), // 小助手第一次回复
new HumanMessage(userQuery2Part1) // 用户追问
];
console.log(`用户追问: ${userQuery2Part1}`);
const response2 = await chatModel.invoke(messages2);
console.log(`客服小助手回复: ${response2.content}`);
// 预期输出会基于之前的对话上下文,更深入地排查或建议送修。
// 5. 探索模型参数:temperature 的影响
console.log("\n--- 场景三:调整 temperature 观察模型回复风格 ---");
// 降低温度,让回答更严谨、事实性强
const chatModelStrict = new ChatOpenAI({ modelName: "gpt-3.5-turbo", temperature: 0.0 });
const messagesStrict = [
new SystemMessage("你是一个严谨的科学研究员,请客观描述地球是圆的还是平的。"),
new HumanMessage("地球是什么形状?")
];
const responseStrict = await chatModelStrict.invoke(messagesStrict);
console.log(`严谨模式 (temperature=0.0): ${responseStrict.content}`);
// 提高温度,让回答更具创造性、发散性
const chatModelCreative = new ChatOpenAI({ modelName: "gpt-3.5-turbo", temperature: 0.8 });
const messagesCreative = [
new SystemMessage("你是一个充满想象力的诗人,请用诗歌描述地球的形状。"),
new HumanMessage("地球是什么形状?")
];
const responseCreative = await chatModelCreative.invoke(messagesCreative);
console.log(`创意模式 (temperature=0.8): ${responseCreative.content}`);
console.log("\n--- 恭喜,你已初步掌握 LangChain ChatModel 的核心用法! ---");
}
runChatModelDemo();
2. 使用 LLM (Python - 了解即可,ChatModel 更常用)
虽然 ChatModel 更推荐,但为了完整性,我们快速看一下 LLM 的用法。
import os
from dotenv import load_dotenv
from langchain_openai import OpenAI # 注意这里是 OpenAI 而不是 ChatOpenAI
load_dotenv()
if not os.getenv("OPENAI_API_KEY"):
raise ValueError("OPENAI_API_KEY 环境变量未设置。请在 .env 文件中配置。")
print("\n--- LangChain LLM 实战:简单文本补全 ---")
# 初始化 LLM 模型 (通常使用较旧的模型或者特定场景)
# 注意:OpenAI 官方也推荐使用 gpt-3.5-turbo 等 ChatModel 来进行文本补全
# 此处为了演示 LLM 类,我们使用 text-davinci-003(如果可用,但通常会提示废弃)
# 或者可以直接用 ChatOpenAI,但传入的不是消息列表,而是字符串。
# 为了避免混淆,我们这里直接用 ChatOpenAI 但只传入单字符串。
# 如果你真的需要旧的 LLM 接口,可能需要降级 langchain-openai 版本或使用其他提供商。
# 这里我们用 ChatOpenAI 来模拟 LLM 的文本补全行为,因为更现代。
llm_model_as_chat = ChatOpenAI(model_name="gpt-3.5-turbo", temperature=0.7)
prompt = "请用一句话总结智能客服知识库的核心价值:"
print(f"输入文本: {prompt}")
response_llm = llm_model_as_chat.invoke(prompt) # 直接传入字符串
print(f"LLM 风格回复: {response_llm.content}")
# 预期输出:智能客服知识库通过集中管理信息,快速响应用户查询,提升服务效率和用户满意度。
print("\n--- LLM 风格演示结束 ---")
2. 使用 LLM (TypeScript - 了解即可,ChatModel 更常用)
import { config } from 'dotenv';
import { OpenAI } from '@langchain/openai'; // 注意这里是 OpenAI 而不是 ChatOpenAI
import { ChatOpenAI } from '@langchain/openai'; // 引入 ChatOpenAI 用于模拟
config();
if (!process.env.OPENAI_API_KEY) {
throw new Error("OPENAI_API_KEY 环境变量未设置。请在 .env 文件中配置。");
}
console.log("\n--- LangChain LLM 实战:简单文本补全 ---");
async function runLLMDemo() {
// 初始化 LLM 模型 (通常使用较旧的模型或者特定场景)
// 注意:OpenAI 官方也推荐使用 gpt-3.5-turbo 等 ChatModel 来进行文本补全
// 此处为了演示 LLM 类,我们使用 text-davinci-003(如果可用,但通常会提示废弃)
// 或者可以直接用 ChatOpenAI,但传入的不是消息列表,而是字符串。
// 为了避免混淆,我们这里直接用 ChatOpenAI 来模拟 LLM 的文本补全行为,因为更现代。
const llmModelAsChat = new ChatOpenAI({ modelName: "gpt-3.5-turbo", temperature: 0.7 });
const prompt = "请用一句话总结智能客服知识库的核心价值:";
console.log(`输入文本: ${prompt}`);
const responseLlm = await llmModelAsChat.invoke(prompt); // 直接传入字符串
console.log(`LLM 风格回复: ${responseLlm.content}`);
// 预期输出:智能客服知识库通过集中管理信息,快速响应用户查询,提升服务效率和用户满意度。
console.log("\n--- LLM 风格演示结束 ---");
}
runLLMDemo();
通过这些代码,你现在应该对 LangChain 如何与大模型交互有了清晰的认识。对于我们的智能客服小助手项目,ChatModel 将是我们的主力军,因为它能更好地处理对话上下文和角色扮演。
坑与避坑指南
作为一名资深 AI 架构师,我见过无数新手在这里踩坑。别担心,我已经帮你把路上的“地雷”都标记出来了。
API Key 管理:头号大忌!
- 坑:直接把
OPENAI_API_KEY硬编码在代码里,或者上传到 Git 仓库。这简直是在裸奔,分分钟被盗用,然后你的信用卡账单就爆炸了! - 避坑:永远使用环境变量!
.env文件配合dotenv库是最佳实践。在生产环境中,使用云服务商提供的密钥管理服务(如 AWS Secrets Manager, Azure Key Vault, Google Secret Manager)。
- 坑:直接把
LLMvs.ChatModel的选择困境- 坑:纠结到底用哪个?或者为了旧习惯,非要用
LLM去处理多轮对话。 - 避坑:优先使用
ChatModel! 除非你有非常明确的理由(比如对接只能接受纯文本的旧模型),否则现代大模型(尤其是基于 Transformer 架构的)都是为对话而生。ChatModel通过SystemMessage赋予模型“人格”,通过HumanMessage/AIMessage维护上下文,这才是发挥大模型潜力的正确姿势。你的智能客服小助手,99% 的场景都会用到ChatModel。
- 坑:纠结到底用哪个?或者为了旧习惯,非要用
模型参数
temperature的玄学- 坑:不理解
temperature的作用,随便设置一个值,导致模型回复要么过于死板,要么胡言乱语。 - 避坑:
temperature接近0.0:适用于需要准确、事实性、确定性高的场景。例如:从知识库中提取信息、总结报告、代码生成。客服小助手在提供解决方案或信息时,通常会倾向于低temperature,以减少幻觉和不确定性。temperature接近1.0:适用于需要创造性、发散性、新颖性高的场景。例如:写诗、头脑风暴、故事创作。- 经验法则:对于客服应用,
temperature通常设置在0.0到0.5之间。你可以根据实际测试效果微调。
- 坑:不理解
Token 限制与成本意识
- 坑:不了解大模型的 Token 限制,一股脑把所有历史对话和知识库内容都塞进去,结果不是报错就是天价账单。
- 避坑:
- 每个模型都有其上下文窗口限制(例如 GPT-3.5-turbo 可能是 4K, 16K,GPT-4 可能更大)。超出限制会导致模型截断输入或报错。
- Token 消耗直接影响成本。每次 API 调用都会根据输入和输出的 Token 数量计费。
- 策略:对于客服小助手,我们需要智能地管理对话历史(例如,只保留最近几轮对话),并在必要时对知识库内容进行摘要或检索(这会是后续 RAG 章节的重点!)。
错误处理与重试
- 坑:不处理网络错误、API 限流等问题,导致应用崩溃或用户体验差。
- 避坑:LangChain 内部对一些常见的 API 错误有重试机制,但你仍然需要考虑更全面的错误捕获和用户友好提示。例如,当模型返回空内容时,你的客服小助手应该能说一句“抱歉,我暂时无法回答这个问题,请您换个方式提问。”而不是直接报错。
📝 本期小结
恭喜你!本期我们深入探索了 LangChain 与大语言模型交互的核心基石:LLM 和 ChatModel。你现在不仅理解了它们之间的区别,更掌握了如何在智能客服项目中灵活运用 ChatModel 来驱动对话和角色扮演。
我们还一起排查了模型参数 temperature 的奥秘,并学习了如何避开常见的“地雷”,如 API Key 管理、Token 限制和模型选择。记住,对于你的智能客服小助手,ChatModel 配合低 temperature 将是你的黄金组合。
这些知识是构建任何 LangChain 应用的基石。在接下来的课程中,我们将在此基础上,为我们的智能客服小助手添加记忆、工具调用等更高级的能力,让它真正成为一个全能的 AI 助手!
准备好了吗?下一站,我们去探索如何让模型“记住”之前的对话,也就是——记忆(Memory)!那将是你的客服小助手从“傻瓜”到“聪明”的关键一步!