当前位置: 首页 > news >正文

AI智能体技能开发实战:从LLM工具封装到复杂任务自动化

1. 项目概述与核心价值

最近在探索AI智能体(Agent)的落地应用时,我偶然发现了一个非常有意思的开源项目:alexpolonsky/agent-skill-jlm-coffee。这个项目名字乍一看有点“缝合怪”的感觉,但深入研究后,我发现它精准地指向了当前AI应用开发中的一个关键痛点——如何让大语言模型(LLM)驱动的智能体,真正具备执行复杂、多步骤现实任务的能力,而不仅仅是进行对话。这个项目以“制作一杯咖啡”为具体场景,构建了一个可复用的智能体技能(Skill),为我们提供了一个绝佳的、可实操的研究范本。

简单来说,这个项目不是一个完整的聊天机器人或客服系统,而是一个标准化的、可被其他智能体调用的“技能模块”。它的核心目标是教会一个AI智能体,如何根据用户模糊的、口语化的指令(比如“我想喝杯拿铁,不要太烫”),去理解意图、拆解步骤、并最终驱动虚拟或真实的设备(在这个案例里,是一个模拟的咖啡机环境)完成一杯咖啡的制作。这背后涉及的关键技术栈,包括大语言模型的理解与规划能力、技能(Skill)的标准化封装、以及与环境(Environment)的交互逻辑,正是当前构建实用型AI智能体的核心。

对于开发者而言,无论你是想构建一个家庭自动化智能体、一个游戏内的NPC助手,还是一个企业级的流程自动化工具,这个项目都极具参考价值。它剥离了花哨的界面和复杂的概念,直击本质:如何将人类语言指令,转化为一系列可靠、可执行、可验证的动作序列。接下来,我将带你深入这个项目的内部,拆解它的设计思路、技术实现,并分享如何将其思想应用到更广泛的场景中。

2. 项目核心架构与设计哲学

2.1 什么是“智能体技能”(Agent Skill)?

在深入代码之前,我们必须先理解“技能”在这个上下文中的定义。这并非指编程技能,而是指一个智能体所具备的、完成特定领域任务的能力单元。一个良好的技能设计,应该具备以下特征:

  1. 高内聚:一个技能只专注于做好一件事。jlm-coffee技能就只关心“制作咖啡”相关的所有子任务,如选择豆子、研磨、萃取、打奶泡等。它不应该去处理查询天气或发送邮件。
  2. 标准化接口:技能需要提供清晰、统一的调用方式。通常,这会是一个函数或API,接收明确的输入参数(如咖啡类型、糖量、温度),并返回明确的执行结果或状态。这允许智能体像搭积木一样组合不同的技能。
  3. 环境感知与交互:技能必须知道如何与它所要操作的对象(即“环境”)进行对话。在这个项目中,环境就是一个模拟的咖啡机,技能需要向它发送“开机”、“研磨”、“萃取”等指令,并接收“水箱缺水”、“豆仓已空”等状态反馈。
  4. 容错与状态管理:真实的操作充满不确定性。一个好的技能需要能处理异常情况(如材料不足、设备故障),并管理任务执行过程中的状态(如“正在加热”、“研磨完成”)。

agent-skill-jlm-coffee项目正是基于这些原则构建的。它将“制作咖啡”这个复杂流程,封装成了一个独立的、拥有标准化输入输出的技能模块,等待被上层的智能体“大脑”(LLM)在合适的时机调用。

2.2 技术栈选型与依赖解析

这个项目通常构建在流行的AI智能体开发框架之上。虽然项目本身可能不显式绑定某个框架,但其设计思想与以下主流方案高度契合:

  • LangChain / LangGraph:这是目前最流行的智能体构建框架之一。其核心概念之一就是“Tool”(工具),与“Skill”异曲同工。本项目可以非常自然地实现为一个LangChain Tool,利用其强大的链条(Chain)和智能体(Agent)编排能力。
  • AutoGen:由微软推出的多智能体协作框架。在这里,“咖啡制作技能”可以被视作一个专长的“助理智能体”,它接收来自“用户代理智能体”的请求并执行。
  • 自定义框架:项目也可能采用更轻量级的自定义实现,核心是围绕一个LLM调用(如OpenAI GPT、Claude或开源模型)构建一个工作流。

