LangChain实战:5分钟用Python搭建你的第一个AI智能体(附完整代码)

📅 发布时间:2026/7/11 7:23:52 👁️ 浏览次数:
LangChain实战:5分钟用Python搭建你的第一个AI智能体(附完整代码)
LangChain实战5分钟用Python搭建你的第一个AI智能体附完整代码如果你是一名Python开发者最近肯定没少听到“AI智能体”这个词。它听起来很酷但似乎又有点遥不可及——复杂的框架、晦涩的概念、动辄几百行的代码让人望而却步。但今天我想带你打破这个迷思。我们不用长篇大论的理论也不搞复杂的架构设计就从一个最具体、最微小的目标开始用5分钟时间写一个能真正跑起来的AI智能体。这个智能体将具备一个非常实用的功能根据你的自然语言描述自动生成并执行Python代码。比如你告诉它“帮我画一个正弦波图”它就能理解你的意图写出对应的matplotlib代码并运行展示结果。这不仅仅是调用API而是让AI具备了“思考-规划-行动”的完整闭环能力。整个过程我们将完全依赖LangChain这个当下最热门的AI应用框架。别担心哪怕你之前从未接触过LangChain跟着下面的步骤你也能亲手把这个“数字助手”搭建出来。1. 环境准备搭建你的专属AI工作台在开始敲代码之前我们需要一个干净、独立的Python环境。这能确保所有依赖包版本一致避免未来可能出现的“在我电脑上能跑”的尴尬局面。我强烈推荐使用Conda来管理环境它比系统自带的Python环境管理要清晰得多。1.1 创建并激活Conda环境打开你的终端Windows用户可以用Anaconda Prompt或PowerShellmacOS/Linux用户直接用终端执行以下命令来创建一个名为langchain_agent的新环境并指定Python版本为3.10。这个版本在稳定性和对新库的支持上取得了很好的平衡。conda create -n langchain_agent python3.10 -y创建完成后激活这个环境conda activate langchain_agent你会看到命令行提示符前面变成了(langchain_agent)这表示你已经成功进入了这个隔离的环境。接下来所有操作都将在这个“沙箱”中进行。1.2 安装核心依赖包我们需要安装三个核心包langchain框架本身、openai库用于调用大模型API、以及langchain-community它包含了许多社区贡献的工具集成。pip install langchain openai langchain-community为了让我们的小智能体能执行代码我们还需要安装python-dotenv来管理API密钥以及matplotlib作为我们第一个演示任务的工具。pip install python-dotenv matplotlib注意这里我们使用pip安装。虽然Conda环境里也可以用conda install但对于LangChain这类更新频繁的生态pip通常能获得最新的版本。只要确保在激活的Conda环境内使用pip就不会污染系统环境。安装完成后可以通过一个快速命令验证LangChain是否安装成功python -c import langchain; print(fLangChain版本: {langchain.__version__})如果看到版本号输出例如0.3.25说明一切就绪。1.3 配置你的大模型访问密钥我们的智能体需要一个“大脑”这里我们选择使用OpenAI的GPT模型例如gpt-3.5-turbo。你需要一个OpenAI的API Key。如果你还没有可以去OpenAI官网注册获取。安全第一永远不要将API Key硬编码在代码中或上传到GitHub。最佳实践是使用环境变量。我们在项目根目录下创建一个名为.env的文件内容如下OPENAI_API_KEY你的实际API密钥然后在Python代码中我们可以通过os和dotenv模块安全地读取它。后面我们会看到具体用法。2. 理解核心组件智能体是如何“思考”的在动手写代码前花两分钟理解一下LangChain构建智能体的核心哲学会让你后面的操作更加得心应手。你可以把LangChain智能体想象成一个配备了高级工具腰带和记事本的工程师。大语言模型 (LLM)这是智能体的“大脑”和“通用知识库”。它负责理解你的指令、进行逻辑推理、制定初步计划。我们通过API与它对话。工具 (Tools)这是智能体的“双手”。大脑再聪明没有手也做不了具体的事。工具就是一个个定义好的函数可以执行特定任务比如执行Python代码、进行网络搜索、查询数据库等。智能体在思考后会决定调用哪个工具。智能体 (Agent)这是智能体的“决策中枢”。它把大脑LLM和双手Tools连接起来。其内部运行着一套复杂的逻辑先让LLM分析用户请求判断是否需要使用工具、使用哪个工具然后调用工具执行最后根据工具返回的结果让LLM再次分析决定是给出最终答案还是继续使用下一个工具。这个过程可能循环多次。代理执行器 (AgentExecutor)这是智能体的“流程控制器”。它负责运行上述决策循环处理工具调用的输入输出管理对话状态记忆并在适当的时候比如达到最大循环次数或任务完成停止。它们之间的关系可以用下面这个简化的表格来理解组件类比在LangChain中的角色关键类/函数LLM大脑与知识库提供理解、推理和规划能力ChatOpenAI,ChatAnthropicTools双手与工具腰带执行具体的、模型自身无法完成的操作Tool,tool装饰器Agent决策中枢根据LLM的推理决定调用哪个工具create_react_agent,AgentTypeAgentExecutor流程控制器驱动智能体运行管理工具调用循环和状态AgentExecutor理解了这套架构你就会明白我们搭建智能体的过程其实就是1. 准备一个大脑LLM2. 为它打造一些好用的工具Tools3. 用一套决策逻辑Agent把它们组装起来4. 最后让一个执行器Executor来运行整个系统。3. 构建第一个工具让AI拥有“执行代码”的手智能体的强大之处在于能使用工具。我们首先来打造第一个也是最核心的一个工具Python代码执行器。这个工具将允许智能体将其生成的代码片段在本地环境中运行并获取结果。在LangChain中创建工具非常灵活。这里我们使用tool装饰器它能将一个普通的Python函数快速“包装”成一个智能体可以识别和调用的工具。在你的代码文件中例如first_agent.py我们开始编写import os from dotenv import load_dotenv from langchain.agents import Tool, AgentExecutor, create_react_agent from langchain_openai import ChatOpenAI from langchain_core.prompts import PromptTemplate import matplotlib.pyplot as plt import io import sys from contextlib import redirect_stdout, redirect_stderr # 1. 加载环境变量中的API密钥 load_dotenv() api_key os.getenv(OPENAI_API_KEY) if not api_key: raise ValueError(请在 .env 文件中设置 OPENAI_API_KEY) # 2. 初始化LLM“大脑” llm ChatOpenAI( modelgpt-3.5-turbo, # 也可使用 gpt-4 获得更强推理能力 temperature0, # 温度设为0使输出更确定、更可靠 openai_api_keyapi_key ) # 3. 定义代码执行工具 from langchain.tools import tool import ast tool def execute_python_code(code_string: str) - str: 执行一段Python代码字符串并返回执行结果或错误信息。 特别适用于数据计算、绘图、文件操作等任务。 参数: code_string (str): 需要执行的Python代码字符串。 返回: str: 代码的标准输出、返回值或执行中捕获的错误信息。 try: # 安全检查禁止导入某些危险模块可根据需要扩展 forbidden_modules [os, subprocess, sys, shutil] tree ast.parse(code_string) for node in ast.walk(tree): if isinstance(node, ast.Import) or isinstance(node, ast.ImportFrom): for alias in (node.names if isinstance(node, ast.Import) else [node]): module_name alias.name.split(.)[0] if module_name in forbidden_modules: return f安全限制禁止导入模块 {module_name}。 # 准备捕获输出 output_capture io.StringIO() error_capture io.StringIO() # 执行代码并重定向输出和错误 with redirect_stdout(output_capture), redirect_stderr(error_capture): # 使用exec执行代码并将最后表达式的值存入_result exec_globals {plt: plt} exec(code_string, exec_globals) # 尝试获取最后一个表达式的值如果存在 _result exec_globals.get(_, None) stdout_value output_capture.getvalue() stderr_value error_capture.getvalue() result_parts [] if stdout_value: result_parts.append(f标准输出:\n{stdout_value}) if stderr_value: result_parts.append(f标准错误:\n{stderr_value}) if _result is not None: result_parts.append(f最后表达式结果: {_result}) # 如果代码生成了图表保存并提示 if plt.get_fignums(): plt.savefig(output_plot.png) result_parts.append(已生成图表并保存为 output_plot.png。) plt.close(all) # 关闭所有图形避免内存累积 return \n---\n.join(result_parts) if result_parts else 代码执行完毕无输出。 except SyntaxError as e: return f语法错误: {e} except Exception as e: return f执行时发生错误: {type(e).__name__}: {e}我们来拆解一下这个工具函数的关键点tool装饰器这是LangChain提供的魔法它自动将函数注册为工具并利用函数的文档字符串内的内容作为工具的描述帮助LLM理解何时该调用它。参数与返回工具函数必须有一个清晰的输入参数这里是code_string并返回一个字符串。这个字符串就是工具执行的结果将被反馈给LLM进行下一步分析。安全执行我们使用了ast模块对代码进行简单的语法分析禁止导入如os、subprocess等可能具有危险性的模块。这是一个基础的安全措施在实际生产环境中你需要更严格的沙箱机制例如使用Docker容器隔离执行。输出捕获使用io.StringIO和redirect_stdout/stderr来捕获代码执行过程中打印到控制台的所有内容这样智能体就能“看到”代码运行的结果。图表处理特别处理了matplotlib绘图的情况自动保存图表文件并关闭图形防止内存泄漏。这个execute_python_code函数现在就是一个标准的LangChain Tool对象了。智能体在思考时会知道有这么一个工具可用其功能描述就是函数文档字符串里的内容。4. 组装与运行创建你的第一个智能体工具准备好了大脑LLM也初始化了现在就是最激动人心的组装时刻。我们将使用LangChain中一种经典且高效的智能体类型——ReAct Agent。ReAct代表“Reasoning Acting”推理行动这种智能体会在思考步骤和行动步骤之间交替进行非常适合需要多步工具调用的任务。4.1 定义工具集并创建智能体继续在first_agent.py中编写# 4. 创建工具列表 tools [execute_python_code] # 目前我们只有一个工具后续可以轻松添加更多 # 5. 定义智能体的提示模板 # 这个模板告诉智能体它的角色、可用的工具以及如何思考 agent_prompt PromptTemplate.from_template( 你是一个强大的Python编程助手。你可以通过执行Python代码来解决用户的问题。 请严格按照以下格式回答 问题用户提出的问题 思考你需要分析问题并决定是否需要运行代码来解决问题。如果需要请规划你将执行的代码。 行动你需要调用的工具名称必须是以下列表中的一个[{tool_names}] 行动输入传递给工具的输入必须是一个有效的Python代码字符串 观察工具执行后的结果 ... (这个“思考/行动/行动输入/观察”的循环可以重复多次) 最终答案当你足够确定答案时或者不需要再执行代码时用清晰的语言给出最终答案。 现在开始 问题{input} 思考{agent_scratchpad} ) # 6. 创建ReAct智能体 agent create_react_agent(llmllm, toolstools, promptagent_prompt) # 7. 创建代理执行器 agent_executor AgentExecutor( agentagent, toolstools, verboseTrue, # 设置为True可以看到智能体详细的思考过程 handle_parsing_errorsTrue, # 优雅地处理解析错误 max_iterations5, # 限制最大循环次数防止无限循环 early_stopping_methodgenerate # 当智能体决定给出最终答案时停止 )这段代码有几个精妙之处tool_names在提示模板中{tool_names}会被自动替换为可用工具的名称列表这里是[execute_python_code]这帮助LLM知道它能做什么。agent_scratchpad这是一个关键变量。在智能体运行过程中LangChain会自动将之前的“思考-行动-观察”历史填充到这里形成上下文让智能体拥有“记忆”知道之前发生了什么。verboseTrue强烈建议在开发调试时开启。开启后你会在控制台看到智能体完整的内部对话包括它的思考、决定调用的工具、工具返回的结果这就像是在观察一个AI的思维链非常有助于理解其工作原理和调试问题。max_iterations这是一个重要的安全阀。防止智能体陷入“思考-行动”的死循环。4.2 与你的智能体对话一切就绪让我们来运行它在文件末尾添加# 8. 运行智能体 if __name__ __main__: print(你的AI代码执行智能体已启动输入 quit 退出。) while True: user_input input(\n你想让我做什么: ).strip() if user_input.lower() in [quit, exit, q]: print(再见) break if not user_input: continue try: # 调用执行器 result agent_executor.invoke({input: user_input}) print(f\n最终答案: {result[output]}) except Exception as e: print(f运行过程中出现错误: {e})保存文件然后在终端中运行python first_agent.py你会看到提示符。现在尝试输入一些指令见证奇迹你的AI代码执行智能体已启动输入 quit 退出。 你想让我做什么: 计算1到100所有整数的和并告诉我结果。观察控制台输出你会看到类似这样的详细过程因为设置了verboseTrue 进入新的AgentExecutor链... 思考用户要求计算1到100所有整数的和。这是一个简单的数学计算可以通过Python代码快速完成。我需要使用execute_python_code工具。 行动execute_python_code 行动输入sum(range(1, 101)) 观察最后表达式结果: 5050 思考我得到了结果5050。这看起来是正确的。我可以直接给出最终答案。 最终答案1到100所有整数的和是5050。 最终答案: 1到100所有整数的和是5050。再试一个更复杂的你想让我做什么: 帮我画一个正弦函数在0到2π之间的图像并设置标题为‘Sine Wave’。智能体会生成并执行类似下面的代码import numpy as np import matplotlib.pyplot as plt x np.linspace(0, 2*np.pi, 100) y np.sin(x) plt.plot(x, y) plt.title(Sine Wave) plt.xlabel(x) plt.ylabel(sin(x)) plt.grid(True) plt.show()并在观察中返回“已生成图表并保存为 output_plot.png。”。你可以打开当前目录下的output_plot.png文件查看生成的图表。5. 扩展与优化从玩具到实用工具恭喜你的第一个AI智能体已经成功运行。但这只是一个起点。下面是一些方向可以让这个智能体变得更强大、更实用。5.1 为智能体添加更多“工具手”一个只会执行代码的智能体能力有限。LangChain社区和langchain-community包提供了海量的预制工具。让我们给它加一个“获取当前天气”的工具。首先安装相关依赖pip install requests然后在代码中定义新工具添加到tools列表中import requests from datetime import datetime tool def get_current_weather(city: str) - str: 获取指定城市的当前天气情况。 # 注意这里使用一个免费的模拟天气API仅作演示。 # 实际应用中请替换为可靠的天气API如OpenWeatherMap并处理API密钥。 try: # 模拟API响应 mock_data { Beijing: {temp: 22, condition: 晴朗, humidity: 40}, Shanghai: {temp: 25, condition: 多云, humidity: 65}, New York: {temp: 18, condition: 小雨, humidity: 80}, } if city in mock_data: data mock_data[city] return f{city}的当前天气温度{data[temp]}°C{data[condition]}湿度{data[humidity]}%。 else: return f未找到{city}的天气信息。目前支持{, .join(mock_data.keys())} except Exception as e: return f获取天气信息失败{e} # 更新工具列表 tools [execute_python_code, get_current_weather]现在重启你的智能体并提问“北京现在的天气怎么样如果温度低于20度用Python代码提醒我‘需要加外套’。” 你会发现智能体能够先调用get_current_weather工具获取信息再根据结果决定是否执行代码逻辑。5.2 引入记忆实现连续对话目前的智能体是“健忘”的每次对话都是独立的。我们可以轻松地为它添加记忆功能让它记住之前的对话上下文。修改创建AgentExecutor的部分from langchain.memory import ConversationBufferMemory # 创建记忆体 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 更新提示模板加入记忆上下文 agent_prompt_with_memory PromptTemplate.from_template( 你是一个强大的Python编程助手。以下是之前的对话历史 {chat_history} 现在请根据历史和新问题继续对话。 你可以通过执行Python代码来解决用户的问题。 请严格按照以下格式回答 问题用户提出的问题 思考你需要分析问题并决定是否需要运行代码来解决问题。如果需要请规划你将执行的代码。 行动你需要调用的工具名称必须是以下列表中的一个[{tool_names}] 行动输入传递给工具的输入 观察工具执行后的结果 ... (这个循环可以重复多次) 最终答案当你足够确定答案时用清晰的语言给出最终答案。 现在开始 新问题{input} 思考{agent_scratchpad} ) # 使用带记忆的提示模板创建智能体和执行器 agent_with_memory create_react_agent(llmllm, toolstools, promptagent_prompt_with_memory) agent_executor_with_memory AgentExecutor( agentagent_with_memory, toolstools, memorymemory, verboseTrue, handle_parsing_errorsTrue, max_iterations5, )现在你可以进行多轮对话了。例如你“我的名字是Alex。”智能体可能不需要工具直接回答“好的我记住了。”——实际上记忆已经保存你“用Python代码写一句问候语包含我的名字。”智能体它会在思考时看到chat_history中包含“我的名字是Alex”从而生成代码print(Hello, Alex!)。5.3 提升代码生成质量与安全当前的代码执行工具虽然能用但生成的代码可能不够优化且存在安全风险。我们可以从两方面改进1. 使用更强大的模型将初始化LLM时的模型从gpt-3.5-turbo换成gpt-4或gpt-4-turbo它们在代码生成和复杂推理上表现更出色。2. 强化安全沙箱对于生产环境绝对不要使用简单的exec。考虑以下方案使用Docker容器将代码发送到一个一次性Docker容器中执行执行完毕后销毁容器。使用专用沙箱库例如pysandbox注意其已停止维护或寻找更新的替代品。严格限制功能在工具函数中通过ast进行更深入的语法树分析禁止文件读写、网络访问、系统调用等所有危险操作只允许纯计算和绘图。例如一个加强版的安全检查函数雏形def check_code_safety(code_string): tree ast.parse(code_string) forbidden_funcs [open, eval, exec, __import__, os.system, subprocess.run] for node in ast.walk(tree): # 检查函数调用 if isinstance(node, ast.Call): if isinstance(node.func, ast.Name): if node.func.id in forbidden_funcs: return False, f禁止调用函数: {node.func.id} # 检查导入 elif isinstance(node, ast.Import): for alias in node.names: if alias.name in [os, sys, subprocess, shutil]: return False, f禁止导入模块: {alias.name} return True, 代码安全检查通过然后在execute_python_code工具的开头调用这个函数如果返回False则直接返回错误信息不执行代码。走到这一步你已经不再是一个LangChain的旁观者而是一个真正的实践者。你亲手搭建的系统从一个简单的代码执行器进化成了一个能调用多种工具、拥有记忆、并能进行多轮复杂任务规划的初级AI智能体。这个过程中遇到的每一个报错、每一次调试都是你对智能体架构理解加深的契机。真正的价值不在于这五分钟的搭建而在于你以此为基础开始探索如何将这套模式应用到你的具体业务场景中——也许是自动化数据分析也许是智能客服的初始原型也许是一个个性化的学习助手。