入門:從原理到實踐的完整路線)
被“大模型Agent開發(fā)入門”這個題目吸引進來的朋友估計和我一樣腦子里已經(jīng)裝了無數(shù)個名詞Function Calling、ReAct、LangChain、Dify、記憶、工具調(diào)用……但真正想動手的時候又不知道從哪里下手。我去年底開始做Agent相關(guān)項目從只會用Python寫死邏輯到今天把一個能查庫存、發(fā)通知、自動填報表的Agent跑在測試環(huán)境里中間踩了不少坑。這篇文章就把我的入門路線、代碼思路和避坑清單整理出來給準備入坑的同行一個參考。不管你是后端開發(fā)、算法工程師、測試同學還是產(chǎn)品經(jīng)理只要有一點點Python基礎(chǔ)能裝Python環(huán)境都能順著這條路線把Agent跑起來。我不打算堆概念而是盡量還原真實的開發(fā)過程包括環(huán)境怎么搭、模型怎么選、代碼怎么寫、框架怎么對比、上線前會遇到哪些坑。1. Agent到底是什么和普通API調(diào)用有什么區(qū)別1.1 從“聊天機器人”到“干活小助手”的質(zhì)變很多人一開始會把“大模型Agent”和“聊天機器人”劃等號。如果只是調(diào)API讓大模型回答“今天天氣怎么樣”那是普通的對話充其量叫LLM應用。真正的Agent是把大模型當作“大腦”讓它根據(jù)目標自主推理、拆解步驟、調(diào)用外部工具然后把結(jié)果反饋給用戶。比如同樣是問天氣一個普通聊天機器人只會回答“我沒辦法獲取實時天氣”而一個Agent會先去調(diào)用天氣API拿到數(shù)據(jù)后告訴你“北京今天晴氣溫-2℃到6℃”。這個“思考-行動-觀察-再思考”的循環(huán)就是Agent的核心本質(zhì)。業(yè)界經(jīng)常提到ReAct模式Reasoning and Acting正是把推理和行動交替執(zhí)行。你可以把它想象成一個新來的實習生領(lǐng)導交代一件事他不會傻坐著而是先理解任務再查資料遇到問題就問然后把結(jié)果整理好交給你。Agent要做的就是這套流程只不過“查資料”變成了調(diào)用API“問”變成了向模型發(fā)出工具請求“整理結(jié)果”變成了生成最終回答。1.2 一個最簡單的Agent循環(huán)是怎么跑的我第一版Agent代碼連框架都沒用就是用Python手寫的一個while循環(huán)大致長這樣messages [{role: system, content: 你是一個樂于助人的助理。}] max_steps 5 for step in range(max_steps): # 1. 把當前對話歷史發(fā)給大模型 response llm_client.chat(messagesmessages) content response[content] # 2. 大模型判斷是否需要調(diào)用工具 if 需要調(diào)用工具 in content: tool_name, tool_args parse_tool_request(content) result run_tool(tool_name, tool_args) # 3. 實際執(zhí)行外部工具 messages.append({role: assistant, content: content}) messages.append({role: tool, content: result}) continue # 4. 如果不需要工具就當作最終回答輸出 print(content) break這一步想清楚之后所有框架都只是把上面這個循環(huán)包裝得更好用而已。我建議你不管最后用什么框架先把這段邏輯寫一遍理解“Agent 大模型 工具 循環(huán)”這個本質(zhì)。1.3 幾個必須搞懂的基礎(chǔ)概念在動手之前下面幾個詞一定要搞明白否則看文檔會一頭霧水。Function Calling / Tool Calling大模型輸出一個結(jié)構(gòu)化的“調(diào)用意圖”比如{name: get_weather, arguments: {city: 北京}}。它本身不執(zhí)行函數(shù)只是告訴你的程序“該去調(diào)用哪個工具了”。System Prompt放在對話開頭用來定角色、定規(guī)則。Agent的行為邊界一大半靠它控制。記憶MemoryAgent和用戶的對話歷史。短期記憶是當前上下文窗口內(nèi)的消息長期記憶則需要外部存儲不知道之前聊了什么就沒法個性化。上下文長度Context Length模型能同時“看到”的token數(shù)量。比如8K、32K、128K超過這個量就得截斷或摘要。ReAct一種推理模式——模型每完成一次“想”和“做”再結(jié)合觀察結(jié)果繼續(xù)下一步。這些概念不用一下子全看懂但看到時要能反應過來后面所有章節(jié)都會碰到。2. 環(huán)境準備從零拉起一套可復現(xiàn)的開發(fā)環(huán)境2.1 硬件與模型選型不是所有人都要上A100很多人被“大模型”三個字嚇住以為必須買幾千塊的顯卡。其實Agent開發(fā)初期完全可以不跑本地大模型。三種常見方案方案成本適合人群代表模型云端API按量付費幾十塊錢能用很久快速驗證想法、不想折騰硬件通義千問、Kimi、DeepSeek、智譜GLM、豆包等本地小模型一臺8G顯存以上的機器數(shù)據(jù)敏感、離線環(huán)境、長期調(diào)優(yōu)Qwen2.5系列1.5B-14B、Llama 3.2本地大模型加速卡中高成本團隊級私有化部署Qwen2.5-72B、DeepSeek系列我的經(jīng)驗是入門階段優(yōu)先用云端API。注冊一個平臺拿到Key就能開始寫代碼。等到需要頻繁測試、大量調(diào)用再考慮本地部署也不遲。2.2 用Ollama快速拉起本地模型如果你還是想完全本地跑我最推薦的就是Ollama。它支持macOS、Linux、Windows把模型下載、啟動、調(diào)用全封裝成一條命令。安裝好之后在終端執(zhí)行ollama pull qwen2.5:7b ollama run qwen2.5:7b一個可以在本地對話的模型就跑起來了。它的接口兼容OpenAI格式Python代碼可以直接這么連import ollama response ollama.chat(modelqwen2.5:7b, messages[ {role: user, content: 你好介紹一下你自己} ]) print(response[message][content])我之前在一臺16G內(nèi)存的MacBook Pro上跑過7B模型雖然生成速度不算快但用來做功能測試完全夠用。如果是企業(yè)私有化部署建議上帶GPU的服務器跑14B或更大參數(shù)模型效果差距明顯。2.3 調(diào)API和本地模型怎么選不只是成本問題很多初學者會糾結(jié)“用哪個”。我踩過一輪坑總結(jié)出來的選擇邏輯是這樣的開發(fā)調(diào)試階段用云端API。速度快、模型智商高、不用操心環(huán)境先驗證流程沒問題。數(shù)據(jù)敏感場景比如企業(yè)內(nèi)部的客戶信息、代碼庫、財務數(shù)據(jù)這類內(nèi)容不能出內(nèi)網(wǎng)。這時候必須本地部署哪怕犧牲一點模型效果。長期成本優(yōu)化如果每天調(diào)用百萬級token本地部署的成本邊際遞減更劃算。離線容災需求有些場景網(wǎng)絡(luò)不穩(wěn)定或者需要7x24小時穩(wěn)定運行本地部署更可靠。另外真正做生產(chǎn)系統(tǒng)時很多人會同時接多個模型簡單任務用便宜的小模型復雜推理用強模型。這種“模型路由”的思路可以從一開始就留好接口。2.4 關(guān)鍵參數(shù)上下文長度、temperature、top_p剛開始我直接照抄別人的代碼完全沒管參數(shù)結(jié)果“nonsense”一堆。后來才意識到Agent本身是不確定系統(tǒng)參數(shù)就是它的“性格開關(guān)”。temperature溫度值越低輸出越穩(wěn)定、越保守值越高越有創(chuàng)造性。做Agent我一般設(shè)0.1~0.3寧可讓它無聊也不能讓它胡編。top_p核采樣控制在候選詞的概率累計范圍。0.9表示每次只從概率最高的一批詞里選值越小越穩(wěn)定。通常和temperature二選一調(diào)整不要同時拉滿。max_tokens / max_length單次生成的最大token數(shù)。如果Agent需要輸出代碼、JSON、長文一定要給足空間否則會被截斷導致解析失敗。上下文長度注意模型的最大上下文限制。對話歷史太大會超限太小會失憶。后面第5章會細說處理策略。response llm_client.chat( messagesmessages, temperature0.2, top_p0.8, max_tokens1024 )這個參數(shù)組合適用于絕大多數(shù)Agent場景實測下來既不會太死板也不會亂飛。3. 核心環(huán)節(jié)實現(xiàn)做一個會查庫存、發(fā)通知的Agent3.1 明確需求場景先定一個能落地的目標我建議第一個Agent不要做“全能助手”而是做一個“單點任務助手”。我自己的例子是做一個查詢庫存并發(fā)送告警的Agent。它需要知道用戶想問哪個商品的庫存如果低于閾值就調(diào)用發(fā)消息的工具通知倉庫管理員。場景越具體后面的Prompt、工具設(shè)計、測試預期就越清晰。你會很清楚地知道“這個Agent到底跑通了沒有”而不是玄學式地“感覺它挺聰明”。3.2 工具注冊把外部能力變成大模型認識的方法要讓大模型知道可以用你定義的函數(shù)需要在請求里傳入“工具定義”。以O(shè)penAI風格接口為例tools [ { type: function, function: { name: get_stock_count, description: 查詢某個商品的實時庫存, parameters: { type: object, properties: { product_id: { type: string, description: 商品ID例如P10001 } }, required: [product_id] } } }, { type: function, function: { name: send_dingtalk_notice, description: 發(fā)送釘釘通知給倉庫管理員, parameters: { type: object, properties: { message: { type: string, description: 告警內(nèi)容 } }, required: [message] } } } ]關(guān)鍵點在于每個工具的description要寫得非常具體。我一開始寫的是“查詢庫存”模型經(jīng)常不知道什么時候該調(diào)用改成“查詢某個商品的實時庫存當用戶給出商品ID時調(diào)用”之后識別率提升一大截。描述文字是模型理解工具用途的重要輸入不要偷懶。3.3 實現(xiàn)真正的Function Calling用代碼把“動作”接上大模型返回一個類似下面的結(jié)構(gòu)化內(nèi)容{ role: assistant, content: null, tool_calls: [ { id: call_123, type: function, function: { name: get_stock_count, arguments: {\product_id\: \P10001\} } } ] }你的程序需要解析tool_calls把里面的參數(shù)交給注冊好的Python函數(shù)然后“模擬”一條工具回復消息傳回去def execute_tool_call(tool_call, tools_map): func_name tool_call[function][name] args json.loads(tool_call[function][arguments]) result tools_map[func_name](**args) return { tool_call_id: tool_call[id], role: tool, content: str(result) }把執(zhí)行結(jié)果附加到對話歷史再繼續(xù)請求模型模型就會基于工具的實際返回內(nèi)容生成最終回答。這一步一定要自己手動實現(xiàn)一遍后面不管用什么框架都不會變成“只會改配置的調(diào)包俠”。3.4 給Agent加記憶不能聊完就忘很多人忽略了記憶導致Agent一多輪就“失憶”。最簡單的短期記憶方案是把歷史消息保存在一個列表里每次請求都帶上。但列表不能無限長否則很快超過上下文限制。我實測了幾種做法滑動窗口只保留最近6-8輪消息。簡單直接適合多數(shù)場景。摘要壓縮每5輪把所有消息丟給模型生成一段摘要然后替換掉舊消息。適合對話很長、需要保留細節(jié)的場景。外部向量存儲把關(guān)鍵信息寫進向量數(shù)據(jù)庫需要時通過相似度檢索召回。適合有大量歷史知識的情況。初期項目用滑動窗口就夠了。真正要落地時我會同時用兩種策略滑動窗口保短期向量庫做長期記憶。3.5 組裝Agent循環(huán)從沒頭沒尾的腳本變成一個小系統(tǒng)當我完成工具注冊和記憶以后整個代碼結(jié)構(gòu)會變得清晰起來分成四個模塊agent/ ├── core_loop.py # 主循環(huán)負責調(diào)度 ├── tools/ # 所有工具函數(shù) ├── memory.py # 記憶管理 └── config.py # 模型、參數(shù)配置主循環(huán)的核心邏輯依然是“調(diào)模型 - 判斷工具 - 執(zhí)行工具 - 再調(diào)模型”。我建議把最大循環(huán)次數(shù)限制在5~8次。因為Agent有時會陷入死循環(huán)連續(xù)調(diào)用同一個工具限制次數(shù)能幫你盡早發(fā)現(xiàn)異常。for step in range(max_steps): response llm.chat(messagesmessages, toolstools) assistant_msg response.choices[0].message if not assistant_msg.tool_calls: return assistant_msg.content messages.append(assistant_msg) for tool_call in assistant_msg.tool_calls: tool_result execute_tool_call(tool_call, tools_map) messages.append(tool_result)這就是一個最小可用的Agent核心。4. 框架對比LangChain、Dify還是自研4.1 從零自己寫自由度最高但要控制復雜度如果你只是寫幾十行Python完全不需要引入框架。自研的好處是所有細節(jié)都受你控制不會出現(xiàn)“框架封裝太深出了問題不知道在哪”的窘境。但一旦你要做多Agent協(xié)作、條件分支、并行工具調(diào)用、長時間任務自己寫就容易亂套。我有個同事用自研代碼做了六個月后來發(fā)現(xiàn)維護成本比業(yè)務邏輯還高。所以我的建議是前期自研跑通流程復雜化以后及時切換框架。4.2 LangChain / LangGraph生態(tài)豐富但不要被“大而全”迷惑LangChain可能是提到Agent最容易被想到的框架。它內(nèi)置了Prompt模板、Memory、Tool、Agent類型等一大堆模塊。優(yōu)點是可以快速拼裝但缺點是抽象層太厚剛?cè)腴T會踩很多“類名看懂但不知道干什么”的坑。LangGraph是LangChain團隊后來推出的更底層編排框架核心是“圖”結(jié)構(gòu)節(jié)點是任務邊是跳轉(zhuǎn)條件。它把Agent循環(huán)可視化了適合做有狀態(tài)、可分支的復雜任務。如果你是第一次接觸我的建議是先不急著用LangChain的Agent封裝用它的ChatOpenAI、tool decorator、Memory模塊自己搭一個幾十行的循環(huán)。這樣既能利用生態(tài)里現(xiàn)成的東西又不至于被它牽著鼻子走。4.3 Dify可視化配置適合產(chǎn)品經(jīng)理快速驗證Dify是一個開源的大模型應用開發(fā)平臺最大的特點是可視化編排。你在網(wǎng)頁上拖拽節(jié)點開始節(jié)點、大模型節(jié)點、工具節(jié)點、知識庫檢索節(jié)點、結(jié)束節(jié)點就能生成一個Agent應用。這種方式特別適合非程序員快速驗證也適合團隊里讓產(chǎn)品經(jīng)理先畫流程再由工程師接入真實代碼。Dify可以接入本地模型和多種云端模型還可以通過“自定義工具”的方式接入自己的API。不過它也有代價一旦流程比較復雜圖節(jié)點的維護成本會比代碼高版本管理也不太方便。我的定位是“原型驗證工具”生產(chǎn)鏈路還是用代碼更踏實。4.4 我的選型建議按階段選擇我個人的策略是分三步走第1周純Python 云端API手寫ReAct循環(huán)完全理解原理。第2~4周引入LangGraph實現(xiàn)工具并行、條件分支、多節(jié)點編排。項目需要快速出Demo時用Dify快速搭界面和流程同步用代碼重構(gòu)底層。這個路線看起來“繞路”但實際學習效率最高。你既不會被框架束縛又能在后續(xù)規(guī)?;瘯r借助框架的能力。對比項自研PythonLangGraphDify學習成本低中高低靈活度高高中適合階段原理學習、輕量場景生產(chǎn)級復雜編排原型、低代碼團隊調(diào)試難度低中低模塊復用自己造輪子生態(tài)豐富內(nèi)置大量工具5. 常見問題與排查技巧實錄5.1 AI Agent怎么扛并發(fā)從“單線程”到“可擴容”很多人第一次做Agent會遇到性能問題模型返回慢一個請求要幾秒甚至十幾秒并發(fā)一上來直接卡死。這里有幾個建議把大模型調(diào)用放在異步接口里。不要用同步阻塞的方式等待模型返回用FastAPI的async或異步客戶端。給Agent流程設(shè)置超時時間。比如單次工具調(diào)用3秒模型調(diào)用15秒整體循環(huán)30秒。寧可超時返回也不要無限等。使用消息隊列削峰。Agent和普通接口不一樣它不是毫秒級操作。如果業(yè)務允許把請求放到Redis或RabbitMQ隊列里異步處理前端輪詢結(jié)果。對模型API做并發(fā)池整理。不同任務分配不同并發(fā)上限避免某個大任務的慢調(diào)用占滿所有連接。from fastapi import FastAPI from contextlib import asynccontextmanager import asyncio app FastAPI() async def run_agent(query: str): return await asyncio.to_thread(agent.run, query) app.post(/agent) async def agent_endpoint(query: str): # 異步提交避免阻塞 task asyncio.create_task(run_agent(query)) return {task_id: str(task)}5.2 Token超限與上下文截斷最常見的報錯就是“This models maximum context length is 8192 tokens”。原因很簡單你把整個對話歷史都塞進去了。處理方式我已經(jīng)在前面提過這里再補充一個經(jīng)驗優(yōu)先提問時截舊消息不要截尾。尾部是模型最近看到的內(nèi)容對你的當前指令和上下文連續(xù)性影響最大。另外可以在對話歷史里插入一個system消息提示“之前的信息已經(jīng)摘要為...”再接入原文模型通常能接受這種“打斷”。還有一種情況是工具返回結(jié)果太長。比如查詢庫存接口返回了1000條明細直接塞進消息里很容易撐爆上下文。我在實踐中的做法是截斷到前50行并在后面追加一句“共1000條已展示前50條如需繼續(xù)請指定條件”。5.3 模型“偷懶”不調(diào)用工具怎么調(diào)教新手最容易遇到的問題模型就是不肯調(diào)用工具明明用戶都說了“查一下A商品庫存”它偏偏回答說“我無法查詢實時庫存”。是我的話會按這個順序排查檢查工具定義中的description是不是太模糊沒有觸發(fā)條件。改成“當用戶詢問任何商品庫存時調(diào)用此工具”。給Prompt加先例在系統(tǒng)提示里明確寫“你具備查詢庫存的能力當用戶詢問庫存時必須調(diào)用get_stock_count工具”??茨P头祷氐脑純?nèi)容有時候模型其實生成了tool_calls但你的解析代碼沒接住。打印一下原始響應確認是模型問題還是代碼問題。換更強的模型小模型1B、3B的指令遵循能力弱經(jīng)常聽不懂“工具調(diào)用”要求。換7B及以上問題立刻緩解。5.4 輸出格式不穩(wěn)定JSON解析失敗怎么辦Agent經(jīng)常需要輸出JSON給下游系統(tǒng)解析。但模型有時會在JSON前后加json標記、加說明文字導致json.loads直接報錯。我試過幾種應對辦法最有效的兩步是在Prompt里指定“只輸出JSON不要包含任何額外說明或代碼塊標記”。在代碼里寫一個貪婪解析函數(shù)先用正則找{...}或[...]最外層結(jié)構(gòu)再嘗試解析。import re import json def parse_json_response(content: str): # 去掉可能的json 標記 content re.sub(r(?:json)?, , content).strip() try: return json.loads(content) except json.JSONDecodeError: match re.search(r\{.*\}, content, re.DOTALL) if match: return json.loads(match.group(0)) raise ValueError(無法解析模型輸出為JSON)5.5 多步任務中的“幻覺”與控制策略AI Agent多步執(zhí)行時間越長越容易在某個中間步驟“自我發(fā)揮”。比如Agent要查庫存-生成補貨單-發(fā)通知結(jié)果它跳過了第二步直接發(fā)通知。我的體會是不要讓模型自己決定“下一步做什么”太開放。給它一個固定的工作流模板比如第1步根據(jù)用戶問題識別商品ID。第2步調(diào)用庫存查詢工具。第3步判斷是否低于閾值。第4步如果低于閾值調(diào)用告警工具。第5步生成總結(jié)回復。在System Prompt里把步驟一條條寫清楚同時限制最大步驟數(shù)。對于關(guān)鍵業(yè)務動作寧可把流程拆成多個小Agent也不要用一個Agent自由發(fā)揮到底。6. 從Demo到落地進階方向與經(jīng)驗分享6.1 企業(yè)私有化部署的取舍最近“企業(yè)大模型私有化部署”這個詞非常熱。如果你們公司已經(jīng)有內(nèi)網(wǎng)GPU服務器想部署開源模型我建議按這個順序做用LM Studio或Ollama在單機上跑通模型。用vLLM或TensorRT-LLM這樣的推理引擎部署為HTTP服務吞吐量比Ollama高不少。配置鑒權(quán)、限流、監(jiān)控比如用Prometheus收集請求量、GPU利用率、平均延遲。結(jié)合向量數(shù)據(jù)庫如Milvus、Qdrant做知識庫檢索讓Agent能回答私有文檔問題。另外糾一個常見認知私有化部署不只是“模型放本地”還包括數(shù)據(jù)鏈路、運維、升級。模型版本更新很頻繁你要考慮部署腳本是否可持續(xù)。我建議把模型文件、推理服務配置、Agent代碼都納入統(tǒng)一的版本管理中。6.2 大模型微調(diào)該不該做什么時候做被“大模型微調(diào)”吸引進來的人很多但我想潑一點冷水90%的Agent項目不需要微調(diào)。在Agent領(lǐng)域效果提升的第一來源是“工程”包括Prompt優(yōu)化、工具設(shè)計、流程編排、記憶策略。微調(diào)是后期手段用來解決“同樣的問題反復錯、且Prompt已經(jīng)改不動”的情況。比如你發(fā)現(xiàn)模型對某個專業(yè)名詞理解錯位而更換Prompt無濟于事這時才考慮收集幾百條數(shù)據(jù)做LoRA微調(diào)。前期微調(diào)不僅成本高還可能因為數(shù)據(jù)量不足導致災難性遺忘。6.3 多模態(tài)Agent不只是“看圖說話”多模態(tài)大模型最近進展很快Agent也開始集成圖像輸入、語音輸入。一個簡單場景是用戶拍一張貨架照片Agent識別商品信息然后查庫存再發(fā)補貨單。實現(xiàn)上并不復雜把圖片經(jīng)過編碼傳給多模態(tài)模型接口在Prompt里增加“根據(jù)圖片識別出商品ID”的指令即可。但要注意圖片大小、清晰度、token消耗——一張高分辨率圖片轉(zhuǎn)成token后可能占幾千token記得在對話里壓縮。6.4 給入坑者的最后建議如果你正在考慮要不要學Agent開發(fā)我的答案很直接值得但別只學“調(diào)API”。把這個領(lǐng)域拆開其實包含三塊能力大模型使用能力、工程落地能力、產(chǎn)品設(shè)計能力。三塊缺一不可。我個人在實際操作中最深的體會是Agent開發(fā)百分之六十的時間花在“讓模型穩(wěn)定聽話”上剩下的時間才是寫業(yè)務邏輯。模型本身的不確定性決定了你必須在外部建立各種約束清晰的工具描述、嚴格的步驟限制、健壯的格式解析、完善的日志追蹤。這些東西不是框架能替你做好的只有自己踩過坑才能真正理解。如果你現(xiàn)在還沒有環(huán)境我建議從今天開始先注冊一個云端模型API的Key用Python寫一個不到一百行的ReAct循環(huán)跑通“查天氣”這個例子。一個小時后你大概率會收到第一條“模型成功調(diào)用工具”的回執(zhí)。那瞬間你會覺得原來Agent真的沒那么玄乎。