项目的关键依赖通常包括:

  • 大语言模型客户端:如openaianthropic, 或litellm等。
  • 智能体框架核心库:如langchainlanggraph等。
  • 模拟环境:为了演示和测试,项目会包含一个coffee_machine_simulator.py之类的模块,用代码模拟一台咖啡机的硬件接口和行为逻辑,避免需要真实硬件才能运行。
  • 配置管理:使用pydantic进行参数验证和设置管理,使用dotenv管理API密钥等敏感信息。

注意:在复现或借鉴此类项目时,第一步永远是仔细阅读requirements.txtpyproject.toml文件。理解每个依赖的作用,能帮你更好地把握项目的技术边界和设计意图。例如,如果看到了fastapi,说明该项目可能还提供了HTTP API服务层,允许技能被远程调用。

2.3 “JLM”的含义与项目定位

项目名中的“JLM”很可能是一个缩写或特定指代。在AI智能体领域,一种常见的解读是“Job, Language, Model”“Just a Language Model”的变体,强调其核心是让语言模型去理解和执行一项具体工作(Job)。另一种可能是代表某个内部项目代号或作者名。无论如何,它不影响我们对项目核心——“Skill”——的理解。

这个项目的定位非常清晰:一个示范性的、端到端的智能体技能实现。它不追求功能的全面性(比如支持全世界所有咖啡种类),而是追求实现路径的完整性和规范性。它向我们展示了:

  1. 如何定义技能的输入输出模式(Schema)。
  2. 如何将自然语言指令解析为结构化参数。
  3. 如何将结构化参数映射为一系列对环境的具体操作。
  4. 如何处理操作中的反馈和异常。
  5. 如何将执行结果以自然语言的形式返回给用户。

3. 核心模块深度拆解与实操

3.1 技能接口(Skill Interface)设计剖析

技能接口是技能与智能体“大脑”之间的契约。在jlm-coffee中,这个接口通常是一个Python函数,并附带有清晰的元数据描述,以便LLM理解何时以及如何调用它。

让我们来看一个可能的核心接口定义:

from pydantic import BaseModel, Field from typing import Literal, Optional class CoffeeOrder(BaseModel): """描述一杯咖啡订单的模型""" coffee_type: Literal[“espresso”, “latte”, “cappuccino”, “americano”] = Field(description=“所需的咖啡种类”) strength: Literal[“single”, “double”] = Field(default=“single”, description=“咖啡浓度:单份或双份”) milk_type: Optional[Literal[“whole”, “skim”, “oat”, “soy”]] = Field(default=None, description=“需要的牛奶类型,如不需要则留空”) sugar_level: int = Field(default=0, ge=0, le=3, description=“糖度等级,0-3”) temperature: Literal[“hot”, “warm”, “extra_hot”] = Field(default=“hot”, description=“咖啡温度”) async def make_coffee_skill(order: CoffeeOrder) -> str: """ 根据订单制作一杯咖啡。 这是一个复杂的多步骤技能,涉及检查原料、操作咖啡机等多个子任务。 Args: order: 一个包含咖啡类型、浓度、牛奶偏好等信息的订单对象。 Returns: str: 描述制作过程和最终结果的字符串。例如:“已成功制作一杯双份浓缩拿铁,使用全脂牛奶,温度较热,未加糖。” Raises: ResourceError: 当咖啡豆、牛奶或水不足时抛出。 MachineError: 当咖啡机发生故障时抛出。 """ # 技能的核心逻辑将在这里实现 # 1. 解析订单 # 2. 与环境(咖啡机)交互 # 3. 返回结果 pass

