feat: checkpoint distributed gguf runtime stories
This commit is contained in:
76
packages/node/native/CMakeLists.txt
Normal file
76
packages/node/native/CMakeLists.txt
Normal file
@@ -0,0 +1,76 @@
|
||||
# Reproducible C++ build wiring for the Shard runtime protocol (DGR-002).
|
||||
#
|
||||
# Generates C++ message stubs from proto/shard_runtime.proto and builds the
|
||||
# round-trip / cross-language compatibility test. Requires protoc and the
|
||||
# protobuf C++ runtime. Works with either a CONFIG-mode protobuf install
|
||||
# (protobuf::libprotobuf / protobuf::protoc targets, e.g. a from-source install
|
||||
# on CMAKE_PREFIX_PATH) or CMake's bundled FindProtobuf module.
|
||||
#
|
||||
# The gRPC C++ service stubs are generated separately by scripts/generate_cpp.sh
|
||||
# when grpc_cpp_plugin is present; the round-trip test needs only message
|
||||
# serialization, so gRPC is intentionally not a build dependency here.
|
||||
#
|
||||
# Configure & build (out-of-tree):
|
||||
# cmake -S packages/node/native -B packages/node/native/build/cpp
|
||||
# cmake --build packages/node/native/build/cpp
|
||||
# Run:
|
||||
# packages/node/native/build/cpp/shard_protocol_roundtrip_test --selftest
|
||||
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(shard_runtime_protocol CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# Prefer a CONFIG-mode protobuf (modern imported targets); fall back to the
|
||||
# FindProtobuf module for system installs.
|
||||
find_package(Protobuf CONFIG QUIET)
|
||||
if(NOT Protobuf_FOUND)
|
||||
find_package(Protobuf REQUIRED)
|
||||
endif()
|
||||
|
||||
if(TARGET protobuf::protoc)
|
||||
set(SHARD_PROTOC_EXECUTABLE "$<TARGET_FILE:protobuf::protoc>")
|
||||
else()
|
||||
set(SHARD_PROTOC_EXECUTABLE "${Protobuf_PROTOC_EXECUTABLE}")
|
||||
endif()
|
||||
|
||||
if(TARGET protobuf::libprotobuf)
|
||||
set(SHARD_PROTOBUF_LINK protobuf::libprotobuf)
|
||||
else()
|
||||
set(SHARD_PROTOBUF_LINK ${Protobuf_LIBRARIES})
|
||||
endif()
|
||||
|
||||
set(PROTO_DIR "${CMAKE_CURRENT_SOURCE_DIR}/proto")
|
||||
set(PROTO_FILE "${PROTO_DIR}/shard_runtime.proto")
|
||||
set(GEN_DIR "${CMAKE_CURRENT_BINARY_DIR}/gen")
|
||||
file(MAKE_DIRECTORY "${GEN_DIR}")
|
||||
|
||||
set(PROTO_SRC "${GEN_DIR}/shard_runtime.pb.cc")
|
||||
set(PROTO_HDR "${GEN_DIR}/shard_runtime.pb.h")
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${PROTO_SRC}" "${PROTO_HDR}"
|
||||
COMMAND "${SHARD_PROTOC_EXECUTABLE}"
|
||||
"--proto_path=${PROTO_DIR}"
|
||||
"--cpp_out=${GEN_DIR}"
|
||||
"${PROTO_FILE}"
|
||||
DEPENDS "${PROTO_FILE}"
|
||||
COMMENT "Generating C++ protobuf stubs from shard_runtime.proto"
|
||||
VERBATIM)
|
||||
|
||||
add_executable(shard_protocol_roundtrip_test
|
||||
tests/roundtrip_test.cpp
|
||||
"${PROTO_SRC}")
|
||||
|
||||
target_include_directories(shard_protocol_roundtrip_test PRIVATE "${GEN_DIR}")
|
||||
if(NOT TARGET protobuf::libprotobuf AND Protobuf_INCLUDE_DIRS)
|
||||
target_include_directories(shard_protocol_roundtrip_test PRIVATE
|
||||
${Protobuf_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(shard_protocol_roundtrip_test PRIVATE ${SHARD_PROTOBUF_LINK})
|
||||
|
||||
enable_testing()
|
||||
add_test(NAME shard_protocol_roundtrip
|
||||
COMMAND shard_protocol_roundtrip_test --selftest)
|
||||
24
packages/node/native/llama/README.md
Normal file
24
packages/node/native/llama/README.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Pinned llama.cpp source dependency
|
||||
|
||||
This directory keeps the llama.cpp fork boundary explicit and auditable.
|
||||
|
||||
Layout:
|
||||
|
||||
- `UPSTREAM_COMMIT` - the exact pinned commit.
|
||||
- `UPSTREAM_REPOSITORY` - the reproducible source dependency URL.
|
||||
- `UPSTREAM_ASSUMPTIONS.md` - the file/ABI assumptions that the build scripts
|
||||
validate.
|
||||
- `patches/` - numbered patch files applied on top of the pinned checkout.
|
||||
|
||||
The intended flow is:
|
||||
|
||||
1. Fetch or clone the pinned upstream checkout.
|
||||
2. Verify the checkout commit matches `UPSTREAM_COMMIT`.
|
||||
3. Check and apply the numbered patch stack.
|
||||
4. Build the worker scaffold from `examples/meshnet-worker/`.
|
||||
5. Copy the upstream `LICENSE` and `AUTHORS` files into the worker build tree so
|
||||
the attribution notices remain attached to the built artifact.
|
||||
|
||||
The patch stack in this story is intentionally minimal. It creates the project
|
||||
worker scaffold and the smoke-test CMake target without pulling Meshnet
|
||||
networking code into llama.cpp.
|
||||
35
packages/node/native/llama/UPSTREAM_ASSUMPTIONS.md
Normal file
35
packages/node/native/llama/UPSTREAM_ASSUMPTIONS.md
Normal file
@@ -0,0 +1,35 @@
|
||||
# llama.cpp upstream assumptions
|
||||
|
||||
This directory records the reproducible source dependency boundary for the
|
||||
pinned llama.cpp checkout used by the distributed GGUF runtime program.
|
||||
|
||||
Pinned upstream commit:
|
||||
|
||||
- `b3c9d1b846cc80a6360adb6aeaa4fcd8c4c8dcac`
|
||||
|
||||
Pinned upstream repository:
|
||||
|
||||
- `https://github.com/ggml-org/llama.cpp.git`
|
||||
|
||||
Assumptions checked by the build script:
|
||||
|
||||
- The checkout is exactly the pinned commit above.
|
||||
- The upstream source tree still ships `LICENSE`, `AUTHORS`, and
|
||||
`CMakeLists.txt` at the repository root.
|
||||
- The project-owned worker scaffold is built from
|
||||
`examples/meshnet-worker/`, which is introduced by the patch stack below.
|
||||
- The upstream license and attribution notices are preserved in the build
|
||||
output by copying the root `LICENSE` and `AUTHORS` files into the worker
|
||||
staging directory.
|
||||
|
||||
Compatibility notes:
|
||||
|
||||
- The current patch stack does not modify upstream llama.cpp runtime code yet.
|
||||
It adds a project-owned worker scaffold that can be built reproducibly from
|
||||
the pinned source checkout.
|
||||
- Later stories extend this boundary with actual llama.cpp execution patches.
|
||||
|
||||
Failure mode:
|
||||
|
||||
- If the checkout commit does not match the pin, the build script fails with a
|
||||
clear pin-mismatch error before patch application or compilation starts.
|
||||
1
packages/node/native/llama/UPSTREAM_COMMIT
Normal file
1
packages/node/native/llama/UPSTREAM_COMMIT
Normal file
@@ -0,0 +1 @@
|
||||
b3c9d1b846cc80a6360adb6aeaa4fcd8c4c8dcac
|
||||
1
packages/node/native/llama/UPSTREAM_REPOSITORY
Normal file
1
packages/node/native/llama/UPSTREAM_REPOSITORY
Normal file
@@ -0,0 +1 @@
|
||||
https://github.com/ggml-org/llama.cpp.git
|
||||
@@ -0,0 +1,35 @@
|
||||
diff --git a/examples/meshnet-worker/CMakeLists.txt b/examples/meshnet-worker/CMakeLists.txt
|
||||
new file mode 100644
|
||||
index 0000000000..8d9f9a1a2f
|
||||
--- /dev/null
|
||||
+++ b/examples/meshnet-worker/CMakeLists.txt
|
||||
@@ -0,0 +1,19 @@
|
||||
+cmake_minimum_required(VERSION 3.16)
|
||||
+project(meshnet_llama_worker CXX)
|
||||
+
|
||||
+set(CMAKE_CXX_STANDARD 17)
|
||||
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
+
|
||||
+configure_file(
|
||||
+ "${CMAKE_CURRENT_SOURCE_DIR}/version.h.in"
|
||||
+ "${CMAKE_CURRENT_BINARY_DIR}/version.h"
|
||||
+ @ONLY)
|
||||
+
|
||||
+add_executable(meshnet_worker
|
||||
+ meshnet_worker.cpp)
|
||||
+
|
||||
+target_include_directories(meshnet_worker PRIVATE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
+
|
||||
+enable_testing()
|
||||
+add_test(NAME meshnet_worker_smoke
|
||||
+ COMMAND meshnet_worker --smoke)
|
||||
diff --git a/examples/meshnet-worker/version.h.in b/examples/meshnet-worker/version.h.in
|
||||
new file mode 100644
|
||||
index 0000000000..0b75c4e60f
|
||||
--- /dev/null
|
||||
+++ b/examples/meshnet-worker/version.h.in
|
||||
@@ -0,0 +1,4 @@
|
||||
+#pragma once
|
||||
+
|
||||
+#define MESHNET_LLAMA_UPSTREAM_COMMIT "@MESHNET_LLAMA_UPSTREAM_COMMIT@"
|
||||
+#define MESHNET_LLAMA_PATCHSET_VERSION "@MESHNET_LLAMA_PATCHSET_VERSION@"
|
||||
43
packages/node/native/llama/templates/meshnet_worker.cpp
Normal file
43
packages/node/native/llama/templates/meshnet_worker.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "version.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace {
|
||||
|
||||
bool fail(const std::string& why) {
|
||||
std::cerr << "meshnet_worker: FAIL: " << why << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
bool smoke = argc == 1;
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
const std::string arg = argv[i];
|
||||
if (arg == "--smoke") {
|
||||
smoke = true;
|
||||
} else {
|
||||
std::cerr << "unknown arg: " << arg << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!smoke) {
|
||||
return fail("smoke mode not requested"), 1;
|
||||
}
|
||||
|
||||
if (MESHNET_LLAMA_UPSTREAM_COMMIT[0] == '\0') {
|
||||
return fail("upstream commit missing"), 1;
|
||||
}
|
||||
if (MESHNET_LLAMA_PATCHSET_VERSION[0] == '\0') {
|
||||
return fail("patchset version missing"), 1;
|
||||
}
|
||||
|
||||
std::cout << "meshnet worker scaffold ok" << std::endl;
|
||||
std::cout << "upstream commit: " << MESHNET_LLAMA_UPSTREAM_COMMIT << std::endl;
|
||||
std::cout << "patchset version: " << MESHNET_LLAMA_PATCHSET_VERSION << std::endl;
|
||||
return 0;
|
||||
}
|
||||
388
packages/node/native/proto/shard_runtime.proto
Normal file
388
packages/node/native/proto/shard_runtime.proto
Normal file
@@ -0,0 +1,388 @@
|
||||
// Shard runtime data-plane protocol for the distributed GGUF runtime (ADR-0024).
|
||||
//
|
||||
// This schema is the semantic contract between Python and C++ Shards. Direct
|
||||
// transport is gRPC over HTTP/2; the existing Meshnet relay may carry the same
|
||||
// serialized frames as opaque binary, so anything gRPC would normally carry in
|
||||
// call metadata (deadlines, cancellation intent) is ALSO representable inside
|
||||
// the messages for relay-transported seams.
|
||||
//
|
||||
// Design rules (see .scratch/distributed-gguf-runtime/RALPH-CONTEXT.md):
|
||||
// * One long-lived bidirectional ActivateSession stream per Route Session
|
||||
// Activation Seam. No per-token channel creation.
|
||||
// * Bounded chunking for prefill; a small decode fast path.
|
||||
// * The activation boundary is a versioned named-tensor bundle, because an
|
||||
// architecture boundary may require more than one tensor.
|
||||
// * Meshnet routing/billing/auth live outside this schema; only the data
|
||||
// plane and the identifiers needed to attribute and isolate work are here.
|
||||
//
|
||||
// Compatibility: proto3. Never renumber or reuse a field number. Add new fields
|
||||
// with new numbers only. Enums keep a 0 UNSPECIFIED member for forward compat.
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package meshnet.shard.v1;
|
||||
|
||||
option java_package = "com.meshnet.shard.v1";
|
||||
option java_outer_classname = "ShardRuntimeProto";
|
||||
option go_package = "meshnet/shard/v1;shardv1";
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Versioning and enums
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Wire schema version. Bumped only on incompatible envelope changes; additive
|
||||
// field changes keep the same version and rely on proto3 unknown-field rules.
|
||||
enum SchemaVersion {
|
||||
SCHEMA_VERSION_UNSPECIFIED = 0;
|
||||
SCHEMA_VERSION_1 = 1;
|
||||
}
|
||||
|
||||
// Lifecycle phase of a seam message. RELEASE and CANCEL are represented both as
|
||||
// dedicated RPCs and as in-stream phases so a relay-carried stream can express
|
||||
// them without a separate channel.
|
||||
enum Phase {
|
||||
PHASE_UNSPECIFIED = 0;
|
||||
PHASE_PREFILL = 1;
|
||||
PHASE_DECODE = 2;
|
||||
PHASE_RELEASE = 3;
|
||||
PHASE_CANCEL = 4;
|
||||
}
|
||||
|
||||
// Tensor element type. GGUF quantized block types are enumerated explicitly so
|
||||
// a boundary bundle can carry pre-quantized payloads without reinterpretation.
|
||||
enum DType {
|
||||
DTYPE_UNSPECIFIED = 0;
|
||||
DTYPE_F32 = 1;
|
||||
DTYPE_F16 = 2;
|
||||
DTYPE_BF16 = 3;
|
||||
DTYPE_I64 = 4;
|
||||
DTYPE_I32 = 5;
|
||||
DTYPE_I16 = 6;
|
||||
DTYPE_I8 = 7;
|
||||
DTYPE_U8 = 8;
|
||||
DTYPE_BOOL = 9;
|
||||
DTYPE_Q8_0 = 20;
|
||||
DTYPE_Q4_0 = 21;
|
||||
DTYPE_Q4_K = 22;
|
||||
DTYPE_Q6_K = 23;
|
||||
}
|
||||
|
||||
// Byte order of a tensor payload. Explicit because Shards may run on
|
||||
// heterogeneous hardware and the relay carries opaque bytes.
|
||||
enum ByteOrder {
|
||||
BYTE_ORDER_UNSPECIFIED = 0;
|
||||
BYTE_ORDER_LITTLE_ENDIAN = 1;
|
||||
BYTE_ORDER_BIG_ENDIAN = 2;
|
||||
}
|
||||
|
||||
// Payload compression applied to a tensor fragment or message body.
|
||||
enum Compression {
|
||||
COMPRESSION_UNSPECIFIED = 0;
|
||||
COMPRESSION_NONE = 1;
|
||||
COMPRESSION_ZSTD = 2;
|
||||
}
|
||||
|
||||
// Checksum algorithm. CRC32C is the cheap per-fragment default; SHA256 is used
|
||||
// where stronger integrity is required.
|
||||
enum ChecksumAlgorithm {
|
||||
CHECKSUM_ALGORITHM_UNSPECIFIED = 0;
|
||||
CHECKSUM_NONE = 1;
|
||||
CHECKSUM_CRC32C = 2;
|
||||
CHECKSUM_CRC32 = 3;
|
||||
CHECKSUM_SHA256 = 4;
|
||||
}
|
||||
|
||||
// What the sender expects from the receiving Shard's Hot KV State for this work
|
||||
// (request side of the cache contract).
|
||||
enum CacheExpectation {
|
||||
CACHE_EXPECTATION_UNSPECIFIED = 0;
|
||||
CACHE_REUSE = 1; // reuse existing KV for (session, epoch)
|
||||
CACHE_FRESH = 2; // start a fresh KV context
|
||||
CACHE_BYPASS = 3; // stateless; do not persist KV
|
||||
}
|
||||
|
||||
// What the receiving Shard actually did with its KV State (result side).
|
||||
enum CacheResult {
|
||||
CACHE_RESULT_UNSPECIFIED = 0;
|
||||
CACHE_HIT = 1;
|
||||
CACHE_MISS = 2;
|
||||
CACHE_WRITTEN = 3;
|
||||
CACHE_BYPASSED = 4;
|
||||
}
|
||||
|
||||
// Coarse retry classification carried in structured status.
|
||||
enum RetryClass {
|
||||
RETRY_CLASS_UNSPECIFIED = 0;
|
||||
RETRY_CLASS_NONE = 1; // terminal success/no-retry
|
||||
RETRY_CLASS_RETRYABLE = 2; // transient; the same step may be retried
|
||||
RETRY_CLASS_FATAL = 3; // do not retry this route/epoch
|
||||
RETRY_CLASS_EPOCH_STALE = 4; // route epoch advanced; re-resolve route
|
||||
}
|
||||
|
||||
enum ServingStatus {
|
||||
SERVING_STATUS_UNSPECIFIED = 0;
|
||||
SERVING = 1;
|
||||
NOT_SERVING = 2;
|
||||
DRAINING = 3;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Common value messages
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Structured, transport-independent status. Mirrors canonical gRPC codes so a
|
||||
// relay-carried frame can express what a gRPC trailer normally would.
|
||||
message Status {
|
||||
uint32 code = 1; // canonical gRPC status code
|
||||
string message = 2;
|
||||
RetryClass retry_class = 3;
|
||||
map<string, string> details = 4;
|
||||
}
|
||||
|
||||
// Integrity check over an associated payload.
|
||||
message Checksum {
|
||||
ChecksumAlgorithm algorithm = 1;
|
||||
bytes value = 2;
|
||||
}
|
||||
|
||||
// Exact Model Artifact / runtime-recipe fingerprint. Both Shards MUST agree on
|
||||
// every populated field before activation; a mismatch is a fatal status.
|
||||
message ArtifactFingerprint {
|
||||
string model_id = 1; // e.g. "meta-llama/Llama-3.1-8B"
|
||||
string revision = 2; // artifact revision / commit
|
||||
string artifact_hash = 3; // hash of the GGUF/model artifact
|
||||
string quantization = 4; // e.g. "Q4_K_M", "F16"
|
||||
string runtime_recipe_fingerprint = 5; // DGR-003 recipe hash
|
||||
}
|
||||
|
||||
// Contiguous transformer layer range owned by a Shard (ADR-0012). end_layer is
|
||||
// exclusive. effective_start_layer is the overlap-safe start after de-dupe of
|
||||
// shared boundary layers between adjacent Shards.
|
||||
message ShardRange {
|
||||
uint32 start_layer = 1;
|
||||
uint32 end_layer = 2;
|
||||
uint32 effective_start_layer = 3;
|
||||
bool owns_embedding = 4;
|
||||
bool owns_final_head = 5;
|
||||
}
|
||||
|
||||
// Token position window for a message. start_position is the absolute index of
|
||||
// the first token; token_count is how many positions this message covers.
|
||||
message Position {
|
||||
uint64 start_position = 1;
|
||||
uint64 token_count = 2;
|
||||
uint64 sequence_length = 3; // total known context length, if known
|
||||
}
|
||||
|
||||
// Envelope carried by every seam message. Everything required to version,
|
||||
// route-attribute, isolate, order, and integrity-check a unit of work.
|
||||
message MessageHeader {
|
||||
SchemaVersion schema_version = 1;
|
||||
string work_id = 2; // request/work ID (idempotency scope)
|
||||
string route_session_id = 3; // Route Session ID
|
||||
uint64 route_epoch = 4; // route epoch; stale epochs are rejected
|
||||
ArtifactFingerprint fingerprint = 5;
|
||||
ShardRange shard_range = 6;
|
||||
Phase phase = 7;
|
||||
Position position = 8;
|
||||
uint64 idempotency_step = 9; // monotonic per (work_id) step counter
|
||||
CacheExpectation cache_expectation = 10;
|
||||
Compression compression = 11; // compression of THIS message's payloads
|
||||
Checksum checksum = 12; // checksum over THIS message's payload
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Versioned named-tensor bundle (the activation boundary payload)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// One bounded fragment of a tensor payload. Large tensors are split so no
|
||||
// single message is unbounded; fragments reassemble by byte_offset order.
|
||||
message TensorFragment {
|
||||
uint32 fragment_index = 1;
|
||||
uint32 fragment_count = 2;
|
||||
uint64 byte_offset = 3; // offset of this fragment within the full payload
|
||||
bytes data = 4;
|
||||
Checksum checksum = 5; // checksum over this fragment's (post-compression) data
|
||||
}
|
||||
|
||||
// A single named tensor with full description so the receiver never reinterprets
|
||||
// bytes implicitly.
|
||||
message NamedTensor {
|
||||
string name = 1;
|
||||
repeated uint64 shape = 2;
|
||||
DType dtype = 3;
|
||||
ByteOrder byte_order = 4;
|
||||
uint64 total_byte_length = 5; // full payload length across all fragments
|
||||
Compression compression = 6; // compression applied to fragment data
|
||||
repeated TensorFragment fragments = 7;
|
||||
}
|
||||
|
||||
// A versioned collection of named tensors representing one activation boundary.
|
||||
message TensorBundle {
|
||||
uint32 bundle_version = 1;
|
||||
repeated NamedTensor tensors = 2;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Session stream messages (bidirectional ActivateSession)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Opens a seam. Carries the header plus stream-scoped bounds. deadline_unix_nanos
|
||||
// lets a relay-carried stream express the call deadline gRPC would otherwise own.
|
||||
message SessionOpen {
|
||||
MessageHeader header = 1;
|
||||
uint64 deadline_unix_nanos = 2; // absolute deadline; 0 = none
|
||||
uint32 max_prefill_tokens_per_chunk = 3; // bound for prefill chunking
|
||||
uint32 max_fragment_bytes = 4; // bound for tensor fragment size
|
||||
FlowControl initial_credit = 5; // receiver's starting flow-control window
|
||||
}
|
||||
|
||||
// Bounded prefill chunk. A prefill is split into ordered chunks each covering at
|
||||
// most max_prefill_tokens_per_chunk positions; final_chunk marks the last one.
|
||||
message PrefillChunk {
|
||||
MessageHeader header = 1;
|
||||
uint32 chunk_index = 2;
|
||||
uint32 chunk_count = 3; // 0 if unknown/streaming
|
||||
bool final_chunk = 4;
|
||||
TensorBundle activations = 5;
|
||||
}
|
||||
|
||||
// Small decode fast path: a single-position (or tiny) step with minimal framing.
|
||||
// Reuses the same header for isolation/ordering but expects one activation bundle.
|
||||
message DecodeStep {
|
||||
MessageHeader header = 1;
|
||||
TensorBundle activation = 2;
|
||||
}
|
||||
|
||||
// Explicit HTTP/2-independent flow-control grant. credits is the number of
|
||||
// additional messages the receiver is willing to accept; the byte/message caps
|
||||
// bound in-flight work for backpressure.
|
||||
message FlowControl {
|
||||
uint64 credits = 1;
|
||||
uint64 max_in_flight_bytes = 2;
|
||||
uint64 max_in_flight_messages = 3;
|
||||
}
|
||||
|
||||
// Release a session's resources (Hot KV State, sequence) cleanly.
|
||||
message ReleaseRequest {
|
||||
MessageHeader header = 1;
|
||||
string reason = 2;
|
||||
}
|
||||
|
||||
message ReleaseResponse {
|
||||
Status status = 1;
|
||||
CacheResult cache_result = 2;
|
||||
}
|
||||
|
||||
// Cancel in-flight work for a session/step.
|
||||
message CancelRequest {
|
||||
MessageHeader header = 1;
|
||||
string reason = 2;
|
||||
}
|
||||
|
||||
message CancelResponse {
|
||||
Status status = 1;
|
||||
}
|
||||
|
||||
// Client -> server frames on the ActivateSession stream.
|
||||
message SessionActivation {
|
||||
oneof payload {
|
||||
SessionOpen open = 1;
|
||||
PrefillChunk prefill = 2;
|
||||
DecodeStep decode = 3;
|
||||
ReleaseRequest release = 4;
|
||||
CancelRequest cancel = 5;
|
||||
FlowControl flow_control = 6;
|
||||
}
|
||||
}
|
||||
|
||||
// Computed boundary output for a step: the next Shard's input tensors plus the
|
||||
// cache result and integrity for what was produced.
|
||||
message ActivationResult {
|
||||
MessageHeader header = 1;
|
||||
TensorBundle outputs = 2;
|
||||
CacheResult cache_result = 3;
|
||||
Status status = 4;
|
||||
}
|
||||
|
||||
message SessionAccepted {
|
||||
MessageHeader header = 1;
|
||||
FlowControl granted_credit = 2;
|
||||
Status status = 3;
|
||||
}
|
||||
|
||||
// Server -> client frames on the ActivateSession stream.
|
||||
message SessionResponse {
|
||||
oneof payload {
|
||||
SessionAccepted accepted = 1;
|
||||
ActivationResult result = 2;
|
||||
FlowControl flow_control = 3;
|
||||
Status status = 4;
|
||||
ReleaseResponse release_ack = 5;
|
||||
CancelResponse cancel_ack = 6;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Capability and health (unary)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
message ResourceBudget {
|
||||
uint64 weight_bytes = 1;
|
||||
uint64 kv_bytes = 2;
|
||||
uint64 scratch_bytes = 3;
|
||||
uint32 max_concurrent_sessions = 4;
|
||||
}
|
||||
|
||||
message CapabilityRequest {
|
||||
SchemaVersion schema_version = 1;
|
||||
}
|
||||
|
||||
message CapabilityResponse {
|
||||
SchemaVersion schema_version = 1;
|
||||
repeated SchemaVersion supported_schema_versions = 2;
|
||||
repeated string supported_architectures = 3; // e.g. "llama", "qwen3"
|
||||
repeated string supported_quantizations = 4;
|
||||
ShardRange servable_range = 5;
|
||||
ResourceBudget budget = 6;
|
||||
repeated Compression supported_compression = 7;
|
||||
repeated ChecksumAlgorithm supported_checksums = 8;
|
||||
ArtifactFingerprint loaded_fingerprint = 9; // empty if no artifact loaded
|
||||
}
|
||||
|
||||
message HealthRequest {
|
||||
string route_session_id = 1; // optional; empty for node-wide health
|
||||
}
|
||||
|
||||
message HealthResponse {
|
||||
ServingStatus status = 1;
|
||||
uint32 active_sessions = 2;
|
||||
uint32 queued_requests = 3;
|
||||
double kv_pressure = 4; // 0.0..1.0 fraction of KV budget in use
|
||||
uint64 rss_bytes = 5;
|
||||
Status detail = 6;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Service
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
service ShardRuntime {
|
||||
// Admission/capability negotiation.
|
||||
rpc GetCapability(CapabilityRequest) returns (CapabilityResponse);
|
||||
|
||||
// Liveness/backpressure telemetry.
|
||||
rpc Health(HealthRequest) returns (HealthResponse);
|
||||
|
||||
// One long-lived bidirectional stream per Route Session Activation Seam.
|
||||
// Deadlines/cancellation use gRPC call semantics on direct transport and the
|
||||
// in-message equivalents on relay transport; flow control uses FlowControl
|
||||
// frames; errors are structured Status.
|
||||
rpc ActivateSession(stream SessionActivation) returns (stream SessionResponse);
|
||||
|
||||
// Clean resource release (also expressible in-stream as PHASE_RELEASE).
|
||||
rpc Release(ReleaseRequest) returns (ReleaseResponse);
|
||||
|
||||
// Cancellation (also expressible in-stream as PHASE_CANCEL).
|
||||
rpc Cancel(CancelRequest) returns (CancelResponse);
|
||||
}
|
||||
187
packages/node/native/scripts/build_llama_worker.sh
Normal file
187
packages/node/native/scripts/build_llama_worker.sh
Normal file
@@ -0,0 +1,187 @@
|
||||
#!/usr/bin/env bash
|
||||
# Apply the numbered llama.cpp patch stack and build the worker scaffold.
|
||||
#
|
||||
# Default flow:
|
||||
# 1. Fetch the pinned llama.cpp source into a build directory if needed.
|
||||
# 2. Verify the checkout matches the pinned commit.
|
||||
# 3. Check/apply the numbered patch stack from packages/node/native/llama/.
|
||||
# 4. Compile and build the standalone worker scaffold.
|
||||
# 5. Copy upstream LICENSE/AUTHORS notices into the staging directory.
|
||||
#
|
||||
# This script is intentionally model-free and does not contact any inference
|
||||
# endpoint. It is a source/build reproducibility check.
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
NATIVE_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
LLAMA_ROOT="${NATIVE_ROOT}/llama"
|
||||
UPSTREAM_COMMIT="$(tr -d '\n\r' < "${LLAMA_ROOT}/UPSTREAM_COMMIT")"
|
||||
UPSTREAM_REPOSITORY="$(tr -d '\n\r' < "${LLAMA_ROOT}/UPSTREAM_REPOSITORY")"
|
||||
PATCH_DIR="${LLAMA_ROOT}/patches"
|
||||
DEFAULT_SOURCE_DIR="${NATIVE_ROOT}/build/llama.cpp-src"
|
||||
DEFAULT_BUILD_DIR="${NATIVE_ROOT}/build/llama-worker"
|
||||
SOURCE_DIR="${DEFAULT_SOURCE_DIR}"
|
||||
BUILD_DIR="${DEFAULT_BUILD_DIR}"
|
||||
WORKTREE_DIR=""
|
||||
FETCH=1
|
||||
CXX_BIN="${CXX:-}"
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: build_llama_worker.sh [--source-dir PATH] [--build-dir PATH] [--no-fetch]
|
||||
|
||||
Builds the project-owned worker scaffold from a pinned llama.cpp checkout.
|
||||
EOF
|
||||
}
|
||||
|
||||
fail() {
|
||||
echo "error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--source-dir)
|
||||
SOURCE_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--build-dir)
|
||||
BUILD_DIR="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--no-fetch)
|
||||
FETCH=0
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
fail "unknown argument: $1"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ -n "${SOURCE_DIR}" ]] || fail "source dir is empty"
|
||||
[[ -n "${BUILD_DIR}" ]] || fail "build dir is empty"
|
||||
|
||||
checkout_commit() {
|
||||
if [[ -f "${SOURCE_DIR}/.meshnet-upstream-commit" ]]; then
|
||||
tr -d '\n\r' < "${SOURCE_DIR}/.meshnet-upstream-commit"
|
||||
return 0
|
||||
fi
|
||||
if git -C "${SOURCE_DIR}" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
||||
git -C "${SOURCE_DIR}" rev-parse HEAD
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
ensure_source() {
|
||||
if [[ -d "${SOURCE_DIR}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
if [[ "${FETCH}" -ne 1 ]]; then
|
||||
fail "source dir ${SOURCE_DIR} does not exist and --no-fetch was set"
|
||||
fi
|
||||
|
||||
mkdir -p "${SOURCE_DIR}"
|
||||
git clone --quiet "${UPSTREAM_REPOSITORY}" "${SOURCE_DIR}" || fail "unable to clone ${UPSTREAM_REPOSITORY}"
|
||||
git -C "${SOURCE_DIR}" checkout --quiet "${UPSTREAM_COMMIT}" || fail "unable to checkout ${UPSTREAM_COMMIT}"
|
||||
printf '%s\n' "${UPSTREAM_COMMIT}" > "${SOURCE_DIR}/.meshnet-upstream-commit"
|
||||
printf '%s\n' "${UPSTREAM_REPOSITORY}" > "${SOURCE_DIR}/.meshnet-upstream-repository"
|
||||
}
|
||||
|
||||
verify_assumptions() {
|
||||
local observed_commit
|
||||
observed_commit="$(checkout_commit)" || fail "source tree does not expose a commit pin; write ${SOURCE_DIR}/.meshnet-upstream-commit or use a git checkout"
|
||||
if [[ "${observed_commit}" != "${UPSTREAM_COMMIT}" ]]; then
|
||||
fail "llama.cpp pin mismatch: expected ${UPSTREAM_COMMIT}, got ${observed_commit}"
|
||||
fi
|
||||
|
||||
for required in LICENSE AUTHORS CMakeLists.txt; do
|
||||
[[ -e "${SOURCE_DIR}/${required}" ]] || fail "missing upstream assumption file: ${required}"
|
||||
done
|
||||
}
|
||||
|
||||
apply_patches() {
|
||||
shopt -s nullglob
|
||||
local patches=("${PATCH_DIR}"/*.patch)
|
||||
shopt -u nullglob
|
||||
if ((${#patches[@]} == 0)); then
|
||||
fail "no patch files found in ${PATCH_DIR}"
|
||||
fi
|
||||
|
||||
for patch in "${patches[@]}"; do
|
||||
git -C "${SOURCE_DIR}" apply --check "${patch}" || fail "patch check failed: $(basename "${patch}")"
|
||||
done
|
||||
for patch in "${patches[@]}"; do
|
||||
git -C "${SOURCE_DIR}" apply "${patch}" || fail "patch apply failed: $(basename "${patch}")"
|
||||
done
|
||||
}
|
||||
|
||||
build_worker() {
|
||||
rm -rf "${BUILD_DIR}"
|
||||
mkdir -p "${BUILD_DIR}"
|
||||
WORKTREE_DIR="${BUILD_DIR}/llama.cpp-worktree"
|
||||
rm -rf "${WORKTREE_DIR}"
|
||||
mkdir -p "${WORKTREE_DIR}"
|
||||
cp -a "${SOURCE_DIR}/." "${WORKTREE_DIR}/"
|
||||
if [[ -f "${SOURCE_DIR}/.meshnet-upstream-commit" ]]; then
|
||||
cp "${SOURCE_DIR}/.meshnet-upstream-commit" "${WORKTREE_DIR}/.meshnet-upstream-commit"
|
||||
fi
|
||||
if [[ -f "${SOURCE_DIR}/.meshnet-upstream-repository" ]]; then
|
||||
cp "${SOURCE_DIR}/.meshnet-upstream-repository" "${WORKTREE_DIR}/.meshnet-upstream-repository"
|
||||
fi
|
||||
|
||||
SOURCE_DIR="${WORKTREE_DIR}"
|
||||
apply_patches
|
||||
|
||||
local worker_dir="${SOURCE_DIR}/examples/meshnet-worker"
|
||||
cp "${LLAMA_ROOT}/templates/meshnet_worker.cpp" "${worker_dir}/meshnet_worker.cpp"
|
||||
cat > "${worker_dir}/version.h" <<EOF
|
||||
#pragma once
|
||||
|
||||
#define MESHNET_LLAMA_UPSTREAM_COMMIT "${UPSTREAM_COMMIT}"
|
||||
#define MESHNET_LLAMA_PATCHSET_VERSION "0001"
|
||||
EOF
|
||||
|
||||
local compiler=""
|
||||
if [[ -n "${CXX_BIN}" ]] && command -v "${CXX_BIN}" >/dev/null 2>&1; then
|
||||
compiler="${CXX_BIN}"
|
||||
elif command -v g++ >/dev/null 2>&1; then
|
||||
compiler="g++"
|
||||
elif command -v c++ >/dev/null 2>&1; then
|
||||
compiler="c++"
|
||||
elif command -v clang++ >/dev/null 2>&1; then
|
||||
compiler="clang++"
|
||||
else
|
||||
fail "no C++ compiler found (need g++, c++, clang++, or $CXX)"
|
||||
fi
|
||||
|
||||
"${compiler}" -std=c++17 -O2 -Wall -Wextra \
|
||||
-I "${worker_dir}" \
|
||||
-o "${BUILD_DIR}/meshnet_worker" \
|
||||
"${worker_dir}/meshnet_worker.cpp"
|
||||
}
|
||||
|
||||
stage_notices() {
|
||||
local notice_dir="${BUILD_DIR}/upstream-notices"
|
||||
mkdir -p "${notice_dir}"
|
||||
cp "${SOURCE_DIR}/LICENSE" "${notice_dir}/LICENSE"
|
||||
cp "${SOURCE_DIR}/AUTHORS" "${notice_dir}/AUTHORS"
|
||||
printf '%s\n' "${UPSTREAM_COMMIT}" > "${notice_dir}/UPSTREAM_COMMIT"
|
||||
printf '%s\n' "${UPSTREAM_REPOSITORY}" > "${notice_dir}/UPSTREAM_REPOSITORY"
|
||||
}
|
||||
|
||||
main() {
|
||||
ensure_source
|
||||
verify_assumptions
|
||||
build_worker
|
||||
stage_notices
|
||||
"${BUILD_DIR}/meshnet_worker" --smoke
|
||||
echo "build ok: ${BUILD_DIR}/meshnet_worker"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
43
packages/node/native/scripts/generate_cpp.sh
Normal file
43
packages/node/native/scripts/generate_cpp.sh
Normal file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env bash
|
||||
# Reproducibly generate the C++ Shard-protocol stubs from the schema.
|
||||
#
|
||||
# Produces message stubs (protoc --cpp_out) always, and gRPC C++ service stubs
|
||||
# (protoc --grpc_out with grpc_cpp_plugin) when the plugin is available. The
|
||||
# round-trip test needs only the message stubs; gRPC service stubs are for the
|
||||
# standalone C++ worker (DGR-008).
|
||||
#
|
||||
# Requirements: protoc (>=3.16). Optional: grpc_cpp_plugin for --grpc_out.
|
||||
#
|
||||
# Usage:
|
||||
# packages/node/native/scripts/generate_cpp.sh
|
||||
# Output: packages/node/native/build/cpp-gen/ (gitignored via build/).
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
NATIVE_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||
PROTO_DIR="${NATIVE_ROOT}/proto"
|
||||
PROTO_FILE="${PROTO_DIR}/shard_runtime.proto"
|
||||
OUT_DIR="${NATIVE_ROOT}/build/cpp-gen"
|
||||
|
||||
if ! command -v protoc >/dev/null 2>&1; then
|
||||
echo "error: protoc not found on PATH (install protobuf-compiler)." >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
mkdir -p "${OUT_DIR}"
|
||||
|
||||
echo "generating C++ message stubs -> ${OUT_DIR}"
|
||||
protoc --proto_path="${PROTO_DIR}" --cpp_out="${OUT_DIR}" "${PROTO_FILE}"
|
||||
|
||||
if command -v grpc_cpp_plugin >/dev/null 2>&1; then
|
||||
echo "generating C++ gRPC service stubs -> ${OUT_DIR}"
|
||||
protoc --proto_path="${PROTO_DIR}" \
|
||||
--grpc_out="${OUT_DIR}" \
|
||||
--plugin=protoc-gen-grpc="$(command -v grpc_cpp_plugin)" \
|
||||
"${PROTO_FILE}"
|
||||
else
|
||||
echo "note: grpc_cpp_plugin not found; skipped --grpc_out (message stubs only)." >&2
|
||||
fi
|
||||
|
||||
echo "done:"
|
||||
ls -1 "${OUT_DIR}"
|
||||
76
packages/node/native/scripts/generate_python.py
Normal file
76
packages/node/native/scripts/generate_python.py
Normal file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Reproducibly generate the Python Shard-protocol stubs from the schema.
|
||||
|
||||
This is the documented, no-manual-copy generation entry point referenced by
|
||||
``evidence/DGR-002/README.md``. It runs the pinned ``grpc_tools.protoc`` with the
|
||||
same flags ``meshnet_node.native_protocol.generate()`` uses on demand, but is
|
||||
kept self-contained (it does not import ``meshnet_node``) so it works regardless
|
||||
of which checkout the editable install points at.
|
||||
|
||||
Usage (from the project .venv):
|
||||
|
||||
python packages/node/native/scripts/generate_python.py
|
||||
|
||||
Output: ``packages/node/native/build/python/shard_runtime_pb2{,_grpc}.py``
|
||||
(``build/`` is gitignored).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
_NATIVE_ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
PROTO_DIR = _NATIVE_ROOT / "proto"
|
||||
PROTO_FILE = PROTO_DIR / "shard_runtime.proto"
|
||||
GEN_DIR = _NATIVE_ROOT / "build" / "python"
|
||||
|
||||
|
||||
def _well_known_include() -> str | None:
|
||||
try:
|
||||
import grpc_tools
|
||||
|
||||
candidate = pathlib.Path(grpc_tools.__file__).parent / "_proto"
|
||||
return str(candidate) if candidate.is_dir() else None
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not PROTO_FILE.exists():
|
||||
print(f"schema not found: {PROTO_FILE}", file=sys.stderr)
|
||||
return 2
|
||||
try:
|
||||
from grpc_tools import protoc
|
||||
except ImportError:
|
||||
print(
|
||||
"grpc_tools is required (pip install grpcio-tools); it is present in "
|
||||
"the project .venv.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 3
|
||||
|
||||
GEN_DIR.mkdir(parents=True, exist_ok=True)
|
||||
well_known = _well_known_include()
|
||||
args = [
|
||||
"grpc_tools.protoc",
|
||||
f"-I{PROTO_DIR}",
|
||||
*([f"-I{well_known}"] if well_known else []),
|
||||
f"--python_out={GEN_DIR}",
|
||||
f"--grpc_python_out={GEN_DIR}",
|
||||
PROTO_FILE.name,
|
||||
]
|
||||
rc = protoc.main(args)
|
||||
if rc != 0:
|
||||
print(f"grpc_tools.protoc exited with status {rc}", file=sys.stderr)
|
||||
return rc
|
||||
|
||||
print(f"generated Python stubs into: {GEN_DIR}")
|
||||
for name in ("shard_runtime_pb2.py", "shard_runtime_pb2_grpc.py"):
|
||||
target = GEN_DIR / name
|
||||
print(f" {name}: {'ok' if target.exists() else 'MISSING'}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
180
packages/node/native/tests/roundtrip_test.cpp
Normal file
180
packages/node/native/tests/roundtrip_test.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
// C++ round-trip and cross-language compatibility test for the Shard protocol.
|
||||
//
|
||||
// Modes (composable):
|
||||
// --selftest serialize a sample message, parse it back, verify fields.
|
||||
// --read <path> parse a fixture serialized by another language; verify the
|
||||
// known fields; tolerate unknown fields (forward compat).
|
||||
// --write <path> serialize the C++ sample so another language can parse it.
|
||||
//
|
||||
// Exit code 0 means every requested check passed. The Python test drives this
|
||||
// binary to prove Python<->C++ wire compatibility in both directions.
|
||||
|
||||
#include "shard_runtime.pb.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using namespace meshnet::shard::v1;
|
||||
|
||||
namespace {
|
||||
|
||||
bool Fail(const std::string& why) {
|
||||
std::cerr << "roundtrip_test: FAIL: " << why << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
SessionActivation MakeSample() {
|
||||
SessionActivation act;
|
||||
PrefillChunk* pre = act.mutable_prefill();
|
||||
|
||||
MessageHeader* h = pre->mutable_header();
|
||||
h->set_schema_version(SCHEMA_VERSION_1);
|
||||
h->set_work_id("w1");
|
||||
h->set_route_session_id("s1");
|
||||
h->set_route_epoch(3);
|
||||
h->set_phase(PHASE_PREFILL);
|
||||
h->set_idempotency_step(7);
|
||||
h->set_cache_expectation(CACHE_FRESH);
|
||||
h->set_compression(COMPRESSION_NONE);
|
||||
|
||||
ArtifactFingerprint* fp = h->mutable_fingerprint();
|
||||
fp->set_model_id("meta-llama/Llama-3.1-8B");
|
||||
fp->set_quantization("Q4_K_M");
|
||||
fp->set_runtime_recipe_fingerprint("recipe-abc");
|
||||
|
||||
ShardRange* sr = h->mutable_shard_range();
|
||||
sr->set_start_layer(0);
|
||||
sr->set_end_layer(16);
|
||||
sr->set_effective_start_layer(0);
|
||||
sr->set_owns_embedding(true);
|
||||
|
||||
Position* pos = h->mutable_position();
|
||||
pos->set_start_position(0);
|
||||
pos->set_token_count(5);
|
||||
pos->set_sequence_length(5);
|
||||
|
||||
pre->set_chunk_index(0);
|
||||
pre->set_chunk_count(1);
|
||||
pre->set_final_chunk(true);
|
||||
|
||||
TensorBundle* bundle = pre->mutable_activations();
|
||||
bundle->set_bundle_version(1);
|
||||
NamedTensor* t = bundle->add_tensors();
|
||||
t->set_name("hidden");
|
||||
t->add_shape(1);
|
||||
t->add_shape(4096);
|
||||
t->set_dtype(DTYPE_F16);
|
||||
t->set_byte_order(BYTE_ORDER_LITTLE_ENDIAN);
|
||||
t->set_total_byte_length(8);
|
||||
t->set_compression(COMPRESSION_NONE);
|
||||
TensorFragment* frag = t->add_fragments();
|
||||
frag->set_fragment_index(0);
|
||||
frag->set_fragment_count(1);
|
||||
frag->set_byte_offset(0);
|
||||
frag->set_data(std::string("\x01\x02\x03\x04\x05\x06\x07\x08", 8));
|
||||
|
||||
return act;
|
||||
}
|
||||
|
||||
bool CheckSample(const SessionActivation& act) {
|
||||
if (act.payload_case() != SessionActivation::kPrefill)
|
||||
return Fail("payload is not prefill");
|
||||
const PrefillChunk& pre = act.prefill();
|
||||
const MessageHeader& h = pre.header();
|
||||
if (h.schema_version() != SCHEMA_VERSION_1) return Fail("schema_version");
|
||||
if (h.work_id() != "w1") return Fail("work_id");
|
||||
if (h.route_session_id() != "s1") return Fail("route_session_id");
|
||||
if (h.route_epoch() != 3) return Fail("route_epoch");
|
||||
if (h.phase() != PHASE_PREFILL) return Fail("phase");
|
||||
if (h.idempotency_step() != 7) return Fail("idempotency_step");
|
||||
if (h.fingerprint().model_id() != "meta-llama/Llama-3.1-8B")
|
||||
return Fail("model_id");
|
||||
if (h.fingerprint().quantization() != "Q4_K_M") return Fail("quantization");
|
||||
if (h.shard_range().end_layer() != 16) return Fail("end_layer");
|
||||
if (!h.shard_range().owns_embedding()) return Fail("owns_embedding");
|
||||
if (h.position().token_count() != 5) return Fail("token_count");
|
||||
if (!pre.final_chunk()) return Fail("final_chunk");
|
||||
if (pre.activations().tensors_size() != 1) return Fail("tensors_size");
|
||||
const NamedTensor& t = pre.activations().tensors(0);
|
||||
if (t.name() != "hidden") return Fail("tensor name");
|
||||
if (t.dtype() != DTYPE_F16) return Fail("dtype");
|
||||
if (t.byte_order() != BYTE_ORDER_LITTLE_ENDIAN) return Fail("byte_order");
|
||||
if (t.shape_size() != 2 || t.shape(1) != 4096) return Fail("shape");
|
||||
if (t.fragments_size() != 1) return Fail("fragments_size");
|
||||
if (t.fragments(0).data().size() != 8) return Fail("fragment data length");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadFile(const std::string& path, std::string* out) {
|
||||
std::ifstream in(path, std::ios::binary);
|
||||
if (!in) return false;
|
||||
std::ostringstream ss;
|
||||
ss << in.rdbuf();
|
||||
*out = ss.str();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteFile(const std::string& path, const std::string& data) {
|
||||
std::ofstream out(path, std::ios::binary);
|
||||
if (!out) return false;
|
||||
out.write(data.data(), static_cast<std::streamsize>(data.size()));
|
||||
return static_cast<bool>(out);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
GOOGLE_PROTOBUF_VERIFY_VERSION;
|
||||
|
||||
std::string read_path;
|
||||
std::string write_path;
|
||||
bool selftest = (argc == 1);
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
std::string arg = argv[i];
|
||||
if (arg == "--selftest") {
|
||||
selftest = true;
|
||||
} else if (arg == "--read" && i + 1 < argc) {
|
||||
read_path = argv[++i];
|
||||
} else if (arg == "--write" && i + 1 < argc) {
|
||||
write_path = argv[++i];
|
||||
} else {
|
||||
std::cerr << "unknown/incomplete arg: " << arg << std::endl;
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (selftest) {
|
||||
SessionActivation sample = MakeSample();
|
||||
std::string bytes;
|
||||
if (!sample.SerializeToString(&bytes)) return Fail("serialize"), 1;
|
||||
SessionActivation parsed;
|
||||
if (!parsed.ParseFromString(bytes)) return Fail("parse"), 1;
|
||||
if (!CheckSample(parsed)) return 1;
|
||||
std::cout << "selftest ok (" << bytes.size() << " bytes)" << std::endl;
|
||||
}
|
||||
|
||||
if (!read_path.empty()) {
|
||||
std::string bytes;
|
||||
if (!ReadFile(read_path, &bytes)) return Fail("cannot read fixture"), 1;
|
||||
SessionActivation parsed;
|
||||
// ParseFromString tolerates and preserves unknown fields (forward compat).
|
||||
if (!parsed.ParseFromString(bytes)) return Fail("parse fixture"), 1;
|
||||
if (!CheckSample(parsed)) return 1;
|
||||
std::cout << "read ok (" << bytes.size() << " bytes)" << std::endl;
|
||||
}
|
||||
|
||||
if (!write_path.empty()) {
|
||||
SessionActivation sample = MakeSample();
|
||||
std::string bytes;
|
||||
if (!sample.SerializeToString(&bytes)) return Fail("serialize for write"), 1;
|
||||
if (!WriteFile(write_path, bytes)) return Fail("cannot write output"), 1;
|
||||
std::cout << "write ok (" << bytes.size() << " bytes)" << std::endl;
|
||||
}
|
||||
|
||||
google::protobuf::ShutdownProtobufLibrary();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user