news 2026/6/1 4:13:37

SuperAGI自定义工具开发指南:从原理到实战集成

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SuperAGI自定义工具开发指南:从原理到实战集成

1. 项目概述:为什么要在SuperAGI中集成自定义工具?

如果你正在探索或已经深度使用SuperAGI这个开源AI智能体框架,那么你迟早会遇到一个核心需求:让智能体去做一些框架本身没有内置的事情。SuperAGI自带的工具集虽然强大,覆盖了网页搜索、代码执行、文件操作等常见场景,但现实世界的任务千变万化。比如,你可能需要智能体去调用一个内部API查询库存,去解析一个特定格式的日志文件,或者去操作一个像Notion、飞书这样的第三方协作工具。这时候,为SuperAGI添加自定义工具(Tool)或工具包(Toolkit)就成了将AI能力与你的专属工作流无缝对接的关键一步。

简单来说,这个过程就是教会SuperAGI的智能体使用“新技能”。一个“工具”可以理解为一个单一、具体的功能函数,比如“发送邮件”;而一个“工具包”则是多个相关工具的集合,比如“邮件管理工具包”,里面包含了发送、接收、标记邮件等多个工具。通过自定义集成,你可以将任何能用代码实现的功能,封装成智能体可以理解和调用的标准化接口,从而极大地扩展智能体的应用边界。这不仅仅是技术上的对接,更是将AI从“通用助手”转变为“领域专家”的核心手段。

我最初接触这个需求,是因为需要让智能体自动处理每日的服务器监控报告。SuperAGI没有现成的工具能直接对接我们的内部监控系统。通过研究其架构并成功集成自定义工具后,不仅自动化了报告生成,还能让智能体在发现异常时自动执行预设的排查指令。这个经历让我深刻体会到,自定义工具能力是释放SuperAGI真正潜力的阀门。接下来,我将基于我的实战经验,为你拆解从思路设计到代码实现,再到调试部署的完整流程,并分享其中容易踩坑的细节。

2. 核心思路与架构设计:理解SuperAGI的工具运行机制

在动手写代码之前,我们必须先搞清楚SuperAGI智能体是如何发现、选择并使用工具的。这决定了我们自定义工具应该以何种形式“嵌入”到这个系统中。SuperAGI的架构设计遵循了一种清晰的责任链模式。

2.1 智能体的工具使用决策流程

当一个智能体(Agent)被赋予任务时,它的“大脑”(通常是大型语言模型,如GPT-4)会首先分析任务目标。然后,它会查询自己“已知”的所有工具列表,评估每个工具的描述和功能,判断哪一个或哪几个工具的组合能最有效地完成当前步骤。这个“已知工具列表”就是我们能扩展的地方。智能体做出选择后,会生成一个符合工具输入格式的调用请求。SuperAGI的后端服务接收到这个请求,会找到对应的工具代码并执行,最后将执行结果返回给智能体,供其进行下一步分析和决策。

这个过程的关键在于“工具描述”。智能体并非直接理解我们的代码,而是通过我们为工具定义的名称(name)、描述(description)以及参数(parameters)的JSON Schema来“理解”工具能做什么、需要什么。因此,编写一个清晰、准确、无歧义的工具描述,与编写功能正确的代码同等重要。一个模糊的描述可能导致智能体错误地调用工具或无法理解其用途。

2.2 自定义工具的两种集成路径

根据你的需求范围,通常有两条集成路径:

  1. 单一工具集成:适用于添加一个独立、功能特定的工具。例如,一个专门用于查询今日天气的工具。这种方式轻量、快速,直接修改工具配置文件或向工具管理类注册即可。
  2. 工具包集成:适用于将一系列相关的工具模块化。例如,构建一个“数据库运维工具包”,里面包含“查询慢SQL”、“备份状态检查”、“连接数监控”等多个工具。这种方式更利于管理和维护,符合高内聚、低耦合的软件设计原则。

在SuperAGI的具体实现中,工具信息通常被维护在一个全局的配置或注册中心里。我们的核心工作,就是按照框架规定的格式,创建我们的工具类,并将其注册到这个中心,使得智能体在规划任务时能够感知到它的存在。这通常涉及修改或创建Python代码文件,并确保其能被主程序正确加载。

2.3 设计前的关键考量