设计要点解析:

  1. 强类型与验证:使用PydanticBaseModel定义输入参数,这不仅是类型提示,更提供了运行时验证。Field中的description至关重要,它是LLM理解这个参数含义的“说明书”。
  2. 枚举与约束Literal类型限定了参数的合法取值范围,防止用户或LLM产生不合理请求(如coffee_type: “cola”)。gele用于约束数值范围。
  3. 清晰的文档字符串(Docstring):函数的文档字符串是LLM理解该技能功能的主要依据。必须清晰、无歧义地描述功能、参数和返回值。许多智能体框架(如LangChain)会直接利用这些文档来生成工具的调用说明。
  4. 异步支持:使用async def声明函数,因为与硬件或网络服务的交互通常是IO密集型操作,异步可以提高在并发场景下的效率。

3.2 模拟环境(Simulated Environment)的构建

由于连接真实咖啡机成本高昂且不便测试,构建一个高保真的模拟环境是此类项目的标准做法。这个模拟环境有几个关键职责:

  1. 状态管理:维护咖啡机的内部状态,如水箱水位、豆仓余量、锅炉温度、是否开机等。
  2. 动作映射:将高级指令(如“研磨双份浓缩咖啡豆”)映射为一系列低级的、原子性的状态变更。
  3. 物理逻辑模拟:引入真实的约束和延迟。例如,从开机到达到萃取温度需要时间;研磨会消耗咖啡豆;制作完一杯咖啡后需要清理冲煮头。
  4. 异常生成:根据状态随机或按规则产生异常,如“豆仓已空”、“蒸汽棒堵塞”,用于测试技能的鲁棒性。

一个简化的模拟环境类可能长这样:

class CoffeeMachineSimulator: def __init__(self): self.water_level = 1000 # 毫升 self.bean_level = 500 # 克 self.is_on = False self.brew_head_temp = 25 # 摄氏度 self._target_temp = 93 async def power_on(self): if self.is_on: return “咖啡机已处于开机状态。” self.is_on = True await asyncio.sleep(2) # 模拟开机延迟 return “咖啡机已开机,正在预热...” async def heat_up(self): if not self.is_on: raise MachineError(“请先开机。”) while self.brew_head_temp < self._target_temp: await asyncio.sleep(0.5) self.brew_head_temp += 10 if self.brew_head_temp > self._target_temp: self.brew_head_temp = self._target_temp return f“预热完成,冲煮头温度已达{self.brew_head_temp}°C。” async def grind_beans(self, grams: int): if self.bean_level < grams: raise ResourceError(f“咖啡豆不足。需要{grams}g, 仅剩{self.bean_level}g。”) self.bean_level -= grams await asyncio.sleep(grams * 0.02) # 研磨时间与克数成正比 return f“已研磨{grams}g咖啡豆。” # ... 其他方法如 brew_espresso, steam_milk, clean 等

实操心得:在构建模拟环境时,日志(Logging)至关重要。你需要详细记录每一个状态变更和接收到的指令。这不仅能帮助调试,还能在技能执行失败时,提供完整的“操作回放”,让你精准定位是技能逻辑问题,还是环境模拟问题。

3.3 技能内部的工作流引擎

make_coffee_skill函数内部并非简单的一两条指令,它需要编排一个完整的工作流。这个工作流通常是状态机(State Machine)有向无环图(DAG)的体现。

对于“制作拿铁”这个订单,工作流可能如下:

开始 ├─> 检查咖啡机电源 -> 若关机则开机 ├─> 等待预热至目标温度 ├─> 检查原料(水、豆、牛奶)是否充足 ├─> 研磨咖啡豆 ├─> 萃取浓缩咖啡 ├─> 蒸汽打奶泡 ├─> 混合咖啡与牛奶 └─> 清理冲煮头与蒸汽棒 结束

在代码中,这个工作流可能通过一个简单的async函数序列来实现,也可能使用更正式的工作流引擎(如PrefectLuigi,或在LangGraph中定义为StateGraph)。

