Skip to content

枚举与常量

如何使用本页:第一部分(导入 + 各类型参考表)适合查询某个具体枚举成员的值和含义;第二部分「使用场景指南」按实际开发任务分组,包含代码示例和常见坑点,不确定用哪个枚举时从这里入手。

枚举分散在 nnrp.core.enumsnnrp.core.messages 子模块,通过顶层 nnrp 命名空间统一再导出。

导入

python
# 推荐:顶层导入
from nnrp import (
    MessageType, HeaderFlags, FrameClass, ErrorCode,
    TransportId, TransportPolicy, LossTolerance, PayloadKind,
    FlowUpdateScopeKind, FlowUpdateReason, FlowUpdateBackpressureLevel, FlowUpdateFlags,
    ResultHintBudgetPolicy, ResultHintCongestionState, ResultHintReason,
)

# 精确导入
from nnrp.core.enums import WireFormat, MessageType, HeaderFlags, FrameClass, ErrorCode
from nnrp.core.messages.control import (
    ErrorScope, CacheObjectKind, CacheAckStatus, CacheInvalidateScope, CachePutFlags,
    SessionPatchField, SessionPatchAckStatus, SessionPatchRejectReason,
    FlowUpdateScopeKind, FlowUpdateReason, FlowUpdateBackpressureLevel, FlowUpdateFlags,
    ResultHintBudgetPolicy, ResultHintCongestionState, ResultHintReason,
    TransportId, TransportPolicy, LossTolerance, PayloadKind, ControlExtensionFlags,
)
from nnrp.core.messages.data import (
    InputProfile, TileIndexMode, TensorDType, TensorLayout, ScalePolicy,
    ResultFlags, SubmitMode, BudgetPolicy, ResultClass, SectionFlags,
)

线路格式

WireFormat(IntEnum)

成员说明
CURRENT0当前唯一支持的线路格式(NNRP/1)

消息类型

MessageType(IntEnum)

成员方向说明
CLIENT_HELLO0x01C→S连接建立,携带客户端能力集
SERVER_HELLO_ACK0x02S→C握手应答,确认能力协商结果
SESSION_PATCH0x03C→S会话参数动态调整请求
SESSION_PATCH_ACK0x04S→C会话参数调整结果
CLOSE0x05双向优雅关闭
ERROR0x06双向协议错误通知
FRAME_SUBMIT0x10C→S提交帧数据
FRAME_CANCEL0x11C→S取消帧提交
RESULT_PUSH0x12S→C推送处理结果
RESULT_DROP0x13S→C通知结果被丢弃
CACHE_PUT0x14C→S存储缓存对象
CACHE_ACK0x15S→C缓存存储结果
CACHE_INVALIDATE0x16C→S缓存失效请求
FLOW_UPDATE0x17双向流控窗口更新
RESULT_HINT0x18S→C服务端提示(背压/队列状态)
TRANSPORT_PROBE0x19双向传输路径探测
TRANSPORT_PROBE_ACK0x1A双向路径探测应答
SESSION_MIGRATE0x1BS→C会话迁移通知
SESSION_MIGRATE_ACK0x1CC→S会话迁移确认
PING0x20双向保活探测
PONG0x21双向保活应答

包头标志

HeaderFlags(IntFlag)

成员位掩码说明
NONE0x00无标志
ACK_REQUIRED0x01接收方须显式确认
CAN_DROP0x02允许在背压下丢弃
STALE0x04数据已过期
EOS0x08流结束标记
RETRANSMIT0x10重传包
KEYFRAME0x20关键帧

帧分类

FrameClass(IntEnum)

成员说明
KEYFRAME0完整关键帧,不依赖任何先前帧
DELTA1增量帧,依赖前一关键帧
RETRANSMIT2重传帧
DISCARDABLE3可丢弃帧,服务端高负载时可跳过

错误码

ErrorCode(IntEnum)

