【免费下载链接】OpenJarvisPersonal AI, On Personal Devices项目地址https://gitcode.com/gh_mirrors/op/OpenJarvis点击查看免费下载OpenJarvis 内置了一套可复现、标准化的推理引擎性能基准测试框架用于量化本地 LLM 推理引擎如 Ollama、vLLM 等的延迟与吞吐能力。本文将带你掌握其两大内置基准Latency / Throughput的指标含义与统计口径理解BaseBenchmark抽象基类与BenchmarkSuite聚合器的底层实现熟练使用jarvis bench run命令行完成样本数、引擎、模型的自由组合并通过三步走自定义属于自己的 Benchmark 并注册到 CLI 与 Suite 中。一、基准测试框架概览定位与组成OpenJarvis 的基准测试框架benchmarking framework用标准化、可复现的测试来度量推理引擎性能。它位于src/openjarvis/bench/目录核心模块如下文件职责_stubs.pyBaseBenchmark抽象基类、BenchmarkResult结果数据类、BenchmarkSuite批量运行器_stats.py共享统计工具compute_stats输出 mean/p50/p95/min/max/stdlatency.py内置延迟基准LatencyBenchmarkthroughput.py内置吞吐基准ThroughputBenchmarkenergy.py能量效率基准EnergyBenchmark按 token 统计 J/tok、功率 W 等__init__.py通过ensure_registered()在导入时自动注册全部基准框架自带两个核心基准基准Registry 键度量内容Latency延迟latency单次调用推理延迟mean、p50、p95、min、maxThroughput吞吐throughput每秒生成的 token 数从src/openjarvis/bench/__init__.py的实现可以看出import openjarvis.bench时会触发ensure_registered()把latency、throughput、energy三个基准全部写入注册表因此无需任何手动初始化即可通过 CLI 使用。二、BaseBenchmark 抽象基类所有基准的统一契约所有基准都必须继承 BaseBenchmark 抽象基类。它定义了两个抽象属性与一个抽象方法from abc import ABC, abstractmethod from openjarvis.bench._stubs import BenchmarkResult from openjarvis.engine._stubs import InferenceEngine class BaseBenchmark(ABC): property abstractmethod def name(self) - str: Short identifier for this benchmark. property abstractmethod def description(self) - str: Human-readable description of what this benchmark measures. abstractmethod def run( self, engine: InferenceEngine, model: str, *, num_samples: int 10, ) - BenchmarkResult: Execute the benchmark and return results.几点说明engine参数类型是InferenceEngine抽象基类定义于src/openjarvis/engine/_stubs.py它要求每个引擎实现同步generate()方法返回包含content与usage字段的 dict基准测试正是基于generate()进行计时与 token 统计。实际源码中run()还支持warmup_samples预热样本数与**kwargs透传以便把energy_monitor等可选依赖注入给特定基准见_stubs.py第 90-97 行。BenchmarkResult统一结果结构每次基准运行都会产出一个 BenchmarkResult字段类型说明benchmark_namestr基准名称如latencymodelstr被测模型enginestr所用引擎后端engine.engine_idmetricsdict[str, float]测得的指标键值对metadatadict[str, Any]附加元数据samplesint运行的样本数errorsint遇到的错误数源码中的BenchmarkResult还额外携带了能量相关的可选字段warmup_samples、total_energy_joules、energy_per_token_joules、energy_method等由能量基准填充普通基准保持默认值即可。三、内置基准详解3.1 Latency Benchmark逐调用延迟延迟基准使用短固定提示词测量单次调用延迟每次样本都向引擎发送一个简单 prompt 并记录墙钟时间。其实现位于src/openjarvis/bench/latency.py提示词轮换内置三句固定提示词Hello、What is 22?、Explain gravity in one sentence_CANNED_PROMPTS按样本序号取模轮换保证多次运行的输入分布一致预热支持在正式测量前可执行warmup_samples次预热请求避免冷启动如模型加载、显存分配污染数据异常处理每次请求失败仅计数到errors不会中断整个基准。产出指标经_stats.py的compute_stats(latency, latencies)计算指标说明mean_latency所有成功样本的平均延迟p50_latency中位数延迟50 分位p95_latency95 分位延迟尾部性能min_latency最快单次调用max_latency最慢单次调用std_latency延迟标准差源码新增衡量稳定性示例输出latency (10 samples, 0 errors) mean_latency: 0.2345 p50_latency: 0.2100 p95_latency: 0.3800 min_latency: 0.1500 max_latency: 0.4200从源码看CLI 的 Rich 表格渲染器bench_cmd.py中的_render_stats_table会把mean_/p50_/p95_/min_/max_/std_前缀的指标自动聚合成 Avg / Median / Min / Max / Std / P95 多列表格便于横向对比。3.2 Throughput Benchmark每秒 token 吞吐吞吐基准向引擎发送一条较长的固定提示词Write a short paragraph about artificial intelligence._PROMPT同时记录耗时与生成的完成 token 数。实现位于src/openjarvis/bench/throughput.py每次样本通过result.get(usage, {})读取completion_tokens单样本吞吐 completion_tokens / elapsed与延迟基准一样也支持预热并会调用engine_info()把引擎的自描述信息如 SDK 版本、上下文大小、宿主芯片写入metadata[engine_info]。产出指标指标说明tokens_per_second总完成 token 数 ÷ 总耗时同时输出 mean/p50/p95/min/max/std 统计族total_tokens全部样本的完成 token 总数total_time_seconds全部样本的墙钟总耗时latency_seconds每样本延迟统计族源码新增示例输出throughput (10 samples, 0 errors) tokens_per_second: 45.6789 total_tokens: 1250.0000 total_time_seconds: 27.36003.3 统计口径说明compute_stats()src/openjarvis/bench/_stats.py是全部基准共享的统计核心分位数采用线性插值法计算即对排序后的样本位置k (len-1) * p在两相邻值之间线性插值这比简单的最近邻分位更精确同时输出std_标准差以量化抖动。p50直接使用statistics.median。四、结果解读指南延迟指标mean_latency平均响应时间适合做总体性能对比p50_latency中位数典型响应时间受离群值影响小于均值p95_latency95% 请求的最坏响应时间直接关系用户体验——若过高部分用户会感知明显卡顿min/max_latency最佳与最差单次调用两者差距过大说明性能不一致。健康度提示一个健康的配置通常满足p95 / p50 2。若 p95 远高于中位数建议排查引擎是否出现资源争抢contention、热降频thermal throttling或内存压力memory pressure。吞吐指标tokens_per_second核心吞吐指标越高越好。常见量级参考纯 CPU5–20 tokens/秒消费级 GPURTX 3060–409030–100 tokens/秒数据中心 GPUA100、H100100–500 tokens/秒total_tokens / total_time吞吐计算背后的原始数据可用于校验引擎确实产出了有效输出而非返回空响应。以上量级为文档给出的典型参考区间实际表现取决于模型参数量、量化方式、批处理大小与系统负载请以本机实测为准。五、BenchmarkSuite批量运行与序列化BenchmarkSuitesrc/openjarvis/bench/_stubs.py第 101-153 行负责运行一组基准并提供聚合、序列化工具from openjarvis.bench._stubs import BenchmarkSuite from openjarvis.bench.latency import LatencyBenchmark from openjarvis.bench.throughput import ThroughputBenchmark suite BenchmarkSuite([LatencyBenchmark(), ThroughputBenchmark()]) # 运行全部基准 results suite.run_all(engine, model, num_samples20) # 序列化为 JSONL每行一个 JSON 对象 jsonl suite.to_jsonl(results) # 获取摘要 dict summary suite.summary(results)方法一览方法返回类型说明run_all(engine, model, num_samples10)list[BenchmarkResult]顺序运行全部基准to_jsonl(results)str序列化为 JSONL 格式summary(results)dict[str, Any]生成摘要字典JSONL 输出格式每行一个 JSON 对象便于按行追加到日志或统计系统{benchmark_name: latency, model: qwen3:8b, engine: ollama, metrics: {mean_latency: 0.234, p50_latency: 0.21, p95_latency: 0.38, min_latency: 0.15, max_latency: 0.42}, metadata: {}, samples: 10, errors: 0} {benchmark_name: throughput, model: qwen3:8b, engine: ollama, metrics: {tokens_per_second: 45.67, total_tokens: 1250.0, total_time_seconds: 27.36}, metadata: {}, samples: 10, errors: 0}Summary 输出格式{ benchmark_count: 2, benchmarks: [ { name: latency, model: qwen3:8b, engine: ollama, metrics: {mean_latency: 0.234, ...}, samples: 10, errors: 0 }, { name: throughput, model: qwen3:8b, engine: ollama, metrics: {tokens_per_second: 45.67, ...}, samples: 10, errors: 0 } ] }六、CLI 用法jarvis bench runCLI 入口实现位于src/openjarvis/cli/bench_cmd.py。执行流程为加载配置 → 注册全部基准 → 解析引擎与模型 → 组装BenchmarkSuite→ 运行并渲染/输出结果。# 使用默认设置10 个样本运行全部基准 jarvis bench run # 增加样本数以提升统计精度 jarvis bench run -n 50 # 只运行延迟基准 jarvis bench run -b latency # 只运行吞吐基准20 个样本 jarvis bench run -b throughput -n 20 # 指定模型与引擎 jarvis bench run -m qwen3:8b -e ollama # 以 JSON 摘要形式输出到 stdout jarvis bench run --json # 将 JSONL 结果写入文件 jarvis bench run -o results.jsonl # 组合使用 jarvis bench run -b latency -n 100 -m qwen3:8b --json -o latency.jsonl选项参考选项类型默认值说明-m,--model MODELstringauto被测模型省略时自动取引擎list_models()的第一个模型-e,--engine ENGINEstringauto引擎后端省略时从配置自动解析-n,--samples Nint10每个基准的样本数-b,--benchmark NAMEstringall指定运行的基准latency/throughput/ 自定义名称-o,--output PATHpathnone将 JSONL 结果写入文件--jsonflagoff以 JSON 摘要输出到 stdout-w,--warmup Nint0测量前的预热迭代次数源码新增见bench_cmd.py第 183-190 行输出优先级同时指定-o与--json时文件写入与 stdout 摘要都会产生仅指定-o时不打印 Rich 表格仅指定--json时输出摘要 JSON两者都未指定时渲染为 Rich 统计表格。从bench_cmd.py源码看jarvis bench run还支持通过--setup-energy自动运行scripts/setup-energy-monitor.sh初始化能量监控并在telemetry.gpu_metrics开启或运行 energy 基准时自动挂载能量监视器能量相关选项与jarvis bench skillsPinchBench 技能评估命令不在本文档基准主题范围内此处仅作提示。七、添加自定义 Benchmark自定义基准只需三步继承BaseBenchmark实现逻辑注册到BenchmarkRegistry然后通过 CLI 或BenchmarkSuite使用。7.1 实现基准类以下示例实现一个输入长度越长、延迟越高的context_length基准import time from openjarvis.bench._stubs import BaseBenchmark, BenchmarkResult from openjarvis.core.registry import BenchmarkRegistry from openjarvis.core.types import Message, Role from openjarvis.engine._stubs import InferenceEngine class ContextLengthBenchmark(BaseBenchmark): Measures how latency scales with input length. property def name(self) - str: return context_length property def description(self) - str: return Measures latency scaling with increasing input length def run( self, engine: InferenceEngine, model: str, *, num_samples: int 10, ) - BenchmarkResult: latencies {} errors 0 for length in [100, 500, 1000, 2000]: prompt x * length messages [Message(roleRole.USER, contentprompt)] t0 time.time() try: engine.generate(messages, modelmodel) latencies[flatency_{length}_tokens] time.time() - t0 except Exception: errors 1 return BenchmarkResult( benchmark_nameself.name, modelmodel, engineengine.engine_id, metricslatencies, sampleslen(latencies), errorserrors, )7.2 注册基准推荐使用ensure_registered()模式它在测试清空注册表后依然能存活def ensure_registered() - None: Register the benchmark if not already present. if not BenchmarkRegistry.contains(context_length): BenchmarkRegistry.register_value(context_length, ContextLengthBenchmark)也可以在类定义时直接使用装饰器BenchmarkRegistry.register(context_length) class ContextLengthBenchmark(BaseBenchmark): ...为什么优先用ensure_registered()BenchmarkRegistry继承自RegistryBasesrc/openjarvis/core/registry.py其中clear()会在测试中清空全部条目装饰器只在模块导入时执行一次注册表一旦被清空就无法恢复。内置的latency、throughput、energy基准全部采用ensure_registered()模式见各自文件末尾与bench/__init__.pyCLI 在查找基准前也会先调用ensure_registered()。测试用例tests/bench/test_latency.py同样通过 autouse fixture 在注册表清理后重新注册验证了这一模式的必要性。注意若 key 已存在register_value与register都会抛出ValueError因此先contains检查再注册是幂等安全的写法。7.3 使用你的基准注册完成后即可通过 CLI 直接调用jarvis bench run -b context_length也可以通过BenchmarkSuite或注册表按需实例化from openjarvis.core.registry import BenchmarkRegistry bench_cls BenchmarkRegistry.get(context_length) bench bench_cls() result bench.run(engine, model, num_samples5)由于jarvis bench run在未指定-b时会遍历注册表运行全部基准见bench_cmd.py第 246 行新注册的基准会自动纳入默认全量运行。八、延伸框架的可扩展设计从源码结构可以进一步归纳该框架的三个设计要点注册表驱动发现BenchmarkRegistry是RegistryBase的类型化子类之一与EngineRegistry、ToolRegistry等共享同一套注册逻辑src/openjarvis/core/registry.py每个注册表有独立的条目存储互不串扰引擎抽象解耦基准只依赖InferenceEngine.generate()契约因此天然适用于 Ollama、vLLM、MLX 等任何已注册引擎无需为基准适配特定后端统计与渲染分离指标计算统一收敛到_stats.pyCLI 侧通过识别mean_/p50_/p95_/min_/max_/std_前缀自动分组渲染成统计表格新增基准只要沿用compute_stats()命名约定即可获得一致的终端展示。九、总结OpenJarvis 的基准测试框架以BaseBenchmark为统一契约、BenchmarkRegistry为发现机制、BenchmarkSuite为聚合入口配合jarvis bench runCLI能够在不同引擎、模型与样本量之间建立可复现的性能对照。理解p95/p50比例与 token 吞吐量级可以帮助你判断本地部署是否遇到资源争抢或热降频而ensure_registered() 注册表的扩展范式则让自定义基准可以无缝接入 CLI、Suite 与测试体系成为一套既能开箱即用、又能深度定制的推理性能测量工具链。/DSMLparameter /DSMLinvoke /DSMLtool_calls赞分享【免费下载链接】OpenJarvisPersonal AI, On Personal Devices项目地址https://gitcode.com/gh_mirrors/op/OpenJarvis点击查看免费下载相关推荐SeaTunnel Zeta 引擎基准测试Benchmark完全指南架构、指标解读与本地执行SeaTunnel Zeta 引擎基准测试Benchmark完全指南架构、指标解读与本地执行 SeaTunnel 的 Zeta 引擎在数据量增长和使用场景数据集成ETL大数据批处理流处理变更数据捕获如何15分钟搭建个人微信公众号RSS订阅服务终极指南如何15分钟搭建个人微信公众号RSS订阅服务终极指南 你是否厌倦了在微信、浏览器和各种阅读器之间来回切换只为追踪几个喜欢的公众号更新信息碎片化让有价值的内后端前端vite-vue3-chrome-extension-v3发布指南从打包到Chrome商店上架全流程vite vue3 chrome extension v3发布指南从打包到Chrome商店上架全流程 想要将你的Vue 3 Chrome扩展发布到Chrome上一篇3个简单步骤掌握Python通达信数据读取mootdx金融分析终极指南下一篇CKEditor 5 CKBox 集成全指南文件管理、图片上传与图片编辑一体化接入创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
