这篇我按“先跑起来、再讲取舍”的方式写《会用LangChain只是起点能解释失败才算真正入门》。概念会讲但重点放在代码怎么组织、哪里容易踩坑。摘要先把这篇文章的目标说清楚看完之后你应该能判断这件事值不值得做以及从哪里动手。最近面试了不少转做大模型应用的开发者发现一个普遍现象大家的 Demo 都能跑RAG 检索也能出答案但一旦提到“生产环境”、“权限控制”或者“全链路追踪”很多人就卡壳了。这其实不是能力问题而是思维惯性。在学校或自学阶段我们习惯于print(response)这种线性调试但在企业级应用中Agent 不再是单线程脚本它是并发执行、涉及外部工具调用、需要严格审计的复杂系统。今天不聊虚的概念直接从 LangChain 实战的角度拆解如何从一个“能跑通的 Prompt 调用”进化到一个“可观测、可控的工程化应用”。我会结合最近踩过的坑分享一套从 Junior 到 Senior 的进阶路径。目录别一上来就写 Chain先搞清楚 LangChain 到底解决了什么核心组件不仅仅是 LLMChain项目实战构建一个具备可观测性的 Agent从 Demo 到工程化你需要补齐的能力栈总结别一上来就写 Chain先搞清楚 LangChain 到底解决了什么很多初学者拿到 LangChain第一反应是封装 API。其实 LangChain 的核心价值不在于帮你调接口而在于编排Orchestration。它解决的是三个核心痛点1. 标准化交互统一不同 LLM Provider 的输入输出格式。2. 状态管理让对话历史、工具调用结果能在 Chain 中流转。3. 可观测性基础通过 Tracing 机制让你看到每一步发生了什么而不仅仅是最后的结果。如果你只是简单封装了一个get_answer()函数那根本不需要 LangChain。只有当你需要串联 Prompt - LLM - Parser - Tool - LLM 这种复杂逻辑时LangChain 的Chain和Agent概念才有意义。核心组件不仅仅是 LLMChain在构建应用时我对 LangChain 组件的使用是有取舍的。早期版本喜欢用LLMChain但现在我更推荐组合使用ChatModel、PromptTemplate和OutputParser。1. Prompt 工程的工程化Prompt 不是写死的字符串它是代码的一部分。from langchain_core.prompts import ChatPromptTemplate # 错误做法硬编码 Prompt prompt 你是一个助手请回答{question} # 正确做法结构化 Prompt分离系统指令与用户输入 template You are an expert financial assistant. Context: {context} Question: {question} Rules: 1. Only use provided context. 2. If context is empty, say I dont know. 3. Cite sources if available. Answer: prompt ChatPromptTemplate.from_template(template)在实际项目中我发现很多 Bug 源于 Prompt 缺乏边界约束。比如模型 hallucination幻觉往往是因为没有明确告诉它“不知道”时的行为。2. 工具调用Tool Calling的陷阱这是从 Demo 走向生产的关键分水岭。很多开发者写的 Agent 能调工具但无法处理工具报错、权限校验或循环调用。以搜索工具为例简单的实现可能长这样from langchain_core.tools import tool tool def search_web(query: str): Search the web for current information. # 假设这里直接调用了 API return fResults for {query}但在生产环境中你必须考虑超时处理搜索 API 挂了怎么办速率限制每分钟调用次数限制安全性是否允许调用敏感接口项目实战构建一个具备可观测性的 Agent为了让大家直观感受差异我重构了一个常见的“客服问答 Agent”。重点在于引入LangSmith风格的日志记录和异常捕获机制而非仅仅关注结果。场景描述我们需要一个 Agent它能接收用户问题检索知识库模拟 RAG并根据预设规则回答。关键在于当检索失败或模型输出不符合规范时系统要有明确的降级策略并能记录完整链路供后续排查。代码实现注重健壮性的 Agent 结构import logging from typing import List, Dict, Any from langchain_core.messages import HumanMessage, AIMessage from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser # 配置日志替代 print便于后续接入 ELK 或 Sentry logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class RobustSupportAgent: def __init__(self): self.llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) self.prompt ChatPromptTemplate.from_messages([ (system, You are a support agent. Answer based strictly on the provided context.), (human, Context:\n{context}\n\nUser Question:\n{question}) ]) # 使用 RunnablePassthrough 进行链式编排而非简单的 LCEL self.chain self.prompt | self.llm | StrOutputParser() def retrieve_context(self, question: str) - str: 模拟 RAG 检索实际项目中应连接 Vector DB logger.info(fRetrieving context for query: {question}) # 这里可以加入重试机制、缓存查询等工程化逻辑 return The refund policy allows returns within 30 days. def run(self, user_question: str) - Dict[str, Any]: 执行 Agent 逻辑包含完整的异常处理和日志记录 start_time __import__(time).time() try: # 1. 获取上下文 context self.retrieve_context(user_question) # 2. 构建请求参数 inputs {context: context, question: user_question} # 3. 执行生成 response self.chain.invoke(inputs) # 4. 后处理校验简单示例检查是否包含特定关键词以防幻觉 if refund not in response.lower(): logger.warning(Response may not contain expected info, checking fallback) response Please contact support for further assistance. duration __import__(time).time() - start_time return { status: success, response: response, latency_ms: int(duration * 1000), logs: logger.handlers # 示意实际应存入 DB } except Exception as e: logger.error(fAgent execution failed: {str(e)}, exc_infoTrue) return { status: error, message: Internal server error, debug: str(e) } # 测试 agent RobustSupportAgent() result agent.run(How can I get my money back?) print(result)关键点解析1. 日志优先注意logging的使用。在生产环境中你不可能靠print调试。每一层检索、生成、后处理的日志都是未来排查问题的线索。2. 异常隔离run方法包裹了完整的try-except。大模型调用是非确定性的网络抖动、Token 限制、API 超时都可能发生。Agent 必须优雅地降级而不是直接崩溃。3. 可观测性字段返回结果中包含latency_ms和status。这些指标对于评估模型性能、优化链路至关重要。招聘 JD 里常提到的“性能优化”指的就是对这类数据的监控和分析。从 Demo 到工程化你需要补齐的能力栈回到开头的话题为什么很多团队效率没提升因为大家花 80% 的时间在调 Prompt只有 20% 的时间在思考如何让应用稳定运行。结合近期的招聘趋势如果你想从“会调 API”进阶到“AI 应用工程师”建议按以下顺序补齐能力1. 基础层熟练掌握 LangChain 的 LCELLangChain Expression Language语法理解Runnable的并行与串行逻辑。2. 数据层不只是调用 Embedding API要懂得如何处理 Chunking 策略、向量数据库的索引更新和元数据过滤。3. 工程层* 权限控制Agent 调用的工具是否有访问限制是否需要对用户身份鉴权* 缓存策略相同的 Query Context 组合是否命中缓存* 可观测性集成 LangSmith 或 Arize Phoenix追踪 Trace ID分析 Token 消耗和延迟分布。4. 评估层建立自动化的评估集Eval Set定期检测 Prompt 变更是否导致质量下降。总结LangChain 只是一个工具包它没有魔法。真正的竞争力在于你能否将大模型的能力嵌入到现有的企业级工程规范中。当一个 Agent 能够清晰记录每一步的执行耗时、能够优雅处理工具的失败、并且能够通过日志回溯到具体的 Prompt 版本时它才具备了上生产环境的资格。别急着卷 Agent 的智能程度先把权限、日志和可观测性这套“脏活”干漂亮。这才是区分 Demo 开发者和工程化工程师的分水岭。资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。如果你想看完整资料目录可以在评论区留言「资料」也欢迎告诉我你更关注AI大模型里的哪类内容。
LangChain 应用上线即崩?从权限日志拆解 Agent 工程化断点
发布时间:2026/7/14 19:38:10
这篇我按“先跑起来、再讲取舍”的方式写《会用LangChain只是起点能解释失败才算真正入门》。概念会讲但重点放在代码怎么组织、哪里容易踩坑。摘要先把这篇文章的目标说清楚看完之后你应该能判断这件事值不值得做以及从哪里动手。最近面试了不少转做大模型应用的开发者发现一个普遍现象大家的 Demo 都能跑RAG 检索也能出答案但一旦提到“生产环境”、“权限控制”或者“全链路追踪”很多人就卡壳了。这其实不是能力问题而是思维惯性。在学校或自学阶段我们习惯于print(response)这种线性调试但在企业级应用中Agent 不再是单线程脚本它是并发执行、涉及外部工具调用、需要严格审计的复杂系统。今天不聊虚的概念直接从 LangChain 实战的角度拆解如何从一个“能跑通的 Prompt 调用”进化到一个“可观测、可控的工程化应用”。我会结合最近踩过的坑分享一套从 Junior 到 Senior 的进阶路径。目录别一上来就写 Chain先搞清楚 LangChain 到底解决了什么核心组件不仅仅是 LLMChain项目实战构建一个具备可观测性的 Agent从 Demo 到工程化你需要补齐的能力栈总结别一上来就写 Chain先搞清楚 LangChain 到底解决了什么很多初学者拿到 LangChain第一反应是封装 API。其实 LangChain 的核心价值不在于帮你调接口而在于编排Orchestration。它解决的是三个核心痛点1. 标准化交互统一不同 LLM Provider 的输入输出格式。2. 状态管理让对话历史、工具调用结果能在 Chain 中流转。3. 可观测性基础通过 Tracing 机制让你看到每一步发生了什么而不仅仅是最后的结果。如果你只是简单封装了一个get_answer()函数那根本不需要 LangChain。只有当你需要串联 Prompt - LLM - Parser - Tool - LLM 这种复杂逻辑时LangChain 的Chain和Agent概念才有意义。核心组件不仅仅是 LLMChain在构建应用时我对 LangChain 组件的使用是有取舍的。早期版本喜欢用LLMChain但现在我更推荐组合使用ChatModel、PromptTemplate和OutputParser。1. Prompt 工程的工程化Prompt 不是写死的字符串它是代码的一部分。from langchain_core.prompts import ChatPromptTemplate # 错误做法硬编码 Prompt prompt 你是一个助手请回答{question} # 正确做法结构化 Prompt分离系统指令与用户输入 template You are an expert financial assistant. Context: {context} Question: {question} Rules: 1. Only use provided context. 2. If context is empty, say I dont know. 3. Cite sources if available. Answer: prompt ChatPromptTemplate.from_template(template)在实际项目中我发现很多 Bug 源于 Prompt 缺乏边界约束。比如模型 hallucination幻觉往往是因为没有明确告诉它“不知道”时的行为。2. 工具调用Tool Calling的陷阱这是从 Demo 走向生产的关键分水岭。很多开发者写的 Agent 能调工具但无法处理工具报错、权限校验或循环调用。以搜索工具为例简单的实现可能长这样from langchain_core.tools import tool tool def search_web(query: str): Search the web for current information. # 假设这里直接调用了 API return fResults for {query}但在生产环境中你必须考虑超时处理搜索 API 挂了怎么办速率限制每分钟调用次数限制安全性是否允许调用敏感接口项目实战构建一个具备可观测性的 Agent为了让大家直观感受差异我重构了一个常见的“客服问答 Agent”。重点在于引入LangSmith风格的日志记录和异常捕获机制而非仅仅关注结果。场景描述我们需要一个 Agent它能接收用户问题检索知识库模拟 RAG并根据预设规则回答。关键在于当检索失败或模型输出不符合规范时系统要有明确的降级策略并能记录完整链路供后续排查。代码实现注重健壮性的 Agent 结构import logging from typing import List, Dict, Any from langchain_core.messages import HumanMessage, AIMessage from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.output_parsers import StrOutputParser # 配置日志替代 print便于后续接入 ELK 或 Sentry logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class RobustSupportAgent: def __init__(self): self.llm ChatOpenAI(modelgpt-3.5-turbo, temperature0) self.prompt ChatPromptTemplate.from_messages([ (system, You are a support agent. Answer based strictly on the provided context.), (human, Context:\n{context}\n\nUser Question:\n{question}) ]) # 使用 RunnablePassthrough 进行链式编排而非简单的 LCEL self.chain self.prompt | self.llm | StrOutputParser() def retrieve_context(self, question: str) - str: 模拟 RAG 检索实际项目中应连接 Vector DB logger.info(fRetrieving context for query: {question}) # 这里可以加入重试机制、缓存查询等工程化逻辑 return The refund policy allows returns within 30 days. def run(self, user_question: str) - Dict[str, Any]: 执行 Agent 逻辑包含完整的异常处理和日志记录 start_time __import__(time).time() try: # 1. 获取上下文 context self.retrieve_context(user_question) # 2. 构建请求参数 inputs {context: context, question: user_question} # 3. 执行生成 response self.chain.invoke(inputs) # 4. 后处理校验简单示例检查是否包含特定关键词以防幻觉 if refund not in response.lower(): logger.warning(Response may not contain expected info, checking fallback) response Please contact support for further assistance. duration __import__(time).time() - start_time return { status: success, response: response, latency_ms: int(duration * 1000), logs: logger.handlers # 示意实际应存入 DB } except Exception as e: logger.error(fAgent execution failed: {str(e)}, exc_infoTrue) return { status: error, message: Internal server error, debug: str(e) } # 测试 agent RobustSupportAgent() result agent.run(How can I get my money back?) print(result)关键点解析1. 日志优先注意logging的使用。在生产环境中你不可能靠print调试。每一层检索、生成、后处理的日志都是未来排查问题的线索。2. 异常隔离run方法包裹了完整的try-except。大模型调用是非确定性的网络抖动、Token 限制、API 超时都可能发生。Agent 必须优雅地降级而不是直接崩溃。3. 可观测性字段返回结果中包含latency_ms和status。这些指标对于评估模型性能、优化链路至关重要。招聘 JD 里常提到的“性能优化”指的就是对这类数据的监控和分析。从 Demo 到工程化你需要补齐的能力栈回到开头的话题为什么很多团队效率没提升因为大家花 80% 的时间在调 Prompt只有 20% 的时间在思考如何让应用稳定运行。结合近期的招聘趋势如果你想从“会调 API”进阶到“AI 应用工程师”建议按以下顺序补齐能力1. 基础层熟练掌握 LangChain 的 LCELLangChain Expression Language语法理解Runnable的并行与串行逻辑。2. 数据层不只是调用 Embedding API要懂得如何处理 Chunking 策略、向量数据库的索引更新和元数据过滤。3. 工程层* 权限控制Agent 调用的工具是否有访问限制是否需要对用户身份鉴权* 缓存策略相同的 Query Context 组合是否命中缓存* 可观测性集成 LangSmith 或 Arize Phoenix追踪 Trace ID分析 Token 消耗和延迟分布。4. 评估层建立自动化的评估集Eval Set定期检测 Prompt 变更是否导致质量下降。总结LangChain 只是一个工具包它没有魔法。真正的竞争力在于你能否将大模型的能力嵌入到现有的企业级工程规范中。当一个 Agent 能够清晰记录每一步的执行耗时、能够优雅处理工具的失败、并且能够通过日志回溯到具体的 Prompt 版本时它才具备了上生产环境的资格。别急着卷 Agent 的智能程度先把权限、日志和可观测性这套“脏活”干漂亮。这才是区分 Demo 开发者和工程化工程师的分水岭。资料展示下面是我整理的AI大模型学习资料和工具包预览适合收藏后按主题逐步学习。如果你想看完整资料目录可以在评论区留言「资料」也欢迎告诉我你更关注AI大模型里的哪类内容。