成员说明
UNSUPPORTED_VERSION0x0001不支持请求的协议版本
AUTH_FAILED0x0002认证失败
INVALID_STATE0x0003当前状态不允许该操作
MALFORMED_HEADER0x0004包头格式错误
MALFORMED_BODY0x0005包体格式错误
UNSUPPORTED_CAPABILITY0x0006客户端请求的能力不被支持
LIMIT_EXCEEDED0x0007超出配置限制
FRAME_EXPIRED0x0008帧已过期(超出延迟预算)
FRAME_CANCELLED0x0009帧已被客户端取消
CACHE_MISS0x000A请求的缓存对象不存在
SERVER_BUSY0x000B服务端暂时无法处理
INTERNAL_ERROR0x000C服务端内部错误

错误作用域

ErrorScope(IntEnum)

成员说明
CONNECTION0连接级错误(致命,需重连)
SESSION1会话级错误
FRAME2帧级错误(可恢复)

传输与连接

TransportId(IntEnum)

成员说明
UNSPECIFIED0未指定,由服务端选择
QUIC1QUIC 传输
TCP2TCP 传输

TransportPolicy(IntEnum)

成员说明
AUTO0无要求,自动选择
PREFER_QUIC1优先使用 QUIC
PREFER_TCP2优先使用 TCP
FORCE_QUIC3强制使用 QUIC
FORCE_TCP4强制使用 TCP

LossTolerance(IntEnum)

成员说明
STRICT0不允许丢包
BEST_EFFORT1尽力而为
LOW_LATENCY2低延迟优先,允许少量丢包
FIRE_AND_FORGET3高丢包容忍

ControlExtensionFlags(IntFlag)

成员位掩码说明
NONE0x0000无标志
CRITICAL0x0001关键扩展,接收方不识别则必须拒绝

载荷类型

PayloadKind(IntFlag)

成员位掩码说明
NONE0x00
TENSOR0x01Tensor 载荷(神经渲染推理)
TOKEN_CHUNK0x02Token 流块(大模型生成)
AUDIO_CHUNK0x04音频块
VIDEO_CHUNK0x08视频块
STRUCTURED_EVENT0x10结构化事件
TOOL_DELTA0x20Tool 调用增量
OPAQUE_BYTES0x40不透明二进制

数据面枚举

InputProfile(IntEnum)

成员说明
UNSPECIFIED0未指定
CHANGED_TILES_LUMA1仅包含变化瓦片的亮度数据
DENSE_LUMA_FRAME2完整帧亮度数据

TileIndexMode(IntEnum)

成员说明
DENSE_RANGE0密集连续区间
RAW_U161原始 uint16 列表
DELTA_U162增量编码 uint16
BITSET3位图编码

TensorDType(IntEnum)

成员说明
FP160半精度浮点
FP321单精度浮点
FP8_E4M32FP8 E4M3
FP8_E5M23FP8 E5M2
INT84有符号 8 位整数
UINT85无符号 8 位整数
INT166有符号 16 位整数
UINT167无符号 16 位整数

TensorLayout(IntEnum)

成员说明
NHWC0Batch-Height-Width-Channel
NCHW1Batch-Channel-Height-Width

ScalePolicy(IntEnum)

成员说明
NONE0无量化缩放
LINEAR1线性缩放
ZERO_POINT2带零点的线性缩放

SubmitMode(IntEnum)

成员说明
INLINE0所有对象内联在包体中
REFERENCE1通过缓存键引用已存储对象
MIXED2内联与引用混合

BudgetPolicy(IntFlag)

成员位掩码说明
NONE0x00严格模式,不允许降质
ALLOW_PARTIAL0x01允许部分结果
ALLOW_STALE_REUSE0x02允许重用过期缓存结果
ALLOW_DEGRADED0x04允许降质结果
ALLOW_DROP0x08允许直接丢弃

ResultClass(IntEnum)

成员说明
COMPLETE0完整结果
PARTIAL1部分结果(缺少部分瓦片)
STALE_REUSE2服务端重用了旧缓存结果
DEGRADED3质量降级结果

ResultFlags(IntFlag)

成员位掩码说明
NONE0x0000无标志
STALE0x0001结果来自缓存/过期数据
FALLBACK0x0002使用了降级 fallback 路径
PARTIAL0x0004结果不完整

