@huggingface/tasks 0.20.4 → 0.20.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"local-apps.d.ts","sourceRoot":"","sources":["../../src/local-apps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,YAAY,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,kBAAkB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAClD,GAAG,CACD;IACA;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC;CACtD,GACD;IACA;;;;OAIG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,EAAE,GAAG,eAAe,GAAG,eAAe,EAAE,CAAC;CACzG,CACH,CAAC;AAsBF,iBAAS,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE7C;AAED,iBAAS,mBAAmB,CAAC,KAAK,EAAE,SAAS,WAE5C;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAU9C;AAED,iBAAS,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE3D;AAUD,iBAAS,cAAc,CAAC,KAAK,EAAE,SAAS,WAEvC;AAmZD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU;;;;;;yBAjZS,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAiDzC,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAmF3D,SAAS,KAAG,eAAe,EAAE;;;;;;oCAuS3B,SAAS;yBAjPT,SAAS,KAAG,eAAe,EAAE;;;;;;;yBAoF9B,SAAS,KAAG,eAAe,EAAE;;;;;;;yBA7B/B,SAAS,KAAG,eAAe,EAAE;;;;;;;;;;;;;;yBApIzB,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9CjD,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAIpC,SAAS,KAAG,eAAe,EAAE;;;;;;;yBAmRnB,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAM9C,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBA3CtD,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;CA0RtC,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"local-apps.d.ts","sourceRoot":"","sources":["../../src/local-apps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,YAAY,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,kBAAkB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAClD,GAAG,CACD;IACA;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC;CACtD,GACD;IACA;;;;OAIG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,EAAE,GAAG,eAAe,GAAG,eAAe,EAAE,CAAC;CACzG,CACH,CAAC;AAsBF,iBAAS,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE7C;AAED,iBAAS,mBAAmB,CAAC,KAAK,EAAE,SAAS,WAE5C;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAU9C;AAED,iBAAS,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE3D;AA0BD,iBAAS,cAAc,CAAC,KAAK,EAAE,SAAS,WAEvC;AA6ZD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU;;;;;;yBA3ZS,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAiDzC,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAmF3D,SAAS,KAAG,eAAe,EAAE;;;;;;oCAiT3B,SAAS;yBA3PT,SAAS,KAAG,eAAe,EAAE;;;;;;;yBAoF9B,SAAS,KAAG,eAAe,EAAE;;;;;;;yBA7B/B,SAAS,KAAG,eAAe,EAAE;;;;;;;;;;;;;;yBApIzB,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9CjD,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAIpC,SAAS,KAAG,eAAe,EAAE;;;;;;;yBA6RnB,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAM9C,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBArDtD,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;CAuStC,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC"}
@@ -43,6 +43,20 @@ function isAmdRyzenModel(model) {
43
43
  function isMlxModel(model) {
44
44
  return model.tags.includes("mlx");
45
45
  }
46
+ /**
47
+ * Returns the model's chat template string, coalescing across sources:
48
+ * GGUF metadata > chat_template_jinja file > tokenizer_config.json
49
+ */
50
+ function getChatTemplate(model) {
51
+ const ct = model.gguf?.chat_template ?? model.config?.chat_template_jinja ?? model.config?.tokenizer_config?.chat_template;
52
+ if (typeof ct === "string") {
53
+ return ct;
54
+ }
55
+ if (Array.isArray(ct)) {
56
+ return ct[0]?.template;
57
+ }
58
+ return undefined;
59
+ }
46
60
  function isUnslothModel(model) {
47
61
  return model.tags.includes("unsloth") || isLlamaCppGgufModel(model);
48
62
  }
@@ -338,24 +352,33 @@ const snippetMlxLm = (model) => {
338
352
  ];
339
353
  };
340
354
  const snippetPi = (model, filepath) => {
341
- const quantTag = getQuantTag(filepath);
342
355
  const modelName = model.id.split("/").pop() ?? model.id;
356
+ const isMLX = isMlxModel(model);
357
+ // Step 1: Server — differs by backend
358
+ const serverStep = isMLX
359
+ ? {
360
+ title: "Start the MLX server",
361
+ setup: "# Install MLX LM:\nuv tool install mlx-lm",
362
+ content: `# Start a local OpenAI-compatible server:\nmlx_lm.server --model "${model.id}"`,
363
+ }
364
+ : {
365
+ title: "Start the llama.cpp server",
366
+ setup: "# Install llama.cpp:\nbrew install llama.cpp",
367
+ content: `# Start a local OpenAI-compatible server:\nllama-server -hf ${model.id}${getQuantTag(filepath)} --jinja`,
368
+ };
369
+ // Step 2: Pi config — port and provider name differ
343
370
  const modelsJson = JSON.stringify({
344
371
  providers: {
345
- "llama-cpp": {
372
+ [isMLX ? "mlx-lm" : "llama-cpp"]: {
346
373
  baseUrl: "http://localhost:8080/v1",
347
374
  api: "openai-completions",
348
375
  apiKey: "none",
349
- models: [{ id: modelName }],
376
+ models: [{ id: isMLX ? model.id : modelName }],
350
377
  },
351
378
  },
352
379
  }, null, 2);
353
380
  return [
354
- {
355
- title: "Start the llama.cpp server",
356
- setup: "# Install llama.cpp:\nbrew install llama.cpp",
357
- content: `# Start a local OpenAI-compatible server:\nllama-server -hf ${model.id}${quantTag} --jinja`,
358
- },
381
+ serverStep,
359
382
  {
360
383
  title: "Configure the model in Pi",
361
384
  setup: "# Install Pi:\nnpm install -g @mariozechner/pi-coding-agent",
@@ -363,7 +386,7 @@ const snippetPi = (model, filepath) => {
363
386
  },
364
387
  {
365
388
  title: "Run Pi",
366
- content: `# Start Pi in your project directory:\npi`,
389
+ content: "# Start Pi in your project directory:\npi",
367
390
  },
368
391
  ];
369
392
  };
@@ -604,7 +627,9 @@ exports.LOCAL_APPS = {
604
627
  prettyLabel: "Pi",
605
628
  docsUrl: "https://github.com/badlogic/pi-mono",
606
629
  mainTask: "text-generation",
607
- displayOnModelPage: (model) => isLlamaCppGgufModel(model) && !!model.gguf?.chat_template?.includes("tools"),
630
+ displayOnModelPage: (model) => (isLlamaCppGgufModel(model) || isMlxModel(model)) &&
631
+ model.pipeline_tag === "text-generation" &&
632
+ !!getChatTemplate(model)?.includes("tools"),
608
633
  snippet: snippetPi,
609
634
  },
610
635
  };
@@ -126,6 +126,27 @@ curl -X POST "http://localhost:8000/v1/chat/completions" \\
126
126
  (0, vitest_1.expect)(snippet[1].content).toContain(`"id": "Llama-3.2-3B-Instruct-GGUF"`);
127
127
  (0, vitest_1.expect)(snippet[2].content).toContain("pi");
128
128
  });
