
1. 项目概述为什么现在要自己动手做AI编程智能体最近几个月AI编程领域的热度几乎被“智能体”这个词给承包了。无论是技术社区还是产品发布会你都能看到LangChain、Claude Code、DeepSeek这些名字频繁出现。作为一个在软件开发一线摸爬滚打了十多年的老码农我最初看到这些新概念时第一反应也是有点懵这不就是给大语言模型LLM套了层壳吗有什么新鲜的但当我真正沉下心来尝试用传统的API调用方式去让模型帮我完成一个稍微复杂点的编程任务时问题就暴露出来了。比如我想让模型帮我写一个包含用户认证、数据增删改查的完整后端模块。直接提问的结果往往是模型能给出漂亮的代码片段但文件结构是乱的依赖没说明甚至不同代码块之间逻辑都对不上。它缺乏一个“思考-执行-验证”的循环能力更像是一个有问必答、但不管落地的“顾问”。而这恰恰就是“AI编程智能体”要解决的核心问题。它不是一个简单的聊天机器人而是一个具备一定自主性的数字助手。你可以把它理解为一个初级程序员你给它一个模糊的需求比如“搭建一个博客系统的评论模块”它能自己拆解任务先设计数据库表结构然后写模型层代码接着是API接口最后可能还会写点简单的单元测试。它会调用代码解释器来验证语法会检索文档来确认API用法如果出错了它还能根据错误信息调整策略重新尝试。所以这个系列文章的目的很明确我们不谈空泛的概念就实实在在地从零开始手把手搭建一个能真正干活的AI编程智能体。我会用最主流的开源框架LangChain作为骨架结合当前性价比和性能都备受瞩目的DeepSeek模型作为“大脑”一步步把它构建起来。你会看到智能体是如何理解任务、使用工具比如搜索、读写文件、执行命令、并持续迭代的。无论你是想提升自己的开发效率还是对AI应用开发感兴趣这个实践过程都会让你对“智能体”有一个透彻的、接地气的理解。2. 核心组件选型LangChain DeepSeek为什么是它们搭建一个智能体就像组装一台电脑你需要选对主板框架和CPU模型。市面上选择很多但经过反复对比和实测我最终锁定了LangChain作为框架DeepSeek系列模型作为核心LLM。这个组合不是拍脑袋决定的下面我详细拆解一下背后的考量。2.1 框架之争为什么是LangChain而不是LangGraph或Dify首先明确一点LangChain和LangGraph不是互斥关系而更像是“基础库”和“高级框架”的关系。LangGraph是建立在LangChain之上的专门用于构建有状态、多步骤的智能体工作流。LangChain它的定位是“构建LLM应用的工具包”。它提供了极其丰富的模块化组件比如与各种模型对接的LLM接口、管理对话历史的Memory、定义工具的Tool类、以及组织调用链的Chain。它的优势在于灵活和透明。你可以清晰地控制智能体的每一个环节从提示词Prompt模板的编写到工具调用的逻辑再到输出的解析全部尽在掌握。这对于学习和理解智能体的底层原理至关重要。官方文档详尽社区庞大遇到问题基本都能找到解决方案。LangGraph它引入了“图”的概念特别适合描述那些有循环、分支、并行等复杂逻辑的智能体。比如一个智能体可能需要先判断任务类型再决定调用A工具还是B工具然后根据工具返回的结果决定是继续还是结束。用LangGraph来描绘这种流程非常直观。但对于我们初识智能体的目标来说它引入了一定的抽象复杂度。Dify/Coze等平台这类属于低代码/无代码的AI应用平台。它们优点是快拖拖拽拽就能做出一个能用的智能体。但缺点是黑盒化你很难深入定制底层逻辑也无法将智能体无缝集成到你自己的代码工程里。学习它们你更多是在学习某个平台的使用方法而非智能体本身的技术。我的选择理由从零学习核心目标是“理解原理”和“获得完全的控制权”。因此从最基础、最模块化的LangChain开始是打下坚实根基的最佳路径。理解了LangChain再去看LangGraph会觉得水到渠成。而平台类工具更适合在明确需求后快速构建原型或轻量级应用。2.2 模型选择DeepSeek何以成为开源新贵模型是智能体的“大脑”它的成本、能力和稳定性直接决定智能体的表现。OpenAI的GPT系列固然强大但API费用和网络稳定性是长期绕不开的痛点。而DeepSeek特别是DeepSeek-V3和最新的V4 Flash在近期以其惊人的性能价格比成为了开源社区和许多企业的首选。极高的性价比DeepSeek API的定价策略极具侵略性相同性能下成本远低于主流商用API。这对于需要频繁调用、进行长上下文推理的编程智能体来说意味着你可以用更低的成本进行大量的实验和迭代。出色的代码能力DeepSeek系列模型在多项代码生成基准测试如HumanEval, MBPP中名列前茅其对编程语言语法、逻辑的理解和生成能力已经达到了顶尖水平完全足以胜任编程助手的工作。友好的上下文长度支持128K甚至更长的上下文这意味着智能体可以记住更长的对话历史和多轮工具调用结果对于处理复杂的、多步骤的编程任务至关重要。灵活的部署方式除了使用官方API你还可以通过开源库如ollama,vllm,lmstudio在本地或自己的服务器上部署DeepSeek模型。这为数据敏感或需要离线使用的场景提供了可能。实操心得模型版本选择对于编程智能体我强烈推荐使用deepseek-chat或deepseek-coder系列的最新版本。deepseek-chat通用对话能力强对指令的理解更精准deepseek-coder则在代码专项上更精炼。起步阶段使用官方API的deepseek-chat是平衡成本与效果的最佳选择。后续我们会演示如何配置。2.3 环境与工具准备你的编程战场工欲善其事必先利其器。在写第一行代码之前我们需要把环境搭建好。这里我会给出一个清晰、可复现的清单。1. 基础环境Python版本 3.10。这是LangChain和大多数AI库的主要语言环境。包管理工具推荐使用pip但为了环境隔离我强烈建议使用conda或venv创建虚拟环境。# 使用 venv 创建虚拟环境 python -m venv ai_agent_env # 激活环境 (Linux/macOS) source ai_agent_env/bin/activate # 激活环境 (Windows) ai_agent_env\Scripts\activate2. 核心依赖安装在激活的虚拟环境中运行以下命令安装核心库。我们不会一次性安装所有而是按需引入保持环境干净。pip install langchain langchain-community langchain-corelangchain: 核心框架。langchain-community: 包含大量第三方集成工具、模型等。langchain-core: 基础抽象和运行时。3. 模型接入依赖我们要通过API调用DeepSeek所以需要安装OpenAI SDK因为DeepSeek API兼容OpenAI格式。pip install openai4. 代码编辑器/IDEVSCode无疑是当前最流行的选择拥有海量的AI和Python插件。我们后续会提到的“Claude Code”本质上是VSCode的一个扩展它集成了Claude模型的能力。但我们的目标是自己构建智能体因此更推荐使用纯净的VSCode搭配Python、Jupyter等基础插件即可。PyCharm专业Python IDE对代码导航、重构支持更好社区版免费。注意事项尽量避免在全局Python环境中直接安装。使用虚拟环境可以避免不同项目间的依赖冲突这是Python开发的一个好习惯。另外请确保你的网络环境能够稳定访问DeepSeek的API服务api.deepseek.com。3. 智能体基石与大模型DeepSeek建立连接智能体的一切思考都源于大模型。因此我们的第一步就是教会LangChain如何与DeepSeek对话。这里的关键是理解LangChain的ChatModel抽象层。3.1 获取并安全存储API Key首先你需要去DeepSeek的官网注册账号并获取API Key。这个过程很简单和大多数云服务类似。安全第一永远不要将API Key硬编码在代码中常见的做法是将其存储在环境变量里。# 在终端中设置环境变量 (临时重启后失效) export DEEPSEEK_API_KEYyour_api_key_here # 或者更推荐的做法是写入shell配置文件(~/.bashrc, ~/.zshrc)或使用.env文件在Python中我们可以使用os模块或python-dotenv库来读取。pip install python-dotenv创建一个名为.env的文件在项目根目录内容如下DEEPSEEK_API_KEYyour_actual_deepseek_api_key然后在你的Python代码开头加载它from dotenv import load_dotenv import os load_dotenv() # 加载 .env 文件中的所有变量 api_key os.getenv(DEEPSEEK_API_KEY) if not api_key: raise ValueError(请在 .env 文件中设置 DEEPSEEK_API_KEY)3.2 初始化DeepSeek聊天模型LangChain为兼容OpenAI API格式的模型提供了统一的接口ChatOpenAI。DeepSeek的API端点base_url与OpenAI不同我们需要在初始化时指定。from langchain_openai import ChatOpenAI # 初始化DeepSeek模型 llm ChatOpenAI( modeldeepseek-chat, # 指定模型名称 openai_api_keyapi_key, # 传入你的API Key openai_api_basehttps://api.deepseek.com, # 指定DeepSeek的API基础地址 temperature0.1, # 控制创造性编程任务需要较低的值以保证确定性 max_tokens2048, # 单次回复的最大token数 ) # 进行一次简单的测试对话 from langchain_core.messages import HumanMessage response llm.invoke([HumanMessage(content你好请用Python写一个函数计算斐波那契数列的第n项。)]) print(response.content)参数详解model: 这里填写deepseek-chat。如果你想使用代码专用模型可以尝试deepseek-coder如果API支持。openai_api_base:这是关键必须指向DeepSeek的端点https://api.deepseek.com。如果指向默认的OpenAI端点调用会失败。temperature: 取值范围0~2。值越低输出越确定、保守值越高输出越随机、有创造性。对于代码生成我通常设置在0.1到0.3之间以平衡准确性和一点点探索性。max_tokens: 限制模型单次响应的长度。根据任务复杂度调整对于代码生成2048或4096通常足够。3.3 与原生API调用的区别为什么需要LangChain你可能会有疑问我直接用requests库发HTTP请求不也一样吗为什么要多一层LangChain让我们看一个直接调用和通过LangChain调用的简单对比。原生API调用示例import requests import json url https://api.deepseek.com/chat/completions headers { Authorization: fBearer {api_key}, Content-Type: application/json } data { model: deepseek-chat, messages: [{role: user, content: 写一个Python的hello world。}], temperature: 0.1 } response requests.post(url, headersheaders, jsondata) result response.json() print(result[choices][0][message][content])LangChain调用如前所示看起来LangChain的代码似乎更复杂但它的优势在于抽象和组合。统一的接口无论后端是DeepSeek、GPT还是本地部署的Ollama模型你与llm对象交互的方式invoke,stream都是一样的。更换模型时你只需要修改初始化参数业务逻辑代码几乎不用动。消息历史管理LangChain提供了ChatMessageHistory等组件能轻松管理多轮对话的上下文这是构建对话式智能体的基础。链式调用Chain的基础llm对象可以轻松地与其他组件如提示词模板、输出解析器、工具连接起来形成复杂的处理流水线。这是构建智能体的核心模式。实操心得流式输出在处理长文本生成如生成一篇文档或长代码时使用流式输出可以极大改善用户体验无需等待全部生成完毕。LangChain对此有很好的支持。for chunk in llm.stream([HumanMessage(content写一个长故事)]): print(chunk.content, end, flushTrue) # 逐块打印在构建智能体时将关键步骤如“思考中”、“正在调用工具”、“生成代码”以流式或日志形式输出能让整个过程更加透明和可调试。4. 赋予智能体“手脚”工具Tools的定义与使用一个只会思考的模型只是一个知识库。智能体之所以“智能”是因为它能利用“工具”来影响外部世界。对于编程智能体来说工具就是它的手脚可以是执行Shell命令、读写文件、搜索网页、查询数据库等等。4.1 理解LangChain中的Tool在LangChain中一个Tool本质上是一个可被模型调用的函数。它需要三个核心部分名称name模型识别工具的唯一标识。描述description用自然语言描述这个工具的功能。这部分至关重要模型完全依靠描述来决定在什么情况下调用哪个工具。描述必须清晰、准确说明输入是什么、输出是什么、用来解决什么问题。执行函数func实际的Python函数包含工具要执行的逻辑。4.2 构建编程智能体的核心工具集下面我们来定义几个对编程智能体至关重要的工具。工具一执行Shell命令这是智能体与本地开发环境交互的最直接方式可以运行脚本、安装包、启动服务等。from langchain.tools import Tool import subprocess import sys def execute_shell_command(command: str) - str: 在安全环境下执行Shell命令并返回结果。 参数: command (str): 要执行的Shell命令字符串。 返回: str: 命令的标准输出和标准错误。 try: # 使用subprocess.run来安全地执行命令并设置超时 result subprocess.run( command, shellTrue, capture_outputTrue, textTrue, timeout30, # 设置超时防止长时间运行 cwd./workspace # 指定工作目录隔离智能体操作范围 ) output fSTDOUT:\n{result.stdout}\n if result.stderr: output fSTDERR:\n{result.stderr}\n output f返回码: {result.returncode} return output except subprocess.TimeoutExpired: return 错误命令执行超时30秒。 except Exception as e: return f执行命令时发生异常{str(e)} # 将函数包装成Tool shell_tool Tool( nameexecute_shell, funcexecute_shell_command, description在本地工作区的Shell环境中执行命令。用于运行脚本、安装Python包(pip install)、查看目录(ls)、启动服务等。 输入应该是一个完整的、可执行的命令字符串。例如pip install requests 或 python -m http.server 8000。 )工具二读写文件智能体需要能查看现有代码、创建新文件或修改文件。import os def read_file(file_path: str) - str: 读取指定路径文件的内容。 try: # 限制文件读取范围防止访问系统文件 safe_path os.path.join(./workspace, file_path.lstrip(/)) if not os.path.exists(safe_path): return f错误文件 {safe_path} 不存在。 with open(safe_path, r, encodingutf-8) as f: return f.read() except Exception as e: return f读取文件时出错{str(e)} def write_file(file_path: str, content: str) - str: 将内容写入指定路径的文件。如果文件存在则覆盖。 try: safe_path os.path.join(./workspace, file_path.lstrip(/)) # 确保目录存在 os.makedirs(os.path.dirname(safe_path), exist_okTrue) with open(safe_path, w, encodingutf-8) as f: f.write(content) return f成功写入文件{safe_path} except Exception as e: return f写入文件时出错{str(e)} read_tool Tool( nameread_file, funcread_file, description读取工作区内指定文件的内容。输入是文件的相对路径例如src/main.py。 ) write_tool Tool( namewrite_file, funcwrite_file, description将内容写入工作区内的指定文件。输入应该是一个JSON字符串包含file_path和content两个键。例如{{\file_path\: \test.py\, \content\: \print(\\\hello\\\)\}}。 )工具三搜索网络可选当智能体需要查找最新的文档、库用法或解决特定错误时网络搜索工具非常有用。这里以模拟搜索为例实际可以接入Serper、Google Search等API。# 假设我们有一个模拟搜索函数实际应用中需替换为真正的搜索API def mock_web_search(query: str) - str: 模拟网络搜索返回相关摘要。实际应接入Serper/Google Search API。 # 这里只是一个占位符 return f模拟搜索关键词 {query} 的结果\n- 相关文档1: ...\n- Stack Overflow解答: ...\n- 官方指南: ... search_tool Tool( nameweb_search, funcmock_web_search, description在互联网上搜索信息。当需要查找未知的API文档、解决特定错误代码或获取最新技术信息时使用。输入是一个搜索查询字符串。 )4.3 工具集成的安全与边界安全是重中之重赋予AI执行命令和读写文件的能力是强大的也是危险的。我们必须设立边界工作目录隔离所有文件操作都限制在./workspace目录下。使用os.path.join和路径检查防止智能体通过../../../这样的路径逃逸到系统目录。命令白名单/黑名单在生产环境中应对execute_shell工具执行的命令进行过滤。禁止执行rm -rf /、format等危险命令。可以维护一个允许的命令前缀列表如[pip install, python, ls, cat]。超时控制对执行时间长的命令如复杂编译设置超时防止阻塞。权限最小化运行智能体的系统用户应具有最小必要权限不要使用root或管理员账户。注意事项在开发调试阶段你可以先放宽限制但心中必须要有这根弦。一个有效的测试方法是故意让智能体去执行“请列出系统根目录文件”这样的指令观察你的安全机制是否生效。5. 组装智能体让模型学会思考与行动现在我们有了“大脑”LLM和“手脚”Tools。接下来我们需要一个“决策机制”来让大脑指挥手脚。在LangChain中这通常通过“代理”Agent来实现。5.1 理解ReAct模式与AgentExecutor目前最主流、效果最好的智能体范式是ReAct(Reason Act)。模型在行动前会先进行“思考”Reasoning解释它为什么要调用某个工具以及期望得到什么然后执行行动Act最后根据工具返回的结果进行下一步的思考或给出最终答案。LangChain的AgentExecutor就是这个范式的实现者。它负责将用户的输入、对话历史、可用工具列表整合成一个提示词Prompt给LLM。解析LLM的输出判断是应该调用工具还是直接给出最终答案。如果调用工具则执行对应的工具函数并将结果作为新的上下文喂给LLM继续循环。直到LLM输出最终答案循环结束。5.2 创建提示词模板提示词是引导模型行为的关键。我们需要一个专门为智能体设计的提示词模板告诉它你是谁你有什么能力你应该如何思考。from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder # 构建系统提示词 system_prompt 你是一个专业的AI编程助手可以调用工具来帮助用户完成编程任务。 你拥有以下工具 {tools} 你必须严格遵守以下规则 1. 在决定使用哪个工具时请先简要说明你的思考过程Reasoning。 2. 每次只能调用一个工具。 3. 工具调用必须严格按照其描述所要求的输入格式。 4. 根据工具返回的结果决定下一步是继续调用工具还是给出最终答案。 5. 如果你认为任务已经完成或者无法通过现有工具完成请直接给出清晰、友好的最终答案。 用户的问题可能是中文或英文请用相应的语言回复。 对话历史 {chat_history} 现在开始处理用户的最新请求 {input} prompt ChatPromptTemplate.from_messages([ (system, system_prompt), MessagesPlaceholder(variable_namechat_history), # 预留位置存放历史消息 (human, {input}), MessagesPlaceholder(variable_nameagent_scratchpad), # 预留位置存放智能体的思考-行动记录 ])提示词要点解析{tools} 运行时会被替换为可用工具的名称和描述列表。{chat_history} 存储用户与智能体的多轮对话让智能体有上下文记忆。{agent_scratchpad} 这是LangChain Agent专用的占位符用于在运行过程中自动插入模型之前的“思考”和“行动”记录保持思维的连贯性。5.3 配置Agent并创建执行器我们将使用LangChain提供的create_react_agent函数它封装了ReAct模式的标准逻辑。from langchain.agents import create_react_agent, AgentExecutor from langchain.memory import ConversationBufferMemory # 1. 准备工具列表 tools [shell_tool, read_tool, write_tool, search_tool] # 将之前定义的工具放入列表 # 2. 创建记忆组件用于保存对话历史 memory ConversationBufferMemory(memory_keychat_history, return_messagesTrue) # 3. 创建ReAct智能体 agent create_react_agent(llm, tools, prompt) # 4. 创建智能体执行器这是驱动整个循环的核心 agent_executor AgentExecutor( agentagent, toolstools, memorymemory, verboseTrue, # 开启详细日志方便调试能看到“思考”过程 handle_parsing_errorsTrue, # 处理模型输出解析错误避免程序崩溃 max_iterations10, # 限制最大迭代次数防止陷入死循环 early_stopping_methodgenerate, # 当模型连续两次输出最终答案时停止 )关键参数说明verboseTrue强烈建议在开发时开启。它会在控制台打印出模型的完整思考链Chain of Thought包括它决定调用哪个工具、调用的参数、工具返回的结果等。这是调试智能体逻辑的最重要依据。handle_parsing_errorsTrue 模型有时可能不会输出完全符合LangChain期望的格式比如一个包含工具调用和参数的JSON块。设置这个参数可以让执行器尝试从错误中恢复或让模型重试而不是直接抛出异常。max_iterations10 安全阀。防止智能体在一个简单问题上无限循环调用工具。early_stopping_methodgenerate 停止条件之一。当模型连续两次输出即不调用工具时认为它已准备好给出最终答案。5.4 运行你的第一个智能体现在让我们用一个简单的任务来测试这个智能体。# 任务让智能体创建一个Python文件并运行它 result agent_executor.invoke({ input: 请你在工作区创建一个名为 hello_agent.py 的Python文件内容是一个简单的HTTP服务器然后运行它并告诉我它是否成功启动。 }) print(\n 智能体最终回答 ) print(result[output])当你运行这段代码时如果verboseTrue你会在控制台看到类似下面的输出 进入新的AgentExecutor链... 思考用户想让我创建一个Python HTTP服务器文件并运行它。我需要先创建文件然后执行它。 首先我应该使用 write_file 工具来创建这个文件。 动作{action: write_file, action_input: {\file_path\: \hello_agent.py\, \content\: \from http.server import HTTPServer, SimpleHTTPRequestHandler\\n\\nserver HTTPServer((\\\localhost\\\, 8000), SimpleHTTPRequestHandler)\\nprint(\\\Server started at http://localhost:8000\\\)\\nserver.serve_forever()\}} 观察成功写入文件./workspace/hello_agent.py 思考文件已经创建好了。现在我需要运行它。由于这是一个会长期运行的服务我应该用后台方式运行或者只运行一下看看有没有报错。先尝试运行一下。 动作{action: execute_shell, action_input: cd workspace python hello_agent.py } 观察STDOUT: Server started at http://localhost:8000 返回码: 0 思考命令返回码是0并且输出了启动成功的消息。看来服务器已经成功在后台启动了。我可以检查一下进程是否在运行。 动作{action: execute_shell, action_input: ps aux | grep python hello_agent.py} 观察...进程列表 思考进程存在。任务完成。现在可以给用户最终答案了。 最终答案已成功在工作区创建了 hello_agent.py 文件并启动了一个简单的HTTP服务器运行在 http://localhost:8000。进程正在后台运行中。 链结束。通过这个详细的日志你可以清晰地看到智能体“思考-行动-观察-再思考”的完整过程。这就是ReAct智能体的核心魅力。6. 实战演练构建一个需求分析与代码生成智能体让我们用一个更贴近真实开发的场景来深化理解。假设我们接到一个需求“帮我用FastAPI创建一个用户管理API包含用户注册和登录功能并使用SQLite数据库。”我们将引导智能体一步步完成这个任务。为了更高效我们需要对工具和提示词做一些增强。6.1 增强工具代码静态检查在让智能体直接运行代码前最好先进行语法检查。我们添加一个code_lint工具。import ast def check_python_syntax(code: str) - str: 检查Python代码的语法是否正确。 try: ast.parse(code) return 代码语法正确。 except SyntaxError as e: return f语法错误第{e.lineno}行{e.msg}\n错误文本{e.text} lint_tool Tool( namecode_lint, funccheck_python_syntax, description检查给定的Python代码字符串是否存在语法错误。输入是一段完整的Python代码。 ) # 记得将 lint_tool 加入到 tools 列表中 tools.append(lint_tool)6.2 设计分步任务提示词对于复杂任务我们可以通过系统提示词引导智能体进行分步规划。修改之前的系统提示词加入更明确的指导system_prompt_enhanced 你是一个资深的AI全栈开发助手。请以结构化的方式解决复杂的编程任务。 你的工作流程应该是 1. **需求分析**理解用户需求明确技术栈如框架、数据库。 2. **系统设计**规划文件结构、数据库表、API端点。 3. **迭代实现**按照依赖顺序如先创建模型再写API逐个实现模块。每个模块完成后进行语法检查。 4. **集成测试**在全部实现后尝试运行主程序检查是否有运行时错误。 你拥有以下工具 {tools} 规则 - 每次调用工具前用【思考】开头说明意图。 - 优先使用 write_file 创建或修改代码文件。 - 创建新文件后可立即用 code_lint 检查语法。 - 所有文件操作必须在 ./workspace 目录下。 - 最终请提供如何启动服务的说明。 当前对话历史 {chat_history} 现在请开始处理任务 {input} # 使用新的提示词模板更新 agent prompt_enhanced ChatPromptTemplate.from_messages([...]) # 类似之前替换system部分 agent create_react_agent(llm, tools, prompt_enhanced) agent_executor AgentExecutor(agentagent, toolstools, memorymemory, verboseTrue, ...)6.3 观察智能体执行复杂任务现在运行这个增强版的智能体。result agent_executor.invoke({ input: 使用FastAPI和SQLite创建一个用户管理系统。需要用户注册用户名、邮箱、密码哈希存储和登录返回JWT令牌的API。请分步完成。 })在verbose日志中你会看到智能体开始进行系统性的工作第一步创建项目结构。它可能会先调用execute_shell创建虚拟环境或目录然后用write_file创建requirements.txt、main.py、models.py、database.py等文件。第二步实现数据模型。在models.py中定义SQLAlchemy的User模型包含字段和密码哈希方法。写入文件后调用code_lint检查。第三步实现数据库连接和工具函数。创建database.py编写数据库引擎、会话管理、密码哈希验证函数。第四步实现API路由。在main.py中编写FastAPI应用创建/register和/login端点。每写完一个端点可能都会进行语法检查。第五步集成与测试。最后它可能会尝试运行python main.py来启动FastAPI开发服务器或者至少给出启动命令。整个过程中智能体就像一个有条不紊的初级开发者不断地“思考-行动-观察”逐步将模糊的需求转化为具体的、可运行的代码文件。实操心得控制迭代与纠偏智能体有时会“跑偏”比如在实现JWT时陷入细节反复修改同一个文件。这时max_iterations参数就起到了作用。你也可以在观察日志时通过抛出异常或在提示词中强调“请先完成核心功能细节后续优化”来引导它。智能体的表现很大程度上取决于提示词的质量和工具的粒度。7. 调试与优化让你的智能体更可靠构建智能体的过程不是一蹴而就的你会遇到各种问题。下面是一些常见问题的排查思路和优化技巧。7.1 常见问题速查表问题现象可能原因解决方案智能体不调用工具直接回答“我无法完成”1. 工具描述不清晰。2. 提示词未明确要求使用工具。3. 模型温度temperature过高导致输出随机。1. 重写工具描述明确使用场景和输入格式。2. 在系统提示词中强调“你必须使用工具”。3. 降低temperature如设为0.1。智能体陷入无限循环反复调用同一工具1. 工具返回的结果未能让模型理解任务已进展。2. 模型对当前状态判断错误。1. 检查工具返回的信息是否清晰。例如执行成功应返回“成功”而非空字符串。2. 在提示词中加入“如果你认为上一步已经成功请进行下一步”。3. 设置较小的max_iterations。模型输出格式解析错误Parsing error模型没有严格按照LangChain要求的JSON格式输出工具调用指令。1. 设置handle_parsing_errorsTrue。2. 在提示词中提供更清晰的格式示例。3. 使用更强大的模型如DeepSeek最新版本。工具执行出错如文件不存在、命令失败1. 智能体对工作环境状态理解有误。2. 路径或命令拼写错误。1. 增强工具的健壮性在工具函数内做好错误捕获并返回详细的错误信息给模型。2. 让智能体在操作前先使用read_file或execute_shell如ls查看状态。智能体生成的代码有逻辑错误模型本身的知识局限或上下文不足。1. 要求智能体在生成代码后用code_lint或编写简单测试来验证。2. 将复杂任务分解为更小的子任务逐个验证。7.2 高级优化技巧定制输出解析器Output ParserLangChain默认的ReAct代理使用特定的格式解析模型输出。如果模型经常不遵守你可以自定义一个更鲁棒的解析器使用正则表达式或尝试多种格式来提取工具调用信息。使用更智能的Agent类型除了create_react_agentLangChain还提供了create_self_ask_with_search_agent、create_openai_tools_agent等。对于编程任务OpenAI的function calling格式被很多模型兼容可以尝试create_openai_tools_agent它能产生更结构化的工具调用请求。引入“验证”步骤在关键操作后如写入重要文件、安装关键依赖可以设计一个验证工具或者让智能体在提示词中养成“验证”的习惯。例如“在安装requests包后请验证安装是否成功。”实现长时记忆ConversationBufferMemory会保存所有历史可能导致上下文过长。对于超长对话可以使用ConversationSummaryMemory或ConversationBufferWindowMemory来摘要或只保留最近几轮对话。流式输出最终结果在agent_executor.invoke()时使用stream模式可以实时看到智能体的思考过程和最终答案的生成体验更好。7.3 一个调试案例智能体不创建文件假设你让智能体“创建一个app.py文件”但它总是回答“我已经在思考中创建了”却没有实际调用write_file工具。排查步骤检查verbose日志首先看模型输出的原始内容。是不是模型输出了类似{action: write_file, ...}的文本但被错误解析了检查工具描述write_file的描述是否足够清晰输入格式要求是JSON字符串描述里写明白了吗修改提示词在系统提示词中明确写出“当你需要创建或修改文件时你必须调用write_file工具不要只在思考中描述。”提供示例在提示词中直接给一个工具调用的例子。简化任务测试先给一个极其简单的任务测试工具调用是否正常如“请调用write_file工具创建一个名为test.txt的文件内容为hello”。通过这种层层递进的调试你能逐渐摸清智能体的“脾气”并找到最优的配置方式。构建一个稳定可靠的智能体是一个需要耐心和反复迭代的过程。