test_node流程详解

假设用户输入的需求是:"写一个判断字符串是否为回文(正读反读都一样)的函数,需要忽略大小写和空格。"

我们来模拟整个数据流向,看看文件里到底写了什么,以及它是怎么被测试的。


🎬 镜头一:AI 的真实返回(JSON 结构化输出)

当代码走到 response = structured_llm.invoke(prompt) 时,Claude 在底层其实不是返回一段聊天文本,而是严格按照我们定义的 Pydantic Schema,返回了一个类似这样的 JSON 数据包

复制代码
{
  "code": "def is_palindrome(s: str) -> bool:\n    \"\"\"判断字符串是否为回文\"\"\"\n    clean_s = s.replace(' ', '').lower()\n    return clean_s == clean_s[::-1]",
  "test_code": "assert is_palindrome('racecar') == True\nassert is_palindrome('hello') == False\nassert is_palindrome('A man a plan a canal Panama') == True",
  "description": "实现了回文判断,并处理了空格和大小写问题。"
}

我们的 real_coder_node 收到这个对象后,把它们分别存入全局的 State 字典中:

state["current_code"] = response.code

state["current_test_code"] = response.test_code


🎬 镜头二:临时文件里到底写了什么?

现在流程走到了 tester_node

代码执行到了这一步:full_executable_code = f"{func_code}\n\n# --- 测试用例 ---\n{test_code}"

然后,tempfile 模块在你的操作系统里(比如 /tmp/tmp_a1b2c3.py)悄悄创建了一个文件。如果你在这个时候用记事本打开这个临时文件,你看到的内容将是一段完美拼装的、可独立运行的 Python 脚本:

复制代码
# /tmp/tmp_a1b2c3.py 文件里的真实内容:

def is_palindrome(s: str) -> bool:
"""判断字符串是否为回文"""
clean_s = s.replace(' ', '').lower()
return clean_s == clean_s[::-1]

# --- 测试用例 ---
assert is_palindrome('racecar') == True
assert is_palindrome('hello') == False
assert is_palindrome('A man a plan a canal Panama') == True

🎬 镜头三:它被执行,就是直接进行测试了吗?

是的!绝对是的! 这正是 Python 语言中 assert(断言)关键字的精妙之处。

当我们的系统调用 subprocess.run(["python", "/tmp/tmp_a1b2c3.py"]) 时,就相当于你在黑色的命令行窗口里敲下了回车键运行这个脚本。

这里会出现两种结局(这就构成了测试):

结局 A:代码完美无 Bug(测试通过)
  • Python 解释器从上到下运行。
  • 遇到 assert is_palindrome('racecar') == True,计算结果确实是 True。Python 什么都不会说,继续往下走。
  • 所有代码悄无声息地运行完毕。
  • 子进程以状态码 0 正常退出(代表 Success)。
  • 我们的 subprocess 捕获到 returncode == 0,判断测试通过。它清空报错信息,让 LangGraph 走向结束节点。
结局 B:代码有 Bug(测试失败触发循环)

假设 Claude 脑抽了,忘记写 .lower() 转换大小写。

  • Python 解释器运行到第三个测试用例:assert is_palindrome('A man a plan a canal Panama') == True
  • 因为没转大小写,'A' != 'a',计算结果变成了 False
  • 轰隆! assert 关键字一旦遇到 False,就会立刻引发解释器级别的崩溃,抛出 AssertionError
  • 子进程异常终止,状态码非 0(比如退出码 1)。
  • 这个报错的详细日志(Traceback)会被抛出到标准错误流(stderr)中。

此时,我们的 tester_node 捕获到了这段"临终遗言",把它塞进了全局 State 的 error_message 里:

复制代码
Traceback (most recent call last):
File "/tmp/tmp_a1b2c3.py", line 11, in <module>
assert is_palindrome('A man a plan a canal Panama') == True
AssertionError

紧接着,路由函数看到有了报错,就会把带有这段报错信息的 State 踢回给 Coder 节点。Claude 下一次就会看到自己因为 **'A man a plan a canal Panama'**这个测试用例没过而翻车,进而恍然大悟:"哦,我忘了处理大小写!"


相关推荐
qq_54702617911 小时前
LangChain 中间件(Middleware)
中间件·langchain
Cha0DD11 小时前
【由浅入深探究langchain】第二十集-SQL Agent+Human-in-the-loop
人工智能·python·ai·langchain
Cha0DD11 小时前
【由浅入深探究langchain】第十九集-官方的SQL Agent示例
人工智能·python·ai·langchain
Barkamin19 小时前
LangChain简单介绍
langchain
百年੭ ᐕ)੭*⁾⁾1 天前
Chroma简单上手
人工智能·语言模型·langchain·chroma·rag
Roselind_Yi1 天前
【吴恩达2026 Agentic AI】面试向+项目实战(含面试题+项目案例)-2
人工智能·python·机器学习·面试·职场和发展·langchain·agent
JaydenAI1 天前
[RAG在LangChain中的实现-04]常用的向量存储和基于向量存储的检索器
python·langchain·ai编程
Roselind_Yi1 天前
【吴恩达2026 Agentic AI】面试向+项目实战(含面试题+项目案例)-1
人工智能·python·面试·职场和发展·langchain·gpt-3·agent
chushiyunen1 天前
langchain和pytorch结合笔记
pytorch·笔记·langchain