在设计自定义工具时,有几个问题需要提前想清楚:

  • 工具的职责是否单一?一个工具最好只做一件事。比如,“获取用户信息并发送邮件”就应该拆分成“获取用户信息”和“发送邮件”两个工具。这能让智能体更灵活地组合它们,也便于调试。
  • 输入输出是否明确且结构化?工具应该接受定义清晰的参数(如user_id: str),并返回结构化的数据(如JSON)。避免使用过于复杂或模糊的参数,这会让智能体困惑。
  • 是否需要处理异常和边界情况?工具代码必须有健壮的错误处理。当网络超时、API返回错误、输入无效时,工具应该返回明确的错误信息,而不是崩溃。这能帮助智能体理解失败原因并尝试其他策略。
  • 工具是否具有普适性?考虑这个工具是否只在当前项目有用,还是可以抽象为通用工具。如果是后者,花时间完善其文档和配置会更有长期价值。

注意:在开始编码前,强烈建议通读一遍SuperAGI官方文档中关于工具开发的部分(如果存在),并浏览其tools目录下的现有工具源码。这是理解框架约定和最佳实践最快的方式,能避免你重新发明轮子或写出不兼容的代码。

3. 实战:逐步构建并集成一个自定义工具

理论说得再多,不如亲手实现一个。我们以一个实际场景为例:为SuperAGI添加一个“天气查询工具”。这个工具将调用一个公开的天气API,根据城市名返回当前的天气状况。

3.1 环境准备与项目结构探查

首先,确保你有一个可运行的SuperAGI开发或部署环境。通常,你需要克隆其GitHub仓库,并按照README完成依赖安装和环境配置(如设置数据库和API密钥)。

关键的一步是熟悉项目结构。工具相关的代码通常位于superagi/toolsapp/tools这样的目录下。进去看看,你会发现类似这样的结构:

tools/ ├── __init__.py ├── base_tool.py # 工具基类定义 ├── tool_factory.py # 工具工厂类,负责注册和获取工具 ├── web_search.py # 内置的网页搜索工具示例 ├── write_file.py # 内置的写文件工具示例 └── ... # 其他内置工具

你的目标就是在这里创建一个新文件,或者在一个新的工具包目录下创建文件。同时,查看tool_factory.py或类似的注册文件,了解工具是如何被加载的。有些版本可能通过装饰器注册,有些则需要在配置列表中声明。

3.2 创建自定义工具类

我们在tools目录下创建一个新文件weather_query.py

# superagi/tools/weather_query.py import requests import json from typing import Type, Optional from pydantic import BaseModel, Field from superagi.tools.base_tool import BaseTool from superagi.lib.logger import logger # 首先,定义工具的输入参数模型。这会被转换成JSON Schema供AI模型理解。 class WeatherQueryInput(BaseModel): city_name: str = Field(..., description="The name of the city to query the weather for, e.g., 'Beijing' or 'New York'.") # 然后,创建工具类,继承自BaseTool。 class WeatherQueryTool(BaseTool): """ 一个用于查询指定城市当前天气状况的工具。 """ # 工具的唯一标识符,智能体通过这个名字来调用它。 name: str = "Weather Query Tool" # 对工具能力的详细描述。这是AI选择工具的主要依据,务必清晰准确。 description: str = ( "Useful for fetching the current weather information of a specified city. " "Input should be a valid city name. The tool will return temperature, humidity, weather condition, and other details." ) # 指定上面定义的参数模型。 args_schema: Type[BaseModel] = WeatherQueryInput # 工具的能力版本,用于后续迭代管理。 tool_id: int = 1001 # 自定义一个唯一的ID,避免与内置工具冲突 # 这是工具的核心执行函数,_execute是基类约定的方法名。 def _execute(self, city_name: str) -> str: """ 执行天气查询。 Args: city_name (str): 城市名称。 Returns: str: 格式化的天气信息字符串,或错误信息。 """ # 在实际项目中,API密钥应从安全配置中读取,切勿硬编码。 api_key = self.get_tool_config("WEATHER_API_KEY") if not api_key: return "Error: Weather API key is not configured. Please set the WEATHER_API_KEY in the tool configuration." # 构建请求URL(这里以OpenWeatherMap API为例,你需要替换成可用的API) base_url = "http://api.openweathermap.org/data/2.5/weather" params = { "q": city_name, "appid": api_key, "units": "metric" # 使用摄氏度 } try: logger.info(f"[WeatherQueryTool] Querying weather for city: {city_name}") response = requests.get(base_url, params=params, timeout=10) response.raise_for_status() # 如果HTTP请求失败,抛出异常 data = response.json() # 解析API返回的JSON数据 main_info = data.get("main", {}) weather_info = data.get("weather", [{}])[0] wind_info = data.get("wind", {}) temperature = main_info.get("temp", "N/A") humidity = main_info.get("humidity", "N/A") condition = weather_info.get("description", "N/A") wind_speed = wind_info.get("speed", "N/A") result_str = ( f"The current weather in {city_name} is:\n" f"- Temperature: {temperature}°C\n" f"- Humidity: {humidity}%\n" f"- Condition: {condition}\n" f"- Wind Speed: {wind_speed} m/s" ) logger.info(f"[WeatherQueryTool] Query successful: {result_str}") return result_str except requests.exceptions.Timeout: error_msg = f"Error: Request timeout while querying weather for {city_name}." logger.error(f"[WeatherQueryTool] {error_msg}") return error_msg except requests.exceptions.RequestException as e: error_msg = f"Error: Network error occurred. Details: {str(e)}" logger.error(f"[WeatherQueryTool] {error_msg}") return error_msg except (KeyError, IndexError, json.JSONDecodeError) as e: error_msg = f"Error: Failed to parse the weather API response. Details: {str(e)}" logger.error(f"[WeatherQueryTool] {error_msg}") return error_msg

