一、从 API 调用到应用开发,中间缺了什么?
如今调用一个大模型 API 已经变得非常简单,几行代码就能拿到回复。但一旦你试图把大模型能力集成到实际产品中,就会发现事情没那么单纯。
1.1 原生 API 开发的三大痛点
痛点一:每家厂商的 SDK 都是"方言"
不同模型服务商提供的接口差异巨大。同样是发送对话请求,OpenAI 用 chat.completions.create,通义千问有自己的参数体系,Claude 的消息结构又完全不同。项目初期接了一家,后期想接入另一家,就意味着从请求构造到响应解析全要重新适配。
痛点二:通用逻辑反复编写
任何稍微正式一点的项目都会面临这些琐碎但必要的工作:
- 网络请求失败后如何自动重试
- Token 超出上下文窗口时怎么截断或摘要
- 多轮对话如何维护历史消息列表
- 系统提示词和用户输入如何组合拼装
这些代码和具体业务无关,但每个项目都得写一遍。
痛点三:高级能力需要自己设计架构
当产品需要以下能力时,开发者几乎要从零开始搭建:
- RAG(检索增强生成):文档怎么分块?向量怎么存?检索结果怎么注入 Prompt?
- Agent(智能体):模型如何自主决定调用哪个工具?执行顺序怎么控制?出错怎么回退?
- 对话记忆:多轮上下文如何管理?摘要怎么做?关键信息怎么提取?
每一项都是一个独立的子系统工程。
1.2 LangChain的解决思路
用一个真实场景(从 GPT-4o 切换到通义千问)来感受差异:更换底层模型需要改动多少代码。
使用 OpenAI 原生 SDK:
from openai import OpenAI client = OpenAI(api_key="sk-xxx") response = client.chat.completions.create( model="gpt-4o", messages=[{"role": "user", "content": "帮我总结这篇文章的核心观点"}] ) print(response.choices[0].message.content)切换到通义千问?整套逻辑要重写:
import dashscope from dashscope import Generation dashscope.api_key = "sk-xxx" response = Generation.call( model="qwen-turbo", messages=[{"role": "user", "content": "帮我总结这篇文章的核心观点"}] ) print(response.output.choices[0].message.content)SDK 包要换、请求方法名要换、参数结构要换、响应解析路径也要换。这不是换个配置能解决的,几乎等于重写。
使用 LangChain :
from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o", api_key="sk-xxx") response = llm.invoke("帮我总结这篇文章的核心观点") print(response.content)切换到通义千问?改一行代码:
from langchain_community.llms import Tongyi import os os.environ["DASHSCOPE_API_KEY"] = os.environ.get("DASHSCOPE_API_KEY", "") llm = Tongyi(model_name="qwen-turbo") response = llm.invoke("帮我总结这篇文章的核心观点") print(response)关键区别在于:在 LangChain 体系中,invoke 之后的所有代码(Prompt 组装、链式编排、输出解析、错误处理)完全不需要修改。模型切换被隔离在了初始化那一行。
二、LangChain 提供的核心价值
用一个比喻来理解:LangChain 是大模型世界的"适配器 + 工具箱"。
它解决的问题很聚焦:在所有大模型服务之上建立统一的调用规范。开发者基于这个规范编写的业务逻辑,不依赖于任何具体模型供应商。
价值维度 | 具体体现 |
模型无关 | 统一 |
组件库 | Prompt 模板、输出解析器、记忆管理、工具定义等常见需求 都有内置实现 |
流程编排 | 通过 LCEL 语法用管道操作符连接各个组件,流程可视化 |
工程能力 | 内置流式响应、重试机制、回调追踪等生产级特性 |
三、主流 LLM 开发框架横向对比
在选型之前,有必要了解 LangChain 在整个生态中的位置。下面整理了几个常见的开发方案,帮助你根据项目特点做出判断。框架速览:
LangChain:
目前社区规模最大的 LLM 应用框架。它的定位是提供一个"什么都能做"的工具集合——模型接入、向量存储、链式编排、Agent 系统一应俱全。适合需要快速验证想法、频繁更换组件的通用场景。
需要注意:框架更新频率较高,偶尔会有接口变动。对于只需要简单 Prompt → Response 的项目来说,可能显得有些臃肿。
LlamaIndex:
专注于数据检索与大模型的结合。如果你在做的是文档问答、知识库搜索这类以检索为核心能力的应用,LlamaIndex 提供的索引策略(向量索引、关键词索引、图谱索引等)和数据连接器(支持 PDF、数据库、网页等多种数据源)会非常实用。
它的短板在于非检索场景(比如纯 Agent 应用)的能力不如 LangChain 完善。
Semantic Kernel:
微软推出的 AI 开发框架,设计理念偏向企业级工程实践。插件系统清晰(Prompt 和原生函数统一定义为 Plugin),Planner 组件可以让大模型自动拆解任务。与 Azure OpenAI 服务集成尤为方便。
适合微软技术栈团队,但国内社区规模较小,遇到问题时参考资料有限。
Haystack:
一个较早出现的 NLP 管道框架,在大模型流行之前就已经在检索增强领域有积累。它的 Pipeline 架构设计清晰,各组件(检索器、排序器、生成器)边界明确,内置的评估工具可以帮助量化 RAG 效果。
缺点是面向大模型原生的特性(如 Function Calling、多轮对话管理)支持不如 LangChain 活跃,且中文社区很小。
直接调用原生 API:
不使用任何框架,通过 HTTP 请求直接调用模型服务。方案最轻量,没有任何额外依赖。适合只需要单次对话交互的极简场景。
一旦项目需要加入检索、记忆、Agent 等能力,这些功能都得自己从头开发。
如何做出选择:
你的情况 | 建议方案 |
要快速搭建一个包含多种能力的 LLM 应用 | LangChain |
核心需求是文档检索 + 问答 | LlamaIndex |
团队主要使用微软技术栈,需要 Planner 能力 | Semantic Kernel |
已有成熟架构,只需要偶尔调用模型 | 原生 API |
实际工程实践中,框架并非互斥。不少团队会同时使用 LangChain 和 LlamaIndex:用 LlamaIndex 负责检索层,用 LangChain 负责应用编排层。 关于就业市场,从国内招聘平台的数据来看,提到 LangChain 的岗位数量远超其他框架。这反映出企业对 LangChain 的认可度最高,也意味着学习 LangChain 在职场上的实用价值更大。
四、LangChain 的模块化架构
很多人一开始把 LangChain 当作一个单独的库,实际上它是一整套工具生态。从底层接口定义到生产部署监控,每个子项目负责不同环节。
核心包分工:
langchain-core:底层协议层
整个生态的基石。它定义了所有基础抽象接口——模型接口(BaseChatModel)、检索器接口(BaseRetriever)、可执行协议(Runnable)。这个包不包含任何具体模型的实现,只规定"接口长什么样"。正因为没有业务逻辑,它的 API 非常稳定,极少出现破坏性更新。
langchain-community:第三方适配器集合
你想接入的任何服务,几乎都能在这里找到封装好的类。包括各厂商的模型(OpenAI、通义千问、DeepSeek)、向量数据库(Chroma、Milvus、FAISS)、文档解析器(PDF、Word、网页爬取)、工具封装(搜索、代码执行、API 调用)等。这个包由社区维护,更新频繁,覆盖范围广。
langchain(主包):高级应用组件
在 core 和 community 之上,主包提供了开箱即用的应用模板。比如预置的对话检索链(ConversationalRetrievalChain)、各类 Agent 实现(ReAct、StructuredChat)、记忆管理器(ConversationBufferMemory、ConversationSummaryMemory)。它让你不需要从头拼装底层组件就能快速搭建完整应用。
配套工具矩阵:
除了核心代码包,LangChain 生态还有几个配套工具,覆盖从开发到部署的完整生命周期:
LangGraph:复杂工作流编排
传统的链式结构是线性的——从 A 到 B 到 C。但很多场景需要更灵活的控制流:
- Agent 需要反复思考、行动、观察结果的循环
- 某些步骤需要根据条件跳转到不同分支
- 关键操作需要人工审核确认后再继续
LangGraph 用图结构(节点表示操作,边表示流转关系)和状态管理来解决这些问题。它本质上是一个有状态的工作流引擎。
LangServe:服务化部署
开发完的 Chain 或 Runnable,如何快速提供给其他系统调用?LangServe 可以把它们一键转换为 REST API,自动生成 invoke(单次调用)、stream(流式输出)、batch(批量处理)等端点,还附带 OpenAPI 规范文档。不需要额外写 FastAPI 或 Flask 代码。
LangSmith:观测与调试平台
LLM 应用最难的部分是排查问题——模型返回了什么?哪一步耗时最长?Token 消耗了多少?LangSmith 提供完整的执行追踪能力,记录每次调用的输入、输出、中间步骤、性能指标。还支持 Prompt 版本管理和效果评估(Evals),适合生产环境的持续优化。
使用场景速查:
你的需求 | 需要的组件 |
调用某个模型的 API | langchain-core + langchain-community |
快速搭建 RAG 或 Agent 应用 | langchain 主包 |
Agent 需要循环决策或人工介入 | langgraph |
把应用发布为 HTTP 接口 | langserve |
线上问题排查或效果评估 | langsmith |
从零创建项目骨架 | langchain-cli |
实际项目中这些工具经常组合使用。一个典型的架构可能是:用 langchain 写业务逻辑,用 langgraph 管理 Agent 循环,用 langserve 部署上线,用 langsmith 监控运行状态。
五、快速上手:LangChain 安装与模型调用
在深入理解架构之前,先让代码跑起来。
版本说明:LangChain 的包结构在 1.0 版本经历了一次重大调整。本教程基于 1.x 版本编写,以下是关键变化:langchain.memory、langchain.chains 等传统模块已从主包移除,迁移到了独立的 langchain-classic 包。如果看到 ModuleNotFoundError: No module named langchain.memory 这类错误,需要安装 langchain-classic,并将 import 路径改为 from langchain_classic.memory import ...如果想沿用旧写法不改 import,可以降级到 langchain<1.0(推荐 0.3.x)
安装步骤: # 安装 LangChain 核心库(1.x) pip install "langchain>=1.0" "langchain-core>=1.0" # 安装第三方集成支持(模型、向量库、文档加载器等) pip install "langchain-community>=0.3" # 安装传统 Chain / Memory API(如需使用 ConversationBufferMemory 等) pip install langchain-classic # 按需安装模型集成包 pip install langchain-openai # OpenAI 兼容模型 pip install dashscope # 通义千问官方 SDK调用通义千问:
from langchain_community.llms import Tongyi import os # 从环境变量读取 API Key os.environ["DASHSCOPE_API_KEY"] = os.environ.get("DASHSCOPE_API_KEY", "") # 初始化模型 llm = Tongyi( model_name="qwen-turbo", temperature=0.7, top_p=0.8, max_tokens=2000 ) # 发起调用 response = llm.invoke("介绍一下Python语言") print(response)调用deepseek:
from langchain_deepseek import ChatDeepSeek import os os.environ["DEEPSEEK_API_KEY"] = os.environ.get("DEEPSEEK_API_KEY", "") llm = ChatDeepSeek(model="deepseek-chat", temperature=0.7) response = llm.invoke("介绍一下Python语言") print(response)调用豆包(火山方舟):
from langchain_openai import ChatOpenAI import os llm = ChatOpenAI( model="doubao-seed-1-8-251228", openai_api_key=os.environ.get("VOLC_API_KEY"), openai_api_base="https://ark.cn-beijing.volces.com/api/v3", max_tokens=2048, temperature=0.7, streaming=True ) # 流式输出 for chunk in llm.stream("用通俗的话解释一下:什么是LangChain?"): text = getattr(chunk, "content", chunk) if isinstance(text, list): text = "".join( item.get("text", "") for item in text if isinstance(item, dict) and item.get("type") == "text" ) if text: print(text, end="", flush=True) print()六、Token介绍
Token 是大模型处理文本的最小单位,理解它对于控制成本和输出长度非常关键。Token 不等于字符,模型不会按字符处理文本,而是按 Token 切分:
- 中文:1 个汉字约等于 1~2 个 Token
- 英文:1 个单词约等于 1~2 个 Token
- 数字和符号:通常 1 个字符 = 1 个 Token
为什么需要关注 Token?
成本控制:API 按 Token 数量计费,不是按字符数。
长度限制:max_tokens 参数控制的是Token 数量,不是字数。如果设置为 2000,中文大约能生成 1000~1500 字。
上下文窗口:每个模型有最大 Token 限制(如 128K),包括输入 Prompt 和输出回复的总和。超出限制会报错或被截断。
动手计算:一段文本消耗多少 Token。通过 tiktoken 库可以准确计算文本的 Token 数量。
pip install tiktoken""" Token 计数示例 - 了解文本消耗多少 Token """ import tiktoken # 使用 cl100k_base 编码(GPT-3.5/4 系列模型的 tokenizer) encoding = tiktoken.get_encoding("cl100k_base") # ========== 示例1:中文古诗 ========== text_cn = "床前明月光,疑是地上霜" tokens_cn = encoding.encode(text_cn) print(f"中文文本: {text_cn}") print(f"Token数量: {len(tokens_cn)}") print() # ========== 示例2:英文句子 ========== text_en = "The quick brown fox jumps over the lazy dog" tokens_en = encoding.encode(text_en) print(f"英文文本: {text_en}") print(f"Token数量: {len(tokens_en)}") print() # ========== 示例3:代码片段 ========== text_code = "def hello(): print('Hello World')" tokens_code = encoding.encode(text_code) print(f"代码片段: {text_code}") print(f"Token数量: {len(tokens_code)}") print() # ========== 示例4:多轮对话的 Token 消耗 ========== messages = [ {"role": "system", "content": "你是一个翻译助手"}, {"role": "user", "content": "把这句话翻译成英文:人工智能正在改变世界"}, {"role": "assistant", "content": "Artificial intelligence is changing the world."} ] total_tokens = 0 for msg in messages: content = msg["content"] tokens = encoding.encode(content) total_tokens += len(tokens) print(f"{msg['role']}: {len(tokens)} tokens") print(f"\n总Token数: {total_tokens}")执行结果:
中文文本: 床前明月光,疑是地上霜 Token数量: 16 英文文本: The quick brown fox jumps over the lazy dog Token数量: 9 代码片段: def hello(): print('Hello World') Token数量: 8 system: 11 tokens user: 26 tokens assistant: 8 tokens 总Token数: 45 (base) PS D:\learn_claude_code>从这个结果可以看出:
- 中文文本的 Token 消耗量明显高于英文(10 个汉字、一个标点 = 16 个 Token)
- 代码片段的 Token 效率较高,关键符号(括号、引号等)各占一个 Token
- 一次简单的三轮对话,仅输入部分就消耗了 45 个 Token(不含模型调用)
获取 API 调用实际消耗的 Token 数。调用完成后,模型返回的响应中会包含实际消耗的 Token 统计。
from langchain_community.chat_models import ChatTongyi from langchain_core.messages import HumanMessage import os os.environ["DASHSCOPE_API_KEY"] = os.environ.get("DASHSCOPE_API_KEY", "") chat_model = ChatTongyi(model_name="qwen-turbo", temperature=0) response = chat_model.invoke([HumanMessage(content="用三句话解释什么是人工智能")]) print(f"回复: {response.content}") # 从返回消息中读取 token usage(不同版本/模型字段名可能略有差异) usage = None for key in ("usage_metadata", "response_metadata", "token_usage"): value = getattr(response, key, None) if value: usage = value break print(f"\n--- Token统计 ---") print(usage)回复: 人工智能是计算机科学的一个分支,旨在开发能够模拟人类智能行为的系统和程序。 它通过机器学习、深度学习等技术,使计算机具备感知、推理和决策的能力。 如今,人工智能已广泛应用于医疗、交通、金融等多个领域。 --- Token统计 --- {'input_tokens': 14, 'output_tokens': 89, 'total_tokens': 103}这段代码演示了如何从 LangChain 返回的 AIMessage 对象中提取 Token 使用数据。不同模型供应商的字段名可能不同,常见的有 usage_metadata、response_metadata、token_usage。注意 input_tokens 是 14(包含 system prompt + user prompt 的开销),output_tokens 是 89(模型生成的三句话)。
Token 优化建议:
- 精简提示词:去掉冗余描述,减少输入 Token 消耗
- 合理设置 max_tokens:根据实际需求限制输出长度,避免浪费
- 压缩对话历史:多轮对话中只保留关键信息,定期做摘要
- 按需选模型:简单任务用 turbo/mini 版本,复杂任务再用旗舰款
七、第一章上半部分总结
直接调用大模型 API 虽然简单,但面临三大痛点:各家 SDK 接口互不兼容、通用逻辑(重试、截断、历史维护)反复编写、高级能力(RAG、Agent)需要从零设计架构。通过 GPT-4o 切换到通义千问的对比可以看到,原生 SDK 切换模型几乎等于重写,而 LangChain 只需修改初始化那一行代码,后续业务逻辑完全不变。
LangChain 的本质是在所有大模型服务之上建立统一的调用规范,提供"适配器 + 工具箱"的能力——模型无关、组件丰富、流程可编排、工程能力完善。
在框架选型上,文章对比了 LlamaIndex、Semantic Kernel、Haystack 和原生 API,LangChain 在生态规模和就业市场占据绝对优势。但实际项目中框架并非互斥,不少团队会同时使用 LangChain 和 LlamaIndex。
在动手实操部分,我们完成了 LangChain 的安装、四种不同模型的调用(通义千问、DeepSeek、豆包、Ollama),并学习了常用参数的含义和使用建议。同时深入了解了 Token 的概念,通过 tiktoken 库计算了中英文和代码的 Token 消耗,并从 API 响应中提取了实际的 Token 统计数据。