SectionFlags(IntFlag)

成员位掩码说明
NONE0x0000无标志
MIXED_CODEC0x0001各瓦片使用不同编解码器
FIXED_STRIDE0x0002固定步长布局

缓存枚举

CacheObjectKind(IntEnum)

成员说明
CAMERA_BLOCK0x0001相机参数块
TILE_INDEX_BLOCK0x0002瓦片索引块(别名 TILE_INDEX_TEMPLATE
TENSOR_SECTION_TABLE0x0003Tensor 分区表
CODEC_TABLE0x0004编解码辅助表(别名 CODEC_AUX_BLOCK
REUSABLE_RESULT_OBJECT0x0005可复用结果对象(别名 FALLBACK_RESOURCE
PAYLOAD_LAYOUT_TEMPLATE0x0006载荷布局模板
PROMPT_SEGMENT0x0007Prompt 段(大模型场景)
TOOL_SCHEMA0x0008Tool Schema
STRUCTURED_EVENT_SCHEMA0x0009结构化事件 Schema

CacheAckStatus(IntEnum)

成员说明
ACCEPTED0存储成功
REJECTED1拒绝(容量不足或策略拒绝)
REPLACED2替换了已存在的旧条目

CacheInvalidateScope(IntEnum)

成员说明
WHOLE_SESSION0清空整个会话缓存(别名 SESSION
NAMESPACE1按命名空间清除
OBJECT_KIND2按对象类型清除
OBJECT_KEY3清除特定条目(别名 ENTRY

CachePutFlags(IntFlag)

成员位掩码说明
NONE0x00默认
PINNED0x01固定缓存,不被 LRU 驱逐
REUSABLE0x02可跨帧复用

会话补丁枚举

SessionPatchField(IntFlag)

成员位掩码说明
NONE0x00无字段
TARGET_CADENCE0x01目标帧率(别名 TARGET_FPS
QUALITY_TIER0x02质量档位
DEGRADE_POLICY0x04降质策略
ACTIVE_LANE_MASK0x08活跃视角掩码(别名 ACTIVE_VIEW_MASK
PREFERRED_CODEC0x10首选编解码器
PREFERRED_COMPRESSION0x20首选压缩方式
PROFILE_PATCH0x40完整 Profile 更新

SessionPatchAckStatus(IntEnum)

成员说明
ACCEPTED0全部字段已应用
PARTIALLY_APPLIED1部分字段已应用
REJECTED2完全拒绝

SessionPatchRejectReason(IntEnum)

成员说明
NONE0
UNSUPPORTED_FIELD1不支持的字段
INVALID_RANGE2值超出允许范围
UNSUPPORTED_STRATEGY3不支持的策略
INVALID_LANE_MASK4非法视角掩码(别名 INVALID_VIEW_MASK
RATE_LIMITED5补丁频率受限

流控枚举

FlowUpdateScopeKind(IntEnum)

成员说明
CONNECTION0连接级别
SESSION1会话级别
OPERATION2操作级别

FlowUpdateReason(IntEnum)

成员说明
GRANT0授予更多配额
REDUCE1降低配额
PAUSE2暂停
RESUME3恢复
CONGESTION4拥塞通知

FlowUpdateBackpressureLevel(IntEnum)

成员说明
NONE0无背压
SOFT1软背压(建议降速)
HARD2硬背压(必须降速)

FlowUpdateFlags(IntFlag)

成员位掩码说明
NONE0x00
CREDIT_VALID0x01credit 字段有效
RETRY_AFTER_VALID0x02retry_after_ms 字段有效
BACKGROUND_ONLY0x04仅影响后台低优先级操作
DRAIN_IN_FLIGHT_ONLY0x08仅排空在途操作后生效

结果提示枚举

ResultHintBudgetPolicy(IntEnum)

成员说明
NONE0无建议
FULL1建议使用全额预算
PARTIAL2建议接受部分结果
STALE_REUSE3建议接受缓存重用
DROP4建议客户端直接丢弃

ResultHintCongestionState(IntEnum)

成员说明
NONE0无拥塞
STEADY1稳定态
ELEVATED2轻度拥塞
SATURATED3严重饱和

ResultHintReason(IntEnum)

成员说明
NONE0
QUEUE_FULL1队列满
SERVER_BUSY2服务端繁忙
BUDGET_EXCEEDED3预算超出
SUPERSEDED4被后续提交取代

扩展类型常量

python
# 控制扩展块类型 ID(uint16)
CLIENT_HELLO_TRANSPORT_POLICY_EXTENSION     = 0x0101
SERVER_HELLO_ACK_TRANSPORT_POLICY_EXTENSION = 0x0102
CLIENT_HELLO_LOSS_TOLERANCE_EXTENSION       = 0x0103
SERVER_HELLO_ACK_LOSS_TOLERANCE_EXTENSION   = 0x0104
CLIENT_HELLO_PAYLOAD_CAPABILITIES_EXTENSION = 0x0105
SERVER_HELLO_ACK_PAYLOAD_CAPABILITIES_EXTENSION = 0x0106

使用场景指南

场景一:建立连接与协商传输

相关枚举TransportIdTransportPolicyLossToleranceWireFormat

握手时客户端在 CLIENT_HELLO 里声明传输偏好,服务端在 SERVER_HELLO_ACK 里确认。

python
from nnrp import TransportId, TransportPolicy, LossTolerance
from nnrp.client import ClientProfile, ClientDialPolicy, dial_client

# 希望优先 QUIC,容忍少量丢包,降级到 TCP 也可以
profile = ClientProfile(
    transport_policy=TransportPolicy.PREFER_QUIC,
    loss_tolerance=LossTolerance.LOW_LATENCY,
)
dial_policy = ClientDialPolicy(
    preferred_transport=TransportId.QUIC,
    fallback_transport=TransportId.TCP,
)
session = await dial_client("render.example.com", 4433,
                             profile=profile, dial_policy=dial_policy,
                             config=quic_cfg)

常见坑点

  • FORCE_QUIC 在 TCP-only 防火墙下直接握手失败,生产环境建议用 PREFER_QUIC 而非 FORCE_QUIC
  • LossTolerance.FIRE_AND_FORGET 不保证顺序,适合遥测/统计场景,切勿用于帧提交主路径。
  • WireFormat.CURRENT 是目前唯一合法值,不要硬编码数字 0,以便未来升级时编译器能帮你找到所有调用点。

场景二:提交帧数据

相关枚举InputProfileSubmitModeBudgetPolicyPayloadKindTileIndexMode

python
from nnrp import InputProfile, SubmitMode, BudgetPolicy, PayloadKind, TileIndexMode
from nnrp.client import SubmitRequest, TensorSectionData

# 只发送变化瓦片(增量帧),引用缓存中的重用对象
request = SubmitRequest(
    frame_id=42,
    tile_ids=(3, 7, 12),                          # 只有这三个瓦片有变化
    sections=(TensorSectionData(...),),
    input_profile=InputProfile.CHANGED_TILES_LUMA,
    submit_mode=SubmitMode.MIXED,                 # 部分内联,部分引用缓存
    budget_policy=BudgetPolicy.ALLOW_PARTIAL | BudgetPolicy.ALLOW_STALE_REUSE,
    inference_budget_ms=8,
    tile_index_mode=TileIndexMode.RAW_U16,
)
await session.submit_frame(request)

常见坑点

  • BudgetPolicy 是位掩码(IntFlag,多个策略用 | 组合,不是用逗号分隔的列表。BudgetPolicy.NONE 是严格模式,服务端任何降质行为都会返回 ResultClass.DEGRADED 并触发错误。
  • SubmitMode.REFERENCE 要求提前调用 session.put_cache(),否则服务端会返回 ErrorCode.CACHE_MISS
  • tile_ids 为空元组时,TileIndexMode 的值无效,服务端会忽略瓦片索引字段。

场景三:处理帧结果

相关枚举ResultClassResultFlags

python
from nnrp import ResultClass, ResultFlags

result = await session.receive_result(frame_id=42, timeout=0.05)

match result.metadata.result_class:
    case ResultClass.COMPLETE:
        apply_full_result(result)
    case ResultClass.PARTIAL:
        # 只有部分瓦片完成,result_flags 中会有 PARTIAL 位
        apply_partial_result(result)
    case ResultClass.STALE_REUSE:
        # 服务端重用了上一帧缓存——视频渲染时可直接复用上帧
        pass
    case ResultClass.DEGRADED:
        # 质量降级,检查 applied_budget_policy 了解实际使用的策略
        log_degraded(result.metadata.applied_budget_policy)

# 检查附加标志
if result.metadata.result_flags & ResultFlags.FALLBACK:
    metrics.increment("degraded_fallback")

常见坑点

  • 不要只检查 COMPLETE 然后对其他情况报错STALE_REUSEDEGRADED 在高负载下是正常现象,应在业务层决定是否接受。
  • ResultFlags.STALEResultClass.STALE_REUSE 含义重叠但粒度不同:前者是位标志(可与其他标志共存),后者是主类别,业务逻辑优先判断 result_class

场景四:错误处理

相关枚举ErrorCodeErrorScope

python
from nnrp import ErrorCode
from nnrp.core.enums import ErrorScope
from nnrp.errors import NnrpProtocolError

try:
    await session.submit_frame(request)
except NnrpProtocolError as e:
    match e.error_code:
        case ErrorCode.FRAME_EXPIRED:
            # 帧已过期,跳过本帧,继续下一帧
            pass
        case ErrorCode.SERVER_BUSY:
            # 服务端繁忙,等待后重试(见 ResultHint 背压信号)
            await asyncio.sleep(0.05)
        case ErrorCode.AUTH_FAILED:
            # 认证失败,不可重试,重建连接
            raise

    if e.error_scope == ErrorScope.CONNECTION:
        # 连接级错误是致命的,必须重新建立连接
        await session.close()
        session = await dial_client(...)
    elif e.error_scope == ErrorScope.FRAME:
        # 帧级错误可恢复,只需跳过当前帧
        pass

常见坑点

  • ErrorScope.CONNECTION 错误不可在同一 Session 上重试,必须重新握手。不少开发者在连接级错误后仍向旧 session 发送数据,导致死锁。
  • ErrorCode.LIMIT_EXCEEDED 可能是每秒补丁频率受限(见 SessionPatchRejectReason.RATE_LIMITED),不一定是硬件资源耗尽。

场景五:缓存操作

相关枚举CacheObjectKindCachePutFlagsCacheAckStatusCacheInvalidateScope

python
from nnrp import CacheObjectKind, CachePutFlags, CacheAckStatus, CacheInvalidateScope

# 存储一个可复用的 Tensor 分区表,并固定不被 LRU 驱逐
ack = await session.put_cache(
    kind=CacheObjectKind.TENSOR_SECTION_TABLE,
    key=b"tst-v1",
    data=serialized_tensor_section_table,
    flags=CachePutFlags.PINNED | CachePutFlags.REUSABLE,
)

match ack.status:
    case CacheAckStatus.ACCEPTED:
        pass  # 正常存储
    case CacheAckStatus.REPLACED:
        log.warning("key %s already existed, replaced", ack.key)
    case CacheAckStatus.REJECTED:
        # 容量不足或策略拒绝,降级为 INLINE 提交
        use_inline_submit = True

# 会话结束前或模型切换时清除特定类型的缓存
await session.invalidate_cache(
    scope=CacheInvalidateScope.OBJECT_KIND,
    kind=CacheObjectKind.TENSOR_SECTION_TABLE,
)

常见坑点

  • CachePutFlags.PINNED 不受 LRU 驱逐,但仍受服务端总缓存配额限制,大量 PINNED 对象可能导致后续 CACHE_PUT 全部被 REJECTED。
  • CacheObjectKind.TILE_INDEX_BLOCK 有别名 TILE_INDEX_TEMPLATE,两者值相同;代码里统一用一个,避免混用产生混乱。
  • CacheInvalidateScope.WHOLE_SESSION 会清空整个会话的所有缓存对象,慎用,通常只在会话重置时才需要这个粒度。

场景六:流控与背压

相关枚举FlowUpdateScopeKindFlowUpdateReasonFlowUpdateBackpressureLevelFlowUpdateFlagsResultHintBudgetPolicyResultHintCongestionStateResultHintReason

python
from nnrp import (
    FlowUpdateReason, FlowUpdateBackpressureLevel,
    ResultHintCongestionState, ResultHintBudgetPolicy,
)

# 服务端推送 RESULT_HINT,客户端据此调整发送速率
async def handle_result_hints(session):
    async for hint in session.result_hints():
        if hint.congestion_state == ResultHintCongestionState.SATURATED:
            # 严重饱和:立即停止提交,等待明确的 FLOW_UPDATE RESUME
            await session.pause_submit()
        elif hint.congestion_state == ResultHintCongestionState.ELEVATED:
            # 轻度拥塞:降低提交频率
            frame_interval_ms = frame_interval_ms * 1.5

        if hint.budget_policy == ResultHintBudgetPolicy.DROP:
            # 服务端建议客户端直接丢弃下一帧提交
            skip_next_frame = True

# 服务端推送 FLOW_UPDATE 时的处理
async def handle_flow_update(update):
    match update.reason:
        case FlowUpdateReason.PAUSE:
            await session.pause_submit()
        case FlowUpdateReason.RESUME:
            await session.resume_submit()
        case FlowUpdateReason.CONGESTION:
            if update.backpressure == FlowUpdateBackpressureLevel.HARD:
                # 硬背压:必须立即停止
                await session.pause_submit()

常见坑点

  • ResultHint 是建议,不是命令,但忽略 SATURATED 状态持续提交会导致服务端队列溢出,最终触发 RESULT_DROP(服务端直接丢帧)。
  • FlowUpdateFlags.CREDIT_VALID 标志未置位时,credit 字段值无意义,不要直接用于速率计算。
  • FlowUpdateFlags.RETRY_AFTER_VALID 置位时,retry_after_ms 才有效;不检查此标志直接用 retry_after_ms 可能读到默认零值,导致客户端立即重试(等于无退避)。

场景七:会话动态调整

相关枚举SessionPatchFieldSessionPatchAckStatusSessionPatchRejectReason

python
from nnrp import SessionPatchField, SessionPatchAckStatus, SessionPatchRejectReason

# 在会话进行中动态调整目标帧率和质量档位
ack = await session.patch(
    fields=SessionPatchField.TARGET_CADENCE | SessionPatchField.QUALITY_TIER,
    target_cadence=30,   # 从 60fps 降为 30fps(省电模式)
    quality_tier=1,
)

match ack.status:
    case SessionPatchAckStatus.ACCEPTED:
        pass
    case SessionPatchAckStatus.PARTIALLY_APPLIED:
        # 部分字段被接受,检查哪些字段被拒绝
        for rejected_field, reason in ack.rejected_fields.items():
            if reason == SessionPatchRejectReason.RATE_LIMITED:
                # 补丁频率受限,稍后重试
                await asyncio.sleep(1.0)
            elif reason == SessionPatchRejectReason.INVALID_RANGE:
                log.error("Invalid value for field %s", rejected_field)
    case SessionPatchAckStatus.REJECTED:
        log.warning("Patch fully rejected: %s", ack.reject_reason)

常见坑点

  • SessionPatchField 是位掩码(IntFlag,同时请求多个字段时必须用 | 组合,不要多次发送单字段补丁(每次都计入频率限制)。
  • 服务端对 SESSION_PATCH 有频率限制(默认每秒若干次),高频补丁(如每帧都 patch)会触发 RATE_LIMITED,应在客户端合批。
  • SessionPatchAckStatus.PARTIALLY_APPLIED 时,已被接受的字段不会回滚,需要在客户端自行记录哪些字段当前生效,以便下次补丁时构造正确的 diff。

NNRP Documentation