async def make_coffee_skill(order: CoffeeOrder): machine = CoffeeMachineSimulator() steps_log = [] try: # 步骤1: 准备阶段 steps_log.append(await machine.power_on()) steps_log.append(await machine.heat_up()) # 步骤2: 检查资源 required_beans = 18 if order.strength == “double” else 9 if machine.bean_level < required_beans: raise ResourceError(“咖啡豆不足”) if machine.water_level < 200: raise ResourceError(“水箱水量不足”) if order.milk_type and milk_supply.get(order.milk_type, 0) < 150: raise ResourceError(f“{order.milk_type}牛奶不足”) # 步骤3: 执行制作 steps_log.append(await machine.grind_beans(required_beans)) steps_log.append(await machine.brew_espresso(order.strength)) if order.milk_type: steps_log.append(await machine.steam_milk(order.milk_type, order.temperature)) steps_log.append(“正在混合咖啡与牛奶...”) if order.sugar_level > 0: steps_log.append(f“正在添加{order.sugar_level}份糖...”) # 步骤4: 收尾工作 steps_log.append(await machine.clean_brew_head()) # 整合日志,生成用户友好的回复 result_message = f“已为您制作一杯{order.strength}份{order.coffee_type}” if order.milk_type: result_message += f“, 使用{order.milk_type}牛奶” result_message += f“, 温度{order.temperature}” if order.sugar_level: result_message += f“, 添加了{order.sugar_level}份糖” result_message += “。\n\n制作过程如下:\n” + “\n”.join(f“- {step}” for step in steps_log) return result_message except (ResourceError, MachineError) as e: # 优雅地处理错误,并给出可操作的提示 error_msg = f“制作失败:{e}。请补充原料或检查设备后重试。” # 这里可以附加当前机器状态,帮助用户诊断 error_msg += f“\n当前状态:豆仓{self.bean_level}g, 水箱{self.water_level}ml。” return error_msg

关键设计模式模板方法模式在这里得到了很好的体现。make_coffee_skill定义了一个制作咖啡的算法骨架(准备、检查、制作、收尾),而具体的步骤(如grind_beanssteam_milk)则委托给环境对象去实现。这使得技能逻辑与具体的硬件操作解耦,未来若要适配不同品牌的咖啡机,只需替换或继承CoffeeMachineSimulator类即可。

4. 与大语言模型(LLM)的集成与编排

4.1 将技能封装为LLM可调用的“工具”(Tool)

单独的技能没有智能。它需要被一个LLM驱动的智能体“大脑”所调用。主流框架都提供了将函数封装为“工具”的机制。以LangChain为例:

from langchain.tools import Tool from langchain.agents import initialize_agent, AgentType from langchain_openai import ChatOpenAI # 将我们的技能函数封装成Tool coffee_tool = Tool.from_function( func=make_coffee_skill, name=“MakeCoffee”, description=“”” 根据详细订单制作一杯咖啡。订单需包含咖啡种类、浓度、牛奶类型、糖度和温度。 在调用此工具前,你必须与用户确认订单的所有细节。 “””, args_schema=CoffeeOrder # 使用Pydantic模型作为参数模式 ) # 初始化LLM和智能体 llm = ChatOpenAI(model=“gpt-4”, temperature=0) agent = initialize_agent( tools=[coffee_tool], # 将咖啡工具注入智能体 llm=llm, agent=AgentType.STRUCTURED_CHAT_ZERO_SHOT_REACT_DESCRIPTION, # 适合处理结构化工具 verbose=True # 打印思考过程,便于调试 ) # 现在,智能体可以处理用户关于咖啡的自然语言请求了 async def handle_user_request(user_input: str): response = await agent.arun(user_input) return response

当用户说“帮我做一杯热拿铁,加一份糖”,LLM会基于coffee_tool的描述,理解到自己需要调用MakeCoffee工具,并尝试从对话中提取出coffee_type: “latte”temperature: “hot”sugar_level: 1等信息,组装成符合CoffeeOrder模型的参数,然后调用我们的技能函数。

4.2 提示工程(Prompt Engineering)的关键作用

LLM并非天生就知道如何完美地使用工具。我们需要通过系统提示词(System Prompt)来引导它。一个针对咖啡订单场景的提示词可能包含:

