从零构建ReAct Agent:Python实现与核心逻辑解析

1. 为什么你需要亲手实现一个ReAct Agent?

如果你对AI Agent(智能体)感兴趣,或者已经用过了像AutoGPT、LangChain这类框架,你可能会觉得它们很强大,但同时又有点“黑盒”。你输入一个任务,它就开始自动搜索、思考、执行,最后给你一个答案。整个过程看起来很酷,但内部到底是怎么运转的?提示词长什么样?LLM(大语言模型)在每一步究竟接收到了什么信息?工具调用失败时,Agent会不会“卡住”?

这些问题,只有当你亲手从零开始构建一个Agent时,才能找到最清晰的答案。而ReAct(Reasoning + Acting) 范式,正是理解这一切的绝佳起点。它不像一些复杂框架那样封装了无数层抽象,它的核心思想极其简洁:让模型学会“三思而后行”。具体来说,就是让模型在解决问题时,交替进行思考(Thought)行动(Action)观察(Observation)。思考用于分析当前情况和规划下一步;行动则是调用外部工具(比如搜索网络、查询数据库);观察是接收工具返回的结果,作为下一步思考的依据。这个循环会一直持续,直到模型认为已经得到足够信息,可以输出最终答案。

我刚开始接触Agent时,直接上手机器学习框架,虽然能跑起来,但总觉得隔着一层纱。后来我决定抛开框架,用最基础的Python,参照ReAct论文的原型,自己实现一遍。这个过程让我恍然大悟,原来Agent的核心逻辑可以如此清晰。你会发现,所谓的“智能”,很大程度上依赖于我们精心设计的提示词和可靠的工具调用循环。通过这次构建,你不仅能深刻理解ReAct,更能获得一种“造轮子”的自信,未来再去使用或定制任何Agent框架,你都能一眼看穿其本质。

所以,这篇文章就是带你走一遍我走过的路。我们将完全使用Python标准库和requests,不依赖任何重型框架,从零开始,一步步搭建一个能真实运行、具备搜索和查找能力的ReAct Agent。我会把每一行代码的逻辑、每一个设计选择背后的考量,以及我实际调试中踩过的坑,都毫无保留地分享给你。当你跟着完成时,你得到的不仅仅是一段可以运行的代码,更是一张深入AI Agent世界的清晰地图。

2. 拆解ReAct的核心循环:它到底是怎么“想”和“做”的?

在动手写代码之前,我们必须像建筑师看蓝图一样,彻底理解ReAct的工作流程。很多教程会直接扔给你一个循环图,但我想带你像侦探一样,拆解其中的每一个环节。整个流程的核心是一个受控的循环,Agent在这个循环里扮演一个“拥有工具的使用者”,而LLM则是它的“大脑”。

第一步:接收任务与初始化。 我们给Agent一个问题,比如“ChatGPT是哪个公司的?”。同时,我们要给Agent一个“工作手册”,也就是提示词模板。这个模板至关重要,它定义了Agent的“人格”和“能力范围”。它会告诉LLM:你现在是一个ReAct Agent,你可以进行三种操作(Search, Lookup, Finish),并且这是几个示例(Few-shot Learning)。我们把问题拼接到这个模板后面,就形成了给LLM的初始提示。

第二步:生成“思考”与“行动”。 这是循环的开始。我们将拼接好的提示词发送给LLM(比如通过OpenAI或国内的通义千问API)。这里的关键是,我们要求LLM严格按照“Thought X: ... Action X: ...”的格式输出。Thought部分是模型对当前情况的内部分析和推理,这部分内容不会直接影响外部世界,只是它的“内心戏”。Action部分则是它决定要对外部世界采取的具体操作。例如,它可能输出:“Thought 1: 我需要先知道ChatGPT是什么,然后才能查找它的公司。Action 1: Search[ChatGPT]”。

第三步:解析与执行行动。 我们的程序需要像老师批改作业一样,严格解析LLM返回的文本,准确提取出ThoughtAction字符串。一旦提取出Action,比如Search[ChatGPT],程序就要调用对应的工具函数——这里是搜索维基百科的函数。这个函数会访问外部API或网页,获取关于“ChatGPT”的摘要信息。

