AI Agent 開發(fā)的坑(Function Call)
引言
AI Agent(智能代理)是當前AI領(lǐng)域的熱門話題,它能夠理解用戶意圖、調(diào)用工具、執(zhí)行任務(wù)并給出智能回答。本文將帶你從零開始,一步步構(gòu)建一個功能完整的AI Agent,并分享開發(fā)過程中的關(guān)鍵問題和解決方案。
什么是AI Agent?
AI Agent是一個能夠感知環(huán)境、做出決策并執(zhí)行行動的智能系統(tǒng)。它結(jié)合了大型語言模型(LLM)的推理能力和各種工具的實用功能,能夠完成復(fù)雜的任務(wù)。
項目架構(gòu)設(shè)計
核心組件
我們的AI Agent包含以下核心組件:
- 語言模型:負責理解用戶意圖和生成回答
- 工具系統(tǒng):提供具體的功能實現(xiàn)
- 工作流引擎:協(xié)調(diào)各個組件的工作
- 狀態(tài)管理:跟蹤執(zhí)行過程
技術(shù)棧選擇
# 核心依賴
from langgraph.graph import StateGraph, END
from mcp.server import Server
from openai import OpenAI開發(fā)過程與關(guān)鍵問題
問題1:LangGraph配置錯誤
錯誤信息:
ValueError: Checkpointer requires one or more of the following 'configurable' keys: thread_id, checkpoint_id解決方案:
# 錯誤做法:在AgentState中包含保留字段
class AgentState(TypedDict):
thread_id: str # ? 這是LangGraph保留字段
checkpoint_id: str # ? 這是LangGraph保留字段
# 正確做法:避免使用保留字段名
class AgentState(TypedDict):
messages: List[Dict[str, Any]]
current_step: str
tools_used: List[str]
final_result: str經(jīng)驗總結(jié):框架的保留字段名不能用作狀態(tài)字段,需要仔細閱讀文檔。
問題2:無限循環(huán)問題
錯誤信息:
GraphRecursionError: Recursion limit of 25 reached without hitting a stop condition解決方案:
# 使用條件邊避免無限循環(huán)
workflow.add_conditional_edges(
"agent",
self._should_continue, # 決策函數(shù)
{
"tools": "tools", # 需要工具 → 調(diào)用工具
"end": END # 完成任務(wù) → 結(jié)束
}
)
def _should_continue(self, state: AgentState) -> str:
if state["current_step"] == "tool_call":
return"tools"
else:
return"end"經(jīng)驗總結(jié):工作流設(shè)計必須考慮停止條件,避免無限循環(huán)。
問題3:工具調(diào)用格式問題
問題描述:模型不理解如何調(diào)用工具,直接回答問題而不使用工具。
解決方案:
# 明確的系統(tǒng)提示
system_prompt = """重要:當需要調(diào)用工具時,你必須使用以下格式:
TOOL_CALL: 工具名 參數(shù)JSON
例如:
- 用戶說"讀取當前目錄",你應(yīng)該回復(fù):TOOL_CALL: list_directory {"directory_path": "."}
- 用戶說"讀取demo.py文件",你應(yīng)該回復(fù):TOOL_CALL: read_file {"file_path": "demo.py"}
不要直接回答用戶的問題,而是調(diào)用相應(yīng)的工具。"""經(jīng)驗總結(jié):系統(tǒng)提示必須明確、具體,包含格式示例。
問題4:API格式?jīng)_突
錯誤信息:
messages with role "tool" must be a response to a preceeding message with "tool_calls"解決方案:
# 錯誤做法:使用tool角色
conversation.append({"role": "tool", "content": f"工具結(jié)果: {tool_result}"})
# 正確做法:使用assistant角色
conversation.append({"role": "assistant", "content": f"我調(diào)用了工具 {tool_name},結(jié)果是:{tool_result}"})經(jīng)驗總結(jié):要遵循API規(guī)范,避免使用不支持的對話角色。
最終實現(xiàn)效果
經(jīng)過修復(fù)后,我們的AI Agent能夠成功執(zhí)行各種任務(wù):
文件操作
用戶: 請幫我讀取當前目錄的內(nèi)容
Agent: 當前目錄的內(nèi)容包括以下文件和子目錄:
- `demo.py`
- `langgraph_demo.py`
- `__pycache__`(這是一個緩存目錄)情感分析
用戶: 分析這句話的情感:'這個產(chǎn)品真的很棒,我非常喜歡!'
Agent: 根據(jù)分析結(jié)果,這句話的情感是積極的。表達了對產(chǎn)品的高度贊賞和喜愛。數(shù)據(jù)處理
用戶: 計算這些數(shù)字的統(tǒng)計信息:[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Agent: 這些數(shù)字的統(tǒng)計信息如下:
- 總數(shù): 10
- 總和: 55
- 平均值: 5.50
- 最小值: 1
- 最大值: 10關(guān)鍵技術(shù)要點
1. 工具系統(tǒng)設(shè)計
class FileToolsServer:
def __init__(self):
self.server = Server("file-tools")
@self.server.list_tools()
async def list_tools() -> ListToolsResult:
# 定義工具接口
@self.server.call_tool()
async def call_tool(name: str, arguments: dict) -> CallToolResult:
# 實現(xiàn)工具邏輯2. 狀態(tài)管理
class AgentState(TypedDict):
messages: List[Dict[str, Any]] # 對話歷史
current_step: str # 執(zhí)行步驟
tools_used: List[str] # 工具使用記錄
final_result: str # 最終輸出3. 錯誤處理
try:
tool_result = self._call_tool(tool_name, tool_args)
except Exception as e:
tool_result = f"工具調(diào)用失敗: {str(e)}"開發(fā)建議
1. 漸進式開發(fā)
- 先實現(xiàn)簡單的工具調(diào)用
- 逐步添加復(fù)雜功能
- 每個階段都要充分測試
2. 調(diào)試技巧
- 添加詳細的日志輸出
- 使用print語句跟蹤執(zhí)行流程
- 分步驟驗證每個組件
3. 代碼組織
- 分離工具定義和實現(xiàn)
- 使用統(tǒng)一的錯誤處理
- 保持代碼的可讀性和可維護性
擴展方向
- 增加更多工具:網(wǎng)絡(luò)請求、數(shù)據(jù)庫操作、圖像處理等
- 優(yōu)化決策邏輯:使用更智能的工具選擇策略
- 添加記憶功能:記住用戶偏好和歷史交互
- 實現(xiàn)并行處理:同時執(zhí)行多個工具任務(wù)
- 增加安全控制:限制工具使用權(quán)限
總結(jié)
AI Agent的開發(fā)是一個迭代的過程,需要不斷調(diào)試和優(yōu)化。關(guān)鍵是要理解:
- 框架限制:了解使用的框架有哪些限制和保留字段
- API規(guī)范:嚴格遵循API的使用規(guī)范
- 系統(tǒng)提示:提供明確、具體的指令給模型
- 錯誤處理:做好異常情況的處理
通過這個實戰(zhàn)項目,我們不僅學(xué)會了如何構(gòu)建AI Agent,更重要的是掌握了解決實際開發(fā)問題的方法。這為未來的AI應(yīng)用開發(fā)奠定了堅實的基礎(chǔ)。





































