ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从零构建生产级AI智能体系统:Agent、Skills与Harness工程化实战

从零构建生产级AI智能体系统:Agent、Skills与Harness工程化实战 最近在跟几个做AI应用落地的团队交流发现一个普遍痛点大家都能用API快速调用大模型但一到构建稳定、可维护、能上生产的智能体Agent系统就卡在了工程化这一关。Agent本身的概念很火网上demo也很多但如何设计一个高内聚、低耦合的Agent架构如何像搭积木一样管理各种能力Skills如何用一套工程框架Harness来统一处理推理、监控、部署这些问题直接决定了项目能否从“玩具”变成“工具”。本文将从一线工程视角出发彻底拆解“Agent Skills Harness”这套技术栈。我不会只讲空洞的理论而是结合具体的架构设计、代码示例和部署实践带你走通从零搭建一个生产级Agent系统的全流程。无论你是想深入理解Agent工程化还是正在为团队技术选型或是关注AI领域的就业方向这篇文章都能提供一份详实的“地图”。1. 核心概念辨析Agent, Skills, Harness 究竟是什么在深入实战之前我们必须厘清这几个关键术语避免后续讨论出现歧义。它们常常被混用但在工程语境下各有明确的边界。1.1 Agent智能体具备自主决策与执行能力的AI单元你可以把Agent理解为一个“AI员工”。它不仅仅是一个语言模型而是一个具备感知、规划、决策和执行能力的完整系统。核心特征目标驱动接收一个高层目标如“分析本季度销售数据并生成报告”。自主规划能够将目标拆解为一系列可执行的子任务。工具使用可以调用外部工具Skills来获取信息或执行操作。记忆与学习拥有短期对话上下文和长期向量数据库记忆并能从历史交互中学习。工程化视角在代码层面一个Agent通常是一个类或服务它封装了与大模型LLM的交互逻辑、任务规划器Planner、工具调用器Tool Executor以及记忆管理模块。1.2 Skills技能/工具Agent可调用的原子能力Skills是Agent完成具体任务的“手”和“脚”。一个Skill就是一个独立的功能模块通常对应一个API调用、一个数据库查询或一段特定的业务逻辑代码。关键属性原子性每个Skill应只做好一件事。例如“查询天气”、“发送邮件”、“计算数据统计量”。标准化接口通常包含name、description、parameters输入参数模式和execute执行函数等标准字段。这使Agent能通过自然语言描述来理解和调用它们。可组合性多个Skills可以被一个Agent在同一个任务链中顺序或并行调用。常见类型网络工具搜索引擎、API客户端如GitHub、Jira。计算工具计算器、代码解释器。系统工具文件读写、数据库查询。自定义业务工具查询内部CRM系统、触发审批流程。1.3 Harness工程框架/套件Agent系统的“操作系统”这是最容易被误解的概念。Harness不是某个具体工具而是一套工程化框架和最佳实践的集合用于“驾驭”或“管理”Agent和Skills的整个生命周期。你可以把它类比为Kubernetes之于容器。核心职责生命周期管理提供Agent/Skill的注册、发现、加载和卸载机制。运行时协调管理多个Agent之间的协作多智能体系统处理任务调度和资源分配。可观测性集成日志、指标Metrics和追踪Tracing让你能看清Agent的决策过程和工具调用链路。配置与部署统一管理模型参数、API密钥、工具配置支持不同环境开发、测试、生产的部署。评估与测试提供基准测试框架用于评估Agent在不同任务上的性能、稳定性和成本。简单总结三者的关系Harness提供了一个稳固的“舞台”和“后台管理系统”Agent是在舞台上表演的“演员”而Skills是演员手中可随时取用的“道具”。没有HarnessAgent和Skills就是散兵游勇难以规模化管理和运维。2. 环境准备与核心工具选型开始构建之前我们需要搭建开发环境并选择合适的技术栈。这里以Python生态为例因为它拥有最丰富的AI库和社区支持。2.1 基础环境配置确保你的开发机满足以下条件操作系统Linux (Ubuntu 20.04)、macOS 或 WSL2 (Windows)。Python版本3.9 或 3.103.11需注意某些库的兼容性。包管理工具pip和venv推荐或conda。首先创建一个干净的虚拟环境并安装基础依赖# 创建并激活虚拟环境 python -m venv agent_env source agent_env/bin/activate # Linux/macOS # agent_env\Scripts\activate # Windows # 升级pip pip install --upgrade pip # 安装核心AI与Web框架 pip install openai langchain langchain-community langgraph fastapi uvicorn pydantic2.2 核心库说明与选型理由LangChain / LangGraph这是当前构建Agent事实上的标准框架。它提供了Agent、Tool、Chain等高级抽象极大简化了开发流程。LangGraph特别适合构建有状态、多步骤的复杂Agent工作流。FastAPI Uvicorn用于将我们的Agent系统封装成高性能的HTTP API服务方便前端或其他系统集成。Pydantic用于数据验证和设置管理确保配置和输入输出的结构化与安全。关于DeepSeek Harness等网络热词在撰写本文时像“DeepSeek Harness”这样的项目可能处于早期内测或概念阶段。在工程化选型中我们应优先选择社区活跃、文档完善、经过生产验证的开源框架如LangChain或者根据上述Harness的职责自行搭建轻量级框架。本文将采用后者即基于成熟开源库构建我们自己的Harness核心模块这能让你更深刻地理解其原理。3. 实战第一步设计与实现标准化Skill让我们从最基础的单元——Skill开始。一个好的Skill设计是系统可维护性的基石。3.1 定义Skill基类我们首先定义一个所有Skill都必须遵守的契约基类。这保证了所有工具都能被Agent以统一的方式发现和调用。# file: skills/base_skill.py from abc import ABC, abstractmethod from typing import Any, Dict, Optional from pydantic import BaseModel, Field class SkillInput(BaseModel): Skill输入参数的基类使用Pydantic进行验证。 # 例如一个查询天气的Skill输入可能是 {city: Beijing} pass class BaseSkill(ABC): 所有Skill的抽象基类。 name: str Field(descriptionSkill的唯一名称如 get_weather) description: str Field(descriptionSkill功能的自然语言描述用于让LLM理解何时调用它。) args_schema: Optional[type[BaseModel]] None # 定义输入参数的结构 def __init__(self, name: str, description: str): self.name name self.description description abstractmethod async def execute(self, input_data: Dict[str, Any]) - Dict[str, Any]: 执行Skill的核心方法。 Args: input_data: 包含调用参数的字典。 Returns: 执行结果的字典。 pass def to_langchain_tool(self): 将本Skill转换为LangChain可识别的Tool对象。 from langchain.tools import StructuredTool # 注意这里简化了转换实际需根据args_schema适配 return StructuredTool.from_function( funclambda **kwargs: self.execute(kwargs), nameself.name, descriptionself.description, # args_schemaself.args_schema, # 可传入更精细的schema )3.2 实现几个具体Skill示例接下来我们实现两个具体的Skill一个模拟获取天气一个执行数学计算。# file: skills/weather_skill.py import random from skills.base_skill import BaseSkill, SkillInput from pydantic import Field from typing import Dict, Any class WeatherInput(SkillInput): city: str Field(description城市名称例如北京、上海) class WeatherSkill(BaseSkill): 一个模拟的天气查询Skill。在生产环境中应接入真实的天气API。 def __init__(self): super().__init__( nameget_weather, description获取指定城市的当前天气情况。输入应为包含city字段的JSON对象。 ) self.args_schema WeatherInput async def execute(self, input_data: Dict[str, Any]) - Dict[str, Any]: city input_data.get(city, 未知城市) # 模拟API调用返回随机数据 temperatures [22, 25, 18, 30, 15] conditions [晴朗, 多云, 小雨, 大风] return { city: city, temperature: random.choice(temperatures), condition: random.choice(conditions), unit: 摄氏度, source: 模拟数据 }# file: skills/calculator_skill.py import math from skills.base_skill import BaseSkill from pydantic import Field from typing import Dict, Any class CalculatorSkill(BaseSkill): 一个简单的数学计算Skill。 def __init__(self): super().__init__( namecalculator, description执行基础数学运算。支持加()、减(-)、乘(*)、除(/)、乘方(**)等。输入示例: {expression: 3 5 * 2} ) async def execute(self, input_data: Dict[str, Any]) - Dict[str, Any]: # 警告在生产环境中直接eval是极度危险的这里仅用于演示。 # 真实场景应使用安全表达式求值库如 asteval或解析器。 expression input_data.get(expression, ) try: # 限制可用的命名空间增加一点安全性 safe_globals {__builtins__: None, math: math} result eval(expression, {__builtins__: None}, safe_globals) return {expression: expression, result: result, status: success} except Exception as e: return {expression: expression, result: None, status: error, message: str(e)}4. 构建Harness核心Skill与Agent的管理系统现在我们来搭建Harness的核心部分——一个集中管理Skills和Agent的注册中心。4.1 实现Skill注册中心# file: harness/skill_registry.py import inspect from typing import Dict, Type, Any from skills.base_skill import BaseSkill class SkillRegistry: Skill注册中心单例模式用于全局管理所有可用的Skill。 _instance None _skills: Dict[str, BaseSkill] {} def __new__(cls): if cls._instance is None: cls._instance super(SkillRegistry, cls).__new__(cls) return cls._instance def register(self, skill: BaseSkill): 注册一个Skill实例。 if skill.name in self._skills: raise ValueError(fSkill with name {skill.name} is already registered.) self._skills[skill.name] skill print(f[Harness] Skill registered: {skill.name}) def get(self, skill_name: str) - BaseSkill: 根据名称获取Skill实例。 skill self._skills.get(skill_name) if not skill: raise KeyError(fSkill {skill_name} not found in registry.) return skill def list_all(self) - Dict[str, str]: 列出所有已注册Skill的名称和描述。 return {name: skill.description for name, skill in self._skills.items()} def to_langchain_tools(self): 将所有注册的Skill转换为LangChain Tool列表。 return [skill.to_langchain_tool() for skill in self._skills.values()] # 全局唯一的注册中心实例 skill_registry SkillRegistry()4.2 实现一个简单的Agent运行器这个运行器负责加载Skill、初始化LLM、并执行Agent的推理循环。# file: harness/agent_runner.py import os from typing import List, Optional from langchain.agents import AgentExecutor, create_react_agent from langchain_core.prompts import PromptTemplate from langchain_openai import ChatOpenAI # 使用OpenAI API # 或 from langchain_community.chat_models import ChatOllama # 使用本地Ollama from harness.skill_registry import skill_registry class AgentRunner: 一个基于LangChain ReAct模式的Agent运行器。 def __init__(self, model_name: str gpt-3.5-turbo, temperature: float 0.1): 初始化运行器。 Args: model_name: 使用的LLM模型名称。 temperature: 模型温度参数控制随机性。 # 注意你需要设置环境变量 OPENAI_API_KEY self.llm ChatOpenAI(modelmodel_name, temperaturetemperature) # 从注册中心获取所有工具 self.tools skill_registry.to_langchain_tools() # 定义ReAct Agent的提示词模板 self.prompt PromptTemplate.from_template( 你是一个有帮助的AI助手可以调用工具来解决问题。 你可以使用的工具如下 {tools} 请严格按照以下格式回应 思考你需要先思考当前问题和可用工具 行动要调用的工具名称 行动输入调用该工具的输入参数必须是有效的JSON字符串 当你得到工具返回的观察结果后可以继续思考并行动。 如果问题已经解决或者没有合适的工具请最终输出 最终答案你的回答 现在开始 问题{input} {agent_scratchpad} # LangChain会自动填充思考-行动-观察的历史 ) # 创建ReAct Agent self.agent create_react_agent(llmself.llm, toolsself.tools, promptself.prompt) # 创建执行器 self.agent_executor AgentExecutor(agentself.agent, toolsself.tools, verboseTrue, handle_parsing_errorsTrue) async def run(self, query: str) - str: 执行Agent推理。 try: result await self.agent_executor.ainvoke({input: query}) return result.get(output, Agent未返回明确结果。) except Exception as e: return fAgent执行出错: {str(e)}5. 整合与测试构建完整的Agent服务我们将上述模块整合并通过一个FastAPI服务暴露出来形成一个可用的Agent系统。5.1 创建主应用并初始化# file: main.py import uvicorn from fastapi import FastAPI, HTTPException from pydantic import BaseModel from contextlib import asynccontextmanager from skills.weather_skill import WeatherSkill from skills.calculator_skill import CalculatorSkill from harness.skill_registry import skill_registry from harness.agent_runner import AgentRunner # 定义API请求/响应模型 class AgentRequest(BaseModel): query: str model: str gpt-3.5-turbo class AgentResponse(BaseModel): success: bool answer: str error: str None # 生命周期管理启动时初始化关闭时清理 asynccontextmanager async def lifespan(app: FastAPI): # 启动时注册所有Skill print(Initializing Harness and registering skills...) weather_skill WeatherSkill() calc_skill CalculatorSkill() skill_registry.register(weather_skill) skill_registry.register(calc_skill) print(fSkills registered: {list(skill_registry.list_all().keys())}) yield # 应用运行中 # 关闭时清理资源 print(Shutting down Harness...) # 可以在这里关闭数据库连接等 # 创建FastAPI应用 app FastAPI(titleAgent Harness Demo, lifespanlifespan) # 全局Agent运行器实例可根据请求参数创建不同配置的runner _runner_cache {} def get_agent_runner(model: str gpt-3.5-turbo) - AgentRunner: 获取或创建指定模型的Agent运行器简单缓存。 if model not in _runner_cache: _runner_cache[model] AgentRunner(model_namemodel) return _runner_cache[model] app.get(/) async def root(): return {message: Agent Harness API is running., available_skills: skill_registry.list_all()} app.post(/agent/query, response_modelAgentResponse) async def query_agent(request: AgentRequest): 主接口向Agent提问。 try: runner get_agent_runner(request.model) answer await runner.run(request.query) return AgentResponse(successTrue, answeranswer) except Exception as e: raise HTTPException(status_code500, detailstr(e)) if __name__ __main__: # 启动服务http://localhost:8000 uvicorn.run(app, host0.0.0.0, port8000)5.2 运行与测试服务启动服务在终端中确保已设置OPENAI_API_KEY环境变量然后运行export OPENAI_API_KEYyour-api-key-here # Linux/macOS # set OPENAI_API_KEYyour-api-key-here # Windows python main.py测试API使用curl或Postman等工具测试。查看首页和已注册Skillcurl http://localhost:8000/向Agent提问它会自动决定是否及如何调用Skillcurl -X POST http://localhost:8000/agent/query \ -H Content-Type: application/json \ -d {query: 北京今天的天气怎么样然后计算一下气温25摄氏度相当于多少华氏度, model: gpt-3.5-turbo}预期的Agent执行过程在服务日志中可见会是思考用户问了两个问题先需要天气然后需要计算。行动调用get_weather工具输入{city: 北京}。观察收到天气结果例如{“temperature”: 22, ...}。思考拿到了温度22度现在需要将其转换为华氏度。公式是F C * 9/5 32。行动调用calculator工具输入{expression: 22 * 9/5 32}。观察收到计算结果例如71.6。最终答案北京今天天气为...气温22摄氏度约等于71.6华氏度。6. 工程化进阶Harness的关键特性实现上面的Demo是一个最小可行系统。一个生产级的Harness还需要更多特性。6.1 可观测性集成日志与链路追踪在生产中我们必须知道Agent每一步做了什么、调用了什么、耗时多久、消耗了多少Token。# file: harness/observability.py import time import logging from functools import wraps from typing import Callable, Any # 配置结构化日志 logging.basicConfig(levellogging.INFO, format%(asctime)s - %(name)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) def trace_tool_call(func: Callable) - Callable: 装饰器追踪Skill执行的耗时和结果。 wraps(func) async def wrapper(self, input_data: Dict[str, Any], *args, **kwargs): start_time time.time() tool_name self.name logger.info(fTool CALL started: {tool_name}, input: {input_data}) try: result await func(self, input_data, *args, **kwargs) duration (time.time() - start_time) * 1000 # 毫秒 logger.info(fTool CALL succeeded: {tool_name}, duration: {duration:.2f}ms, result: {result}) # 可以在这里将追踪数据发送到OpenTelemetry、Prometheus等 return result except Exception as e: logger.error(fTool CALL failed: {tool_name}, error: {str(e)}) raise return wrapper # 使用方法装饰Skill的execute方法 # class WeatherSkill(BaseSkill): # trace_tool_call # async def execute(self, input_data): # ...6.2 配置管理集中管理API密钥与模型参数使用Pydantic Settings管理配置支持从环境变量、配置文件读取。# file: config/settings.py from pydantic_settings import BaseSettings from typing import Optional class Settings(BaseSettings): 应用配置。 # OpenAI openai_api_key: str openai_base_url: Optional[str] None # 可用于配置代理 default_model: str gpt-3.5-turbo # 服务 app_host: str 0.0.0.0 app_port: int 8000 # 日志级别 log_level: str INFO class Config: env_file .env # 从.env文件加载 extra ignore # 忽略未定义的额外环境变量 # 全局配置对象 settings Settings()在.env文件中配置OPENAI_API_KEYsk-你的真实密钥 DEFAULT_MODELgpt-4o-mini LOG_LEVELDEBUG6.3 技能市场与动态加载更高级的Harness可以实现Skill的动态发现和加载例如从一个中央仓库或目录加载。# file: harness/skill_loader.py import importlib import pkgutil from pathlib import Path def discover_and_register_skills(skills_package_path: str): 自动发现指定包路径下所有继承自BaseSkill的类并注册。 package importlib.import_module(skills_package_path) for _, module_name, _ in pkgutil.iter_modules(package.__path__): full_module_name f{skills_package_path}.{module_name} module importlib.import_module(full_module_name) for attr_name in dir(module): attr getattr(module, attr_name) if (isinstance(attr, type) and issubclass(attr, BaseSkill) and attr ! BaseSkill): try: skill_instance attr() # 实例化Skill skill_registry.register(skill_instance) logger.info(fAuto-registered skill: {skill_instance.name}) except Exception as e: logger.error(fFailed to instantiate skill {attr_name}: {e})7. 常见问题与排查思路在开发和部署Agent系统时你会遇到一些典型问题。问题现象可能原因排查步骤与解决方案Agent不调用任何Skill直接回答1. LLM提示词Prompt未清晰说明工具使用格式。2. Skill描述description不够清晰LLM无法理解其用途。3. 模型能力不足如使用过于简单的模型。1. 检查并优化Agent的提示词模板强化工具使用指令。2. 重写Skill的description使其更精确、无歧义包含清晰的输入输出示例。3. 升级到更强大的模型如GPT-4系列或在提示词中加入少量示例Few-shot。Skill调用参数解析错误1. LLM生成的“行动输入”不是有效的JSON。2. 参数类型或结构与Skill定义的args_schema不匹配。1. 在Agent执行器中启用handle_parsing_errorsTrue并尝试修复JSON。2. 在Skill的description中明确说明参数格式例如“输入必须是一个JSON对象包含‘city’字段值为字符串”。3. 使用LangChain的StructuredTool它能提供更严格的参数验证。服务响应慢或超时1. LLM API调用延迟高。2. 某个Skill执行缓慢如依赖的外部API慢。3. Agent陷入“思考-行动”循环步骤过多。1. 为LLM和外部API调用设置合理的超时timeout。2. 为耗时Skill实现异步async调用并考虑加入缓存。3. 在Agent执行器中设置max_iterations最大迭代次数和early_stopping_method提前停止方法防止无限循环。生产环境内存/CPU占用高1. 同时处理大量请求每个请求都加载大模型和上下文。2. 记忆模块如长上下文向量存储未做分页或清理。1. 实现请求队列和限流。2. 考虑使用模型API服务而非本地加载超大模型。3. 对记忆存储实施TTL生存时间策略定期清理旧会话。安全性问题如Calculator Skill的eval1. Skill执行了危险操作如任意代码执行、未鉴权的数据访问。这是最高优先级问题1. 永远不要在生产环境使用eval。对于计算使用ast.literal_eval或numexpr等安全库。2. 对所有Skill进行输入验证和沙箱化。3. 为Agent设定明确的权限边界禁止其调用高危系统命令或访问敏感数据。8. 最佳实践与工程建议基于上述实战和常见问题总结出以下工程化建议帮助你构建稳健的Agent系统。Skill设计原则单一职责一个Skill只做一件事。防御性编程对输入进行严格的验证和清理假设所有输入都可能是恶意的。幂等性尽可能让Skill的执行是幂等的即相同输入产生相同结果便于重试和调试。完备的文档在description中提供清晰、无歧义的自然语言描述和1-2个调用示例。Agent提示词工程明确指令在系统提示词中清晰定义Agent的角色、可用工具、输出格式和约束。提供示例在提示词中加入1-2个完整的“思考-行动-观察-最终答案”的示例Few-shot能极大提升工具调用的准确性。设定边界明确告诉Agent什么不能做例如“你不能直接执行系统命令”、“你不能在未授权时访问用户文件”。Harness架构设计配置外置所有API密钥、模型参数、服务地址都应通过环境变量或配置中心管理绝对不要硬编码在代码中。依赖注入通过Skill注册中心等模式管理依赖方便测试和替换。例如测试时可以将真实的“发送邮件Skill”替换为“模拟发送邮件Skill”。可观测性先行在项目初期就集成日志、指标和分布式追踪。记录每一次LLM调用输入、输出、Token用量、每一次工具调用输入、输出、耗时和每一次用户会话。安全与合规权限最小化每个Skill只拥有完成其任务所需的最小权限。内容审核在Agent的输入和输出层加入审核机制过滤不当内容。数据隐私明确用户数据的存储、使用和清理策略遵守相关法律法规。成本控制监控LLM API的Token消耗设置预算和告警防止意外高额账单。测试与评估单元测试为每个Skill编写单元测试模拟各种正常和异常输入。集成测试测试Agent与多个Skill协作完成端到端任务的流程。评估基准建立一套标准问题集Benchmark定期运行以评估Agent性能的稳定性防止模型更新或代码变更导致效果回退。9. 技术发展与就业展望掌握“Agent Skills Harness”这一套技术栈意味着你站在了AI工程化应用的前沿。从就业市场看相关的岗位需求正在快速增长AI应用工程师/Agent工程师负责将大模型能力与具体业务结合设计并实现智能体工作流。LLM运维工程师/大模型后端开发负责大模型服务的部署、维护、监控和性能优化保障Agent系统的稳定性。提示词工程师/AI产品工程师深入理解业务设计高效的Agent提示词和Skill组合提升任务完成率。AI基础设施研发研发类似Harness的底层框架、工具链和平台为上层应用提供支撑。学习路径建议基础巩固精通Python理解异步编程掌握FastAPI等Web框架。核心掌握深入理解LangChain/LangGraph等框架源码掌握Agent、Chain、Tool的核心概念。工程深化学习分布式系统、可观测性OpenTelemetry、配置管理、容器化Docker/K8s知识将其应用于AI系统。业务结合选择一个垂直领域如客服、编程助手、数据分析深入理解其业务流程设计并落地解决实际问题的Agent系统。构建生产级的AI智能体系统技术只是骨架真正的血肉是对业务的理解、对工程细节的执着和对安全边界的敬畏。从今天搭建的这个Demo开始逐步融入日志、监控、配置管理、安全防护和自动化测试你就能搭建起真正可靠、可扩展的AI应用基础设施。
返回列表