你是一个专业的咖啡师智能体。你的目标是理解用户的咖啡需求,并操作咖啡机为他们制作咖啡。 你拥有一个名为`MakeCoffee`的工具。在调用该工具前,你必须与用户确认以下所有信息: 1. 咖啡种类(意式浓缩、拿铁、卡布奇诺、美式)。 2. 浓度(单份或双份)。 3. 是否需要牛奶?如果需要,是什么类型(全脂、脱脂、燕麦奶、豆奶)? 4. 需要加糖吗?需要几份(0-3)? 5. 对温度有什么偏好(热、温、特热)? 只有当你收集齐所有这些信息,并且用户确认后,你才能调用`MakeCoffee`工具。 如果用户的需求模糊不清,请主动询问以澄清。 如果工具执行失败并返回错误信息,请向用户友好地解释问题所在,并建议解决方案。

这个提示词做了几件关键事:

  1. 设定角色:让LLM进入“专业咖啡师”的心智模式。
  2. 明确流程:强制LLM遵循“确认-再执行”的流程,避免误操作。
  3. 定义交互协议:告诉LLM在什么情况下调用工具,以及如何处理工具的返回结果(成功或失败)。

实操心得:工具描述的颗粒度coffee_tooldescription字段和系统提示词需要分工协作。工具描述应聚焦于工具的功能性(输入输出是什么),而系统提示词则侧重于策略性(何时、为何以及如何调用工具)。避免在工具描述中写入过多的策略性内容,这会使工具变得不通用。

4.3 多技能协作与智能体规划

一个实用的智能体不可能只会做咖啡。它可能还需要“查询天气”、“播放音乐”、“控制灯光”。jlm-coffee项目展示的单一技能,是构建复杂智能体的基石。

当智能体拥有多个工具时,LLM的核心能力——规划与决策——就变得至关重要。LLM需要根据用户的目标(“我想在温暖的灯光下,边听爵士乐边喝杯咖啡”),自主规划出一个动作序列:

  1. 调用“灯光控制”技能,将灯光调至暖色调。
  2. 调用“音乐播放”技能,播放爵士乐歌单。
  3. 与用户交互,确认咖啡订单细节。
  4. 调用“MakeCoffee”技能制作咖啡。

这就是智能体框架(如LangGraph)大显身手的地方。它们允许你定义更复杂的状态流转逻辑,让LLM在每一步根据当前状态决定下一个动作,甚至实现循环、条件分支等复杂控制流。

5. 测试、部署与扩展实践

5.1 单元测试与集成测试策略

对于技能类项目,测试必须分层进行:

  1. 单元测试(技能逻辑):直接测试make_coffee_skill函数。模拟不同的CoffeeOrder输入,验证其返回的字符串是否符合预期,是否能正确抛出异常。

    def test_make_espresso(): order = CoffeeOrder(coffee_type=“espresso”, strength=“double”) # 这里需要模拟(mock)CoffeeMachineSimulator,使其返回预定行为 result = make_coffee_skill(order) assert “双份浓缩” in result assert “制作失败” not in result
  2. 单元测试(模拟环境):测试CoffeeMachineSimulator的每一个方法,确保状态变更和物理逻辑模拟正确。

  3. 集成测试(技能+环境):将真实的技能和模拟环境连接起来,进行端到端测试。验证从订单到最终结果的全流程。

  4. 智能体层面测试:这是最复杂的一层。你需要测试LLM是否能正确理解用户意图并调用技能。这通常通过基于场景的对话测试来完成。你可以编写一系列测试用例,模拟用户对话,然后断言智能体的最终回复中是否包含预期的关键信息。

    async def test_agent_coffee_order(): response = await handle_user_request(“我要一杯卡布奇诺”) # 断言LLM会询问浓度、牛奶类型等细节,而不是直接调用工具 assert “浓度” in response or “牛奶” in response

5.2 部署为可复用的服务

为了让其他智能体或系统方便地调用,最好将技能部署为一个独立的服务(如HTTP API)。

from fastapi import FastAPI, HTTPException from pydantic import BaseModel app = FastAPI(title=“Coffee Making Skill API”) class CoffeeOrderRequest(BaseModel): # 可以复用或适配之前的CoffeeOrder模型 ... @app.post(“/make-coffee”) async def make_coffee_endpoint(order: CoffeeOrderRequest): try: result = await make_coffee_skill(order) return {“status”: “success”, “message”: result} except ResourceError as e: raise HTTPException(status_code=400, detail=str(e)) except MachineError as e: raise HTTPException(status_code=503, detail=str(e))

