快速利用langGraph构建一个Agent(基于deepseek)

# 在同目录.env文件下读取API_KEY
import os
from dotenv import load_dotenv  # 从 .env 文件读取键值对,并将它们添加到环境变量中。
load_dotenv(override=True)      # (override=True) => .env 文件中的变量会 强制覆盖 系统中同名的环境变量

DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")    # 通过键名(如 "PATH")获取操作系统或 .env 文件中的环境变量值
print(DEEPSEEK_API_KEY)
# 初始化大模型
from langchain.chat_models import init_chat_model

# model:模型名称 model_provider模型提供者 会自动加载langchain-deepseek依赖包 会在底层尝试读取下面的DEEPSEEK_API_KEY环境变量
model = init_chat_model(model="deepseek-chat",model_provider="deepseek")
# 对大模型进行交互
result = model.invoke("你好,介绍一下自己")
print(result.content)
你好!很高兴认识你!😊

我是DeepSeek,由深度求索公司创造的AI助手。让我简单介绍一下自己:

**我的特点:**
- 📚 知识截止到2024年7月,是DeepSeek的最新版本模型
- 💬 纯文本对话模型,擅长各种文字交流和分析
- 📁 支持文件上传功能——可以处理图像、txt、pdf、ppt、word、excel等文件,并从中读取文字信息
- 🌐 支持联网搜索(需要你在Web/App手动点开联网搜索按键)
- 💾 拥有128K的上下文长度,能记住我们对话的详细内容

**我能帮你做什么:**
- 回答各种问题,提供信息和建议
- 协助写作、翻译、总结文档
- 分析和处理你上传的文件内容
- 进行逻辑推理和问题解决
- 创意写作和头脑风暴

**使用方式:**
- 完全免费使用,没有收费计划
- 可以通过官方应用商店下载App

我的回复风格比较热情细腻,很乐意用心帮助你解决各种问题!有什么我可以帮你的吗?不管是学习、工作还是生活上的困惑,我都很愿意和你一起探讨!✨

预购建Agent API image-20251008185535682

import requests
from pydantic import BaseModel, Field
from langchain_core.tools import tool

class WeatherQuery(BaseModel): # 定义工具参数结构的地方 Pydantic 会自动帮你检查输入参数的类型、是否缺失、是否符合描述等。
    """天气查询参数"""
    loc: str = Field(..., description="城市名称或城市代码,例如 '北京' 或 '110101'") # 注意 ... 表示“必填项”。

# 添加获取天气的自定义工具(调用高德api)
# @tool 装饰器要求函数 docstring 简洁明了地说明用途、参数、返回值
# @tool(args_schema=WeatherQuery):表示这个工具函数使用 WeatherQuery 作为参数结构。Agent 在调用这个工具时,会自动用这个模型来解析输入,确保输入格式正确。
@tool(args_schema=WeatherQuery)
def get_weather(loc):
    """
    获取指定地点的实时天气信息。

    参数:
        loc (str): 要查询的城市名称或城市代码。例如 "北京"、"110101" 等。

    返回:
        dict: 返回一个包含天气信息的 JSON 字典,主要字段包括:
            - "status": 接口调用状态("1" 表示成功)
            - "count": 返回结果数量
            - "info": 返回说明信息
            - "infocode": 状态码
            - "lives": 实时天气数据列表,常见字段如下:
                - "province": 省份
                - "city": 城市名称
                - "adcode": 城市编码
                - "weather": 天气现象(如 "晴"、"多云")
                - "temperature": 温度(单位:℃)
                - "winddirection": 风向
                - "windpower": 风力级别
                - "humidity": 湿度(百分比)
                - "reporttime": 数据发布时间
    """
    # api接口地址
    url = "https://restapi.amap.com/v3/weather/weatherInfo?parameters"

    # 设置查询参数
    params = {
        "key":os.getenv("GAODE_MAP"),
        "city":loc,
        "extensions":"base",
        "output":"JSON"
    }

    # 最终发送的"https://restapi.amap.com/v3/weather/weatherInfo?key=abc123&city=110101&extensions=base&output=JSON"
    response = requests.get(url,params=params)
    # 解析响应结果
    return response.json()

