1. 从一个具体的需求场景说起最近在做一个智能客服的原型需要让系统能根据用户的问题自动去查询内部知识库然后组织语言回答。最开始的想法很简单不就是调用一下大模型的API把问题和查到的资料拼在一起发过去再把返回的结果展示出来吗听起来像是一个字符串拼接加HTTP请求的活儿。但真动手做起来才发现这里面的水有多深。比如用户问“你们公司的退货政策是什么”。我首先得从一堆PDF、Word文档和网页里找到关于“退货政策”的片段。这涉及到文档加载、文本分割。然后我不能把找到的所有内容都一股脑塞给大模型因为大模型有上下文长度限制而且无关信息会干扰判断这就需要做“检索”。检索出来的内容怎么和用户的问题一起组合成一个能让大模型理解并高质量回答的“提示词”Prompt这又是一个学问。最后调用大模型API拿到回复可能还需要对回复进行后处理比如提取关键信息、格式化输出。整个过程涉及文档加载、文本分割、向量化存储、语义检索、提示词工程、大模型调用、输出解析等多个环节。如果每个环节都自己从头写不仅工作量巨大而且会陷入各种细节的泥潭文本分割用按字符还是按语义向量数据库选哪个提示词怎么设计效果最好不同大模型的API调用方式还不一样……就在我对着requests库和一堆正则表达式头疼的时候LangChain进入了视野。它不是一个具体的AI模型而是一个框架一个“胶水”和“脚手架”。它的核心价值在于把上述这些构建AI应用所必需的、繁琐且通用的组件进行了标准化封装和串联。它定义了一套清晰的接口和概念让你可以像搭积木一样快速组合出功能复杂的AI应用而不用关心每个“积木”内部复杂的实现。你可以把LangChain理解为AI应用开发领域的“Spring Framework”它负责管理流程、集成组件让你专注于业务逻辑。所以当你看到“使用LangChain来调用AI大模型”这个标题时它的内涵远不止发送一个API请求那么简单。它关乎如何系统化、工程化地去构建一个以大型语言模型LLM为核心的智能应用。接下来我将从一个实践者的角度带你深入LangChain的核心看看它如何让“调用大模型”这件事变得高效、可控且强大。2. LangChain的核心架构不只是“调用”而是“编排”很多人对LangChain的第一印象是“一个用来调用OpenAI API的Python库”。这个理解太片面了也低估了它的价值。LangChain的野心在于成为LLM应用开发的操作系统。要理解它必须先理清其最核心的几个抽象概念它们构成了LangChain的骨架。2.1 基石Model I/O模型输入/输出这是最贴近“调用大模型”的一层但它做了关键的统一抽象。LLMs大语言模型 代表那些接收文本、返回文本的模型比如GPT-4、Claude、文心一言、通义千问等。LangChain提供了LLM基类以及对应各种供应商OpenAI, Anthropic, 百度等的封装如ChatOpenAI。你不再需要记忆每个API不同的参数名而是通过统一的invoke()或generate()方法来调用。from langchain_openai import ChatOpenAI # 初始化一个ChatGPT模型 llm ChatOpenAI(modelgpt-4, temperature0.7) # 统一调用方式 response llm.invoke(你好请介绍一下你自己。) print(response.content)Chat Models聊天模型 这是LLMs的一个特化子类专门为多轮对话设计。它的输入和输出不是简单的字符串而是结构化的消息列表比如SystemMessage,HumanMessage,AIMessage。这更符合实际应用场景。from langchain_core.messages import HumanMessage, SystemMessage messages [ SystemMessage(content你是一个专业的科技文章翻译助手。), HumanMessage(content请将以下英文翻译成中文LangChain is a framework for developing applications powered by language models.) ] response llm.invoke(messages) print(response.content) # 输出LangChain是一个用于开发由语言模型驱动的应用程序的框架。Prompt Templates提示词模板 这是LangChain解决“字符串拼接”问题的利器。它允许你创建带有变量的模板将用户输入、上下文数据等动态地注入到固定的提示词结构中避免代码中充斥杂乱的字符串格式化操作。from langchain_core.prompts import ChatPromptTemplate # 定义一个提示词模板 template ChatPromptTemplate.from_messages([ (system, 你是一个擅长{style}风格的诗人。), (user, 请以{style}风格写一首关于{topic}的诗。) ]) # 将变量填充到模板中生成最终的消息列表 prompt template.invoke({style: 豪放, topic: 泰山}) # 将生成的消息列表直接发给模型 response llm.invoke(prompt) print(response.content)为什么这样设计统一接口意味着你的核心业务代码与具体的大模型供应商解耦。今天你用OpenAI明天想换成国产的DeepSeek或智谱AI理论上你只需要换一行初始化模型的代码后面的调用逻辑完全不变。这极大地提升了代码的可维护性和可移植性。2.2 记忆Memory让对话拥有“上下文”单纯的单次问答无法构成智能对话。Memory组件负责在多次交互中持久化和管理对话历史。ConversationBufferMemory 最简单的记忆只是把之前的对话内容全部缓存起来作为上下文传递给下一次调用。缺点是上下文会越来越长可能触发模型token限制。ConversationBufferWindowMemory 只保留最近K轮对话像一个滑动窗口解决了上下文膨胀的问题。ConversationSummaryMemory 更高级的策略。它不会传递所有历史记录而是让大模型自动对之前的对话进行总结然后将这个总结作为新的上下文。这能极大地压缩token消耗保留对话的核心脉络。在LangChain中Memory通常与Chain或Agent结合使用它们会自动从Memory中读取历史并将新的输入输出写入Memory开发者无需手动拼接历史消息。2.3 链Chains将组件“链接”成工作流这是LangChain的灵魂所在。如果说Model I/O是零件那么Chain就是组装线。一个Chain是一个预先定义好的、对组件的调用序列。最简单的链是LLMChain它组合了一个提示词模板和一个LLM。但Chain的强大在于其组合性。你可以创建复杂的链例如SequentialChain顺序链让一个链的输出作为另一个链的输入。这正是解决我们开头“智能客服”场景的关键。假设我们要构建一个“翻译并总结”的链先让模型将一段英文翻译成中文再让另一个模型或同一个模型对中文内容进行总结。from langchain.chains import LLMChain, SequentialChain from langchain_core.prompts import PromptTemplate # 定义第一个链翻译 translation_template PromptTemplate( input_variables[english_text], template将以下英文翻译成地道的中文{english_text} ) translation_chain LLMChain(llmllm, prompttranslation_template, output_keychinese_text) # 定义第二个链总结 summary_template PromptTemplate( input_variables[chinese_text], template用一句话总结以下中文内容{chinese_text} ) summary_chain LLMChain(llmllm, promptsummary_template, output_keysummary) # 组合成顺序链 overall_chain SequentialChain( chains[translation_chain, summary_chain], input_variables[english_text], # 整个链的输入 output_variables[chinese_text, summary], # 整个链的输出 verboseTrue # 打印执行过程调试时非常有用 ) # 运行 result overall_chain.invoke({english_text: Artificial Intelligence is transforming industries by automating complex tasks and providing>pip install langchain langchain-openai langchain-community chromadb pypdflangchain: 核心框架。langchain-openai: OpenAI模型的官方集成。langchain-community: 包含大量第三方集成如文档加载器。chromadb: 轻量级本地向量数据库。pypdf: 用于读取PDF文件。确保你已设置好OpenAI的API密钥可以通过环境变量设置export OPENAI_API_KEY你的-api-key或者在代码中设置import os os.environ[“OPENAI_API_KEY”] ‘你的-api-key’3.2 步骤一文档加载与处理假设我们有一个名为company_handbook.pdf的公司手册PDF文件。from langchain_community.document_loaders import PyPDFLoader from langchain_text_splitters import RecursiveCharacterTextSplitter # 1. 加载文档 loader PyPDFLoader(“./company_handbook.pdf”) documents loader.load() print(f”加载了 {len(documents)} 页文档。”) # 2. 分割文本 text_splitter RecursiveCharacterTextSplitter( chunk_size500, # 每个块的最大字符数 chunk_overlap50, # 块之间的重叠字符数避免语义断裂 length_functionlen, separators[“\n\n”, “\n”, “。”, “”, “”, “,”, ” “, “”] # 分割符优先级 ) chunks text_splitter.split_documents(documents) print(f”将文档分割成了 {len(chunks)} 个文本块。”)关键参数解析chunk_size500 这个值需要权衡。太小可能丢失上下文太大会导致检索不精准且消耗更多token。对于通用知识500-1000是个不错的起点。chunk_overlap50 重叠是为了防止一个完整的句子或概念被硬生生切在两块之间保证检索时边界信息的连续性。3.3 步骤二向量化与存储接下来我们将文本块转换成向量并存入Chroma数据库。from langchain_openai import OpenAIEmbeddings from langchain_chroma import Chroma # 初始化Embedding模型 embeddings OpenAIEmbeddings(model“text-embedding-3-small”) # 创建向量数据库。persist_directory指定持久化目录否则数据只在内存中。 vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, persist_directory“./chroma_db” # 数据将保存在本地chroma_db文件夹 ) print(“向量数据库创建并持久化完成。”) # 从此处开始我们可以从持久化的目录加载数据库无需重新生成向量 # vectorstore Chroma(persist_directory“./chroma_db”, embedding_functionembeddings)3.4 步骤三构建检索链现在我们创建一个检索器并将其与LLM组合成一个问答链。from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA from langchain_core.prompts import PromptTemplate # 初始化LLM llm ChatOpenAI(model“gpt-3.5-turbo”, temperature0) # 从向量库创建检索器 retriever vectorstore.as_retriever( search_type“similarity”, # 相似性搜索 search_kwargs{“k”: 4} # 返回最相关的4个块 ) # 自定义提示词模板告诉模型基于上下文回答 prompt_template “””请仅根据以下提供的上下文信息来回答问题。如果上下文信息不足以回答问题请直接说“根据已知信息无法回答该问题”不要编造信息。 上下文 {context} 问题{question} 请用中文给出答案””” PROMPT PromptTemplate( templateprompt_template, input_variables[“context”, “question”] ) # 创建检索问答链 qa_chain RetrievalQA.from_chain_type( llmllm, chain_type“stuff”, # 最常用的类型将所有检索到的文档“塞”进提示词 retrieverretriever, chain_type_kwargs{“prompt”: PROMPT}, # 使用我们自定义的提示词 return_source_documentsTrue # 返回源文档便于追溯和调试 )关键点解析chain_type“stuff” 这是最简单的RAG链类型它把检索到的所有文档内容拼接起来放入提示词的{context}占位符。优点是简单直接缺点是有可能超过模型的上下文窗口。其他类型如map_reduce,refine可以处理更长的文档但更复杂。自定义提示词 这是减少模型幻觉、提升答案准确性的关键。明确的指令“仅根据上下文…”能极大约束模型的行为。在实际项目中需要精心设计和迭代优化提示词。3.5 步骤四提问与测试现在我们可以向这个知识库提问了。# 提问 question “我们公司的年假政策是怎样的” result qa_chain.invoke({“query”: question}) print(f”问题{question}”) print(f”答案{result[‘result’]}”) print(“\n 参考来源 ) for i, doc in enumerate(result[‘source_documents’]): print(f”[{i1}] 片段内容前200字符: {doc.page_content[:200]}…”) print(f” 来源{doc.metadata.get(‘source’, ‘N/A’)} 第{doc.metadata.get(‘page’, ‘N/A’)}页\n”)运行这段代码系统会从向量库中检索与“年假政策”相关的文本片段将它们与问题一起填入提示词模板发送给GPT-3.5并返回基于文档的答案。同时我们还能看到答案具体来源于哪几个文档片段这提供了可解释性。4. 避坑指南与进阶思考在真实项目中应用LangChain你会遇到比示例更多的问题。以下是一些常见的“坑”和应对策略。4.1 文本分割的“艺术”与“科学”文本分割是RAG效果的基石但并没有银弹。坑1固定长度分割切断语义。一个完整的操作步骤或概念描述可能被切成两半导致检索到的片段信息不全。对策 优先使用RecursiveCharacterTextSplitter并调整separators顺序让它优先按段落、句子分割。对于代码、Markdown等结构化文本使用专用的分割器如MarkdownHeaderTextSplitter。坑2分割过细导致信息碎片化。每个chunk包含的信息太少模型缺乏足够的上下文来理解。对策 适当增大chunk_size例如1000-2000字符。同时可以尝试语义分割使用嵌入模型计算句子间的语义变化在语义边界处进行分割如SemanticChunker但这会显著增加处理时间。经验之谈 没有最好的分割策略只有最适合你数据类型的策略。务必在构建完向量库后用一些典型问题测试检索结果观察返回的chunk是否完整、相关。这是一个需要反复试验和调整的过程。4.2 检索质量优化超越简单相似度默认的向量相似度搜索similarity有时不够精准。问题 用户问“如何报销”可能检索到的是“财务报销制度总则”、“去年报销数据统计”等片段而最关键的“报销流程步骤”可能因为表述不同而排名靠后。对策1混合搜索Hybrid Search。结合语义搜索向量相似度和关键词搜索如BM25。Chroma和Weaviate等数据库支持此功能。关键词搜索能保证术语的精确匹配语义搜索能保证意图的匹配两者结合效果更鲁棒。retriever vectorstore.as_retriever( search_type“similarity_score_threshold”, # 按分数阈值过滤 search_kwargs{“k”: 10, “score_threshold”: 0.7} # 先取10个再过滤分数0.7的 )对策2重排序Re-ranking。先用向量检索出Top K个比如20个候选文档然后使用一个更精细但更慢的重排序模型如Cohere的rerank或BGE的交叉编码器对这20个文档进行精排选出最相关的3-4个。这能显著提升最终答案的质量但会增加延迟和成本。LangChain可以与CohereRerank等组件轻松集成。4.3 提示词工程从“能用”到“好用”我们之前用的提示词只是一个基础版本。要让模型回答得更精准、格式更统一需要精心设计提示词。结构化输出 要求模型以JSON、XML或特定格式返回便于后续程序处理。prompt_template “”” 请根据上下文回答问题并以JSON格式输出包含’answer’和’confidence’两个字段。 上下文{context} 问题{question} JSON输出 “””少样本学习Few-shot 在提示词中提供几个输入输出的例子引导模型遵循特定的回答风格或逻辑。prompt_template “”” 你是一个严谨的法律顾问。请根据提供的法律条文片段回答问题。 示例 问题合同违约的后果是什么 上下文根据《合同法》第107条当事人一方不履行合同义务或者履行合同义务不符合约定的应当承担继续履行、采取补救措施或者赔偿损失等违约责任。 回答根据《合同法》第107条违约方需要承担继续履行、采取补救措施或赔偿损失等责任。 现在请回答真实问题 上下文{context} 问题{question} 回答 “””链式提示Chain of Thought 对于复杂问题提示模型“一步一步思考”把推理过程也输出这能提升复杂逻辑问题的准确性。4.4 生产环境部署的考量Demo跑通只是第一步要上线还需考虑异步与流式响应 LangChain支持异步调用ainvoke,astream对于Web应用使用异步可以避免阻塞提升并发能力。流式响应stream可以将大模型的回答逐词返回提升用户体验。可观测性与监控 你需要监控链的每一步检索到了哪些文档提示词最终长什么样模型调用的耗时和token消耗是多少答案是否准确LangChain提供了callbacks机制可以方便地集成日志、追踪如LangSmith和监控工具。成本控制 大模型API调用和Embedding是按token计费的。需要监控token使用量优化提示词长度合理设置chunk_size并对用户请求进行限流和配额管理。版本管理与实验 当你调整分割策略、提示词、模型参数时如何评估效果如何回滚使用LangChain的LangSmith平台商业产品或自行搭建评估体系如基于准确率、相关性打分是必要的。5. LangChain vs. LangGraph vs. 其他框架在社区中LangGraph和CrewAI也常被提及它们与LangChain是什么关系LangChain 核心是链Chains适用于定义明确的、顺序执行的线性工作流。它的抽象层次高开发效率高是构建大多数RAG和简单Agent应用的绝佳起点。LangGraph 可以看作是LangChain的“升级版”或“补充”它基于图Graph的概念。在LangGraph中你将应用定义为一个有状态图节点是函数或工具边是条件流转。这特别适合描述复杂的、有循环、有分支的多智能体Multi-Agent工作流。例如一个评审流程Agent A写稿 - Agent B评审 - 如果通过则结束否则返回给A修改。这种带循环和状态判断的流程用LangGraph来描述比用LangChain的SequentialChain要清晰和强大得多。简单说LangChain擅长“流水线”LangGraph擅长“流程图”。CrewAI 是一个更上层的、专注于多智能体协作的框架。它基于LangChain构建提供了更高阶的抽象比如“角色”Role、“任务”Task、“流程”Process。它让你可以像组建一个团队一样定义不同角色的AI Agent如研究员、写手、校对员并为他们分配任务和设定协作流程。CrewAI内部可能使用LangGraph来编排这些Agent的工作流。如何选择如果你是初学者或构建标准的RAG、简单工具调用应用从LangChain开始。如果你需要构建包含复杂决策循环、状态持久化、多路径选择的应用如游戏NPC、复杂决策系统深入学习和使用LangGraph。如果你想快速搭建一个分工明确的多AI智能体团队来完成复杂项目如自动研究并撰写报告可以评估CrewAI。至于Dify、FastGPT等产品它们属于低代码/无代码的AI应用平台。它们提供了可视化界面封装了模型、知识库、工作流等能力让非开发者也能通过拖拽搭建AI应用。而LangChain/LangGraph是面向开发者的代码框架提供了最大的灵活性和控制力但需要编程能力。两者是不同赛道的工具。6. 总结与个人体会绕了一大圈再回到最初的标题“使用LangChain来调用AI大模型”。现在你应该明白这绝不仅仅是一个API封装库。它是一个完整的开发范式迫使你以结构化的方式去思考AI应用你的数据在哪怎么处理模型如何与数据交互任务流程是什么是否有记忆是否需要自主决策我个人从早期的“手搓”管道切换到LangChain后最大的感受是开发效率的质变和心智负担的减轻。我不再需要关心不同向量数据库的SDK差异不再需要手动管理复杂的对话历史拼接也能快速实验不同的检索策略和提示词模板。它的模块化设计使得调试、替换组件比如换一个Embedding模型变得非常容易。然而LangChain也并非没有缺点。其抽象层较多初期学习曲线较陡。在极端性能敏感的场景下其额外的封装可能带来轻微开销。但对于绝大多数旨在快速构建可靠、可维护AI应用的项目来说它的价值远大于这些成本。最后给初学者的建议不要试图一开始就掌握LangChain的所有细节。从解决一个具体问题开始比如本文的本地知识库问答把核心流程Load - Split - Embed - Store - Retrieve - Generate跑通。然后再逐步深入每个环节的调优分割策略、检索算法、提示词工程最后再去探索更高级的Agent和LangGraph。在这个过程中你会自然而然地理解这个框架的精髓并能够用它来释放大模型的真正潜力。