第四步:形成“观察”并更新上下文。 工具函数返回的结果(比如一段描述文本)就成为了Observation。接下来是最精妙的一步:我们把“Thought”、“Action”和这个新的“Observation”作为一个完整的步骤,追加到最初的提示词后面。然后,整个流程回到第二步。现在,LLM收到的提示词包含了历史的所有步骤(Thought1, Action1, Observation1),它在此基础上进行新一轮的思考。例如,它可能看到Observation1里提到了“OpenAI”,那么它下一步的Thought2可能就是“ChatGPT由OpenAI创建,那么我需要搜索OpenAI来了解其子公司和产品”,Action2则可能是Search[OpenAI]

第五步:循环终止。 这个“思考-行动-观察”的循环会一直进行,直到模型生成的Action是Finish[最终答案]。此时,程序跳出循环,提取出Finish[]括号中的内容作为最终答案返回。我们通常也会设置一个最大步数(比如8步),防止问题过于复杂导致无限循环。

这个循环的巧妙之处在于,它将模型的推理过程(Thought)外部化、结构化,使得整个决策过程变得可追踪、可调试。同时,通过将工具调用结果(Observation)反馈给模型,实现了与外部世界的闭环交互。你之后会发现,无论多复杂的Agent框架,其底层都离不开这个基本的交互循环。

3. 搭建你的开发环境与工具函数

理论清楚了,我们开始动手。首先确保你有一个Python环境(3.8以上即可)。我们不需要TensorFlow或PyTorch,只需要几个轻量级的库来处理网络请求和HTML解析。打开你的终端,创建一个新的项目目录,然后安装依赖:

pip install requests beautifulsoup4