代码要点解析:

  1. 继承BaseTool:这是所有SuperAGI工具的基类,提供了框架所需的通用接口和生命周期管理。
  2. 定义args_schema:使用Pydantic的BaseModel来严格定义输入参数。Fielddescription字段至关重要,它直接告诉AI模型这个参数需要什么。这里我们只定义了一个city_name参数。
  3. 编写_execute方法:这是工具的业务逻辑核心。它接收定义好的参数,执行操作,并返回一个字符串结果。返回的字符串应尽可能信息丰富且格式友好,便于智能体阅读和进行后续推理。
  4. 错误处理与日志:代码中包含了全面的异常捕获(网络超时、请求异常、解析错误)。使用框架的logger记录日志,便于在SuperAGI的控制台或日志文件中追踪工具的执行情况。
  5. 配置管理:API密钥通过self.get_tool_config获取,这是一种安全的最佳实践,避免将敏感信息硬编码在源码中。你需要在SuperAGI的管理界面中预先配置WEATHER_API_KEY

3.3 注册工具到SuperAGI框架

创建了工具类之后,我们需要让SuperAGI知道它的存在。注册方式取决于你使用的SuperAGI版本。

方式一:通过工具工厂注册(常见于较早版本)找到tool_factory.py或类似的管理文件,在工具字典中添加你的新工具。

# 在 tool_factory.py 中 from superagi.tools.weather_query import WeatherQueryTool class ToolFactory: @classmethod def get_tool(cls, tool_name: str, **kwargs): tools = { # ... 其他内置工具 ... "Weather Query Tool": WeatherQueryTool(), } return tools.get(tool_name)

方式二:通过配置列表或自动发现(常见于较新版本)新版本可能采用更动态的注册方式,例如在config/tools.yaml__init__.py中声明。

# 假设存在 config/tools.yaml tools: - name: "Weather Query Tool" class: "superagi.tools.weather_query.WeatherQueryTool" config: - key: "WEATHER_API_KEY" value: "" # 值可在管理界面设置

或者,框架可能自动扫描tools目录下所有继承BaseTool的类。这种情况下,你只需要确保你的工具类被正确导入到包的__init__.py文件中。

# 在 tools/__init__.py 中添加 from .weather_query import WeatherQueryTool __all__ = [..., 'WeatherQueryTool']

方式三:通过API动态注册(高级用法)有些架构允许通过管理API在运行时添加工具。这通常需要查阅最新的官方文档。

实操心得:最可靠的方法是查看现有内置工具是如何被引用的。在SuperAGI的Web界面创建一个使用“Write File”工具的智能体,然后去后台日志或数据库里搜索这个工具名的调用记录,反向追踪它的加载路径,你就能找到正确的注册点。

3.4 配置工具参数与权限

