NOOA:用Python类封装AI智能体,简化复杂应用开发

📅 2026/8/10 11:29:55
NOOA:用Python类封装AI智能体,简化复杂应用开发
如果你正在尝试将AI智能体集成到Python项目中但被复杂的回调、状态管理和多步流程搞得焦头烂额那么NVIDIA Labs刚刚开源的NOOA可能就是你一直在等的那个“解药”。这不是又一个试图包办一切的“全能”框架而是一个极其精炼的抽象它将一个功能完整的AI智能体封装成了一个单一的Python类。这意味着你可以像实例化一个User或Order对象一样创建一个Agent对象然后用.run()方法让它去执行任务。这种设计哲学直指当前AI应用开发中的一个核心痛点概念复杂性与工程简洁性之间的失衡。过去构建一个能调用工具、拥有记忆、并能处理复杂逻辑的智能体往往意味着你要深入一个框架的“领域特定语言”DSL学习各种装饰器、钩子和生命周期。NOOA试图用最经典的面向对象编程OOP范式来打破这堵墙。它不发明新概念而是让你用最熟悉的class和method来思考和构建AI能力。本文将带你彻底拆解NOOA从核心设计到一行行代码实战看看这个“Python类即智能体”的理念到底能为我们带来什么。1. 这篇文章真正要解决的问题在深入代码之前我们必须先厘清NOOA究竟要解决什么问题。当前AI智能体开发领域看似繁荣LangChain、AutoGPT等框架层出不穷但开发者尤其是那些希望快速将AI能力嵌入现有业务系统的工程师普遍面临几个困境过高的认知负荷许多框架引入了大量新概念Chains, Agents, Tools, Memories, Vector Stores等。要完成一个简单任务你不得不先成为该框架的“专家”学习其特有的配置方式和抽象模型。与现有代码库的整合困难智能体框架往往自成体系其设计模式如大量使用装饰器、异步回调、复杂的事件驱动模型与传统的、基于类和方法封装的业务代码格格不入。将智能体“嵌入”到一个现有的MVC或微服务架构中常常需要编写大量的胶水代码。调试和测试的复杂性当智能体的行为不符合预期时由于其内部状态分散、执行流程非线性和依赖外部模型定位问题变得异常困难。传统的单元测试方法很难直接应用。“过度设计”的恐惧对于许多应用场景我们需要的可能不是一个能自我进化、拥有长期记忆的“超级智能体”而只是一个能可靠地调用几个API、根据条件做出判断的“自动化函数”。但现有框架的入门门槛让实现这个简单目标也变得很重。NOOA的核心理念是“降维打击”它不试图在功能丰富度上竞争而是追求极致的开发者体验DX和集成友好度。它要解决的问题很明确让一个Python开发者在不学习新框架语法的情况下用最少的代码构建出一个可工作、可测试、可维护的AI智能体。它的解决方案是一个智能体就是一个Python类实例。这个类有清晰的生命周期方法如初始化、运行、清理有明确的内部状态属性和对外暴露的简洁接口方法。所有复杂的智能体逻辑如与大模型交互、工具调用、记忆管理都被封装在这个类的内部。对外它只是一个行为良好的对象。2. NOOA核心概念当智能体成为一个“对象”理解NOOA关键在于理解它的三个核心设计原则这决定了它与其他框架的根本不同。2.1 原则一极简抽象——Agent类即一切在NOOA的世界里核心抽象只有一个Agent类。这个类是你的智能体的蓝图。它通常包含__init__方法用于初始化智能体的“大脑”如配置使用的LLM模型、“技能”工具集和“记忆”上下文管理。run方法智能体的主入口。你传入一个任务描述字符串它返回执行结果。这是你与智能体交互的主要方式。内部状态属性如对话历史、临时变量等用于在多次run调用或复杂任务步骤间保持状态。这种设计带来的最大好处是心智模型极其简单。你不需要思考“我应该创建一个Chain还是Agent”“这个Tool应该注册到哪里”。你只需要思考“我的这个智能体对象需要有什么能力方法需要记住什么属性”2.2 原则二原生Python零新语法NOOA完全基于原生Python构造。它不要求你学习一种新的配置语言YAML/JSON DSL也不强制使用特定的装饰器来声明工具。工具可以就是类的一个普通方法记忆可以就是一个列表属性。框架只提供一些基础工具类和辅助函数来简化通用模式如调用OpenAI API但绝不强制你使用。这意味着你可以用任何你喜欢的Python测试框架如pytest来测试你的智能体像测试任何其他类一样。你可以轻松地将智能体类集成到现有的Web框架如FastAPI、Django中将其作为一个服务层组件。你可以利用Python的所有生态包括类型提示Type Hints、日志模块、异步编程等来构建更健壮的智能体。2.3 原则三明确的生命周期与状态管理由于智能体被封装为一个对象它的生命周期变得非常清晰实例化创建对象加载配置初始化资源。运行调用run方法传入输入获取输出。在此过程中对象的内部状态可能发生变化。序列化/持久化你可以将智能体对象的状态属性通过pickle、json或存入数据库来保存实现“记忆”的长期化。销毁当对象不再需要时可以被垃圾回收或显式清理。这种明确性对于构建长期运行的服务或需要保持会话状态的应用程序至关重要。你可以轻松地将会话ID映射到一个特定的智能体实例上。3. 环境准备与前置条件在开始编码前你需要准备好Python环境。NOOA作为一个理念先行的框架其具体实现可能依赖一些基础库。我们假设你使用的是NVIDIA Labs官方提供的NOOA参考实现或类似架构。基础环境要求Python 3.8确保你的Python版本足够新。pip标准的Python包管理工具。核心依赖安装NOOA的核心是设计模式但其实现通常会依赖与大模型交互的库。最常用的是openai库。我们通过pip安装# 安装openai库用于调用GPT等模型 pip install openai # 可选但推荐安装python-dotenv用于管理环境变量如API密钥 pip install python-dotenv获取API密钥你需要一个OpenAI API密钥或其他兼容OpenAI API的模型服务密钥如Azure OpenAI, Ollama等。访问 OpenAI平台 创建API Key。安全提示永远不要将API密钥硬编码在代码中或提交到版本控制系统如Git。推荐的做法是将其设置为环境变量。创建一个名为.env的文件在项目根目录# .env 文件 OPENAI_API_KEY你的-api-key-here OPENAI_BASE_URLhttps://api.openai.com/v1 # 如果使用其他兼容服务修改此处然后在Python代码中通过os或dotenv加载# config.py 或直接在代码开头 import os from dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的环境变量 OPENAI_API_KEY os.getenv(OPENAI_API_KEY) if not OPENAI_API_KEY: raise ValueError(请在 .env 文件中设置 OPENAI_API_KEY 环境变量)4. 从零构建你的第一个NOOA智能体让我们从一个最简单的例子开始创建一个能进行对话的智能体。我们将遵循NOOA的设计模式但不直接使用任何尚未发布的框架代码而是展示其思想。4.1 步骤一定义智能体基类首先我们定义一个所有智能体的基类BaseAgent。这个类负责处理最通用的逻辑比如与LLM的通信。# agent/base.py import json import logging from abc import ABC, abstractmethod from typing import Any, Dict, List, Optional import openai # 设置日志 logging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__) class BaseAgent(ABC): 智能体基类封装了与LLM通信的基础能力。 def __init__(self, model: str gpt-3.5-turbo, api_key: Optional[str] None, base_url: Optional[str] None): 初始化智能体。 Args: model: 使用的LLM模型名称。 api_key: OpenAI API密钥。如果为None将从环境变量读取。 base_url: API基础URL用于兼容其他服务。 self.model model self.client openai.OpenAI( api_keyapi_key or os.getenv(OPENAI_API_KEY), base_urlbase_url or os.getenv(OPENAI_BASE_URL, https://api.openai.com/v1) ) # 记忆存储对话历史 self.memory: List[Dict[str, str]] [] def _call_llm(self, messages: List[Dict[str, str]]) - str: 调用LLM并返回文本响应。内部方法。 try: response self.client.chat.completions.create( modelself.model, messagesmessages, temperature0.7, ) content response.choices[0].message.content if content is None: return return content.strip() except Exception as e: logger.error(f调用LLM失败: {e}) raise def add_to_memory(self, role: str, content: str): 向记忆中添加一条消息。 self.memory.append({role: role, content: content}) def clear_memory(self): 清空记忆。 self.memory.clear() abstractmethod def run(self, input_text: str) - str: 智能体的主要运行方法。子类必须实现。 pass4.2 步骤二实现一个简单的对话智能体现在我们继承BaseAgent创建一个具体的对话智能体ConversationAgent。# agent/conversation_agent.py from typing import List, Dict from .base import BaseAgent class ConversationAgent(BaseAgent): 一个简单的对话智能体能进行多轮上下文对话。 def __init__(self, model: str gpt-3.5-turbo, system_prompt: str 你是一个有用的助手。, api_key: Optional[str] None, base_url: Optional[str] None): super().__init__(model, api_key, base_url) self.system_prompt system_prompt # 初始化时将系统提示加入记忆 self.add_to_memory(system, system_prompt) def run(self, user_input: str) - str: 运行智能体处理用户输入调用LLM返回助手回复。 Args: user_input: 用户的输入文本。 Returns: 智能体的回复文本。 # 1. 将用户输入加入记忆 self.add_to_memory(user, user_input) # 2. 准备发送给LLM的消息使用完整的记忆 messages_for_llm self.memory.copy() # 3. 调用LLM获取回复 assistant_response self._call_llm(messages_for_llm) # 4. 将助手回复加入记忆 self.add_to_memory(assistant, assistant_response) # 5. 返回回复 return assistant_response4.3 步骤三运行并测试智能体创建一个主程序来使用我们的智能体。# main.py import os from dotenv import load_dotenv from agent.conversation_agent import ConversationAgent # 加载环境变量 load_dotenv() def main(): # 实例化一个对话智能体 agent ConversationAgent( modelgpt-3.5-turbo, system_prompt你是一个精通Python编程的专家助手。请用中文回答。 ) print(对话智能体已启动。输入 退出 或 quit 结束对话。) print(- * 40) while True: try: user_input input(\n你: ) if user_input.lower() in [退出, quit, exit]: print(对话结束。) break # 调用智能体的run方法 response agent.run(user_input) print(f助手: {response}) except KeyboardInterrupt: print(\n用户中断。) break except Exception as e: print(f\n发生错误: {e}) break if __name__ __main__: main()运行这个程序python main.py你应该能看到一个交互式对话界面智能体会根据你的输入用中文回答Python相关问题。这就是一个最基础的、遵循NOOA理念的智能体。5. 能力升级为智能体添加“工具”技能一个只会对话的智能体能力有限。真正的威力在于让智能体能够调用外部工具函数。在NOOA模式中这通常意味着为智能体类添加一些方法并教会LLM在适当的时候调用它们。5.1 定义工具与工具调用协议我们需要一个机制让LLM知道智能体有哪些工具可用以及如何调用它们。这里我们实现一个简单的“函数调用”模式。# agent/tool_agent.py import json import re from typing import Dict, Any, Callable, List, Optional from .base import BaseAgent class Tool: 工具类描述一个可被智能体调用的函数。 def __init__(self, name: str, func: Callable, description: str, params_schema: Optional[Dict] None): self.name name self.func func self.description description self.params_schema params_schema or {} def execute(self, **kwargs) - Any: 执行工具函数。 return self.func(**kwargs) class ToolAgent(BaseAgent): 能够理解并调用工具的智能体。 def __init__(self, model: str gpt-3.5-turbo, system_prompt: str 你是一个可以调用工具来帮助用户的助手。, api_key: Optional[str] None, base_url: Optional[str] None): super().__init__(model, api_key, base_url) self.system_prompt system_prompt self.tools: Dict[str, Tool] {} # 工具注册表 self.add_to_memory(system, system_prompt) def register_tool(self, tool: Tool): 注册一个工具。 self.tools[tool.name] tool logger.info(f工具已注册: {tool.name}) def _get_tools_description(self) - str: 生成工具描述文本用于提示词。 if not self.tools: return 当前没有可用的工具。 desc_lines [你可以使用以下工具] for name, tool in self.tools.items(): params_desc json.dumps(tool.params_schema, ensure_asciiFalse) if tool.params_schema else 无参数 desc_lines.append(f- {name}: {tool.description} (参数: {params_desc})) desc_lines.append(\n当你需要调用工具时请严格按照以下格式回复) desc_lines.append(TOOL_CALL: {tool_name: 工具名, parameters: {参数键值对}}) desc_lines.append(我会执行工具并返回结果。) return \n.join(desc_lines) def run(self, user_input: str, max_iterations: int 5) - str: 运行智能体支持多轮工具调用。 Args: user_input: 用户输入。 max_iterations: 最大工具调用迭代次数防止无限循环。 Returns: 最终回复给用户的文本。 # 将用户输入加入记忆 self.add_to_memory(user, user_input) for iteration in range(max_iterations): # 准备消息系统提示 完整记忆 当前工具描述 messages_for_llm self.memory.copy() # 在系统提示后插入最新的工具描述 tools_desc_message {role: system, content: self._get_tools_description()} # 通常我们会把工具描述放在最前面或合并这里简化处理插入到用户输入前 # 更优的做法是动态构建提示这里为演示简化 # 实际上更好的设计是在每次调用LLM前重新构造包含最新工具描述的提示。 # 为了示例清晰我们假设系统提示已经包含了工具描述。 # 调用LLM llm_response self._call_llm(messages_for_llm) # 解析LLM响应检查是否包含工具调用 tool_call_match re.search(rTOOL_CALL:\s*(\{.*?\}), llm_response, re.DOTALL) if tool_call_match: # 解析工具调用 try: tool_call_json tool_call_match.group(1) tool_call_data json.loads(tool_call_json) tool_name tool_call_data.get(tool_name) parameters tool_call_data.get(parameters, {}) if tool_name in self.tools: # 执行工具 logger.info(f执行工具: {tool_name}, 参数: {parameters}) tool_result self.tools[tool_name].execute(**parameters) result_str f工具 {tool_name} 执行成功结果: {tool_result} # 将工具执行结果作为一条“系统”或“用户”消息加入记忆让LLM继续处理 self.add_to_memory(user, result_str) # 继续下一轮循环 continue else: error_msg f未知的工具: {tool_name} self.add_to_memory(user, error_msg) continue except json.JSONDecodeError as e: error_msg f工具调用格式错误: {e} self.add_to_memory(user, error_msg) continue except Exception as e: error_msg f工具执行出错: {e} self.add_to_memory(user, error_msg) continue else: # LLM的响应是普通文本没有工具调用作为最终回复 self.add_to_memory(assistant, llm_response) return llm_response # 如果达到最大迭代次数 return 已达到最大处理步骤可能陷入循环。请检查您的请求或工具配置。5.2 创建并注册具体工具现在我们定义几个具体的工具函数并注册到智能体中。# tools/calculator.py def add_numbers(a: float, b: float) - float: 将两个数字相加。 return a b def get_current_weather(city: str) - str: 获取指定城市的当前天气模拟。 # 这里模拟一个API调用 weather_data { 北京: 晴25°C, 上海: 多云23°C, 深圳: 阵雨28°C } return weather_data.get(city, f未找到{city}的天气信息。) # main_with_tools.py import os from dotenv import load_dotenv from agent.tool_agent import ToolAgent, Tool from tools.calculator import add_numbers, get_current_weather load_dotenv() def main(): # 1. 实例化智能体 agent ToolAgent( modelgpt-3.5-turbo, system_prompt你是一个有用的助手可以调用工具来帮助用户。 当用户请求涉及计算或查询信息时请判断是否需要调用工具。 如果需要请严格按照指定的TOOL_CALL格式回复。 如果不需要请直接回答用户的问题。 ) # 2. 创建并注册工具 calculator_tool Tool( nameadd_numbers, funcadd_numbers, description计算两个数字的和。, params_schema{a: number, b: number} ) weather_tool Tool( nameget_current_weather, funcget_current_weather, description获取指定城市的当前天气情况。, params_schema{city: string} ) agent.register_tool(calculator_tool) agent.register_tool(weather_tool) print(工具智能体已启动。) print(- * 40) # 3. 测试对话 test_queries [ 北京今天天气怎么样, 帮我计算一下123和456的和。, 先告诉我深圳的天气然后再计算10加20等于多少。, 你叫什么名字 # 这个不需要工具 ] for query in test_queries: print(f\n用户: {query}) response agent.run(query) print(f助手: {response}) print(- * 20) # 4. 查看记忆对话历史 print(\n 对话历史 ) for msg in agent.memory: print(f{msg[role]}: {msg[content][:100]}...) # 只打印前100字符 if __name__ __main__: main()运行这个程序你会看到智能体能够理解自然语言请求并选择性地调用我们注册的工具来完成计算和查询天气的任务。这就是NOOA模式下一个具备“技能”的智能体的雏形。6. 运行结果与效果验证运行main_with_tools.py你可能会看到类似下面的输出具体回复因模型随机性略有不同工具智能体已启动。 ---------------------------------------- 用户: 北京今天天气怎么样 助手: TOOL_CALL: {tool_name: get_current_weather, parameters: {city: 北京}} ---------------------------------------- 用户: 帮我计算一下123和456的和。 助手: TOOL_CALL: {tool_name: add_numbers, parameters: {a: 123, b: 456}} ---------------------------------------- 用户: 先告诉我深圳的天气然后再计算10加20等于多少。 助手: TOOL_CALL: {tool_name: get_current_weather, parameters: {city: 深圳}} ---------------------------------------- 用户: 你叫什么名字 助手: 我是一个AI助手由NOOA框架驱动。你可以叫我助手。 ---------------------------------------- 对话历史 system: 你是一个有用的助手可以调用工具来帮助用户... user: 北京今天天气怎么样 assistant: TOOL_CALL: {tool_name: get_current_weather, parameters: {city: 北京}} user: 工具 get_current_weather 执行成功结果: 晴25°C assistant: 北京今天的天气是晴25°C。 user: 帮我计算一下123和456的和。 assistant: TOOL_CALL: {tool_name: add_numbers, parameters: {a: 123, b: 456}} user: 工具 add_numbers 执行成功结果: 579 assistant: 123和456的和是579。 ...如何验证智能体工作正常工具调用识别观察LLM的回复是否准确识别了需要工具的请求并输出了格式正确的TOOL_CALLJSON。工具执行检查日志或输出确认工具函数被正确调用并返回了结果如“晴25°C”和“579”。上下文连贯性对于多步请求如“先查天气再计算”观察智能体是否能在第一轮工具调用得到结果后继续处理剩余请求。这需要更复杂的循环逻辑上述示例进行了简化。一个完整的实现应能处理这种多轮交互。纯对话能力对于不需要工具的请求如“你叫什么名字”智能体应能直接生成合理的自然语言回复而不触发工具调用。7. 常见问题与排查思路在开发和运行NOOA风格智能体时你可能会遇到以下典型问题问题现象可能原因排查方式解决方案导入错误ModuleNotFoundError1. 依赖库未安装如openai。2. 文件路径或模块导入语句错误。1. 运行pip list检查依赖。2. 检查import语句和sys.path。1. 使用pip install -r requirements.txt安装所有依赖。2. 使用相对导入或设置PYTHONPATH。API调用失败AuthenticationError或RateLimitError1. API密钥错误或未设置。2. 达到API调用频率或额度限制。1. 检查.env文件和环境变量。2. 查看OpenAI控制台用量统计。1. 确保OPENAI_API_KEY正确设置。2. 等待限制重置或升级套餐。LLM不按格式回复不触发工具调用1. 系统提示词system_prompt未清晰指示工具调用格式。2. 模型能力不足如gpt-3.5-turbo在某些复杂指令下表现不稳定。3. 工具描述不够清晰。1. 打印出发送给LLM的完整消息列表检查提示词。2. 尝试更简单的示例或更换模型如gpt-4。1. 优化系统提示词明确要求使用TOOL_CALL格式并提供清晰示例。2. 使用Function Calling等官方工具调用协议而非依赖文本解析。工具调用JSON解析失败1. LLM生成的JSON格式不标准如缺少引号、尾随逗号。2. 正则表达式未能正确匹配。1. 打印出LLM的原始响应检查JSON部分。2. 使用json.loads()并捕获异常。1. 在提示词中严格要求输出标准、有效的JSON。2. 使用更健壮的JSON解析库如json5或尝试从文本中提取JSON。工具函数执行时报参数错误1. LLM生成的参数类型错误如字符串传给数字参数。2. 参数缺失或多余。1. 打印出parameters字典的内容。2. 检查工具函数的参数定义和类型注解。1. 在工具描述params_schema中明确参数类型。2. 在调用工具前增加参数验证和类型转换逻辑。智能体陷入无限循环1. 工具执行结果又被LLM解释为需要新的工具调用。2.max_iterations设置过高或未生效。1. 在每次迭代打印日志观察记忆内容的变化。2. 检查循环终止条件。1. 优化提示词明确区分“工具执行结果”和“用户新输入”。2. 确保max_iterations参数有效并设置合理的值如5-10。记忆上下文过长导致API开销大或模型遗忘1. 对话轮次过多memory列表不断增长。2. 模型有上下文长度限制如4096、8192 tokens。1. 计算记忆列表的大致token数可用tiktoken库。2. 观察后期回复质量是否下降。1. 实现记忆窗口或摘要功能只保留最近N轮对话或对历史进行总结。2. 使用支持更长上下文的模型。8. 最佳实践与工程建议将NOOA理念应用到实际项目中以下最佳实践能帮助你构建更稳健、可维护的智能体系统清晰的职责分离工具层将工具函数定义在独立的模块如tools/目录中。每个工具应功能单一、易于测试。工具函数本身不应包含智能体逻辑。智能体层Agent类负责编排工作流、管理状态、与LLM交互。它应该对工具的具体实现一无所知只通过接口调用。配置层将模型名称、API端点、系统提示词等配置信息外置如使用Pydantic Settings管理便于不同环境部署。使用类型提示Type Hints为所有工具函数、Agent方法、数据结构添加详细的类型提示。这不仅能提高代码可读性还能借助mypy等工具进行静态检查提前发现潜在的类型错误。实现健壮的工具调用协议上述示例中的TOOL_CALL文本解析是脆弱的。在生产环境中应优先使用LLM供应商官方的函数调用Function Calling或工具调用Tool Calling功能。OpenAI的API直接支持在请求中传递工具定义并以结构化JSON返回工具调用请求极大地提高了可靠性。状态管理与持久化对于需要长期记忆的智能体如客服机器人设计一个Memory类来管理对话历史。可以支持多种后端如内存、Redis、数据库。实现save_state()和load_state()方法方便将会话状态保存到文件或数据库实现智能体的“休眠”与“唤醒”。全面的日志与监控在关键节点接收输入、调用LLM、调用工具、返回输出添加详细的日志记录。记录每次LLM交互的输入token数、输出token数和耗时用于成本分析和性能优化。考虑集成像LangSmith这样的AI应用监控平台用于跟踪链式调用、调试和评估。编写单元测试与集成测试单元测试单独测试每个工具函数。集成测试测试整个Agent.run()流程。可以使用模型的固定响应通过Mock来测试工具调用逻辑避免每次测试都调用真实API产生费用和延迟。错误处理与降级策略LLM API调用可能失败网络、限流。实现重试机制如tenacity库。工具调用可能失败。智能体应能捕获异常并将友好的错误信息反馈给LLM或用户。设计降级策略当核心工具不可用时是否能用其他方式近似回答或者直接告知用户能力受限。安全与权限工具权限不是所有工具都应被任意调用。例如发送邮件、操作数据库的函数需要更严格的权限控制。可以在Tool类或Agent中增加权限检查逻辑。输入输出过滤对用户输入和LLM输出进行必要的清洗和过滤防止注入攻击或不当内容。NVIDIA Labs的NOOA项目其价值不在于提供又一个功能繁复的框架而在于提出并验证了一种极其优雅的智能体构建范式用最经典的OOP思想化解最前沿的AI复杂性。它让AI智能体从一种需要专门学习和理解的“新物种”回归为一个你可以用import、class、def和if-else来轻松驾驭的普通Python对象。这种设计带来的直接好处是更低的集成成本、更直观的调试体验和更强的工程可控性。当你把智能体看作一个对象你可以用依赖注入来管理它的依赖用装饰器来增强它的功能如自动重试、日志记录用继承和多态来创建不同特化的智能体家族用序列化来保存它的状态。所有这些都是Python工程师早已熟练掌握的常规武器。当然本文展示的示例是一个高度简化的实现。一个生产级的NOOA风格框架需要处理更复杂的情况流式响应、异步工具调用、复杂的记忆管理、符合OpenAI标准的功能调用、多智能体协作等。但万变不离其宗其核心架构——一个封装了状态和行为、通过清晰接口与外界交互的Agent类——将始终保持稳定。如果你厌倦了在复杂框架中配置各种组件渴望一种更直接、更Pythonic的方式来构建AI应用那么深入研究NOOA的设计思想并基于此构建你自己的智能体基础设施会是一个非常有价值的投资。你可以从本文的示例代码出发逐步添加你需要的功能最终打造出一个完全贴合你业务需求、且完全受你控制的AI智能体引擎。