部署后,任何能发送HTTP请求的客户端(包括其他智能体)都可以通过调用POST /make-coffee来使用这个技能。这实现了技能与智能体平台的解耦,符合微服务架构的思想。

5.3 技能扩展与自定义

jlm-coffee是一个完美的起点,你可以从多个维度扩展它:

  1. 支持更多咖啡品类:在CoffeeOrder模型和技能逻辑中添加对新品类(如手冲、冷萃)的支持。
  2. 个性化与记忆:让技能记住用户的偏好。例如,用户A总是喝“双份浓缩,不加糖”,用户B喜欢“燕麦拿铁,一份糖”。这需要技能能访问或维护一个简单的用户偏好数据库。
  3. 与真实硬件集成:这是最激动人心的扩展。用CoffeeMachineSimulator的子类,重写其方法,将grind_beans()brew_espresso()等调用替换为通过GPIO、串口、MQTT或HTTP协议控制真实咖啡机的代码。
  4. 技能组合:创建一个“下午茶套餐”技能,它内部依次调用“制作咖啡”技能和“准备甜点”技能。

一个高级技巧:技能版本管理。当你对技能进行升级(如修改参数、优化流程)时,务必通过API版本号(如/v1/make-coffee/v2/make-coffee)或工具名称(如MakeCoffeeV2)进行区分。这可以避免对已有智能体工作流造成破坏性变更。

6. 常见问题与故障排查实录

在实际开发和集成jlm-coffee这类技能时,我踩过不少坑。这里总结一份速查表,希望能帮你节省时间。

问题现象可能原因排查步骤与解决方案
LLM不调用技能,总是自行回答1. 工具描述(description)不清晰或不够有吸引力。
2. 系统提示词未强调必须使用工具。
3. LLM温度(temperature)参数过高,导致随机性太强。
1. 优化工具描述,用“必须”、“仅当”等词强调其专长和必要性。例如:“必须使用此工具来制作咖啡,你无法自行完成。”
2. 在系统提示词开头明确指令:“你必须使用提供的工具来完成任务。”
3. 将temperature调低(如0.1),增加输出的确定性。
LLM调用了技能,但参数总是填错1. Pydantic模型的Field(description)描述不清。
2. LLM未能从对话历史中正确提取信息。
3. 参数类型过于复杂(如嵌套模型)。
1. 为每个字段提供极其简单、无歧义的描述。例如:coffee_type: “只能从[‘espresso’, ‘latte’, ‘cappuccino’, ‘americano’]中选择一项。”
2. 在调用工具前,让LLM将其理解到的参数以文本形式复述一遍并请求用户确认。
3. 尽量使用扁平化的参数结构,避免嵌套。
技能执行成功,但LLM回复的内容很奇怪LLM在收到工具返回的结果后,进行了“过度加工”或错误总结。1. 检查系统提示词中关于“如何处理工具返回结果”的部分。明确指示:“将工具返回的结果,几乎原样地回复给用户,只需在前面加上友好的问候。”
2. 技能返回的结果本身应是一段完整、通顺的自然语言,减少LLM二次加工的必要。
模拟环境行为与预期不符1. 环境的状态机逻辑有bug。
2. 异步操作(asyncio.sleep)导致时序问题。
1. 为模拟环境编写详尽的单元测试,覆盖所有状态转移。
2. 在测试中使用asyncio.run()pytest-asyncio插件确保异步代码正确执行。使用asyncioMockunittestAsyncMock来模拟时间延迟。
集成到大型智能体后性能下降1. 技能内部有同步阻塞操作(如长时间循环)。
2. 网络请求(如调用真实硬件API)超时未设置。
1. 确保技能内部所有IO操作都是异步的(使用async/await)。
2. 为所有外部调用设置合理的超时(asyncio.wait_for),并在技能中妥善处理超时异常,返回友好错误。
部署为API后,并发请求出错1. 技能或模拟环境类中使用了共享的、非线程安全的全局状态。
2. FastAPI等框架默认是异步的,但技能代码不是。
1. 确保每个请求都创建独立的技能和环境实例,避免状态污染。或者,使用线程锁或异步锁来保护共享状态。
2. 确保技能函数和所有底层调用都是async的,与异步框架兼容。