工具注册后,通常还需要在SuperAGI的管理界面进行一些配置:

  1. 添加工具到工具库:在SuperAGI的Web UI中,进入“Tools”或“Toolkits”管理页面,你应该能看到新添加的“Weather Query Tool”。如果看不到,请检查注册步骤和服务器是否已重启。
  2. 设置工具配置:找到你的工具,为其添加配置项。对于我们例子中的WEATHER_API_KEY,你需要在这里填入从天气服务商处申请的真实API密钥。这样,get_tool_config方法才能读到它。
  3. 分配工具给智能体:创建或编辑一个智能体(Agent)时,在“选择工具”的步骤中,从工具列表里勾选“Weather Query Tool”。这样,该智能体就具备了调用这个新工具的能力。

4. 测试与调试:确保你的工具可靠工作

工具集成后,不经过充分测试就直接投入生产环境是危险的。我们需要验证工具是否能被正确调用、执行逻辑是否符合预期、以及错误处理是否健壮。

4.1 单元测试(隔离测试工具逻辑)

为你的工具类编写单元测试,模拟各种输入和API响应。这能确保核心业务逻辑的正确性。

# tests/tools/test_weather_query.py import pytest from unittest.mock import Mock, patch from superagi.tools.weather_query import WeatherQueryTool class TestWeatherQueryTool: @pytest.fixture def tool(self): # 创建一个工具实例,并模拟配置 tool_instance = WeatherQueryTool() tool_instance.get_tool_config = Mock(return_value="test_api_key") return tool_instance def test_execute_success(self, tool): """测试成功查询的场景""" # 模拟一个成功的API响应 mock_response = Mock() mock_response.json.return_value = { "main": {"temp": 22.5, "humidity": 65}, "weather": [{"description": "clear sky"}], "wind": {"speed": 3.1} } mock_response.raise_for_status = Mock() with patch('requests.get', return_value=mock_response) as mock_get: result = tool._execute("Beijing") mock_get.assert_called_once() assert "22.5" in result assert "clear sky" in result assert "Beijing" in result def test_execute_missing_api_key(self): """测试缺少API密钥的场景""" tool = WeatherQueryTool() tool.get_tool_config = Mock(return_value=None) # 模拟未配置密钥 result = tool._execute("Beijing") assert "Error: Weather API key is not configured" in result def test_execute_network_timeout(self, tool): """测试网络超时的场景""" with patch('requests.get', side_effect=requests.exceptions.Timeout): result = tool._execute("Beijing") assert "timeout" in result.lower()

4.2 集成测试(在SuperAGI环境中测试)

单元测试通过后,需要在真实的SuperAGI环境中进行端到端测试。

  1. 创建测试智能体:在Web UI中创建一个新的智能体,只给它分配“Weather Query Tool”这一个工具。
  2. 设计测试任务:给智能体下达明确的任务,例如:“What is the weather like in London today?”。观察智能体的思考过程(如果界面提供了日志)。
  3. 分析执行结果
    • 成功情况:智能体应该能正确识别任务,调用天气工具,并返回结构化的天气信息。
    • 失败情况:尝试一些边界案例,比如输入一个不存在的城市名“XYZCity”。观察工具返回的错误信息是否清晰,以及智能体是否会根据错误信息做出合理反应(例如,提示用户输入有效的城市名)。

4.3 调试技巧与日志查看

调试是开发过程中不可或缺的一环。

  • 善用Logger:我们在工具代码中加入了logger.infologger.error。这些日志会输出到SuperAGI的服务端日志中(通常是控制台或指定的日志文件)。通过查看日志,你可以清晰地看到工具被调用的时间、输入参数、执行步骤以及任何错误信息。
  • 检查数据库:SuperAGI可能会将工具的执行记录存储在数据库中(如tool_executions表)。查询这些记录可以帮助你复盘智能体的工具调用历史。
  • 模拟调用:你可以在Python REPL或一个简单的脚本中直接实例化你的工具类并调用_execute方法,快速验证其功能,而无需启动整个SuperAGI服务。

5. 进阶:构建与集成自定义工具包

当你需要添加一组功能相关的工具时,逐个单独注册会显得杂乱。将它们组织成一个工具包是更优雅的做法。假设我们要创建一个“数据可视化工具包”(DataViz Toolkit),包含“生成折线图”和“生成柱状图”两个工具。

5.1 创建工具包目录结构

首先,在tools目录下创建一个新的包(目录)。

