代码之上:DLL 深度工程参考

如果代码是执行指令,那这份文档就是执行契约。它定义了底层核心在物理时序和内存拓扑上的“潜规则”。

调用状态机 (State Transitions)

stateDiagram-v2 [*] --> EngineCreated: LiteRtLm_CreateEngine EngineCreated --> ConvCreated: LiteRtLm_CreateConversation ConvCreated --> Ready: AppendUserMessage Ready --> Inferencing: LiteRtLm_RunInference Inferencing --> Driving: LiteRtLm_WaitUntilDone Driving --> Ready: bIsDone = 1 Inferencing --> [*]: LiteRtLm_StopMessage EngineCreated --> [*]: LiteRtLm_DestroyEngine

核心洞见:非线程排队

LiteRT-LM DLL 内部不具备自动任务队列。如果在 WaitUntilDone 阻塞循环尚未结束时,强行在另一个线程对同一个 Conversation 调用 RunInference,将导致显存上下文被覆盖或非法访问。开发者必须在应用层确保同一会话的任务串行性。

内存契约与所有权 (Ownership)

显存:持久所有权

Engine 分配的 KV Cache 块是持久的。只要不调用 DestroyConversation,对应的显存块将永远保留。这是实现“零拷贝 Agent 切换”的物理基础。

指针:临时所有权

回调中的 text_chunk 是 DLL 内部 std::string.c_str()

“回调返回之刻,即是指针销毁之时。”

graph TD subgraph DLL[DLL Core Memory] Buffer[Buffer: Hello World] end subgraph App[External App] String[std::string MyResponse] end Buffer -- Pointer --> App Note right of Buffer: 生命周期仅限 Callback 栈帧 App -- Deep Copy --> String Note over String: 数据持久化

驱动心跳本质 (The Driver)

WaitUntilDone 不仅仅是等待。

在 WebGPU 后端下,RunInference 提交的指令是异步的。如果没有人去调用 WaitUntilDone,底层事件循环将处于停滞状态。

它是推理引擎的“曲轴”:每一次调用都在驱动 GPU 任务的推进、Token 的产出以及回调函数的触发。这就是为什么我们建议在后台线程中开启 while(!done) { WaitUntilDone(...) }

CPU 负载
LOW
仅负责事件驱动
响应延迟
< 1ms
亚毫秒级回调触发

全量 API 契约字典 (Physical Dictionary)

LiteRtLm_CreateEngine O(Initial Load)
DLL_EXPORT void* LiteRtLm_CreateEngine(LiteRtLm_Config config);
物理行为:
  • 加载 .bin.gguf 权重文件。
  • 初始化 WebGPU 适配器与编译 Pipeline。
  • 显存分配:按 max_num_tokens 预分配基础显存。
工程陷阱:backend 指定了 GPU 但驱动版本不兼容,此函数可能导致进程静默崩溃或返回空指针。
LiteRtLm_RunInference Non-Blocking
DLL_EXPORT void LiteRtLm_RunInference(void* conv, LiteRtLm_SamplingParams p, LiteRtLmCallback cb, void* user);

增量逻辑: 此函数会检测 conv 的当前状态。如果距离上次推理有新追加的消息,它会先进行 Prefill(预填充)计算,然后才开始 Decode(解码)。