# 封装后的工具遵循 Runnable 接口,可以使用 invoke 方法来运行一个工具
print(get_weather.invoke("南京"))

{'status': '1', 'count': '1', 'info': 'OK', 'infocode': '10000', 'lives': [{'province': '江苏', 'city': '南京市', 'adcode': '320100', 'weather': '晴', 'temperature': '28', 'winddirection': '东', 'windpower': '≤3', 'humidity': '63', 'reporttime': '2025-10-08 11:32:11', 'temperature_float': '28.0', 'humidity_float': '63.0'}]}

检查一下工具定义是否有问题

print(f'''
      name:{get_weather.name}
      description:{get_weather.description}
      argument:{get_weather.args}
      ''')
      name:get_weather
      description:获取指定地点的实时天气信息。

参数:
    loc (str): 要查询的城市名称或城市代码。例如 "北京"、"110101" 等。

返回:
    dict: 返回一个包含天气信息的 JSON 字典,主要字段包括:
        - "status": 接口调用状态("1" 表示成功)
        - "count": 返回结果数量
        - "info": 返回说明信息
        - "infocode": 状态码
        - "lives": 实时天气数据列表,常见字段如下:
            - "province": 省份
            - "city": 城市名称
            - "adcode": 城市编码
            - "weather": 天气现象(如 "晴"、"多云")
            - "temperature": 温度(单位:℃)
            - "winddirection": 风向
            - "windpower": 风力级别
            - "humidity": 湿度(百分比)
            - "reporttime": 数据发布时间
      argument:{'loc': {'description': "城市名称或城市代码,例如 '北京' 或 '110101'", 'title': 'Loc', 'type': 'string'}}

创建langGraph智能体 https://langchain-ai.github.io/langgraph/reference/agents/?h=create_react_agent

# 封装外部函数列表
tools = [get_weather]

from langgraph.prebuilt import create_react_agent

# 利用api一键构建预设好的agent框架:创建一个代理图,该图在满足停止条件之前循环调用工具。
agent = create_react_agent(model=model,tools=tools) 

response = agent.invoke({"messages":[{"role":"user","content":"请用五个字介绍一下你自己"}]})
print(response)
{'messages': [HumanMessage(content='请用五个字介绍一下你自己', additional_kwargs={}, response_metadata={}, id='9b1d6ed2-8b2c-407a-a586-72f5c44698bd'), AIMessage(content='我是智能小助手', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 4, 'prompt_tokens': 381, 'total_tokens': 385, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}, 'prompt_cache_hit_tokens': 0, 'prompt_cache_miss_tokens': 381}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': 'f8f6b8e2-4881-411c-9ca2-01bb4e1c40b8', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--90e6f2de-f8da-4caa-83de-2f69611d0924-0', usage_metadata={'input_tokens': 381, 'output_tokens': 4, 'total_tokens': 385, 'input_token_details': {'cache_read': 0}, 'output_token_details': {}})]}

下面观察一下Agent怎么利用外部工具来思考问题的。这背后也就是一次完整的Function calling调用流程 image