tools/ ├── __init__.py ├── base_tool.py └── dataviz_toolkit/ # 我们的自定义工具包 ├── __init__.py ├── base.py # 工具包基类(可选) ├── line_chart_tool.py └── bar_chart_tool.py

5.2 实现工具包内的各个工具

每个工具的实现方式与之前的单一工具类似,但它们的类可以放在工具包的目录下。

# superagi/tools/dataviz_toolkit/line_chart_tool.py from typing import Type from pydantic import BaseModel, Field from superagi.tools.base_tool import BaseTool import matplotlib.pyplot as plt import io import base64 class LineChartInput(BaseModel): data_points: list = Field(..., description="A list of numerical data points for the Y-axis, e.g., [10, 20, 15, 25].") title: str = Field("Line Chart", description="The title of the chart.") x_labels: list = Field(None, description="Optional labels for the X-axis.") class LineChartTool(BaseTool): name: str = "Generate Line Chart" description: str = "Creates a line chart from a series of data points and returns it as a base64 encoded image string." args_schema: Type[BaseModel] = LineChartInput tool_id: int = 2001 def _execute(self, data_points: list, title: str = "Line Chart", x_labels: list = None) -> str: try: plt.figure(figsize=(10,6)) if x_labels and len(x_labels) == len(data_points): plt.plot(x_labels, data_points, marker='o') else: plt.plot(data_points, marker='o') plt.title(title) plt.grid(True) # 将图表保存到内存缓冲区,并编码为base64 buf = io.BytesIO() plt.savefig(buf, format='png') plt.close() # 关闭图形,释放内存 buf.seek(0) img_base64 = base64.b64encode(buf.read()).decode('utf-8') return f"SUCCESS: Line chart generated. Image data (base64): {img_base64[:100]}..." # 返回部分数据示例 except Exception as e: return f"ERROR: Failed to generate line chart. Details: {str(e)}"

BarChartTool的实现会类似,只是使用plt.bar

5.3 创建并注册工具包

工具包通常需要一个入口文件或配置来声明其包含的所有工具。

方式一:在工具包__init__.py中导出

# superagi/tools/dataviz_toolkit/__init__.py from .line_chart_tool import LineChartTool from .bar_chart_tool import BarChartTool __all__ = ['LineChartTool', 'BarChartTool']

方式二:通过工具包配置文件注册在某些SuperAGI版本中,你可能需要在更高层级的配置中声明这个工具包。

# config/toolkits.yaml toolkits: - name: "Data Visualization Toolkit" description: "A set of tools for generating basic charts." tools: - "Generate Line Chart" - "Generate Bar Chart"

然后,确保这些工具名已经在上层工具工厂或注册中心被正确关联到对应的类。

5.4 在智能体中使用工具包

注册成功后,在智能体的工具选择界面,你可能会看到“Data Visualization Toolkit”作为一个分组出现,里面包含了“Generate Line Chart”和“Generate Bar Chart”两个工具。你可以像选择单个工具一样,将它们分配给智能体。

6. 常见问题、排查技巧与最佳实践实录

在实际开发和集成过程中,你一定会遇到各种问题。以下是我踩过的一些坑和总结出的经验。

6.1 问题排查清单

问题现象可能原因排查步骤
在Web UI的工具列表中看不到新工具1. 工具类未正确注册。
2. 服务器未重启/重载。
3. 工具包__init__.py未导出。
4. 工具ID与现有工具冲突。
1. 检查tool_factory.py或配置文件,确认工具名和类路径正确。
2. 重启SuperAGI后端服务。
3. 检查工具包目录下的__init__.py文件。
4. 查看日志中是否有关于工具加载失败的报错。
智能体无法调用工具,或调用后无反应1. 工具_execute方法参数与args_schema不匹配。
2. 工具执行过程中抛出未处理的异常。
3. AI模型无法理解工具描述。
1. 确保_execute方法的参数名和类型与Pydantic模型完全一致。
2. 查看服务端错误日志,定位异常堆栈信息。
3. 简化并精确化工具的namedescription,确保无歧义。
工具执行返回错误信息,但日志不清晰1. 工具代码中日志记录不充分。
2. 错误被过于笼统地捕获。
1. 在关键步骤(如API调用前后、数据解析前后)添加详细的logger.info
2. 使用更具体的异常捕获,并记录repr(e)traceback
工具配置(如API KEY)读取为None1. 配置键名拼写错误。
2. 未在管理界面正确配置。
3.get_tool_config方法使用有误。
1. 核对代码中的配置键名与UI中设置的键名是否完全一致(区分大小写)。
2. 登录SuperAGI管理后台,确认工具配置已保存。
3. 确认工具类正确继承了BaseTool,从而拥有get_tool_config方法。