129
+ (0, vitest_1.it)("pi - mlx", async () => {
130
+ const { snippet: snippetFunc } = local_apps_js_1.LOCAL_APPS["pi"];
131
+ const model = {
132
+ id: "mlx-community/Llama-3.2-3B-Instruct-mlx",
133
+ tags: ["mlx", "conversational"],
134
+ pipeline_tag: "text-generation",
135
+ config: {
136
+ tokenizer_config: {
137
+ chat_template: "{% if tools %}...{% endif %}",
138
+ },
139
+ },
140
+ inference: "",
141
+ };
142
+ const snippet = snippetFunc(model);
143
+ (0, vitest_1.expect)(snippet[0].setup).toContain("uv tool install mlx-lm");
144
+ (0, vitest_1.expect)(snippet[0].content).toContain('mlx_lm.server --model "mlx-community/Llama-3.2-3B-Instruct-mlx"');
145
+ (0, vitest_1.expect)(snippet[1].setup).toContain("npm install -g @mariozechner/pi-coding-agent");
146
+ (0, vitest_1.expect)(snippet[1].content).toContain('"baseUrl": "http://localhost:8080/v1"');
147
+ (0, vitest_1.expect)(snippet[1].content).toContain('"id": "mlx-community/Llama-3.2-3B-Instruct-mlx"');
148
+ (0, vitest_1.expect)(snippet[2].content).toContain("pi");
149
+ });
129
150
  (0, vitest_1.it)("docker model runner", async () => {
130
151
  const { snippet: snippetFunc } = local_apps_js_1.LOCAL_APPS["docker-model-runner"];
131
152
  const model = {
@@ -1 +1 @@
1
- {"version":3,"file":"local-apps.d.ts","sourceRoot":"","sources":["../../src/local-apps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,YAAY,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,kBAAkB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAClD,GAAG,CACD;IACA;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC;CACtD,GACD;IACA;;;;OAIG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,EAAE,GAAG,eAAe,GAAG,eAAe,EAAE,CAAC;CACzG,CACH,CAAC;AAsBF,iBAAS,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE7C;AAED,iBAAS,mBAAmB,CAAC,KAAK,EAAE,SAAS,WAE5C;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAU9C;AAED,iBAAS,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE3D;AAUD,iBAAS,cAAc,CAAC,KAAK,EAAE,SAAS,WAEvC;AAmZD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU;;;;;;yBAjZS,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAiDzC,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAmF3D,SAAS,KAAG,eAAe,EAAE;;;;;;oCAuS3B,SAAS;yBAjPT,SAAS,KAAG,eAAe,EAAE;;;;;;;yBAoF9B,SAAS,KAAG,eAAe,EAAE;;;;;;;yBA7B/B,SAAS,KAAG,eAAe,EAAE;;;;;;;;;;;;;;yBApIzB,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9CjD,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAIpC,SAAS,KAAG,eAAe,EAAE;;;;;;;yBAmRnB,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAM9C,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBA3CtD,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;CA0RtC,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"local-apps.d.ts","sourceRoot":"","sources":["../../src/local-apps.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAKnD,MAAM,WAAW,eAAe;IAC/B;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG;IACtB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,QAAQ,EAAE,YAAY,CAAC;IACvB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,kBAAkB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,OAAO,CAAC;CAClD,GAAG,CACD;IACA;;OAEG;IACH,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,GAAG,CAAC;CACtD,GACD;IACA;;;;OAIG;IACH,OAAO,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,GAAG,MAAM,EAAE,GAAG,eAAe,GAAG,eAAe,EAAE,CAAC;CACzG,CACH,CAAC;AAsBF,iBAAS,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE7C;AAED,iBAAS,mBAAmB,CAAC,KAAK,EAAE,SAAS,WAE5C;AAED,iBAAS,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAU9C;AAED,iBAAS,wBAAwB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAE3D;AA0BD,iBAAS,cAAc,CAAC,KAAK,EAAE,SAAS,WAEvC;AA6ZD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU;;;;;;yBA3ZS,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAiDzC,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBAmF3D,SAAS,KAAG,eAAe,EAAE;;;;;;oCAiT3B,SAAS;yBA3PT,SAAS,KAAG,eAAe,EAAE;;;;;;;yBAoF9B,SAAS,KAAG,eAAe,EAAE;;;;;;;yBA7B/B,SAAS,KAAG,eAAe,EAAE;;;;;;;;;;;;;;yBApIzB,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBA9CjD,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAIpC,SAAS,KAAG,eAAe,EAAE;;;;;;;yBA6RnB,SAAS,aAAa,MAAM,KAAG,MAAM;;;;;;;yBAM9C,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;;;;;;yBArDtD,SAAS,aAAa,MAAM,KAAG,eAAe,EAAE;;CAuStC,CAAC;AAErC,MAAM,MAAM,WAAW,GAAG,MAAM,OAAO,UAAU,CAAC"}
@@ -40,6 +40,20 @@ function isAmdRyzenModel(model) {
40
40
  function isMlxModel(model) {
41
41
  return model.tags.includes("mlx");
42
42
  }
43
+ /**
44
+ * Returns the model's chat template string, coalescing across sources:
45
+ * GGUF metadata > chat_template_jinja file > tokenizer_config.json
46
+ */
47
+ function getChatTemplate(model) {
48
+ const ct = model.gguf?.chat_template ?? model.config?.chat_template_jinja ?? model.config?.tokenizer_config?.chat_template;
49
+ if (typeof ct === "string") {
50
+ return ct;
51
+ }
52
+ if (Array.isArray(ct)) {
53
+ return ct[0]?.template;
54
+ }
55
+ return undefined;
56
+ }
43
57
  function isUnslothModel(model) {
44
58
  return model.tags.includes("unsloth") || isLlamaCppGgufModel(model);
45
59
  }
@@ -335,24 +349,33 @@ const snippetMlxLm = (model) => {
335
349
  ];
336
350
  };
337
351
  const snippetPi = (model, filepath) => {
338
- const quantTag = getQuantTag(filepath);
339
352
  const modelName = model.id.split("/").pop() ?? model.id;
353
+ const isMLX = isMlxModel(model);
354
+ // Step 1: Server — differs by backend
355
+ const serverStep = isMLX
356
+ ? {
357
+ title: "Start the MLX server",
358
+ setup: "# Install MLX LM:\nuv tool install mlx-lm",
359
+ content: `# Start a local OpenAI-compatible server:\nmlx_lm.server --model "${model.id}"`,
360
+ }
361
+ : {
362
+ title: "Start the llama.cpp server",
363
+ setup: "# Install llama.cpp:\nbrew install llama.cpp",
364
+ content: `# Start a local OpenAI-compatible server:\nllama-server -hf ${model.id}${getQuantTag(filepath)} --jinja`,
365
+ };
366
+ // Step 2: Pi config — port and provider name differ
340
367
  const modelsJson = JSON.stringify({
341
368
  providers: {
342
- "llama-cpp": {
369
+ [isMLX ? "mlx-lm" : "llama-cpp"]: {
343
370
  baseUrl: "http://localhost:8080/v1",
344
371
  api: "openai-completions",
345
372
  apiKey: "none",
346
- models: [{ id: modelName }],
373
+ models: [{ id: isMLX ? model.id : modelName }],
347
374
  },
348
375
  },
349
376
  }, null, 2);
350
377
  return [
351
- {
352
- title: "Start the llama.cpp server",
353
- setup: "# Install llama.cpp:\nbrew install llama.cpp",
354
- content: `# Start a local OpenAI-compatible server:\nllama-server -hf ${model.id}${quantTag} --jinja`,
355
- },
378
+ serverStep,
356
379
  {
357
380
  title: "Configure the model in Pi",
358
381
  setup: "# Install Pi:\nnpm install -g @mariozechner/pi-coding-agent",
@@ -360,7 +383,7 @@ const snippetPi = (model, filepath) => {
360
383
  },
361
384
  {
362
385
  title: "Run Pi",
363
- content: `# Start Pi in your project directory:\npi`,
386
+ content: "# Start Pi in your project directory:\npi",
364
387
  },
365
388
  ];
366
389
  };
@@ -601,7 +624,9 @@ export const LOCAL_APPS = {
601
624
  prettyLabel: "Pi",
602
625
  docsUrl: "https://github.com/badlogic/pi-mono",
603
626
  mainTask: "text-generation",
604
- displayOnModelPage: (model) => isLlamaCppGgufModel(model) && !!model.gguf?.chat_template?.includes("tools"),
627
+ displayOnModelPage: (model) => (isLlamaCppGgufModel(model) || isMlxModel(model)) &&
628
+ model.pipeline_tag === "text-generation" &&
629
+ !!getChatTemplate(model)?.includes("tools"),
605
630
  snippet: snippetPi,
606
631
  },
607
632
  };
@@ -124,6 +124,27 @@ curl -X POST "http://localhost:8000/v1/chat/completions" \\
124
124
  expect(snippet[1].content).toContain(`"id": "Llama-3.2-3B-Instruct-GGUF"`);
125
125
  expect(snippet[2].content).toContain("pi");
126
126
  });
127
+ it("pi - mlx", async () => {
128
+ const { snippet: snippetFunc } = LOCAL_APPS["pi"];
129
+ const model = {
130
+ id: "mlx-community/Llama-3.2-3B-Instruct-mlx",
131
+ tags: ["mlx", "conversational"],
132
+ pipeline_tag: "text-generation",
133
+ config: {
134
+ tokenizer_config: {
135
+ chat_template: "{% if tools %}...{% endif %}",
136
+ },
137
+ },
138
+ inference: "",
139
+ };
140
+ const snippet = snippetFunc(model);
141
+ expect(snippet[0].setup).toContain("uv tool install mlx-lm");
142
+ expect(snippet[0].content).toContain('mlx_lm.server --model "mlx-community/Llama-3.2-3B-Instruct-mlx"');
143
+ expect(snippet[1].setup).toContain("npm install -g @mariozechner/pi-coding-agent");
144
+ expect(snippet[1].content).toContain('"baseUrl": "http://localhost:8080/v1"');
145
+ expect(snippet[1].content).toContain('"id": "mlx-community/Llama-3.2-3B-Instruct-mlx"');
146
+ expect(snippet[2].content).toContain("pi");
147
+ });
127
148
  it("docker model runner", async () => {
128
149
  const { snippet: snippetFunc } = LOCAL_APPS["docker-model-runner"];
129
150
  const model = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@huggingface/tasks",
3
- "version": "0.20.4",
3
+ "version": "0.20.6",
4
4
  "description": "List of ML tasks for huggingface.co/tasks",
5
5
  "keywords": [
6
6
  "hub",
@@ -138,6 +138,29 @@ curl -X POST "http://localhost:8000/v1/chat/completions" \\
138
138
  expect(snippet[2].content).toContain("pi");
139
139
  });
140
140
 
141
+ it("pi - mlx", async () => {
142
+ const { snippet: snippetFunc } = LOCAL_APPS["pi"];
143
+ const model: ModelData = {
144
+ id: "mlx-community/Llama-3.2-3B-Instruct-mlx",
145
+ tags: ["mlx", "conversational"],
146
+ pipeline_tag: "text-generation",
147
+ config: {
148
+ tokenizer_config: {
149
+ chat_template: "{% if tools %}...{% endif %}",
150
+ },
151
+ },
152
+ inference: "",
153
+ };
154
+ const snippet = snippetFunc(model);
155
+
156
+ expect(snippet[0].setup).toContain("uv tool install mlx-lm");
157
+ expect(snippet[0].content).toContain('mlx_lm.server --model "mlx-community/Llama-3.2-3B-Instruct-mlx"');
158
+ expect(snippet[1].setup).toContain("npm install -g @mariozechner/pi-coding-agent");
159
+ expect(snippet[1].content).toContain('"baseUrl": "http://localhost:8080/v1"');
160
+ expect(snippet[1].content).toContain('"id": "mlx-community/Llama-3.2-3B-Instruct-mlx"');
161
+ expect(snippet[2].content).toContain("pi");
162
+ });
163
+
141
164
  it("docker model runner", async () => {
142
165
  const { snippet: snippetFunc } = LOCAL_APPS["docker-model-runner"];
143
166
  const model: ModelData = {
package/src/local-apps.ts CHANGED
@@ -115,6 +115,22 @@ function isMlxModel(model: ModelData) {
115
115
  return model.tags.includes("mlx");
116
116
  }
117
117
 
118
+ /**
119
+ * Returns the model's chat template string, coalescing across sources:
120
+ * GGUF metadata > chat_template_jinja file > tokenizer_config.json
121
+ */
122
+ function getChatTemplate(model: ModelData): string | undefined {
123
+ const ct =
124
+ model.gguf?.chat_template ?? model.config?.chat_template_jinja ?? model.config?.tokenizer_config?.chat_template;
125
+ if (typeof ct === "string") {
126
+ return ct;
127
+ }
128
+ if (Array.isArray(ct)) {
129
+ return ct[0]?.template;
130
+ }
131
+ return undefined;
132
+ }
133
+
118
134
  function isUnslothModel(model: ModelData) {
119
135
  return model.tags.includes("unsloth") || isLlamaCppGgufModel(model);
120
136
  }
@@ -436,17 +452,31 @@ const snippetMlxLm = (model: ModelData): LocalAppSnippet[] => {
436
452
  };
437
453
 
438
454
  const snippetPi = (model: ModelData, filepath?: string): LocalAppSnippet[] => {
439
- const quantTag = getQuantTag(filepath);
440
455
  const modelName = model.id.split("/").pop() ?? model.id;
456
+ const isMLX = isMlxModel(model);
457
+
458
+ // Step 1: Server — differs by backend
459
+ const serverStep: LocalAppSnippet = isMLX
460
+ ? {
461
+ title: "Start the MLX server",
462
+ setup: "# Install MLX LM:\nuv tool install mlx-lm",
463
+ content: `# Start a local OpenAI-compatible server:\nmlx_lm.server --model "${model.id}"`,
464
+ }
465
+ : {
466
+ title: "Start the llama.cpp server",
467
+ setup: "# Install llama.cpp:\nbrew install llama.cpp",
468
+ content: `# Start a local OpenAI-compatible server:\nllama-server -hf ${model.id}${getQuantTag(filepath)} --jinja`,
469
+ };
441
470
 
471
+ // Step 2: Pi config — port and provider name differ
442
472
  const modelsJson = JSON.stringify(
443
473
  {
444
474
  providers: {
445
- "llama-cpp": {
475
+ [isMLX ? "mlx-lm" : "llama-cpp"]: {
446
476
  baseUrl: "http://localhost:8080/v1",
447
477
  api: "openai-completions",
448
478
  apiKey: "none",
449
- models: [{ id: modelName }],
479
+ models: [{ id: isMLX ? model.id : modelName }],
450
480
  },
451
481
  },
452
482
  },
@@ -455,11 +485,7 @@ const snippetPi = (model: ModelData, filepath?: string): LocalAppSnippet[] => {
455
485
  );
456
486
 
457
487
  return [
458
- {
459
- title: "Start the llama.cpp server",
460
- setup: "# Install llama.cpp:\nbrew install llama.cpp",
461
- content: `# Start a local OpenAI-compatible server:\nllama-server -hf ${model.id}${quantTag} --jinja`,
462
- },
488
+ serverStep,
463
489
  {
464
490
  title: "Configure the model in Pi",
465
491
  setup: "# Install Pi:\nnpm install -g @mariozechner/pi-coding-agent",
@@ -467,7 +493,7 @@ const snippetPi = (model: ModelData, filepath?: string): LocalAppSnippet[] => {
467
493
  },
468
494
  {
469
495
  title: "Run Pi",
470
- content: `# Start Pi in your project directory:\npi`,
496
+ content: "# Start Pi in your project directory:\npi",
471
497
  },
472
498
  ];
473
499
  };
@@ -714,7 +740,10 @@ export const LOCAL_APPS = {
714
740
  prettyLabel: "Pi",
715
741
  docsUrl: "https://github.com/badlogic/pi-mono",
716
742
  mainTask: "text-generation",
717
- displayOnModelPage: (model) => isLlamaCppGgufModel(model) && !!model.gguf?.chat_template?.includes("tools"),
743
+ displayOnModelPage: (model) =>
744
+ (isLlamaCppGgufModel(model) || isMlxModel(model)) &&
745
+ model.pipeline_tag === "text-generation" &&
746
+ !!getChatTemplate(model)?.includes("tools"),
718
747
  snippet: snippetPi,
719
748
  },
720
749
  } satisfies Record<string, LocalApp>;