requests库用于调用LLM API和访问维基百科,beautifulsoup4则用来解析维基百科返回的HTML页面,提取我们需要的文本内容。接下来,我们创建一个Python文件,比如叫做react_agent.py。文件开头,我们先导入必要的模块:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
从零构建ReAct Agent
一个纯Python实现,用于深入理解思考-行动-观察循环的核心机制。
"""
import requests
import time
import re
import json
from bs4 import BeautifulSoup

现在,我们来配置最关键的部分——LLM的访问。为了代码的通用性,我们使用与OpenAI API兼容的接口格式。这里我以阿里云的通义千问为例,因为它提供了兼容的端点,且易于获取API Key。你也可以替换成任何支持相同接口的模型服务。

# =============================================================================
# 配置部分:请替换为你自己的API信息
# =============================================================================
OPENAI_API_KEY = "你的API-KEY"  # 例如:sk-xxxxxxxx
OPENAI_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"  # 通义千问兼容端点
MODEL_NAME = "qwen-turbo"  # 或其他你拥有的模型名,如 qwen-max

注意:请务必妥善保管你的API Key,不要上传到公开的代码仓库。你可以从环境变量中读取,这里为了演示清晰直接写在代码里。接下来,我们实现LLM的调用函数。这个函数是整个Agent的“大脑”接入点:

def llm(prompt, stop=None, max_tokens=200, temperature=0):
    """调用LLM API,返回生成的文本。"""
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }
    payload = {
        "model": MODEL_NAME,
        "messages": [{"role": "user", "content": prompt}],
        "temperature": temperature,  # 设为0使输出更确定,有利于格式解析
        "max_tokens": max_tokens
    }
    if stop:
        payload["stop"] = stop  # 停止序列,用于控制生成长度

    try:
        resp = requests.post(OPENAI_BASE_URL, headers=headers, data=json.dumps(payload), timeout=60)
        resp.raise_for_status()  # 如果状态码不是200,抛出异常
        data = resp.json()
        # 从标准兼容格式中提取返回内容
        if "choices" in data and len(data["choices"]) > 0:
            return data["choices"][0]["message"]["content"].strip()
        else:
            print("警告:LLM返回格式异常")
            return ""
    except requests.exceptions.Timeout:
        print("错误:LLM API请求超时")
        return ""
    except Exception as e:
        print(f"LLM调用错误: {e}")
        return ""

这个函数封装了与API的交互。stop参数非常重要,我们后面会用它来告诉LLM在生成完Action后及时停止,不要继续胡言乱语。temperature=0是为了让模型输出尽可能稳定,便于我们后续做格式解析。

4. 构建Agent的“手”:实现搜索与查找工具

Agent有了“大脑”(LLM),还需要“手”来操作外部世界。在经典的ReAct示例中,这双手就是访问维基百科的工具。我们来实现两个核心工具函数:SearchLookup

Search[实体]工具负责去维基百科上搜索一个实体(比如“OpenAI”),并返回第一段摘要信息。如果该实体没有直接对应的页面,则返回一些相似的搜索建议。这里涉及到网络爬虫的基本技巧,我们使用requests获取页面,再用BeautifulSoup解析HTML。

def clean_str(text):
    """清理文本中的编码问题。"""
    try:
        return text.encode().decode("unicode-escape").encode("latin1").decode("utf-8")
    except:
        return text

def search_wikipedia(entity):
    """搜索维基百科实体,返回页面全文和观察摘要。"""
    # 构造搜索URL
    search_url = f"https://en.wikipedia.org/w/index.php?search={entity.replace(' ', '+')}"
    try:
        response = requests.get(search_url, timeout=10)
        soup = BeautifulSoup(response.text, "html.parser")

        # 情况1:搜索结果是列表页(即没有直接匹配的页面)
        result_divs = soup.find_all("div", {"class": "mw-search-result-heading"})
        if result_divs:
            result_titles = [clean_str(div.get_text().strip()) for div in result_divs[:5]]
            return None, f"找不到精确匹配的[{entity}]。相似的条目有:{result_titles}。"

        # 情况2:直接跳转到了条目页面(或消歧义页面)
        page_elements = soup.find_all("p") + soup.find_all("ul")
        page_texts = [p.get_text().strip() for p in page_elements]

        # 处理消歧义页面(例如搜索“Python”可能指向编程语言或蛇)
        if any("may refer to:" in p for p in page_texts):
            # 如果是消歧义页,我们可以递归搜索一个更具体的条目,这里简单返回提示
            return None, f"[{entity}]可能指代多个事物,请提供更具体的名称。"

        # 提取页面主要内容,拼接成全文
        page_content = ""
        for p in page_texts:
            if len(p.split(" ")) > 2:  # 过滤掉过短的段落(可能是导航信息)
                page_content += clean_str(p) + "\n"

        # 生成一个简短的观察摘要(取前5个句子)
        paragraphs = [p.strip() for p in page_content.split("\n") if p.strip()]
        sentences = []
        for p in paragraphs:
            sentences += [s.strip() + '.' for s in p.split('. ') if s.strip()]
        obs = ' '.join(sentences[:5])

        return page_content, obs

    except Exception as e:
        return None, f"网络搜索出错:{str(e)}"

Lookup[关键词]工具则用于在Search获取到的当前页面全文(current_page)中,查找包含特定关键词的句子。这里有一个设计难点:页面内容可能很长,而LLM的上下文有限,我们不能每次都把全文喂给它。所以Lookup需要实现一个“迭代查找”的功能,每次调用返回下一个匹配的句子,并记录查找状态。

def lookup_in_page(page, keyword, lookup_state):
    """在页面文本中查找关键词,返回下一个匹配的句子及其状态。"""
    if not page:
        return "没有页面内容可以查找。", lookup_state

    # 如果关键词变了,或者首次查找,需要重新搜索所有句子
    if lookup_state.get('keyword') != keyword:
        paragraphs = [p.strip() for p in page.split("\n") if p.strip()]
        all_sentences = []
        for p in paragraphs:
            all_sentences += [s.strip() + '.' for s in p.split('. ') if s.strip()]
        # 过滤出包含关键词的句子(不区分大小写)
        matched_sentences = [s for s in all_sentences if keyword.lower() in s.lower()]

        lookup_state['keyword'] = keyword
        lookup_state['results'] = matched_sentences
        lookup_state['index'] = 0  # 重置指针

    # 检查是否还有结果
    if lookup_state['index'] >= len(lookup_state['results']):
        return "没有更多匹配的结果了。", lookup_state

    # 返回当前结果,并移动指针
    result = lookup_state['results'][lookup_state['index']]
    obs = f"(结果 {lookup_state['index'] + 1} / {len(lookup_state['results'])}) {result}"
    lookup_state['index'] += 1
    return obs, lookup_state

我在这里踩过一个坑:最初没有设计lookup_state这个状态字典,导致每次Lookup都只能返回第一个匹配项,Agent无法深入阅读。加入状态记录后,Agent就能像我们手动按“下一个”一样,逐步浏览所有相关句子,这对于提取分散的信息至关重要。

5. 设计Agent的“工作手册”:提示词工程详解

现在到了最核心,也是最体现技巧的部分——构造提示词。你可以把提示词想象成给LLM的一份详细“工作手册”和“岗前培训材料”。它必须清晰定义任务、格式、可用工具,并提供高质量示例。我们的提示词模板REACT_PROMPT是一个长字符串,我把它拆解开来给你看:

第一部分:任务指令。 开宗明义,告诉模型要扮演的角色和行为模式。

解决问答任务时需要交替进行"思考(Thought)"、"行动(Action)"和"观察(Observation)"的步骤。
"思考"可以用来推理当前情况;"行动"可以是以下三种类型:
(1)Search[实体]:在维基百科上搜索该确切实体,如果存在则返回第一段文字;如果不存在,则返回一些相似的实体以供继续搜索。
(2)Lookup[关键词]:在当前文章中返回包含该关键词的下一句。
(3)Finish[答案]:返回最终答案并结束任务。

这部分必须清晰无歧义。我特别强调了SearchLookup的区别:Search是去外部获取新知识,Lookup是在已有知识(当前页面)里精读。

第二部分:少样本示例(Few-shot Examples)。 这是提示词成功的关键。我们提供了2-3个完整的问答示例,展示了从问题开始,到最终Finish的完整推理轨迹。示例必须覆盖不同的情况,比如:

  1. 需要多步搜索和查找的复杂问题(如“Colorado造山运动...”)。这个示例展示了如何通过Search定位主题,再通过Lookup在页面中挖掘细节,最后串联信息得到答案。
  2. 需要从文本中提取命名关系的直接问题(如“Milhouse是以谁命名的?”)。这个示例展示了当第一次Search结果不包含答案时,如何使用Lookup[named after]来找到关键句。
  3. 需要比较和排除的选择题(如“哪一部纪录片是关于芬兰摇滚乐队的...”)。这个示例展示了Search失败(找不到精确匹配)时,如何根据搜索结果进行推理和排除。

每个示例都严格遵循“Question: ... Thought 1: ... Action 1: ... Observation 1: ...”的格式。模型会从这些示例中学习到正确的推理节奏和格式规范。我建议你在自己的实践中,根据你的任务领域,精心构造这样的示例,这比调任何参数都管用。

最后一部分:拼接新问题。 在运行时,我们会把用户的新问题拼接到这个固定模板的后面,形成最终的提示词:

prompt = REACT_PROMPT + f"\nQuestion:{question}\n"

这样,模型就能基于“工作手册”和“历史优秀案例”,开始处理新的任务了。

6. 实现主循环与解析器:让Agent“动”起来

有了大脑、双手和工作手册,现在我们需要一个“调度中心”来协调一切。这就是react_solve主函数和parse_thought_action解析器。主函数控制整个ReAct循环的流程,而解析器则确保我们能准确理解LLM的“输出”。

我们先看解析器。LLM的输出并不总是完美的,有时它可能会重复前缀,或者格式略有偏差。一个健壮的解析器必须能处理这些小毛病。

def parse_thought_action(text, step_num):
    """从LLM返回的文本中解析出第step_num步的Thought和Action。"""
    text = text.strip()
    thought_prefix = f"Thought {step_num}:"
    action_prefix = f"Action {step_num}:"

    # 处理可能重复的前缀
    if text.startswith(thought_prefix):
        text = text[len(thought_prefix):].strip()

    # 方法1:优先使用换行符分割(最规范的格式)
    if f"\n{action_prefix}" in text:
        parts = text.split(f"\n{action_prefix}", 1)
        thought = parts[0].strip()
        action = parts[1].strip()
    # 方法2:如果没有换行,尝试直接找Action前缀
    elif action_prefix in text:
        parts = text.split(action_prefix, 1)
        thought = parts[0].strip()
        action = parts[1].strip()
    # 方法3:使用正则表达式作为兜底
    else:
        action_pattern = rf"Action\s*{step_num}\s*[::]\s*(.+)"
        action_match = re.search(action_pattern, text, re.IGNORECASE)
        if action_match:
            action = action_match.group(1).strip()
            thought = text[:action_match.start()].strip()
        else:
            # 如果都解析失败,可能LLM只输出了Thought
            thought = text
            action = ""

    # 最后,清理thought中可能残留的标记
    thought = re.sub(rf"^(Thought\s*{step_num}\s*[::]\s*)+", "", thought, flags=re.IGNORECASE).strip()
    return thought, action

接下来是核心的主循环函数react_solve。它初始化状态(当前页面、查找状态),然后进入一个for循环,最多执行max_steps步。

def react_solve(question, max_steps=8, verbose=True):
    """使用ReAct范式解决问题,返回答案和完整的推理轨迹。"""
    current_page = None  # 保存当前搜索到的页面全文
    lookup_state = {'keyword': None, 'results': [], 'index': 0}
    answer = None

    if verbose:
        print(f"\n🔍 开始处理问题:{question}")
        print("=" * 60)

    # 1. 构建初始提示词
    prompt = REACT_PROMPT + f"\nQuestion:{question}\n"

    for step in range(1, max_steps + 1):
        # 2. 调用LLM生成Thought和Action
        # 注意stop参数:我们告诉LLM,生成到“Observation X:”或下一个“Thought”之前就停止
        thought_action_text = llm(
            prompt + f"Thought {step}:",
            stop=[f"\nObservation {step}:", f"\nThought {step+1}:", "\nQuestion:"],
            max_tokens=250
        )

        # 3. 解析输出
        thought, action = parse_thought_action(thought_action_text, step)

        # 4. 根据Action类型执行工具调用,得到Observation
        obs = ""
        if action.startswith("Search[") and action.endswith("]"):
            entity = action[len("Search["):-1]
            current_page, obs = search_wikipedia(entity)
            # 执行了新的Search,旧的Lookup状态需要重置
            lookup_state = {'keyword': None, 'results': [], 'index': 0}

        elif action.startswith("Lookup[") and action.endswith("]"):
            keyword = action[len("Lookup["):-1]
            obs, lookup_state = lookup_in_page(current_page, keyword, lookup_state)

        elif action.startswith("Finish[") and action.endswith("]"):
            answer = action[len("Finish["):-1]
            obs = "任务完成。"
            if verbose:
                print(f"✅ 在第{step}步获得最终答案。")

        else:
            obs = f"无效动作格式:'{action}'。请使用Search[实体]、Lookup[关键词]或Finish[答案]。"

        # 5. 将本轮步骤记录到提示词中,形成历史上下文
        step_record = f"Thought {step}:{thought}\nAction {step}:{action}\nObservation {step}:{obs}\n"
        prompt += step_record

        if verbose:
            print(f"**步骤 {step}**")
            print(f"  思考: {thought}")
            print(f"  行动: {action}")
            print(f"  观察: {obs[:150]}...") if len(obs) > 150 else print(f"  观察: {obs}")
            print("-" * 40)

        # 6. 如果得到最终答案,提前结束循环
        if answer:
            break

    # 循环结束,处理结果
    if not answer:
        answer = "经过最大步数尝试,仍无法确定答案。"
        if verbose:
            print("⚠️  达到最大步数限制,未找到答案。")

    if verbose:
        print("=" * 60)
        print(f"💡 最终答案:{answer}")

    return {'answer': answer, 'trajectory': prompt}

这个函数里有几个我调试后留下的重要细节:第一,在调用llm时,stop参数设置了f”\nObservation {step}:“,这能非常有效地防止LLM“抢答”,自己把Observation也编出来。第二,每次执行完Search,我都会重置lookup_state,因为页面已经换了,之前的查找状态自然失效。第三,verbose参数让整个过程可视化,这对于调试和理解Agent行为不可或缺。

7. 运行、测试与调试你的第一个Agent

代码都写好了,是时候见证它的工作了。在文件末尾,我们添加一个测试入口:

if __name__ == "__main__":
    # 测试几个不同复杂度的问题
    test_questions = [
        "ChatGPT是哪个公司开发的?",
        "《哈利波特》的作者J.K.罗琳是哪国人?",
        "特斯拉汽车的CEO埃隆·马斯克还创办了哪家太空探索公司?",
    ]

    for q in test_questions:
        result = react_solve(q, max_steps=6, verbose=True)
        print("\n" + "🌟" * 30 + "\n")
        time.sleep(2)  # 避免请求过于频繁

运行这个脚本(python react_agent.py),你会看到终端里打印出Agent完整的思考过程。以第一个问题为例,你可能会看到类似这样的输出:

🔍 开始处理问题:ChatGPT是哪个公司开发的?
============================================================
**步骤 1**
  思考: 我需要知道ChatGPT是什么,以及它是哪个公司创建的。
  行动: Search[ChatGPT]
  观察: ChatGPT是由OpenAI开发的人工智能聊天机器人。OpenAI是一家美国人工智能研究实验室...
----------------------------------------
**步骤 2**
  思考: 从观察中得知ChatGPT由OpenAI开发。问题问的是“哪个公司”,所以答案就是OpenAI。
  行动: Finish[OpenAI]
  观察: 任务完成。
----------------------------------------
✅ 在第2步获得最终答案。
============================================================
💡 最终答案:OpenAI

这个过程非常直观!Agent首先思考需要搜索“ChatGPT”,然后执行搜索,观察结果得知是OpenAI,接着思考这已经回答了问题,于是果断结束任务。对于更复杂的问题,比如问马斯克的其他公司,Agent可能会先搜索“Elon Musk”,观察结果中找到“SpaceX”,然后可能再搜索“SpaceX”进行确认,最后才给出答案。

调试经验分享:你第一次运行很可能不会这么顺利。常见的问题有:

  1. API调用失败:检查API Key、Base URL和网络连接。给llm函数添加更详细的错误打印。
  2. 解析失败:LLM没有严格按照格式输出。检查你的stop参数是否生效,或者考虑在提示词中更严厉地强调格式。可以临时打印出thought_action_text原始文本来分析。
  3. 工具调用无结果:维基百科可能被屏蔽或访问慢。可以考虑增加超时时间,或者替换为其他知识源(如国内百科的API,但需要注意接口格式适配)。
  4. Agent陷入循环:比如不停地Lookup同一个词。可以在主循环里加入简单的逻辑判断,如果连续三步的Action都一样,则强制干预,返回一个提示观察。

调试的过程,正是你与Agent心智模型对话的过程,也是理解其局限性的最好方式。

8. 超越基础:优化方向与扩展思考

一个能跑起来的基础ReAct Agent已经完成了。但这就是终点吗?远远不是。这只是一个起点,从这里出发,你有无数个可以优化和扩展的方向,让这个Agent变得更强大、更智能。

首先,优化工具集。 我们只实现了维基百科搜索。一个实用的Agent可能需要连接更多工具:

  • 计算器:处理数学问题。可以调用eval(需极度注意安全性)或math库。
  • 天气查询:接入天气API。
  • 数据库查询:连接SQLite或MySQL,让Agent能回答关于私有数据的问题。
  • 代码执行:提供一个安全的沙箱环境执行Python代码片段(例如使用docker隔离或restrictedpython)。 每增加一个工具,你都需要在提示词的“行动”部分更新说明,并提供新的使用示例。

其次,增强推理与规划能力。 基础的ReAct是“走一步看一步”。我们可以引入更高级的策略:

  • 子目标分解:对于复杂问题,在第一步思考时,就要求模型先制定一个计划(Plan),列出几个子目标,然后逐步执行。
  • 自我反思:在得到Observation后,增加一个“Reflection”步骤,让模型评估当前信息是否足够、行动是否有效,必要时调整策略。
  • 长上下文管理:随着步数增加,提示词会越来越长。我们需要设计摘要机制,将过去的步骤压缩成精炼的要点,以节省Token并聚焦关键信息。

第三,提升可靠性与用户体验。

  • 错误处理与重试:网络工具调用失败时,不应直接让Agent“卡死”,而应该让模型思考备选方案或重试。
  • 置信度与溯源:让Agent在给出答案时,附带引用来源(例如,来自Search[OpenAI]页面的第X句)。这对于需要核查的场合非常重要。
  • 人机交互:将单次问答扩展成对话式,记住历史对话上下文。

最后,关于性能与成本。 每一步都需要调用LLM,成本可能很高。在实际应用中,我们需要权衡步数限制与问题复杂度。对于一些简单问题,完全可以设计一个“短路”机制,让模型判断能否直接回答,无需调用工具。

我把自己实现的这个基础版本看作一个“教学原型”。它剥离了所有复杂性,让你能亲手触摸到ReAct的每一个齿轮。当你理解了这些,再去学习LangChain的ReActAgent或AutoGPT的复杂架构,你会发现它们无非是在这个核心循环之上,增加了更多工具、更优的记忆管理、更漂亮的工程封装而已。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值