Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions managed-inference/images/llama-cpp/image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ spec:
qualification:
required: true
execution: enabled
requestGuard: required
profile: dgx-spark-gb10-single
recipeRef: llama-cpp.nemotron-3-nano-30b-a3b.spark-single.v1
platform: linux/arm64
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,13 @@ spec:
value: f16
speculativeDecoding: disabled
limits:
maxRequestBodyBytes: 1048576
maxRequestHeaderBytes: 32768
maxOutputTokens: 4096
requestTimeoutSeconds: 900
shutdownTimeoutSeconds: 25
requestGuard:
upstreamPort: 8082

readiness:
contractRef: llama-cpp.server-readiness/v1
Expand Down
49 changes: 46 additions & 3 deletions managed-inference/schemas/recipe.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -482,13 +482,54 @@
"limits": {
"type": "object",
"required": [
"requestTimeoutSeconds"
"maxRequestBodyBytes",
"maxRequestHeaderBytes",
"maxOutputTokens",
"requestTimeoutSeconds",
"shutdownTimeoutSeconds"
],
"properties": {
"maxRequestBodyBytes": {
"type": "integer",
"minimum": 1,
"maximum": 67108864
},
"maxRequestHeaderBytes": {
"type": "integer",
"minimum": 1,
"maximum": 1048576
},
"maxOutputTokens": {
"type": "integer",
"minimum": 1,
"maximum": 1048576
},
"requestTimeoutSeconds": {
"type": "integer",
"minimum": 1,
"maximum": 86400
},
"shutdownTimeoutSeconds": {
"type": "integer",
"minimum": 1,
"maximum": 86400
}
},
"additionalProperties": false
},
"requestGuard": {
"type": "object",
"required": [
"upstreamPort"
],
"properties": {
"upstreamPort": {
"type": "integer",
"minimum": 1,
"maximum": 65535,
"not": {
"const": 8081
}
}
},
"additionalProperties": false
Expand Down Expand Up @@ -1239,7 +1280,8 @@
"flashAttention",
"kvCache",
"speculativeDecoding",
"limits"
"limits",
"requestGuard"
],
"properties": {
"protocol": {},
Expand All @@ -1264,7 +1306,8 @@
"flashAttention": {},
"kvCache": {},
"speculativeDecoding": {},
"limits": {}
"limits": {},
"requestGuard": {}
},
"propertyNames": {
"not": {
Expand Down
14 changes: 14 additions & 0 deletions scripts/checks/export-llama-cpp-image-config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type ServerImageManifest = {
probes?: unknown;
profile?: unknown;
recipeRef?: unknown;
requestGuard?: unknown;
required?: unknown;
runner?: unknown;
};
Expand Down Expand Up @@ -136,8 +137,13 @@ type LlamaCppQualificationRecipe = {
kvCache: { key: string; value: string };
speculativeDecoding: string;
limits: {
maxRequestBodyBytes: number;
maxRequestHeaderBytes: number;
maxOutputTokens: number;
requestTimeoutSeconds: number;
shutdownTimeoutSeconds: number;
};
requestGuard: { upstreamPort: number };
};
readiness: {
contractRef: string;
Expand Down Expand Up @@ -381,6 +387,7 @@ export function loadLlamaCppImageConfig(
"probes",
"profile",
"recipeRef",
"requestGuard",
"required",
"runner",
]);
Expand Down Expand Up @@ -426,6 +433,11 @@ export function loadLlamaCppImageConfig(
"qualification recipe reference",
/^llama-cpp\.nemotron-3-nano-30b-a3b\.spark-single\.v1$/u,
);
const qualificationRequestGuard = requiredString(
qualification?.requestGuard,
"qualification request guard",
/^required$/u,
);
const qualificationModel = qualification?.model as
| { digest?: unknown; hostPath?: unknown; id?: unknown }
| undefined;
Expand Down Expand Up @@ -588,6 +600,7 @@ export function loadLlamaCppImageConfig(
probes: qualification?.probes,
profile: qualification?.profile,
recipeRef: qualificationRecipeRef,
requestGuard: qualificationRequestGuard,
required: qualification?.required,
runner: qualificationRunner,
};
Expand Down Expand Up @@ -725,6 +738,7 @@ export function loadLlamaCppImageConfig(
agentQualification,
probeBounds: qualification?.probeBounds,
probes: qualification?.probes,
requestGuard: qualificationRequestGuard,
},
recipe: {
capabilities: recipe.spec.capabilities,
Expand Down
69 changes: 67 additions & 2 deletions scripts/checks/llama-cpp-dgx-spark-qualification-contract.mts
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ export type LlamaCppDgxSparkQualificationPlan = {
readonly probes: typeof LLAMA_CPP_DGX_SPARK_QUALIFICATION_PROBES;
readonly profile: typeof LLAMA_CPP_DGX_SPARK_QUALIFICATION_PROFILE;
readonly recipeRef: typeof LLAMA_CPP_DGX_SPARK_QUALIFICATION_RECIPE;
readonly requestGuard: "required";
readonly required: true;
readonly runner: string | null;
};
Expand Down Expand Up @@ -196,6 +197,7 @@ export type LlamaCppDgxSparkExecutionPlan = {
readonly agentQualification: LlamaCppDgxSparkAgentQualificationPlan;
readonly probeBounds: LlamaCppDgxSparkQualificationPlan["probeBounds"];
readonly probes: typeof LLAMA_CPP_DGX_SPARK_QUALIFICATION_PROBES;
readonly requestGuard: "required";
};
readonly recipe: {
readonly capabilities: {
Expand Down Expand Up @@ -274,7 +276,14 @@ export type LlamaCppDgxSparkExecutionPlan = {
readonly value: "f16" | "q8_0" | "q4_0";
};
readonly limits: {
readonly maxRequestBodyBytes: number;
readonly maxRequestHeaderBytes: number;
readonly maxOutputTokens: number;
readonly requestTimeoutSeconds: number;
readonly shutdownTimeoutSeconds: number;
};
readonly requestGuard: {
readonly upstreamPort: number;
};
readonly microBatchSize: number;
readonly port: 8081;
Expand Down Expand Up @@ -915,6 +924,7 @@ export function parseLlamaCppDgxSparkQualificationPlan(
"probes",
"profile",
"recipeRef",
"requestGuard",
"required",
"runner",
],
Expand All @@ -933,6 +943,7 @@ export function parseLlamaCppDgxSparkQualificationPlan(
plan.required !== true ||
plan.profile !== LLAMA_CPP_DGX_SPARK_QUALIFICATION_PROFILE ||
plan.recipeRef !== LLAMA_CPP_DGX_SPARK_QUALIFICATION_RECIPE ||
plan.requestGuard !== "required" ||
plan.platform !== LLAMA_CPP_DGX_SPARK_QUALIFICATION_PLATFORM ||
gpu.vendor !== "nvidia" ||
gpu.fullOffload !== true ||
Expand All @@ -957,6 +968,7 @@ export function parseLlamaCppDgxSparkQualificationPlan(
probes: LLAMA_CPP_DGX_SPARK_QUALIFICATION_PROBES,
profile: LLAMA_CPP_DGX_SPARK_QUALIFICATION_PROFILE,
recipeRef: LLAMA_CPP_DGX_SPARK_QUALIFICATION_RECIPE,
requestGuard: "required",
required: true,
runner: infrastructure.runner,
};
Expand All @@ -979,7 +991,7 @@ export function parseLlamaCppDgxSparkExecutionPlan(
const qualification = record(plan.qualification, "compiled protocol qualification");
requireExactKeys(
qualification,
["agentQualification", "probeBounds", "probes"],
["agentQualification", "probeBounds", "probes", "requestGuard"],
"compiled protocol qualification",
);
if (
Expand All @@ -988,6 +1000,9 @@ export function parseLlamaCppDgxSparkExecutionPlan(
) {
throw new Error("compiled llama.cpp DGX Spark protocol probes are invalid");
}
if (qualification.requestGuard !== "required") {
throw new Error("compiled llama.cpp DGX Spark request-guard activation is invalid");
}
const protocolProbeBounds = parseProtocolProbeBounds(qualification.probeBounds);
const agentQualification = parseAgentQualification(qualification.agentQualification);

Expand Down Expand Up @@ -1245,6 +1260,7 @@ export function parseLlamaCppDgxSparkExecutionPlan(
"microBatchSize",
"port",
"protocol",
"requestGuard",
"slots",
"speculativeDecoding",
],
Expand All @@ -1267,13 +1283,55 @@ export function parseLlamaCppDgxSparkExecutionPlan(
requireExactKeys(kvCache, ["key", "value"], "compiled qualification KV cache");
const allowedKvTypes = new Set(["f16", "q8_0", "q4_0"]);
const limits = record(serve.limits, "compiled qualification request limits");
requireExactKeys(limits, ["requestTimeoutSeconds"], "compiled qualification request limits");
requireExactKeys(
limits,
[
"maxOutputTokens",
"maxRequestBodyBytes",
"maxRequestHeaderBytes",
"requestTimeoutSeconds",
"shutdownTimeoutSeconds",
],
"compiled qualification request limits",
);
const maxRequestBodyBytes = boundedInteger(
limits.maxRequestBodyBytes,
"compiled qualification maximum request body bytes",
1,
64 * 1024 * 1024,
);
const maxRequestHeaderBytes = boundedInteger(
limits.maxRequestHeaderBytes,
"compiled qualification maximum request header bytes",
1,
1024 * 1024,
);
const maxOutputTokens = boundedInteger(
limits.maxOutputTokens,
"compiled qualification maximum output tokens",
1,
contextSize,
);
const requestTimeoutSeconds = boundedInteger(
limits.requestTimeoutSeconds,
"compiled qualification request timeout",
1,
3600,
);
const shutdownTimeoutSeconds = boundedInteger(
limits.shutdownTimeoutSeconds,
"compiled qualification shutdown timeout",
1,
3600,
);
const requestGuard = record(serve.requestGuard, "compiled qualification request guard");
requireExactKeys(requestGuard, ["upstreamPort"], "compiled qualification request guard");
const upstreamPort = boundedInteger(
requestGuard.upstreamPort,
"compiled qualification request-guard upstream port",
1,
65535,
);
if (
serve.protocol !== "openai-completions" ||
serve.authentication !== "bearer" ||
Expand All @@ -1283,6 +1341,7 @@ export function parseLlamaCppDgxSparkExecutionPlan(
serve.idleSleepSeconds !== -1 ||
serve.flashAttention !== "enabled" ||
serve.speculativeDecoding !== "disabled" ||
upstreamPort === serve.port ||
typeof kvCache.key !== "string" ||
!allowedKvTypes.has(kvCache.key) ||
typeof kvCache.value !== "string" ||
Expand Down Expand Up @@ -1347,6 +1406,7 @@ export function parseLlamaCppDgxSparkExecutionPlan(
agentQualification,
probeBounds: protocolProbeBounds,
probes: LLAMA_CPP_DGX_SPARK_QUALIFICATION_PROBES,
requestGuard: "required",
},
recipe: {
capabilities: {
Expand Down Expand Up @@ -1419,8 +1479,13 @@ export function parseLlamaCppDgxSparkExecutionPlan(
},
speculativeDecoding: "disabled",
limits: {
maxRequestBodyBytes,
maxRequestHeaderBytes,
maxOutputTokens,
requestTimeoutSeconds,
shutdownTimeoutSeconds,
},
requestGuard: { upstreamPort },
},
server: {
technology: "llama.cpp",
Expand Down
7 changes: 5 additions & 2 deletions scripts/checks/run-llama-cpp-dgx-spark-qualification.mts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import path from "node:path";
import { fileURLToPath } from "node:url";

import {
buildLlamaCppHostLocalDockerArgv,
buildLlamaCppRequestGuardDockerArgv,
type VerifiedLocalModelArtifact,
} from "../../src/lib/inference/llama-cpp/host-local-runtime.ts";
import {
Expand Down Expand Up @@ -332,7 +332,10 @@ export function buildServerContainerArgv(
hostPort?: number;
},
): string[] {
return buildLlamaCppHostLocalDockerArgv(plan.recipe, {
if (plan.qualification.requestGuard !== "required") {
throw new Error("llama.cpp qualification requires the declarative request guard");
}
return buildLlamaCppRequestGuardDockerArgv(plan.recipe, {
apiKeyHostPath: options.apiKeyHostPath,
containerName: options.containerName,
imageReference: options.imageReference,
Expand Down
Loading
Loading