Sample 应让开发者从入口直接找到模型,并在模型文件内读懂输入如何变成结果。目录和接口围绕这条阅读路径组织。
samples/<领域>/<模型>/
├── model/ # 编译后模型的获取、制品和板卡对应关系
├── conversion/ # 原始权重、导出和编译配方
├── runtime/
│ └── python/
│ ├── main.py # 参数 → 构造模型 → predict → 展示结果
│ ├── cli.py # 参数、发布模型选择、列表、结果展示与保存
│ ├── classify.py # 模型类及完整推理流程;按任务命名
│ └── run.sh # 定位入口,转发参数和退出码
├── evaluator/ # 数据集评估及指标
├── test_data/ # 可直接运行的输入示例
└── tests/ # Sample 的行为与数值回归
utils/
├── py_utils/ # 跨模型复用的 Python Runtime 和工具
└── c_utils/ # 跨模型复用的 C/C++ 能力
utils/tools/ # 可独立执行的维护程序
模型文件按职责命名,例如 classify.py、detect.py、segment.py、matching.py、policy.py。普通单任务 Sample 默认采用三个 Python 文件。多任务家族按任务划分模型文件:Ultralytics YOLO 覆盖 detect / segment / pose / classify / obb 五类任务,每任务一个模型文件加 main.py 与 cli.py,合计约 7–8 个 Python 文件;确有完整职责的后端绑定可另立一个文件并说明其角色。公开接口使用 preprocess、infer、postprocess 和 predict;按完整职责组织文件。
入口依次完成四件事:获取参数、构造具名模型、调用 predict、交付结果。
args = build_parser().parse_args(argv)
selection = resolve_selection(args.target, variant=args.variant)
model = ResNetClassifier(selection.model_path, target=selection.target)
result = model.predict(args.test_img)
print_result(result, selection, args.top_k)该示例展示入口结构;实际入口还须传递所选模型的输入尺寸、类别数、插值、分数策略等默认参数。完整参数由各 Sample 的 CLI 定义。
- 保留清晰的函数调用和必要的分支,不在入口展开张量处理、解码或 SDK 适配。
- 模型构造和
predict调用直接出现在入口中,不藏进通用 dispatch 或整套 application 包装。 - 参数较多时在 CLI 中组织;不把大量配置代码移到 Shell。
- 异常在 CLI 边界转换为易读错误及非零退出码;模型 API 向调用方抛出实际异常。
具名模型类负责初始化,并在本文件内实现三个阶段及其组合:
class ResNetClassifier:
def predict(self, image):
inputs = self.preprocess(image)
outputs = self.infer(inputs)
return self.postprocess(outputs)- 模型类通过
__init__或具名构造方法(如Model.from_model(...))接收模型路径、目标板卡及必要的模型参数,建立可复用的 Runtime。具名构造方法返回可直接调用predict的模型实例;main.py不展开 runner 创建、模型加载或张量绑定。 preprocess展示该模型的输入准备步骤。infer使用公共 Runtime 或明确的本地 SDK 适配执行模型。postprocess展示输出解释、解码和结果构造。predict显式串联三个阶段,返回结构化结果。- 预测过程不承担参数解析、下载模型、安装依赖、打印或保存文件。
- 单模型路径接口允许用户传入自己的编译模型和实际张量参数。发布目录的模型枚举和制品选择属于 CLI。
- 多模型任务明确说明每个模型的输入输出和连接方式;语音等任务可使用表达实际数据流的阶段名。
模型特有的算法和默认值保留在 Sample。公共函数可以直接调用;调用方不必经过 Sample 内额外的转发模块。
CLI 集中维护参数、发布模型及板卡选择、模型列表、预览、标签加载、结果格式化和保存。
- 同一选项只声明一次,
main.py和run.sh使用同一套参数。 - 帮助、模型列表和预览按各命令声明的依赖执行,不触发板端 SDK 加载或实际推理。
target=auto使用硬件身份识别;显式 target 对应明确的模型制品与 SDK。- 实际执行前校验目标板卡和模型元数据。板卡切换不改变模型算法含义。
- 参数只影响其声明的行为,例如输入大小、插值、置信度、Top-K、保存路径和调度设置。
Python 公共能力统一放在 utils/py_utils/,C/C++ 公共能力统一放在 utils/c_utils/。
- SDK 会话负责模型加载、板卡校验、执行及资源生命周期。
- 通用图片读取、标签校验、NV12 转换、张量校验和数学操作按完整职责组织。
- 公共库不依赖某个 Sample 的入口,也不隐藏整套模型前后处理。
- 多个消费者确实共用的能力再抽取;模型专用代码留在模型目录。
- 删除只转发 import、继承后原样转发构造参数的本地文件;直接引用公共实现。
- 保持轻量导入,避免查看参数时连带加载图像库、训练框架或板端 SDK。
额外文件应有独立且完整的职责。例如分词器、跟踪算法、语音前端、CIF、多任务解码或复杂的物理张量绑定。阅读一个普通模型时不应为同一阶段跨越多层包装。
简单的结果展示归入 cli.py,纯 import 转发或参数透传不单独建文件。
增加文件时检查:
- 是否承载完整算法或独立资源生命周期?
- 是否需要单独阅读、测试或复用?
- 拆分后,模型文件是否仍能说明完整的数据流?
文件数和行数用于发现阅读负担,不作为机械合并算法的指标。
run.sh 定位 Python 入口,原样转发参数,并传播退出码。工作目录变化不应使入口失效。需要选择解释器时提供明确的环境变量或文档约定。
Shell 不复制 Python 的参数表、模型列表和板卡选择规则,不自动安装依赖或下载模型。模型准备通过 model/ 中的独立命令完成。
采用 Google-style docstring,说明模块和类的职责、参数、返回值及影响调用者的异常。张量接口写明 shape、dtype、布局和值域;输出说明类别、坐标、分数或序列的语义。
行内注释解释关键算法或平台约束。代码和注释同步更新,普通转发无需逐行复述。
公开业务接口为 preprocess → infer → postprocess,由 predict 串联。
按这套名称提供接口,不另设旧拼写的兼容委托。后处理需要几何信息时,显式传入
对应的 Context。predict 与逐步调用返回相同结果。
每个任务在 docstring/类型定义中具体化五个概念:Input(业务输入)、Tensors(后端物理
输入映射)、Context(本次调用的几何/状态信息)、RawOutputs(结构/metadata 校验后的
原始输出)、Result(业务结果)。Context 存放在本次调用的 prepared 返回值中。有状态任务(跟踪、语音流、生成式)
说明会话的创建、帧或请求的处理顺序,以及 reset 清除哪些状态。
多阶段任务(OCR/SAM/Paraformer):每个 stage 具备公开的 preprocess/infer/postprocess
三步接口,pipeline.predict 按模型顺序调用各阶段。模型之间的数据连接写在 pipeline 中。仅有原生 C++
运行时的 sample(如 samples/llm/*)以其 README 声明的原生等价接口为准。
- 入口直接构造模型并调用
predict;模型文件展示完整推理过程。 - CLI 默认值、模型参数、前处理和后处理与文档一致。
- 加载自定义模型时,校验输入输出的名称、形状、数据类型与量化参数。
- 板卡不匹配、无效输入和 SDK 调用失败时,返回可定位原因的错误。
- 每次预测使用对应输入的几何信息,并说明返回数组的有效期和所有权。
- 多模型任务明确空结果的处理方式、多裁剪区域的顺序,以及各阶段的异常。
行为测试覆盖 predict 与逐步调用的一致性、不同尺寸输入、原始输出的处理、
异常输入及多阶段任务的数据传递。接口或目录变化时,同步更新导入、调用方和文档示例。