6.2 核心避坑指南与最佳实践

  1. 描述即契约:工具的description和参数的description是AI模型理解工具的“说明书”。务必用简洁、无歧义的英语(或模型训练的主要语言)撰写。避免使用技术黑话,多从用户意图的角度描述。例如,“Fetches user profile from the database by user ID”就比“Executes SELECT * FROM users WHERE id=?”要好得多。
  2. 输入验证前置:尽管args_schema能进行基础的类型验证,但在_execute方法内部,仍应对业务逻辑相关的输入进行验证。例如,对于城市名,可以检查其是否为空或是否包含非法字符。将验证失败的信息清晰返回,能帮助智能体更好地与用户交互。
  3. 返回结构化信息:虽然_execute方法返回的是字符串,但你可以返回结构化的文本,如JSON字符串或键值对列表。这能让AI模型更容易提取关键信息进行后续推理。例如,{"status": "success", "temperature": 22, "city": "London"}比一段纯文本描述更易于解析。
  4. 处理异步与长时任务:如果你的工具执行需要很长时间(如训练一个模型),不要让_execute方法同步阻塞。可以考虑将其设计为触发一个异步任务,并立即返回一个任务ID。然后,提供另一个“检查任务状态”的工具供智能体轮询。这符合AI智能体“规划-执行-观察”的循环模式。
  5. 版本管理与兼容性:当更新一个已部署的工具时,注意保持向后兼容性。如果必须修改args_schema,考虑同时维护新旧两个版本的工具,或者通过智能体工作流来协调迁移。在description中也可以加入版本说明。
  6. 安全性是第一要务
    • 永远不要信任输入:智能体生成的输入可能被恶意诱导。对传入_execute的所有参数进行严格的清洗和校验,防止SQL注入、命令注入、路径遍历等攻击。
    • 最小权限原则:工具运行所需的权限(如文件系统访问、网络访问、数据库权限)应被严格控制。不要给工具超过其功能所需的权限。
    • 隔离敏感逻辑:对于执行高风险操作(如删除数据、调用生产环境API)的工具,可以考虑增加一个“确认步骤”,或者将其设计为需要人工审核才能触发。

6.3 性能优化建议

  • 缓存:对于频繁调用且结果变化不快的工具(如某些数据查询),可以在工具内部实现简单的缓存机制(如使用functools.lru_cache),但要注意缓存失效策略。
  • 资源池:如果工具需要创建昂贵资源(如数据库连接、HTTP会话),考虑使用连接池或在工具类初始化时创建,并在多次调用间复用。
  • 超时设置:所有外部调用(网络请求、子进程)都必须设置合理的超时时间,避免一个失败的工具调用拖垮整个智能体执行线程。

为SuperAGI添加自定义工具,是一个将通用AI能力与你的具体业务、数据和环境深度结合的过程。它没有想象中那么复杂,但需要你对框架的运作方式有清晰的理解,并遵循良好的软件工程实践。从设计一个单一、明确功能的工具开始,逐步扩展到复杂的工具包,在这个过程中,你会对智能体的能力边界和潜力有更深刻的体会。记住,最强大的工具往往是那些最贴合你独特需求而打造的。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/1 4:12:23

8个Prompt技巧让Gemini输出质量翻倍

前言最近半年,大模型更新节奏明显加快。Gemini 系列在长上下文、多模态理解和代码生成方面持续迭代,已经成了不少开发者日常工作流的一部分。但在实际使用中,很多人会遇到同一个问题:同样的模型,别人用起来像是"开…

作者头像 李华
网站建设 2026/6/1 4:03:01

基于74LS90与红外传感的纯硬件计数器设计与实现

1. 项目概述:一个源于真实需求的电子计数方案在电子制作和自动化领域,计数是一个基础但至关重要的功能。无论是工厂流水线上的零件统计,还是日常生活中的物料清点,一个可靠、低成本的自动计数系统都能极大提升效率。今天我想分享的…

作者头像 李华