最重要的心得:日志,日志,还是日志!在智能体开发中,问题往往出在LLM的“黑盒决策”与你的代码逻辑之间。务必在技能入口、环境操作、LLM调用前后打上详细的日志。记录下:收到的原始输入、LLM的思考过程(如果框架支持)、工具调用的具体参数、环境的每一步状态变化、最终输出。当出现问题时,这份完整的“审计追踪”是你排查问题的唯一救命稻草。

通过alexpolonsky/agent-skill-jlm-coffee这个项目,我们完成了一次从概念到实现,再到测试部署的完整智能体技能开发之旅。它的价值远不止于“做咖啡”,而是提供了一个清晰的蓝图,告诉我们如何将任何一项复杂的现实世界任务,封装成AI智能体可以理解和可靠执行的数字化技能。下次当你需要让AI去操作一个软件、填写一个表单、分析一份报告时,不妨回想一下这个“咖啡技能”的构建过程,你会发现,底层逻辑是如此相通。

http://www.jsqmd.com/news/759327/

相关文章:

  • 别再手动写CRUD了!用avue-crud快速搞定Vue后台表格(附ElementUI配置避坑)
  • 3步掌握Layerdivider:智能图像分层的高效解决方案
  • 观察 Taotoken 按 Token 计费模式下的成本控制效果
  • 5步实施指南:开源SENAITE LIMS如何重塑实验室数字化转型路径
  • 无人机姿态控制实战:用Python从零搭建四元数PD控制器(附完整仿真代码)
  • 别再傻傻分不清了!一文讲透Autosar CP和AP到底该怎么选(附MCU/MPU芯片清单)
  • 终极指南:如何用WorkshopDL轻松下载Steam创意工坊模组
  • :简单 RAG 入门
  • Nacos 2.2.3安装后登录失败?手把手教你排查鉴权密钥与数据库配置问题
  • TrollInstallerX终极安装指南:iOS越狱工具快速安装与故障排除
  • SeeUPO算法:无Critic强化学习在序列决策中的应用
  • 告别‘一病一药’:用PromptIR这个‘万能插件’搞定所有图像修复难题(含代码实战)
  • 别再只用SSH了!给CentOS 7/8装个图形桌面,用Windows远程桌面直接连(xrdp保姆级教程)
  • 从亚马逊招聘工具到Midjourney翻车:给产品经理的AI偏见风险自查清单
  • Proteus仿真实战:用51单片机驱动6位数码管显示温度计(附完整C代码)
  • Linux深色光标主题设计、安装与自定义全指南
  • LLM代理在科研智能化中的实践与架构设计
  • Multisim 14.2 实战:用运放和RLC电路,手把手教你从零搭建一个五级DAC
  • PyInstaller打包的Matplotlib程序从40MB瘦身到17MB:我的实战记录与思考
  • Pearcleaner:免费开源的Mac应用清理工具,彻底释放存储空间
  • 用Python爬取中国福利彩票官网数据,自动更新到Excel的完整代码(附避坑指南)
  • 从图像分类到CTR预估:手把手拆解SENET模块在FiBiNet中的迁移与应用
  • 终端字符串样式化:从ANSI原理到Chalk库的实战指南
  • 三分钟掌握Steam Depot清单下载:Onekey工具终极指南
  • 从LC谐振到相位噪声:手把手教你理解VCO核心原理与设计权衡
  • REFramework:如何让RE引擎游戏获得无限扩展能力?
  • 高速串行链路技术演进与信号完整性设计
  • 别再只用PI了!手把手教你用准PR控制器搞定逆变器并网电流控制(附MATLAB/Simulink仿真模型)
  • UniBest零基础入门:用快马生成你的第一个跨端待办应用
  • 终极指南:如何用GI-Model-Importer轻松自定义原神角色模型