Module 1 的收官项目——把所有技能整合在一起:用 Tavily 搜索菜谱、用 InMemorySaver 记住用户食材、用 System Prompt 定义厨师角色,构建一个真实可用的个人厨师 Agent。
个人厨师 Agent 是 Module 1 的综合实战项目,它集成了前面所有课程的核心能力:
个人厨师 Agent 是一个真实可用的应用:用户告诉 Agent 家里有什么食材,Agent 搜索对应的菜谱,在后续对话中记住用户的食材,可以持续提供建议、询问具体做法。这正是 LangChain Agent 的典型使用场景——结合工具调用、记忆和角色设定。
from dotenv import load_dotenv
load_dotenv()
import os
from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
from langchain.messages import HumanMessage
from langchain.tools import tool
from langgraph.checkpoint.memory import InMemorySaver
from tavily import TavilyClient
# ────────────────────────────────────
# 组件 1:模型工厂函数
# ────────────────────────────────────
def deepseek_model(**kwargs):
return init_chat_model(
model="deepseek-chat",
model_provider="openai",
api_key=os.environ["DEEPSEEK_API_KEY"],
base_url="https://api.deepseek.com",
max_tokens=1000,
**kwargs
)
# ────────────────────────────────────
# 组件 2:Web 搜索工具
# ────────────────────────────────────
tavily_client = TavilyClient()
@tool
def web_search(query: str) -> dict:
"""Search the web for information"""
return tavily_client.search(query)
# ────────────────────────────────────
# 组件 3:System Prompt(厨师角色定义)
# ────────────────────────────────────
system_prompt = """
You are a personal chef. The user will give you a list of ingredients they have left over in their house.
Using the web search tool, search the web for recipes that can be made with the ingredients they have.
Return recipe suggestions and eventually the recipe instructions to the user, if requested.
"""
# ────────────────────────────────────
# 组件 4 + 5:Agent = 模型 + 工具 + System Prompt + 记忆
# ────────────────────────────────────
agent = create_agent(
model=deepseek_model(),
tools=[web_search],
system_prompt=system_prompt,
checkpointer=InMemorySaver()
)
System Prompt 是这个 Agent 的"灵魂"——它定义了 Agent 的角色、能力边界和响应方式:
system_prompt = """
You are a personal chef. The user will give you a list of ingredients they have left over in their house.
Using the web search tool, search the web for recipes that can be made with the ingredients they have.
Return recipe suggestions and eventually the recipe instructions to the user, if requested.
"""
这个 prompt 做了三件事:
LLM 有大量烹饪知识,不指示使用工具时,它可能直接凭自己的知识回答——这对于菜谱来说看起来合理,但可能与用户现有食材不匹配,或者给出不准确的做法。通过 system prompt 明确要求"search the web",确保 Agent 总是基于搜索结果给出建议,而不是凭空生成。
这里的 web_search 工具比之前的稍有不同——使用了 @tool 的简化写法(不指定 name,自动用函数名),并且 description 来自 docstring:
@tool # 简化写法:name 自动为 "web_search"
def web_search(query: str) -> dict:
"""Search the web for information""" # docstring 作为 description
return tavily_client.search(query)
显式写法(推荐):@tool("web_search", description="Search the web for...")
简化写法(本例):@tool,name = 函数名,description = docstring
简化写法更简洁,但要确保函数名清晰(web_search 而不是 search)、docstring 描述充分。
config = {"configurable": {"thread_id": "1"}}
# 轮次 1:告诉 Agent 有什么食材
response = agent.invoke(
{"messages": [HumanMessage(content="I have some leftover chicken and rice. What can I make?")]},
config
)
print(response['messages'][-1].content)
Agent 调用了 web_search,搜索"chicken and rice recipes",基于搜索结果给出了 3 个建议,并邀请用户选择一个要详细步骤的菜谱。
# 轮次 2:用户要鸡肉炒饭的做法(Agent 记住了上一轮的食材)
response2 = agent.invoke(
{"messages": [HumanMessage(content="Can you give me the detailed recipe for chicken fried rice?")]},
config
)
print(response2['messages'][-1].content)
在轮次 2 里,用户直接说"give me the detailed recipe for chicken fried rice",没有重复提到"chicken and rice"。Agent 之所以能理解这个请求并给出正确回应,是因为InMemorySaver 保存了轮次 1 的对话历史——Agent 知道之前讨论了哪几个菜谱选项。
当用户说"I have some leftover chicken and rice. What can I make?"时,Agent 内部的完整执行流程:
HumanMessage 加入消息列表。Checkpointer 加载当前 thread_id 的历史(第一轮为空)。
模型看到 system prompt(厨师角色)+ 历史消息 + 用户消息。它推理:"用户有 chicken 和 rice,我应该用 web_search 工具找菜谱"。输出一个 tool_call。
LangGraph 执行 web_search("chicken and rice recipes"),获取 Tavily 搜索结果,封装为 ToolMessage 加入消息历史。
模型看到搜索结果,基于真实数据生成菜谱建议。输出最终的 AIMessage(文字答案)。
InMemorySaver 保存此次执行的完整消息历史(包括 HumanMessage + AIMessage + ToolMessage)。下次同 thread_id 调用时自动加载。
至此,Module 1 的 7 个 Lesson 全部完成。以下是完整的知识全景:
init_chat_model — 统一初始化create_agent — 构建 Agentinvoke / stream — 调用方式response_format=Pydantic — 结构化输出structured_response — 取 Pydantic 对象@tool 装饰器 — 定义工具tools=[...] — 绑定到 AgentInMemorySaver — 内存 Checkpointerthread_id — 区分对话上下文Module 1 建立了 LangChain Agent 的完整基础:模型调用、提示工程、工具调用、记忆。Module 2 将深入探索更复杂的 Agent 设计模式——多 Agent 协作、状态管理、更复杂的记忆策略等。个人厨师 Agent 是一个很好的起点,真实项目的 Agent 就是这样一步步构建起来的。