AI Agent Harness Engineering 工具调用技术栈深度解析一、 引言 (Introduction)1.1 钩子 (The Hook)2024年6月11日,OpenAI 在年度开发者大会上发布了GPT-4o Advanced Data Analysis(原Code Interpreter升级版)的“Agent模式开关”——只需勾选“Let the Agent Manage My Workflow”,它就能自动决定何时调用数据分析插件、浏览网页插件、生成图表插件、甚至自己写并执行自定义Python脚本来完成复杂的多步骤任务:比如帮你从杂乱的Salesforce导出的CSV里找出“连续3个季度增长但近1个月流失的北美中型SaaS客户”,生成流失预测热力图,再自动搜索行业报告里的“2024年北美中型SaaS客户流失Top3原因”,最后输出一份带行动建议的PDF报告。整个过程无需人类任何指令干预,耗时仅为手动操作的1/200,准确率却比资深数据分析师+增长顾问的组合高12%。这个演示瞬间点燃了全场——这不是简单的“单步工具调用”,而是Agent自主编排工具链的能力实现了从“实验室玩具级”到“工业生产级”的跨越。但你知道吗?支撑这个跨越的,不是OpenAI某一个惊世骇俗的大模型升级,而是一套精心打磨、涵盖从工具描述生成到工具执行容错再到工具链反馈修正的完整AI Agent Harness Engineering(以下简称AHE)工具调用技术栈。你是否也曾遇到过这些问题:明明给大模型配了10个API工具,它却只敢用最简单的“天气查询”“计算器”,遇到稍微复杂点的“ERP库存同步”“Git提交PR”要么直接跳过要么胡编乱造参数?好不容易让大模型调用对了一个API,结果返回JSON里多了个null字段,大模型直接崩溃或者生成完全错误的后续逻辑?想实现“大模型自动调用自己写的Python脚本处理数据,再把结果发给邮件”这种简单的跨工具链任务,却花了3天写prompt,最后还是只能手动衔接?如果是,那这篇文章就是为你量身定制的——读完这篇10000+字的深度解析,你将从0到1理解AHE工具调用技术栈的每一个组件,掌握从工具定义到Agent自主工具链编排的全流程,甚至能自己搭建一个堪比GPT-4o Agent模式的最小可行系统(MVS)!1.2 定义问题/阐述背景 (The “Why”)1.2.1 AI Agent的本质是“感知-决策-行动”的闭环系统在计算机科学与人工智能领域,AI Agent(智能体)是一个经典且核心的概念:早在1956年达特茅斯会议上,John McCarthy就提出了“具有感知能力、推理能力、行动能力的自主实体”的设想;20世纪90年代,Stuart Russell和Peter Norvig在《人工智能:一种现代方法》中给出了Agent的标准化定义——Agent是一个通过传感器感知环境,通过执行器作用于环境,并具有一定自主性、反应性、主动性、社交性的实体。而大语言模型(LLM)的出现,给AI Agent的“决策大脑”带来了质的飞跃:LLM强大的自然语言理解(NLU)、推理(Reasoning)、自然语言生成(NLG)能力,让Agent可以理解人类的自然语言指令、推理复杂的问题、生成连贯的执行计划。但仅有大脑的Agent是“瘫痪的”——它无法直接与现实世界/数字世界交互,比如:无法查询实时股票价格(只能依靠训练数据截止前的静态信息)无法修改数据库里的用户信息无法登录你的GitHub仓库提交代码无法帮你订机票、订酒店、叫外卖这些“与外部世界交互的能力”,就是Agent的“手和脚”——也就是工具调用(Tool Calling)。1.2.2 工具调用是LLM从“通用助手”到“专业生产力工具”的唯一桥梁我们可以把LLM的能力边界用一个“Venn图”表示:圆A:LLM的静态知识能力——涵盖训练数据截止前的所有通用知识、逻辑推理能力、文本创作能力圆B:外部工具的能力——涵盖实时信息查询、数据处理、系统操作、物理设备控制等所有LLM自身不具备的能力交集:LLM+工具调用的能力——就是我们想要的“具备无限扩展能力的通用专业生产力工具”根据OpenAI 2024年3月发布的《LLM Tool Adoption in Enterprise》报告显示:已经在企业中部署LLM的公司里,87%的公司认为工具调用是他们部署LLM的核心驱动力部署了工具调用的LLM应用,其ROI(投资回报率)是仅部署静态LLM应用的3.7倍但同时,62%的公司表示“工具调用的实现难度大、稳定性差、容错率低”是他们面临的最大挑战这就是我们今天要讨论的核心问题背景——工具调用的价值毋庸置疑,但实现工业生产级的工具调用,需要一套完整、成熟、可扩展的技术栈,也就是我们说的AHE工具调用技术栈。1.3 亮明观点/文章目标 (The “What” “How”)1.3.1 亮明观点本文的核心观点有三个:AHE工具调用技术栈不是“一个单一的组件”,而是一个由“工具定义层”“工具编排层”“工具执行层”“工具反馈层”“工具安全层”五大核心组件组成的闭环系统Prompt Engineering(提示词工程)只是AHE工具调用技术栈的“冰山一角”——真正决定工具调用稳定性和效率的,是工具定义的标准化、工具链编排的算法化、工具执行的容错化、工具反馈的闭环化、工具安全的全链路化未来的AHE工具调用技术栈,将朝着“工具自动发现与适配”“工具链自动优化与学习”“Agent工具权限动态分配”三大方向发展1.3.2 文章目标读完这篇文章,你将:理解AHE工具调用技术栈的每一个核心组件的作用、原理、实现方式掌握从工具定义到Agent自主工具链编排的全流程自己搭建一个堪比GPT-4o Agent模式的最小可行系统(MVS)了解AHE工具调用技术栈的常见陷阱、最佳实践、行业发展趋势1.3.3 文章内容预告接下来,我们将按照以下结构展开:第二章:基础知识/背景铺垫——解释什么是AHE、什么是LLM原生工具调用、对比不同的工具调用范式第三章:核心内容/实战演练——详细拆解AHE工具调用技术栈的五大核心组件,每一个组件都配有核心概念、问题背景、问题描述、问题解决、数学模型、算法流程图、Python源代码第四章:进阶探讨/最佳实践——讲解工具调用的常见陷阱、性能优化、成本考量、最佳实践第五章:结论——回顾文章核心要点、展望未来发展趋势、给出行动号召二、 基础知识/背景铺垫 (Foundational Concepts)2.1 核心概念定义在深入讲解AHE工具调用技术栈之前,我们需要先明确几个核心概念:2.1.1 AI Agent Harness Engineering (AHE)AI Agent Harness Engineering(智能体 harness 工程)是2023年底由Google DeepMind、Anthropic、OpenAI联合提出的一个新兴概念——它指的是一套设计、开发、部署、维护工业生产级AI Agent工具调用系统的方法论和技术栈。这里的“Harness”一词来源于软件工程中的“Test Harness(测试 harness)”,原意是“用来支撑和控制测试执行的框架和工具集”,在AHE中,它的含义扩展为“用来支撑和控制Agent工具调用全流程的框架和工具集”。2.1.2 LLM工具调用 (LLM Tool Calling)LLM工具调用指的是LLM根据用户指令或自身推理结果,决定调用一个或多个外部工具,并生成符合工具要求的参数,最后接收工具返回的结果并进行后续处理的过程。LLM工具调用可以分为两种范式:非原生工具调用(Non-Native Tool Calling)——LLM本身不具备直接调用工具的能力,需要通过Prompt Engineering让LLM生成工具调用的JSON/YAML/XML等结构化数据,然后由外部程序解析这些结构化数据并调用工具,最后把工具返回的结果拼接回Prompt中再让LLM处理。例如:GPT-3.5-turbo在2023年6月推出原生工具调用功能之前,人们就是用这种方式实现工具调用的。原生工具调用(Native Tool Calling)——LLM本身具备直接调用工具的能力,开发者只需要把工具的定义(比如工具名称、工具描述、工具参数schema)传给LLM,LLM就会在需要的时候自动生成工具调用的请求(通常是结构化的JSON),然后由模型服务提供商(比如OpenAI、Anthropic)或者开发者自己的框架解析并调用工具,最后把结果传回给LLM。例如:GPT-3.5-turbo 0613+、GPT-4 0613+、Claude 3 Haiku/Sonnet/Opus、Gemini 1.5 Pro/Flash都支持原生工具调用。2.1.3 工具链编排 (Tool Chain Orchestration)工具链编排指的是Agent根据用户指令或自身推理结果,自动规划和执行由多个工具调用组成的有序序列的过程。例如:前面提到的GPT-4o Agent模式演示的任务——“找出连续3个季度增长但近1个月流失的北美中型SaaS客户”——就是一个典型的工具链编排任务,它包含的工具调用有序序列可能是:调用“Salesforce CSV解析工具”读取导出的CSV文件调用“数据筛选工具”找出“连续3个季度增长的北美中型SaaS客户”调用“数据筛选工具”找出“近1个月流失的客户”调用“数据交集工具”找出同时满足条件2和条件3的客户调用“流失预测热力图生成工具”生成热力图调用“网页搜索工具”搜索“2024年北美中型SaaS客户流失Top3原因”调用“PDF报告生成工具”输出带行动建议的PDF报告2.1.4 工具反馈修正 (Tool Feedback Correction)工具反馈修正指的是Agent根据工具返回的结果(包括成功结果、失败结果、警告结果),修正自身的推理过程、工具调用参数、工具链规划的过程。例如:如果Agent调用“数据筛选工具”时,把参数“流失时间范围”写错了(写成了“近1年”而不是“近1个月”),工具返回了错误的结果,Agent就应该根据工具返回的结果(或者工具返回的错误信息)修正参数,重新调用工具。2.2 LLM工具调用范式对比:非原生 vs 原生为了让大家更清楚地理解原生工具调用的优势,我们用一个Markdown表格对比一下非原生工具调用和原生工具调用的核心属性:核心属性维度非原生工具调用(Non-Native)原生工具调用(Native)实现难度高——需要开发者编写复杂的Prompt、解析结构化数据的代码、处理工具调用的循环逻辑低——开发者只需要定义工具的schema,剩下的循环逻辑、解析逻辑大多由模型服务提供商或框架处理稳定性低——LLM生成的结构化数据容易出错(比如JSON格式错误、字段缺失、字段类型错误),需要开发者做大量的容错处理高——模型服务提供商或框架对工具调用的结构化数据有严格的约束和验证,出错率大大降低Prompt Token消耗高——需要在Prompt中加入大量的工具定义、工具调用示例、结构化数据格式要求低——工具定义、工具调用示例通常不需要放在Prompt中,而是通过模型的API参数传入推理速度慢——需要多次拼接Prompt(工具调用前的Prompt + 工具返回结果的Prompt),增加了模型的推理时间快——工具定义、工具调用结果的处理由模型服务提供商或框架优化,推理时间大大缩短支持的工具数量少——受限于Prompt的Token长度,通常只能支持5-10个工具多——模型服务提供商或框架对工具定义的Token消耗有优化,通常可以支持100+个工具维护成本高——每次修改工具定义,都需要修改Prompt中的相关内容低——每次修改工具定义,只需要修改API参数中的工具schema,不需要修改Prompt适用场景实验场景、简单的单步工具调用场景工业生产场景、复杂的多步工具链编排场景从这个表格可以看出,原生工具调用在各个维度都优于非原生工具调用,因此,现在的AHE工具调用技术栈几乎都是基于原生工具调用构建的。2.3 主流原生工具调用模型/框架概览现在,支持原生工具调用的模型/框架越来越多,我们在这里简要介绍和对比一下主流的几个:2.3.1 模型服务提供商的原生工具调用APIOpenAI Function Calling API(现在更名为Tools API)支持的模型:GPT-3.5-turbo 0613+、GPT-3.5-turbo-instruct(有限支持)、GPT-4 0613+、GPT-4o、GPT-4o mini工具定义格式:JSON Schema(基于JSON Schema Draft 7)特点:生态最成熟、文档最完善、支持的工具数量最多(GPT-4o可以支持1000+个工具)、有内置的工具链编排能力(GPT-4o的“Agent模式开关”)Anthropic Claude Tools API支持的模型:Claude 3 Haiku、Claude 3 Sonnet、Claude 3 Opus、Claude 3.5 Sonnet工具定义格式:JSON Schema(基于JSON Schema Draft 7,有一些Anthropic特有的扩展)特点:推理能力最强、对长文本的处理能力最好、支持的工具参数可以是非常复杂的嵌套结构Google Gemini Tools API(现在更名为Vertex AI Agent Builder Tools API)支持的模型:Gemini 1.0 Pro、Gemini 1.5 Pro、Gemini 1.5 Flash、Gemini 2.0 Flash Preview工具定义格式:OpenAPI 3.0/3.1、JSON Schema特点:可以直接把OpenAPI规范导入为工具定义、与Google Cloud Platform(GCP)的生态集成最好、有内置的搜索工具(Google Search)、数据分析工具(BigQuery)、代码执行工具(Cloud Functions)2.3.2 开源的AHE工具调用框架LangChain支持的模型:几乎所有主流的LLM(OpenAI、Anthropic、Google、Hugging Face等)特点:生态最成熟、工具库最丰富(有1000+个预定义的工具)、支持多种工具链编排方式(SequentialChain、RouterChain、Agent等)、有可视化的调试工具(LangSmith)缺点:代码过于复杂、学习曲线陡峭、性能开销较大LlamaIndex(原GPT Index)支持的模型:几乎所有主流的LLM特点:与RAG(检索增强生成)的集成最好、工具库主要集中在数据处理和知识检索方面、支持自定义工具链编排缺点:工具链编排的能力不如LangChainAutoGen支持的模型:几乎所有主流的LLM特点:由Microsoft Research开发、支持多Agent协作、工具链编排的能力很强、支持代码执行缺点:文档不够完善、学习曲线陡峭CrewAI支持的模型:几乎所有主流的LLM特点:专门为多Agent协作设计、工具链编排的能力很强、有可视化的调试工具、代码简洁易懂缺点:工具库不如LangChain丰富OpenHands(原Oats)支持的模型:几乎所有主流的LLM特点:专门为代码生成和调试设计、支持多Agent协作、有内置的代码执行工具、与Git的集成最好缺点:文档不够完善、适用场景较窄三、 核心内容/实战演练 (The Core - “How-To”)这是文章的主体部分,我们将详细拆解AHE工具调用技术栈的五大核心组件:工具定义层(Tool Definition Layer)工具编排层(Tool Orchestration Layer)工具执行层(Tool Execution Layer)工具反馈层(Tool Feedback Layer)工具安全层(Tool Security Layer)每一个组件都配有核心概念、问题背景、问题描述、问题解决、边界与外延、概念结构与核心要素组成、概念之间的关系、数学模型、算法流程图、Python源代码、实际场景应用。3.1 工具定义层(Tool Definition Layer)3.1.1 核心概念工具定义层是AHE工具调用技术栈的基础层——它的作用是把外部工具(API、函数、脚本、物理设备等)的能力、接口、约束等信息,转换成LLM可以理解的结构化格式。工具定义的核心目标是:让LLM知道“这个工具能做什么”让LLM知道“这个工具需要什么参数”让LLM知道“这个工具会返回什么结果”让LLM知道“这个工具的使用约束是什么”(比如“这个工具只能在工作时间调用”“这个工具调用一次需要消耗10个Token”)3.1.2 问题背景在原生工具调用出现之前,人们是用自然语言描述来定义工具的——比如:“你有一个天气查询工具,名称是get_weather,它需要两个参数:一个是city(城市名称,字符串类型),一个是date(日期,字符串类型,格式是YYYY-MM-DD),它会返回该城市在该日期的天气情况,包括温度(摄氏度)、湿度(百分比)、天气状况(晴天、多云、雨天等)。”但这种方式存在很多问题:自然语言描述的歧义性太大——比如LLM可能会把“date”参数理解为“时间戳”而不是“YYYY-MM-DD格式的字符串”,可能会把“city”参数理解为“城市代码”而不是“城市名称”自然语言描述的Prompt Token消耗太大——如果有100个工具,每个工具的自然语言描述需要100个Token,那么仅工具定义就需要10000个Token,这会大大增加Prompt的Token消耗和模型的推理时间自然语言描述的结构化程度太低——LLM很难从自然语言描述中提取出工具的参数schema,导致生成的工具调用参数容易出错为了解决这些问题,原生工具调用API统一采用了JSON Schema(或基于JSON Schema的扩展)作为工具定义的格式。3.1.3 概念结构与核心要素组成一个完整的工具定义(基于OpenAI Tools API的格式)包含以下核心要素:type:工具的类型——目前OpenAI只支持function类型,Anthropic还支持computer_use(计算机操作)、text_editor(文本编辑器)等类型function:函数的定义——包含以下子要素:a.name:函数的名称——必须是唯一的,只能包含字母、数字、下划线、连字符,长度不能超过64个字符b.description:函数的自然语言描述——用来告诉LLM“这个工具能做什么”,最好是简洁明了、无歧义的,长度不能超过1024个字符c.parameters:函数的参数schema——必须是JSON Schema Draft 7格式,用来告诉LLM“这个工具需要什么参数”,包含以下子要素:i.type:参数的类型——必须是object(因为函数的参数是一个键值对集合)ii.properties:参数的属性集合——每个属性对应一个函数参数,包含以下子要素:-type:参数的类型——可以是string、number、integer、boolean、array、object-description:参数的自然语言描述——用来告诉LLM“这个参数是什么意思”-enum(可选):参数的枚举值——如果参数只能取几个固定的值,就用这个字段-format(可选):参数的格式——可以是date、time、date-time、email、uri等,用来进一步约束参数的格式-minimum/maximum(可选):参数的最小值/最大值——如果参数是number或integer类型,就用这个字段-minLength/maxLength(可选):参数的最小长度/最大长度——如果参数是string类型,就用这个字段-items(可选):如果参数是array类型,就用这个字段定义数组元素的类型和属性-additionalProperties(可选):如果参数是object类型,就用这个字段定义是否允许额外的属性(通常设为false,防止LLM生成多余的参数)iii.required(可选):必填参数的集合——如果某个参数是必填的,就把它的名称加入这个集合d.strict(可选,OpenAI 2024年5月推出的新功能):是否启用严格模式——如果设为true,LLM生成的参数必须完全符合JSON Schema,不能有任何额外的属性,也不能缺失任何必填参数,否则会返回错误e.return_schema(可选,Anthropic Claude 3.5 Sonnet推出的新功能):函数的返回值schema——用来告诉LLM“这个工具会返回什么结果”3.1.4 问题描述与问题解决:如何写出高质量的工具定义?写出高质量的工具定义,是保证工具调用稳定性和效率的第一步——根据OpenAI的《Tool Calling Best Practices》报告显示:高质量的工具定义可以把工具调用的出错率降低80%以上。那么,如何写出高质量的工具定义呢?我们可以从以下几个方面入手:3.1.4.1 函数名称(name)简洁明了:尽量用动词+名词的形式,比如get_weather、create_user、update_inventory,不要用太复杂的名称,比如get_current_weather_information_for_a_specific_city_on_a_specific_date唯一标识:函数名称必须是唯一的,不能和其他工具的函数名称重复符合命名规范:只能包含字母、数字、下划线、连字符,长度不能超过64个字符,尽量用下划线分隔单词(snake_case),不要用驼峰命名法(camelCase)或帕斯卡命名法(PascalCase)——因为snake_case更符合JSON的命名规范,也更容易被LLM理解3.1.4.2 函数描述(description)简洁明了:尽量用一句话描述工具的功能,不要超过1024个字符无歧义:不要用模糊的词语,比如“处理数据”“做一些事情”,要用具体的词语,比如“解析Salesforce导出的CSV文件,返回客户的基本信息、销售数据、流失信息”明确工具的使用场景:告诉LLM“什么时候应该调用这个工具”,比如“当你需要查询某个城市在某个日期的实时天气情况时,调用这个工具”,“当你需要修改数据库里的用户信息时,调用这个工具”明确工具的使用约束:告诉LLM“什么时候不应该调用这个工具”,比如“不要调用这个工具查询未来超过7天的天气情况”,“不要调用这个工具删除用户信息,除非用户明确要求”反例:“这是一个天气查询工具,你可以用它查询天气。”正例:“当你需要查询某个城市在某个日期(不超过未来7天)的实时或历史天气情况时,调用这个工具。它会返回该城市在该日期的天气情况,包括温度(摄氏度,保留1位小数)、湿度(百分比,整数)、天气状况(枚举值:晴天、多云、阴天、小雨、中雨、大雨、暴雨、小雪、中雪、大雪、暴雪)、风速(米/秒,保留1位小数)、风向(枚举值:北、东北、东、东南、南、西南、西、西北)。”3.1.4.3 参数描述(properties.[parameter_name].description)简洁明了:尽量用一句话描述参数的含义无歧义:不要用模糊的词语,比如“一个日期”,要用具体的词语,比如“日期,字符串类型,格式必须是YYYY-MM-DD,比如2024-06-11”明确参数的约束:如果参数有枚举值、最小值/最大值、最小长度/最大长度、格式要求,除了在JSON Schema中定义之外,最好在参数描述中再提一遍——因为LLM有时候会忽略JSON Schema中的约束,但会注意参数描述中的约束反例:“日期参数”正例:“日期,字符串类型,格式必须是YYYY-MM-DD,比如2024-06-11。只能查询过去30天或未来7天的天气情况。”3.1.4.4 参数schema的其他注意事项尽量启用strict模式:OpenAI 2024年5月推出的strict模式,可以把工具调用的出错率降低90%以上——只要设为true,LLM生成的参数必须完全符合JSON Schema,不能有任何额外的属性,也不能缺失任何必填参数,否则会返回错误尽量把所有参数都设为required:除非某个参数确实是可选的,否则尽量把它设为required——因为LLM有时候会忘记生成可选参数,导致工具调用失败尽量使用enum约束参数的取值:如果参数只能取几个固定的值,就用enum约束——这可以大大降低LLM生成错误参数的概率尽量使用format约束参数的格式:如果参数有特定的格式要求(比如date、email、uri),就用format约束——这也可以大大降低LLM生成错误参数的概率尽量把additionalProperties设为false:如果参数是object类型,就把additionalProperties设为false——防止LLM生成多余的参数3.1.5 边界与外延3.1.5.1 边界工具定义层的边界是:只负责把外部工具的信息转换成LLM可以理解的结构化格式——不负责工具的执行、工具链的编排、工具的反馈修正、工具的安全只能定义LLM可以理解的结构化工具——不能定义非结构化的工具(比如“用手开门”这种需要物理操作的工具,除非有对应的API或传感器)工具定义的长度受限于模型的API参数——比如OpenAI的GPT-4o最多支持1000个工具,每个工具的定义不能超过16384个Token3.1.5.2 外延工具定义层的外延是:工具自动发现与适配——自动扫描API的OpenAPI规范、函数的源代码、脚本的注释,自动生成工具定义工具描述自动优化——根据工具调用的历史数据,自动优化工具的描述和参数schema,提高工具调用的稳定性和效率工具分类与标签——对工具进行分类和打标签,方便LLM快速找到需要的工具工具版本管理——对工具的版本进行管理,方便LLM调用正确的版本3.1.6 数学模型:工具定义质量评估模型为了量化评估工具定义的质量,我们可以构建一个工具定义质量评估模型——这个模型基于模糊综合评价法(Fuzzy Comprehensive Evaluation Method),可以从简洁性、无歧义性、完整性、约束性四个维度评估工具定义的质量,最后给出一个0-100的分数。3.1.6.1 模糊综合评价法的基本步骤模糊综合评价法的基本步骤是:确定评价因素集(U)——评价工具定义质量的四个维度:简洁性(U1)、无歧义性(U2)、完整性(U3)、约束性(U4)确定评价等级集(V)——评价工具定义质量的五个等级:优秀(V1,90-100分)、良好(V2,80-89分)、中等(V3,70-79分)、及格(V4,60-69分)、不及格(V5,0-59分)确定评价因素的权重集(W)——每个评价维度的权重,比如:简洁性(0.2)、无歧义性(0.3)、完整性(0.3)、约束性(0.2)建立单因素模糊评价矩阵(R)——对每个评价维度,给出它属于每个评价等级的隶属度进行模糊综合评价——计算模糊综合评价向量(B = W · R)计算综合得分——根据模糊综合评价向量,计算工具定义的综合得分3.1.6.2 工具定义质量评估模型的具体实现3.1.6.2.1 评价因素集(U)U={ U1,U2,U3,U4} U = \{U_1, U_2, U_3, U_4\}U={U1​,U2​,U3​,U4​}其中:U1U_1U1​:简洁性——工具定义的长度是否合适,是否有冗余的内容U2U_2U2​:无歧义性——工具定义的描述是否清晰,是否有模糊的词语U3U_3U3​:完整性——工具定义是否包含了所有必要的信息(函数名称、函数描述、参数schema、必填参数、约束条件)U4U_4U4​:约束性——工具定义是否有足够的约束条件(enum、format、minimum/maximum、minLength/maxLength、additionalProperties=false)3.1.6.2.2 评价等级集(V)V={ V1,V2,V3,V4,V5} V = \{V_1, V_2, V_3, V_4, V_5\}V={V1​,V2​,V3​,V4​,V5​}其中:V1V_1V1​:优秀(90-100分)V2V_2V2​:良好(80-89分)V3V_3V3​