response = agent.invoke({"messages":[{"role":"user","content":"请问杭州天气怎么样?"}]})
print(response['messages'][0])
content='请问杭州天气怎么样?' additional_kwargs={} response_metadata={} id='7d2f1ab9-f811-4a9f-b14e-e10799f3036b'
print(response['messages'][1])
content='我来帮您查询杭州的天气情况。' additional_kwargs={'tool_calls': [{'id': 'call_00_BTcDP6ovv0cyqEAJxsbfC4JF', 'function': {'arguments': '{"loc": "\\u676d\\u5dde"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}], 'refusal': None} response_metadata={'token_usage': {'completion_tokens': 29, 'prompt_tokens': 380, 'total_tokens': 409, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 320}, 'prompt_cache_hit_tokens': 320, 'prompt_cache_miss_tokens': 60}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': 'fe4fec54-f189-4279-b2cb-d5bcdda4a44f', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None} id='run--604daf5c-98d1-4312-a43c-b10f85d8d1fc-0' tool_calls=[{'name': 'get_weather', 'args': {'loc': '杭州'}, 'id': 'call_00_BTcDP6ovv0cyqEAJxsbfC4JF', 'type': 'tool_call'}] usage_metadata={'input_tokens': 380, 'output_tokens': 29, 'total_tokens': 409, 'input_token_details': {'cache_read': 320}, 'output_token_details': {}}
print(response['messages'][2])
content='{"status": "1", "count": "1", "info": "OK", "infocode": "10000", "lives": [{"province": "浙江", "city": "杭州市", "adcode": "330100", "weather": "多云", "temperature": "31", "winddirection": "北", "windpower": "≤3", "humidity": "57", "reporttime": "2025-10-08 12:06:59", "temperature_float": "31.0", "humidity_float": "57.0"}]}' name='get_weather' id='8d63add6-e752-46a2-a095-3fd3d8b1ed7f' tool_call_id='call_00_BTcDP6ovv0cyqEAJxsbfC4JF'
print(response['messages'][3])
content='根据最新的天气数据,杭州目前的天气情况如下:\n\n**杭州天气概况:**\n- **天气状况**:多云\n- **当前温度**:31°C\n- **湿度**:57%\n- **风向风力**:北风,3级及以下\n- **数据更新时间**:2025年10月8日 12:06\n\n今天杭州天气比较温暖,多云天气,温度适中,风力较小,湿度也相对舒适。建议您根据个人体感适当调整穿着。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 104, 'prompt_tokens': 533, 'total_tokens': 637, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 384}, 'prompt_cache_hit_tokens': 384, 'prompt_cache_miss_tokens': 149}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': 'c2d7da82-f71a-42c0-8842-75f77ed84b1b', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None} id='run--734641ea-cb83-456e-ae89-3307348a8761-0' usage_metadata={'input_tokens': 533, 'output_tokens': 104, 'total_tokens': 637, 'input_token_details': {'cache_read': 384}, 'output_token_details': {}}

测试一下并联调用工具的效果

response = agent.invoke({"messages":[{"role":"user","content":"杭州和唐河哪里更热?"}]})
print(response["messages"])
print(len(response["messages"])) # 可见共进行了5轮对话 1.user提问 2.ai准备查询 3.ai查询杭州天气 4.ai查询唐河天气 5. AI最终回复
[HumanMessage(content='杭州和唐河哪里更热?', additional_kwargs={}, response_metadata={}, id='51ebc0ba-ea9d-4a12-bc93-5a763da07412'), AIMessage(content='我来帮您查询杭州和唐河的天气情况,然后比较哪里更热。', additional_kwargs={'tool_calls': [{'id': 'call_00_rRYtjmxThQNP6jbs0mZlcsfW', 'function': {'arguments': '{"loc": "\\u676d\\u5dde"}', 'name': 'get_weather'}, 'type': 'function', 'index': 0}, {'id': 'call_01_o0ridvOeD0N8LhwdFEgPbXRk', 'function': {'arguments': '{"loc": "\\u5510\\u6cb3"}', 'name': 'get_weather'}, 'type': 'function', 'index': 1}], 'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 55, 'prompt_tokens': 383, 'total_tokens': 438, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 320}, 'prompt_cache_hit_tokens': 320, 'prompt_cache_miss_tokens': 63}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': '33a533bb-a645-4b11-bf19-ae2f8e060911', 'service_tier': None, 'finish_reason': 'tool_calls', 'logprobs': None}, id='run--c2d5a473-3bc4-4eb8-8250-28e15bad09ed-0', tool_calls=[{'name': 'get_weather', 'args': {'loc': '杭州'}, 'id': 'call_00_rRYtjmxThQNP6jbs0mZlcsfW', 'type': 'tool_call'}, {'name': 'get_weather', 'args': {'loc': '唐河'}, 'id': 'call_01_o0ridvOeD0N8LhwdFEgPbXRk', 'type': 'tool_call'}], usage_metadata={'input_tokens': 383, 'output_tokens': 55, 'total_tokens': 438, 'input_token_details': {'cache_read': 320}, 'output_token_details': {}}), ToolMessage(content='{"status": "1", "count": "1", "info": "OK", "infocode": "10000", "lives": [{"province": "浙江", "city": "杭州市", "adcode": "330100", "weather": "多云", "temperature": "31", "winddirection": "北", "windpower": "≤3", "humidity": "57", "reporttime": "2025-10-08 12:06:59", "temperature_float": "31.0", "humidity_float": "57.0"}]}', name='get_weather', id='6256dce3-2a9e-4b29-9849-bbba3a5370ba', tool_call_id='call_00_rRYtjmxThQNP6jbs0mZlcsfW'), ToolMessage(content='{"status": "1", "count": "1", "info": "OK", "infocode": "10000", "lives": [{"province": "河南", "city": "唐河县", "adcode": "411328", "weather": "雾", "temperature": "21", "winddirection": "东", "windpower": "≤3", "humidity": "98", "reporttime": "2025-10-08 12:00:20", "temperature_float": "21.0", "humidity_float": "98.0"}]}', name='get_weather', id='bd038575-e199-4dbf-8315-398e857ea94f', tool_call_id='call_01_o0ridvOeD0N8LhwdFEgPbXRk'), AIMessage(content='根据当前的天气数据:\n\n**杭州**:31°C,多云,湿度57%\n**唐河**:21°C,雾,湿度98%\n\n**结论:杭州比唐河更热**,杭州的温度比唐河高出10°C。虽然唐河湿度更高(98%),但由于温度较低,整体体感温度还是杭州更热。', additional_kwargs={'refusal': None}, response_metadata={'token_usage': {'completion_tokens': 75, 'prompt_tokens': 688, 'total_tokens': 763, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 384}, 'prompt_cache_hit_tokens': 384, 'prompt_cache_miss_tokens': 304}, 'model_name': 'deepseek-chat', 'system_fingerprint': 'fp_ffc7281d48_prod0820_fp8_kvcache', 'id': 'b8dadc34-bdcf-4e6f-a840-5d363b160475', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None}, id='run--a9cb645e-0a37-4571-aac1-9bdc5dfe02f8-0', usage_metadata={'input_tokens': 688, 'output_tokens': 75, 'total_tokens': 763, 'input_token_details': {'cache_read': 384}, 'output_token_details': {}})]
5
print(response["messages"][-1].content)
根据当前的天气数据:

**杭州**:31°C,多云,湿度57%
**唐河**:21°C,雾,湿度98%

**结论:杭州比唐河更热**,杭州的温度比唐河高出10°C。虽然唐河湿度更高(98%),但由于温度较低,整体体感温度还是杭州更热。

测试一下串联调用工具的效果

import os
from pydantic import BaseModel, Field
from langchain.tools import tool

# 定义参数结构
class WriteFileInput(BaseModel):
    """写入文件的参数模型"""
    file_path: str = Field(..., description="要写入的文件路径,例如 './output.txt'")
    content: str = Field(..., description="要写入的文本内容")

# 定义工具
@tool(args_schema=WriteFileInput)
def write_to_file(file_path: str, content: str) -> str:
    """
    将指定内容写入到指定文件中。
    
    参数:
        file_path (str): 文件路径,可为相对或绝对路径。
        content (str): 要写入的内容。
    
    返回:
        str: 写入结果说明,例如 "写入成功: ./output.txt"。
    """
    try:
        # 创建目录(若不存在)
        os.makedirs(os.path.dirname(file_path), exist_ok=True)

        # 以 UTF-8 编码写入文件
        with open(file_path, "w", encoding="utf-8") as f:
            f.write(content)

        return f"✅ 文件已成功写入:{file_path}"
    except Exception as e:
        return f"❌ 写入文件失败:{e}"

tools = [write_to_file,get_weather]

agent = create_react_agent(model=model,tools=tools)

result = agent.invoke({"messages":[{"role":"user","content":"杭州和唐河哪里更热?把结果写入./hello.txt"}]})
i = 0
for message in result["messages"]: # 进行了8次对话
    i = i + 1
    print(f'''第{i}次:''' + message.content)
第1次:杭州和唐河哪里更热?把结果写入./hello.txt
第2次:我来帮您查询杭州和唐河的天气情况,然后比较哪里更热。

首先查询杭州的天气:
第3次:{"status": "1", "count": "1", "info": "OK", "infocode": "10000", "lives": [{"province": "浙江", "city": "杭州市", "adcode": "330100", "weather": "多云", "temperature": "31", "winddirection": "东", "windpower": "≤3", "humidity": "56", "reporttime": "2025-10-08 13:32:34", "temperature_float": "31.0", "humidity_float": "56.0"}]}
第4次:现在查询唐河的天气:
第5次:{"status": "1", "count": "1", "info": "OK", "infocode": "10000", "lives": [{"province": "河南", "city": "唐河县", "adcode": "411328", "weather": "雾", "temperature": "23", "winddirection": "北", "windpower": "≤3", "humidity": "87", "reporttime": "2025-10-08 13:30:06", "temperature_float": "23.0", "humidity_float": "87.0"}]}
第6次:根据查询结果:
- 杭州:31℃,多云
- 唐河:23℃,雾

现在将比较结果写入文件:
第7次:✅ 文件已成功写入:./hello.txt
第8次:我已经完成了杭州和唐河的温度比较,并将结果写入了 `./hello.txt` 文件。

**比较结果:**
- 杭州:31℃(多云)
- 唐河:23℃(雾)

**结论:** 杭州比唐河更热,温度高出8℃。

**下面展示一下怎么调用内置的搜索引擎工具:tavily ** https://python.langchain.com/docs/integrations/tools/tavily_search/ **首先要获取api_key保存到.env文件里 ** https://app.tavily.com/home

from langchain_tavily import TavilySearch

tool = TavilySearch(
    max_results=5,      # 返回的最大搜索结果数量。默认为 5。
    topic="general",    # 搜索类别
    # include_answer=False,
    # include_raw_content=False,
    # include_images=False,
    # include_image_descriptions=False,
    # search_depth="basic",
    # time_range="day",
    # include_domains=None,
    # exclude_domains=None
)

tools = [tool]
search_agent = create_react_agent(model=model,tools=tools)

result = search_agent.invoke({"messages":[{"role":"user","content":"请帮我搜索一下牛伟豪是谁"}]})
i = 0
for message in result["messages"]: # 进行了4次对话
    i = i + 1
    print(f'''第{i}次:''' + message.content)
第1次:请帮我搜索一下牛伟豪是谁
第2次:我来帮您搜索牛伟豪的相关信息。
第3次:{"query": "牛伟豪 是谁", "follow_up_questions": null, "answer": null, "images": [], "results": [{"url": "https://zhangge.net/about.html", "title": "博客简介 - 张戈博客", "content": "网站名称:后厂村路灯  \n网站描述:热爱技术分享技术,同时也致力于各类技术教程学习分享。  \n网站地址:  \n网站头像:  \n贵站已加友链\n\n网站名称:后厂村路灯  \n网站描述:热爱技术分享技术,同时也致力于各类技术教程学习分享。  \n网站地址:  \n网站头像:  \n贵站已加友链\n\navatar\n\nJager 2022-6-17 · 11:34\n\n已添加,缓存刷新后可见\n\n已添加,缓存刷新后可见\n\nharries 2022-8-1 · 16:56\n\n风格一致未变\n\n风格一致未变\n\n 8年老站,比我的还久\n\n张戈大佬的介绍印象十分深刻\n\n难得看到老身影~\n\n自从有了chatgpt,再也不用什么硬盘了.\n\n来看下大佬。\n\n博主好,希望可以添加友链,想和博主常联系  \n名称:牛伟豪的博客  \n地址:  \n图标:  \n描述:一个生活技术学习分享网站\n\n博客怎么不更新了\n\n订阅图标按钮 [...] 郝 2019-5-31 · 17:07\n\n博主在吗想让你帮忙解决个问题可以吗\n\n博主在吗想让你帮忙解决个问题可以吗\n\n高 2019-6-5 · 22:03\n\n博主你的主题好酷,叫什么名字!能分享吗!\n\n博主你的主题好酷,叫什么名字!能分享吗!\n\n韩涛博客 2019-6-14 · 17:45\n\n大佬换主题了,感觉非常清爽好用,比之前的简洁了许多,相当不错\n\n大佬换主题了,感觉非常清爽好用,比之前的简洁了许多,相当不错\n\navatar\n\nJager 2019-6-27 · 22:25\n\n老主题用了很多年了,换个口味\n\n老主题用了很多年了,换个口味\n\n牛人是谁 2019-6-27 · 20:33\n\n牛人是谁,太逗了!\n\n牛人是谁,太逗了!\n\n轻全栈 2019-7-2 · 16:31\n\n您好,看到您的博客,感觉做得非常好,也给我自己做博客笃定了信念。我的博客还在补充内容当中,希望有一天可以换下友链。\n\n您好,看到您的博客,感觉做得非常好,也给我自己做博客笃定了信念。我的博客还在补充内容当中,希望有一天可以换下友链。\n\n李军 2019-7-23 · 20:26\n\n膜拜一个先!\n\n膜拜一个先! [...] 2000 年,有幸目睹了一位当时国内最牛程序员的一次编程操作,从此彻底颠覆了我的想法。  \n先说说牛人的业绩,一个工作日,基本没加班,完成一个复杂 C/S 软件的服务器端,用统计小工具数数代码,三万多行。这个软件经过简单的测试,第二天就上线实际运行了,每天数千人访问,没出过大问题。再说开发过程,开发环境是 VS6.0,牛人很少动鼠标,大概嫌耽误时间,各种快捷键运用,让人眼花缭乱,程序基本上不是写出来的,而是粘贴过来,重新排列组合一番,再敲上几个语句补充修正一下,就算大功告成。搞定一个程序块的时间,基本上跟一般人写一条语句的时间差不多。  \n整个工作过程中,看不出明显用于思考的时间,只要不离开座位,键盘的声音就一直连续不停。我想牛人之所以牛,关键就在这里,像运用语句一样运用语句块,程序不是写出来的,而是装配起来的,就产生了如同手工组装劳斯莱斯与模块化装配丰田之间的巨大生产率差异。", "score": 0.49275014, "raw_content": null}, {"url": "https://zh.wikipedia.org/zh-hans/%E6%AD%90%E9%99%BD%E5%81%89%E8%B1%AA", "title": "欧阳伟豪- 维基百科,自由的百科全书", "content": "维基百科\n自由的百科全书\n\n## 目录\n\n# 欧阳伟豪 [...] 欧阳伟豪(英语:Benjamin Au Yeung Wai Hoo,1967年8月17日—),绰号“Ben Sir”,香港粤语语言学家、电视节目主持人、演员,中学时曾是排球和篮球校队成员,1980年代末当过小学体育老师,1995、1997及2005年分别取得香港中文大学英语系学士、语言学硕士和香港科技大学语言学博士学位;对粤语产生兴趣始于修读硕士课程时,其论文主要研究深圳跨境学童的粤语能力。\n\n2004年至2017年9月,欧阳伟豪任职香港中文大学中国语言及文学系高级讲师期间,在无线电视主持几个以粤语教育为题材的综艺节目《最紧要正字》(2006年)、《学是学非》(2013年)、《男人食堂》(“粗口学堂”环节、2016年)。尤在前者“粗口学堂”环节内讲解粤语脏话令他为人熟悉,由此逐渐转型为节目主持人、演员及 YouTuber,2021年4月至2022年7月更正式签约为无线电视基本合约艺人。\n\n## 背景\n\n### 早年生活 [...] ## 曾获奖项与提名\n\n|  |  |  |\n --- \n| 年份 | 奖项 | 结果 |\n| 2016年 | 万千星辉颁奖典礼2016“最佳节目主持” | 提名 |\n| 2017年 | 万千星辉颁奖典礼2017“最佳节目主持” | 提名 |\n\n## 注释\n\n## 参考资料\n\n## 外部链接\n\n需注册\n\n| 规范控制数据库 编辑维基数据链接 | |\n --- |\n| 国际 |  ISNI  VIAF  WorldCat |\n| 各地 |  美国  台湾 |\n| 其他 |  HKCAN |\n\n编辑维基数据链接\n\nWikimedia Foundation\nPowered by MediaWiki", "score": 0.41250706, "raw_content": null}, {"url": "https://blog.niuwh.cn/", "title": "牛伟豪的博客|学习,交友,前端", "content": "Java反射专题总结 · KMP算法之代码理解 · C++ Set、Map容器基础语法指南 · C++ String基础语法完全指南 · leetcode(142) 《环形链表II》算法的数学证明 · Halo-Plus个人博客(本", "score": 0.2404806, "raw_content": null}, {"url": "https://blog.niuwh.cn/archives/kmp-suan-fa-zhi-dai-ma-li-jie", "title": "KMP算法之代码理解 - 牛伟豪的博客", "content": "KMP算法是利用next数字(最大相同前后缀使主串指针不回退的算法,其中next有好几种实现方法,本文是其中一种方法),文章主要探讨代码的实现思路,适合能手算", "score": 0.21388613, "raw_content": null}, {"url": "https://blog.csdn.net/qq_68587393/article/details/129149462", "title": "JS高级---基础总结深入_js基础高级-CSDN博客", "content": "一、JS基本介绍JS的用途:Javascript可以实现浏览器端、服务器端(nodejs)。。。 浏览器端JS由以下三个部分组成: ECMAScript:基础语法(数据类型、运算符、函数", "score": 0.031217646, "raw_content": null}], "response_time": 3.61, "request_id": "69902217-9247-42dc-8990-e5416faa989f"}
第4次:根据搜索结果,我找到了关于牛伟豪的一些信息:

**牛伟豪**是一位技术博主,他拥有一个个人博客网站(blog.niuwh.cn)。从他的博客内容来看:

- 博客名称:牛伟豪的博客
- 博客描述:一个生活技术学习分享网站
- 博客内容涵盖:学习、交友、前端开发等技术领域

从他的博客文章可以看出,他主要分享技术相关内容,包括:
- Java反射专题
- KMP算法理解
- C++ Set、Map容器语法指南
- C++ String语法指南
- LeetCode算法题解
- 个人博客搭建(使用Halo-Plus)

此外,搜索结果中还显示他在其他技术博客(如张戈博客)上留言,希望交换友情链接,这表明他活跃在技术博客圈。

不过,目前搜索结果中关于牛伟豪的个人详细信息(如职业背景、所在地区等)相对有限,主要信息都集中在他的技术博客活动上。如果您需要更详细的个人信息,可能需要更具体的搜索条件。

agent.invoke()里也可以限制agent递推次数

result = agent.invoke(
    {"messages":[{"role":"user","content":"今天杭州天气怎么样?"}]},
    {"recursion_limit":2}
    )
print(result["messages"][-1].content)