From 7f1b7d781d922a21766d050b24e593b661e18a44 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 25 Mar 2026 18:55:41 +0100 Subject: [PATCH 01/32] adding modules for downloading and running gguf modules --- .../huggingface/download/environment.yml | 6 + modules/nf-core/huggingface/download/main.nf | 30 ++++ modules/nf-core/huggingface/download/meta.yml | 60 ++++++++ .../huggingface/download/tests/main.nf.test | 64 ++++++++ .../download/tests/main.nf.test.snap | 34 +++++ .../nf-core/llamacpp-python/run/Dockerfile | 5 + .../llamacpp-python/run/environment.yml | 7 + modules/nf-core/llamacpp-python/run/main.nf | 36 +++++ modules/nf-core/llamacpp-python/run/meta.yml | 50 +++++++ .../run/resources/usr/bin/llamacpp-python.py | 137 ++++++++++++++++++ .../run/tests/data/prompt.json | 11 ++ .../run/tests/data/stub_model.gguf | 0 .../llamacpp-python/run/tests/main.nf.test | 79 ++++++++++ .../run/tests/main.nf.test.snap | 34 +++++ .../llamacpp-python/run/tests/nextflow.config | 7 + 15 files changed, 560 insertions(+) create mode 100644 modules/nf-core/huggingface/download/environment.yml create mode 100644 modules/nf-core/huggingface/download/main.nf create mode 100644 modules/nf-core/huggingface/download/meta.yml create mode 100644 modules/nf-core/huggingface/download/tests/main.nf.test create mode 100644 modules/nf-core/huggingface/download/tests/main.nf.test.snap create mode 100644 modules/nf-core/llamacpp-python/run/Dockerfile create mode 100644 modules/nf-core/llamacpp-python/run/environment.yml create mode 100644 modules/nf-core/llamacpp-python/run/main.nf create mode 100644 modules/nf-core/llamacpp-python/run/meta.yml create mode 100755 modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py create mode 100644 modules/nf-core/llamacpp-python/run/tests/data/prompt.json create mode 100644 modules/nf-core/llamacpp-python/run/tests/data/stub_model.gguf create mode 100644 modules/nf-core/llamacpp-python/run/tests/main.nf.test create mode 100644 modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap create mode 100644 modules/nf-core/llamacpp-python/run/tests/nextflow.config diff --git a/modules/nf-core/huggingface/download/environment.yml b/modules/nf-core/huggingface/download/environment.yml new file mode 100644 index 000000000000..f2267b412f67 --- /dev/null +++ b/modules/nf-core/huggingface/download/environment.yml @@ -0,0 +1,6 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge +dependencies: + - conda-forge::huggingface_hub=1.6.0 diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf new file mode 100644 index 000000000000..50e389afb415 --- /dev/null +++ b/modules/nf-core/huggingface/download/main.nf @@ -0,0 +1,30 @@ +process HF_DOWNLOAD { + tag "$meta.id" + label 'process_medium' + + conda "${moduleDir}/environment.yml" + container "community.wave.seqera.io/library/huggingface_hub:1.6.0--c106a7f9664ca39b" + + input: + tuple val(meta), val(hf_repo), val(hf_file) + + output: + tuple val(meta), path(hf_file), emit: output + tuple val("${task.process}"), val("huggingface_hub"), eval("hf --version 2>&1"), topic: versions, emit: versions_huggingface_hub + + when: + task.ext.when == null || task.ext.when + + script: + """ + export HF_HOME="${workflow.projectDir}/hf_cache" + export HF_HUB_CACHE="${workflow.projectDir}/hf_cache" + STARTDIR=\$PWD + hf download ${hf_repo} ${hf_file} --local-dir \$STARTDIR + """ + + stub: + """ + touch ${hf_file} + """ +} diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml new file mode 100644 index 000000000000..c9a5abe83fe4 --- /dev/null +++ b/modules/nf-core/huggingface/download/meta.yml @@ -0,0 +1,60 @@ +name: huggignface_hub +description: Tool for downloading models from HuggingFace +keywords: + - llm + - llama + - ai +tools: + - huggignface_hub: + description: "HuggingFace Hub CLI interface" + homepage: "https://huggingface.co/docs/huggingface_hub/guides/cli" + licence: ["MIT"] +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]`- prompt_file: + - hf_repo: + type: string + description: HuggingFace repository + - hf_file: + type: string + description: HuggingFace GGUF file +output: + output: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - output: + type: file + description: Model in GGUF format + pattern: "*.gguf" + versions_huggingface_hub: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML + +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - huggingface_hub: + type: string + description: The name of the tool + - hf --version: + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@toniher" + - "@lucacozzuto" +maintainers: + - "@toniher" + - "@lucacozzuto" diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test b/modules/nf-core/huggingface/download/tests/main.nf.test new file mode 100644 index 000000000000..b15446029a9c --- /dev/null +++ b/modules/nf-core/huggingface/download/tests/main.nf.test @@ -0,0 +1,64 @@ +nextflow_process { + + name "Test Process HF_DOWNLOAD" + script "../main.nf" + process "HF_DOWNLOAD" + + tag "modules" + tag "modules_local" + tag "huggingface" + tag "huggingface/download" + + test("download gguf file") { + + when { + process { + """ + input[0] = [ + [ id:'test_model' ], + "ggml-org/gemma-3-1b-it-GGUF", + "gemma-3-1b-it-Q4_K_M.gguf" + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.output.size() == 1 }, + { assert process.out.output[0][0] == [ id:'test_model' ] }, + { assert file(process.out.output[0][1]).name == "gemma-3-1b-it-Q4_K_M.gguf" }, + { assert file(process.out.output[0][1]).size() > 0 }, + { assert snapshot(process.out.versions_huggingface_hub).match() } + ) + } + } + + test("stub - download gguf file") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test_model' ], + "ggml-org/gemma-3-1b-it-GGUF", + "gemma-3-1b-it-Q4_K_M.gguf" + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.output.size() == 1 }, + { assert process.out.output[0][0] == [ id:'test_model' ] }, + { assert file(process.out.output[0][1]).name == "gemma-3-1b-it-Q4_K_M.gguf" }, + { assert snapshot(process.out.versions_huggingface_hub).match() } + ) + } + } +} diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test.snap b/modules/nf-core/huggingface/download/tests/main.nf.test.snap new file mode 100644 index 000000000000..fb0ec0f4e827 --- /dev/null +++ b/modules/nf-core/huggingface/download/tests/main.nf.test.snap @@ -0,0 +1,34 @@ +{ + "stub - download gguf file": { + "content": [ + [ + [ + "HF_DOWNLOAD", + "huggingface_hub", + "1.6.0" + ] + ] + ], + "timestamp": "2026-03-25T17:55:42.821958238", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "download gguf file": { + "content": [ + [ + [ + "HF_DOWNLOAD", + "huggingface_hub", + "1.6.0" + ] + ] + ], + "timestamp": "2026-03-25T17:55:36.08739868", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/llamacpp-python/run/Dockerfile b/modules/nf-core/llamacpp-python/run/Dockerfile new file mode 100644 index 000000000000..aeb89834ee1c --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/Dockerfile @@ -0,0 +1,5 @@ +FROM nvidia/cuda:12.4.1-devel-ubuntu22.04 + +RUN apt-get update && apt-get install -y python3 python3-pip +RUN pip3 install llama-cpp-python \ + --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu124 diff --git a/modules/nf-core/llamacpp-python/run/environment.yml b/modules/nf-core/llamacpp-python/run/environment.yml new file mode 100644 index 000000000000..9f314201924a --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/environment.yml @@ -0,0 +1,7 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json +channels: + - conda-forge + - bioconda +dependencies: + - conda-forge::llama-cpp-python=0.3.16 diff --git a/modules/nf-core/llamacpp-python/run/main.nf b/modules/nf-core/llamacpp-python/run/main.nf new file mode 100644 index 000000000000..5dec0f6bcf28 --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/main.nf @@ -0,0 +1,36 @@ +process LLAMACPP_PYTHON_RUN { + tag "$meta.id" + label 'process_medium' + label 'process_gpu' + + conda "${moduleDir}/environment.yml" + container "${ task.ext.use_gpu ? 'quay.io/nf-core/llama-cpp-python:0.1.9' : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5' }" + + input: + tuple val(meta), path(prompt_file), path(gguf_model) + + output: + tuple val(meta), path("output.txt"), emit: output + tuple val("${task.process}"), val("llama-cpp-python"), eval("python3 -c 'import llama_cpp; print(llama_cpp.__version__)'"), topic: versions, emit: versions_llama_cpp_python + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + prefix = task.ext.prefix ?: "${meta.id}" + """ + llamacpp-python.py \ + --model ${gguf_model} \ + --messages ${prompt_file} \ + --output output.txt \ + ${args} + """ + + stub: + prefix = task.ext.prefix ?: "${meta.id}" + """ + touch output.txt + + """ +} diff --git a/modules/nf-core/llamacpp-python/run/meta.yml b/modules/nf-core/llamacpp-python/run/meta.yml new file mode 100644 index 000000000000..15f4b893829b --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/meta.yml @@ -0,0 +1,50 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json +name: llamacpp-python +description: Python wrapper for running locally-hosted LLM with llama.cpp +keywords: + - llm + - llama + - ai +input: + - prompt_file: + type: file + description: | + Prompt file + Structure: [ val(meta), path(prompt_file) ] + - gguf_model: + type: file + description: | + GGUF model + Structure: [ val(meta), path(gguf_model) ] +output: + - output: + type: file + description: | + Output of the LLM query + Structure: [ val(meta), path("output.txt") ] + pattern: "output.txt" + - versions_llama_cpp_python: + type: file + description: | + File containing software versions + Structure: path(versions.yml) + pattern: "versions.yml" + +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - llama-cpp-python: + type: string + description: The name of the tool + - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': + type: eval + description: The expression to obtain the version of the tool +authors: + - "@toniher" + - "@lucacozzuto" +maintainers: + - "@toniher" + - "@lucacozzuto" + diff --git a/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py b/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py new file mode 100755 index 000000000000..e9e6123544f3 --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py @@ -0,0 +1,137 @@ +#!/usr/bin/env python3 + +import argparse +import json +import os +import sys + +import llama_cpp + + +# Helper to create messages from a text file +def create_messages_from_textfile(textfile, system_prompt): + try: + with open(textfile, "r", encoding="utf-8") as f: + content = f.read() + return [ + {"role": "system", "content": system_prompt.strip()}, + {"role": "user", "content": content.strip()}, + ] + except Exception as e: + print(f"Error reading text file '{textfile}': {e}", file=sys.stderr) + sys.exit(1) + + +# Helper to load messages from JSON or fallback to text +def load_messages(messages_file, system_prompt): + if not os.path.exists(messages_file): + print(f"Messages file '{messages_file}' does not exist.", file=sys.stderr) + sys.exit(1) + try: + with open(messages_file, "r", encoding="utf-8") as f: + content = f.read() + try: + return json.loads(content) + except json.JSONDecodeError: + return create_messages_from_textfile(messages_file, system_prompt) + except Exception as e: + print(f"Error opening messages file '{messages_file}': {e}", file=sys.stderr) + sys.exit(1) + + +def llamacpp_python( + messages_file, + model_file, + temperature=0.9, + output="output.txt", + verbose=False, + context_size=2048, + chat_format="chatml", + seed=None, +): + if not os.path.exists(model_file): + print(f"Model file '{model_file}' does not exist.", file=sys.stderr) + sys.exit(1) + + # Default system prompt + system_prompt = "A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions" + + messages_json = load_messages(messages_file, system_prompt) + + try: + llm = llama_cpp.Llama( + model_path=model_file, + chat_format=chat_format, + n_ctx=context_size, + seed=seed, + ) + response = llm.create_chat_completion( + messages=messages_json, + response_format={"type": "json_object"}, + temperature=temperature, + ) + except Exception as e: + print(f"Error running llama_cpp: {e}", file=sys.stderr) + sys.exit(1) + + if not verbose: + try: + reply = response["choices"][0]["message"]["content"] + except (KeyError, IndexError, TypeError): + reply = response + # Try to parse reply as JSON if it's a string + if isinstance(reply, str): + try: + reply_json = json.loads(reply) + if isinstance(reply_json, dict) and len(reply_json) == 1: + reply = next(iter(reply_json.values())) + else: + reply = reply_json + except Exception: + pass # Leave reply as string if not valid JSON + elif isinstance(reply, dict) and len(reply) == 1: + reply = next(iter(reply.values())) + else: + reply = response + + try: + with open(output, "w", encoding="utf-8") as f: + if isinstance(reply, str): + f.write(reply) + else: + f.write(json.dumps(reply, indent=2)) + if verbose: + print(f"Output written to {output}") + except Exception as e: + print(f"Error writing output file '{output}': {e}", file=sys.stderr) + sys.exit(1) + + +def main(): + parser = argparse.ArgumentParser(description="Submit a process with model.") + parser.add_argument("-s", "--messages", required=True, help="JSON message") + parser.add_argument("-m", "--model", required=True, help="Model used") + parser.add_argument( + "-t", "--temperature", default=0.9, type=float, help="Temperature" + ) + parser.add_argument("-o", "--output", default="output.txt", help="Output text") + parser.add_argument("-c", "--context", default=2048, type=int, help="Context size") + parser.add_argument("--chat_format", default="chatml", help="Chat format") + parser.add_argument("--seed", default=None, type=int, help="Defined seed") + parser.add_argument("--verbose", action="store_true", help="Verbose output") + + args = parser.parse_args() + llamacpp_python( + messages_file=args.messages, + model_file=args.model, + temperature=args.temperature, + output=args.output, + verbose=args.verbose, + context_size=args.context, + chat_format=args.chat_format, + seed=args.seed, + ) + + +if __name__ == "__main__": + main() diff --git a/modules/nf-core/llamacpp-python/run/tests/data/prompt.json b/modules/nf-core/llamacpp-python/run/tests/data/prompt.json new file mode 100644 index 000000000000..7d76ad158bab --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/tests/data/prompt.json @@ -0,0 +1,11 @@ +[ + { + "role": "system", + "content": "A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions" + + }, + { + "role": "user", + "content": "Describe Barcelona in one paragraph" + } +] diff --git a/modules/nf-core/llamacpp-python/run/tests/data/stub_model.gguf b/modules/nf-core/llamacpp-python/run/tests/data/stub_model.gguf new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpp-python/run/tests/main.nf.test new file mode 100644 index 000000000000..a3483d6dc9dc --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test @@ -0,0 +1,79 @@ +nextflow_process { + + name "Test Process LLAMACPP_PYTHON_RUN" + script "../main.nf" + process "LLAMACPP_PYTHON_RUN" + + tag "modules" + tag "modules_local" + tag "llamacpp_python" + tag "llamacpp_python/run" + + test("run inference with downloaded gguf model") { + + config "./nextflow.config" + + setup { + run("HF_DOWNLOAD") { + script "../../../huggingface/download/main.nf" + process { + """ + input[0] = [ + [ id:'test_model' ], + "ggml-org/gemma-3-1b-it-GGUF", + "gemma-3-1b-it-Q4_K_M.gguf" + ] + """ + } + } + } + + when { + process { + """ + input[0] = HF_DOWNLOAD.out.output.map { meta, model -> + [ [ id:'test_run' ], file("${moduleDir}/tests/data/prompt.json"), model ] + } + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.output.size() == 1 }, + { assert process.out.output[0][0] == [ id:'test_run' ] }, + { assert file(process.out.output[0][1]).name == "output.txt" }, + { assert file(process.out.output[0][1]).size() > 0 }, + { assert snapshot(process.out.versions_llama_cpp_python).match() } + ) + } + } + + test("stub - run inference with json prompt") { + + options "-stub" + + when { + process { + """ + input[0] = [ + [ id:'test_run' ], + file("${moduleDir}/tests/data/prompt.json"), + file("${moduleDir}/tests/data/stub_model.gguf") + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.output.size() == 1 }, + { assert process.out.output[0][0] == [ id:'test_run' ] }, + { assert file(process.out.output[0][1]).name == "output.txt" }, + { assert snapshot(process.out.versions_llama_cpp_python).match() } + ) + } + } +} diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap b/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap new file mode 100644 index 000000000000..5f5b167f758b --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap @@ -0,0 +1,34 @@ +{ + "run inference with downloaded gguf model": { + "content": [ + [ + [ + "LLAMACPP_PYTHON_RUN", + "llama-cpp-python", + "0.3.16" + ] + ] + ], + "timestamp": "2026-03-25T18:33:08.596485421", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "stub - run inference with json prompt": { + "content": [ + [ + [ + "LLAMACPP_PYTHON_RUN", + "llama-cpp-python", + "0.3.16" + ] + ] + ], + "timestamp": "2026-03-25T17:23:21.997786726", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + } +} \ No newline at end of file diff --git a/modules/nf-core/llamacpp-python/run/tests/nextflow.config b/modules/nf-core/llamacpp-python/run/tests/nextflow.config new file mode 100644 index 000000000000..7a6b3c247728 --- /dev/null +++ b/modules/nf-core/llamacpp-python/run/tests/nextflow.config @@ -0,0 +1,7 @@ +nextflow.enable.moduleBinaries = true + +process { + withName: 'LLAMACPP_PYTHON_RUN' { + ext.args = "--seed 42" + } +} From 9031f483a189cd2ce880a9eb0fe8b178cd2c99e6 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 25 Mar 2026 19:33:59 +0100 Subject: [PATCH 02/32] adding docker support --- modules/nf-core/huggingface/download/tests/nextflow.config | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 modules/nf-core/huggingface/download/tests/nextflow.config diff --git a/modules/nf-core/huggingface/download/tests/nextflow.config b/modules/nf-core/huggingface/download/tests/nextflow.config new file mode 100644 index 000000000000..68a5630f57cb --- /dev/null +++ b/modules/nf-core/huggingface/download/tests/nextflow.config @@ -0,0 +1,7 @@ +nextflow.enable.moduleBinaries = true + +process { + withName: 'HF_DOWNLOAD' { + containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } + } +} From 04cd556c9a722501fc3c68403240433008e25c4e Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 08:46:54 +0100 Subject: [PATCH 03/32] allow custom HF_HOME cache input and other fixes --- modules/nf-core/huggingface/download/main.nf | 12 ++++++------ modules/nf-core/huggingface/download/meta.yml | 2 +- .../nf-core/huggingface/download/tests/main.nf.test | 6 ++++-- .../huggingface/download/tests/main.nf.test.snap | 4 ++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf index 50e389afb415..63eef3a5bcb2 100644 --- a/modules/nf-core/huggingface/download/main.nf +++ b/modules/nf-core/huggingface/download/main.nf @@ -6,21 +6,21 @@ process HF_DOWNLOAD { container "community.wave.seqera.io/library/huggingface_hub:1.6.0--c106a7f9664ca39b" input: - tuple val(meta), val(hf_repo), val(hf_file) + tuple val(meta), val(hf_repo), val(hf_file), val(hf_home) output: tuple val(meta), path(hf_file), emit: output - tuple val("${task.process}"), val("huggingface_hub"), eval("hf --version 2>&1"), topic: versions, emit: versions_huggingface_hub + tuple val("${task.process}"), val("huggingface_hub"), eval("hf --version 2>&1 | awk '{print \$NF}'"), topic: versions, emit: versions_huggingface_hub when: task.ext.when == null || task.ext.when script: + def hf_home_resolved = hf_home ?: "${workflow.projectDir}/hf_cache" """ - export HF_HOME="${workflow.projectDir}/hf_cache" - export HF_HUB_CACHE="${workflow.projectDir}/hf_cache" - STARTDIR=\$PWD - hf download ${hf_repo} ${hf_file} --local-dir \$STARTDIR + export HF_HOME="${hf_home_resolved}" + export HF_HUB_CACHE=\$HF_HOME + hf download ${hf_repo} ${hf_file} --local-dir \$PWD """ stub: diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index c9a5abe83fe4..8c8332a879e5 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -50,7 +50,7 @@ topics: description: The name of the tool - hf --version: type: eval - description: The expression to obtain the version of the tool + description: The expression to obtain only the version number of the tool (e.g. "1.6.0") authors: - "@toniher" diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test b/modules/nf-core/huggingface/download/tests/main.nf.test index b15446029a9c..94d0112862c4 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test +++ b/modules/nf-core/huggingface/download/tests/main.nf.test @@ -17,7 +17,8 @@ nextflow_process { input[0] = [ [ id:'test_model' ], "ggml-org/gemma-3-1b-it-GGUF", - "gemma-3-1b-it-Q4_K_M.gguf" + "gemma-3-1b-it-Q4_K_M.gguf", + "./hf_cache" ] """ } @@ -45,7 +46,8 @@ nextflow_process { input[0] = [ [ id:'test_model' ], "ggml-org/gemma-3-1b-it-GGUF", - "gemma-3-1b-it-Q4_K_M.gguf" + "gemma-3-1b-it-Q4_K_M.gguf", + "./hf_cache" ] """ } diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test.snap b/modules/nf-core/huggingface/download/tests/main.nf.test.snap index fb0ec0f4e827..406face5c7a6 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test.snap +++ b/modules/nf-core/huggingface/download/tests/main.nf.test.snap @@ -9,7 +9,7 @@ ] ] ], - "timestamp": "2026-03-25T17:55:42.821958238", + "timestamp": "2026-03-26T08:39:57.919278809", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" @@ -25,7 +25,7 @@ ] ] ], - "timestamp": "2026-03-25T17:55:36.08739868", + "timestamp": "2026-03-26T08:38:24.630341776", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" From 537a891ef8b6dbd7ef7962131e0305a39a2acd3d Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 10:12:38 +0100 Subject: [PATCH 04/32] several test fixes --- modules/nf-core/huggingface/download/meta.yml | 98 ++++++++++--------- modules/nf-core/llamacpp-python/run/meta.yml | 83 ++++++++++------ 2 files changed, 103 insertions(+), 78 deletions(-) diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index 8c8332a879e5..f540eb08b6c3 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -1,60 +1,66 @@ -name: huggignface_hub +name: hf_download description: Tool for downloading models from HuggingFace keywords: - - llm - - llama - - ai +- llm +- llama +- ai tools: - - huggignface_hub: - description: "HuggingFace Hub CLI interface" - homepage: "https://huggingface.co/docs/huggingface_hub/guides/cli" - licence: ["MIT"] +- huggingface_hub: + description: "HuggingFace Hub CLI interface" + homepage: "https://huggingface.co/docs/huggingface_hub/guides/cli" + licence: + - "MIT" + identifier: '' input: +- - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]`- prompt_file: + - hf_repo: + type: string + description: HuggingFace repository + - hf_file: + type: string + description: HuggingFace GGUF file + - hf_home: + type: string + description: HuggingFace default cache directory +output: + output: - - meta: type: map description: | Groovy Map containing sample information - e.g. `[ id:'sample1' ]`- prompt_file: - - hf_repo: - type: string - description: HuggingFace repository + e.g. `[ id:'sample1' ]` - hf_file: - type: string - description: HuggingFace GGUF file -output: - output: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1' ]` - - output: - type: file - description: Model in GGUF format - pattern: "*.gguf" - versions_huggingface_hub: - - versions.yml: type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML - + description: Downloaded HuggingFace GGUF file + ontologies: [] + versions_huggingface_hub: + - - ${task.process}: + type: string + description: The name of the process + - huggingface_hub: + type: string + description: The name of the tool + - hf --version 2>&1 | awk '{print \$NF}': + type: eval + description: The expression to obtain the version of the tool topics: versions: - - - ${task.process}: - type: string - description: The name of the process - - huggingface_hub: - type: string - description: The name of the tool - - hf --version: - type: eval - description: The expression to obtain only the version number of the tool (e.g. "1.6.0") - + - - ${task.process}: + type: string + description: The name of the process + - huggingface_hub: + type: string + description: The name of the tool + - hf --version 2>&1 | awk '{print \$NF}': + type: eval + description: The expression to obtain the version of the tool authors: - - "@toniher" - - "@lucacozzuto" +- "@toniher" +- "@lucacozzuto" maintainers: - - "@toniher" - - "@lucacozzuto" +- "@toniher" +- "@lucacozzuto" diff --git a/modules/nf-core/llamacpp-python/run/meta.yml b/modules/nf-core/llamacpp-python/run/meta.yml index 15f4b893829b..18607a776271 100644 --- a/modules/nf-core/llamacpp-python/run/meta.yml +++ b/modules/nf-core/llamacpp-python/run/meta.yml @@ -1,50 +1,69 @@ -# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/subworkflows/yaml-schema.json -name: llamacpp-python +name: llamacpp_python_run description: Python wrapper for running locally-hosted LLM with llama.cpp keywords: - - llm - - llama - - ai +- llm +- llama +- ai +tools: +- llama-cpp-python: + description: "Python wrapper for llama.cpp LLM inference tool" + homepage: "https://llama-cpp-python.readthedocs.io/en/latest/" + licence: + - "MIT" + identifier: '' input: +- - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]`- prompt_file: - prompt_file: type: file description: | Prompt file Structure: [ val(meta), path(prompt_file) ] + ontologies: [] - gguf_model: type: file description: | GGUF model Structure: [ val(meta), path(gguf_model) ] + ontologies: [] output: - - output: - type: file - description: | - Output of the LLM query - Structure: [ val(meta), path("output.txt") ] - pattern: "output.txt" - - versions_llama_cpp_python: - type: file - description: | - File containing software versions - Structure: path(versions.yml) - pattern: "versions.yml" - + output: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - "output.txt": + type: file + description: File with the output of LLM inference request + ontologies: [] + versions_llama_cpp_python: + - - ${task.process}: + type: string + description: The name of the process + - llama-cpp-python: + type: string + description: The name of the tool + - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': + type: eval + description: The expression to obtain the version of the tool topics: versions: - - - ${task.process}: - type: string - description: The name of the process - - llama-cpp-python: - type: string - description: The name of the tool - - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': - type: eval - description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - llama-cpp-python: + type: string + description: The name of the tool + - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': + type: eval + description: The expression to obtain the version of the tool authors: - - "@toniher" - - "@lucacozzuto" +- "@toniher" +- "@lucacozzuto" maintainers: - - "@toniher" - - "@lucacozzuto" - +- "@toniher" +- "@lucacozzuto" From 20b5d26348c628747268de179fefab024d450300 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 11:54:03 +0100 Subject: [PATCH 05/32] Upgrade problem with versions and test --- .../huggingface/download/tests/main.nf.test | 6 ++-- .../download/tests/main.nf.test.snap | 30 +++++++++++-------- .../llamacpp-python/run/tests/main.nf.test | 11 +++---- .../run/tests/main.nf.test.snap | 30 +++++++++++-------- 4 files changed, 43 insertions(+), 34 deletions(-) diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test b/modules/nf-core/huggingface/download/tests/main.nf.test index 94d0112862c4..2173c5d32897 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test +++ b/modules/nf-core/huggingface/download/tests/main.nf.test @@ -5,7 +5,7 @@ nextflow_process { process "HF_DOWNLOAD" tag "modules" - tag "modules_local" + tag "modules_nfcore" tag "huggingface" tag "huggingface/download" @@ -31,7 +31,7 @@ nextflow_process { { assert process.out.output[0][0] == [ id:'test_model' ] }, { assert file(process.out.output[0][1]).name == "gemma-3-1b-it-Q4_K_M.gguf" }, { assert file(process.out.output[0][1]).size() > 0 }, - { assert snapshot(process.out.versions_huggingface_hub).match() } + { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } ) } } @@ -59,7 +59,7 @@ nextflow_process { { assert process.out.output.size() == 1 }, { assert process.out.output[0][0] == [ id:'test_model' ] }, { assert file(process.out.output[0][1]).name == "gemma-3-1b-it-Q4_K_M.gguf" }, - { assert snapshot(process.out.versions_huggingface_hub).match() } + { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } ) } } diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test.snap b/modules/nf-core/huggingface/download/tests/main.nf.test.snap index 406face5c7a6..5565340150b6 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test.snap +++ b/modules/nf-core/huggingface/download/tests/main.nf.test.snap @@ -1,13 +1,15 @@ { "stub - download gguf file": { "content": [ - [ - [ - "HF_DOWNLOAD", - "huggingface_hub", - "1.6.0" + { + "versions_huggingface_hub": [ + [ + "HF_DOWNLOAD", + "huggingface_hub", + "1.6.0" + ] ] - ] + } ], "timestamp": "2026-03-26T08:39:57.919278809", "meta": { @@ -17,13 +19,15 @@ }, "download gguf file": { "content": [ - [ - [ - "HF_DOWNLOAD", - "huggingface_hub", - "1.6.0" + { + "versions_huggingface_hub": [ + [ + "HF_DOWNLOAD", + "huggingface_hub", + "1.6.0" + ] ] - ] + } ], "timestamp": "2026-03-26T08:38:24.630341776", "meta": { @@ -31,4 +35,4 @@ "nextflow": "25.10.4" } } -} \ No newline at end of file +} diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpp-python/run/tests/main.nf.test index a3483d6dc9dc..469ce2d8d258 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test @@ -5,9 +5,10 @@ nextflow_process { process "LLAMACPP_PYTHON_RUN" tag "modules" - tag "modules_local" - tag "llamacpp_python" - tag "llamacpp_python/run" + tag "modules_nfcore" + tag "llamacpp-python" + tag "llamacpp-python/run" + tag "huggingface/download" test("run inference with downloaded gguf model") { @@ -45,7 +46,7 @@ nextflow_process { { assert process.out.output[0][0] == [ id:'test_run' ] }, { assert file(process.out.output[0][1]).name == "output.txt" }, { assert file(process.out.output[0][1]).size() > 0 }, - { assert snapshot(process.out.versions_llama_cpp_python).match() } + { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } ) } } @@ -72,7 +73,7 @@ nextflow_process { { assert process.out.output.size() == 1 }, { assert process.out.output[0][0] == [ id:'test_run' ] }, { assert file(process.out.output[0][1]).name == "output.txt" }, - { assert snapshot(process.out.versions_llama_cpp_python).match() } + { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } ) } } diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap b/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap index 5f5b167f758b..4bd263f10e6e 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap @@ -1,13 +1,15 @@ { "run inference with downloaded gguf model": { "content": [ - [ - [ - "LLAMACPP_PYTHON_RUN", - "llama-cpp-python", - "0.3.16" + { + "versions_llama_cpp_python": [ + [ + "LLAMACPP_PYTHON_RUN", + "llama-cpp-python", + "0.3.16" + ] ] - ] + } ], "timestamp": "2026-03-25T18:33:08.596485421", "meta": { @@ -17,13 +19,15 @@ }, "stub - run inference with json prompt": { "content": [ - [ - [ - "LLAMACPP_PYTHON_RUN", - "llama-cpp-python", - "0.3.16" + { + "versions_llama_cpp_python": [ + [ + "LLAMACPP_PYTHON_RUN", + "llama-cpp-python", + "0.3.16" + ] ] - ] + } ], "timestamp": "2026-03-25T17:23:21.997786726", "meta": { @@ -31,4 +35,4 @@ "nextflow": "25.10.4" } } -} \ No newline at end of file +} From c9997f53e502cd3dbf35b47a370512260adc9877 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 12:27:15 +0100 Subject: [PATCH 06/32] fix precommit linting --- modules/nf-core/huggingface/download/meta.yml | 26 +++++++++---------- modules/nf-core/llamacpp-python/run/meta.yml | 26 +++++++++---------- .../run/resources/usr/bin/llamacpp-python.py | 8 +++--- .../run/tests/data/prompt.json | 1 - 4 files changed, 29 insertions(+), 32 deletions(-) diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index f540eb08b6c3..b3512b4ea075 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -1,16 +1,16 @@ name: hf_download description: Tool for downloading models from HuggingFace keywords: -- llm -- llama -- ai + - llm + - llama + - ai tools: -- huggingface_hub: - description: "HuggingFace Hub CLI interface" - homepage: "https://huggingface.co/docs/huggingface_hub/guides/cli" - licence: - - "MIT" - identifier: '' + - huggingface_hub: + description: "HuggingFace Hub CLI interface" + homepage: "https://huggingface.co/docs/huggingface_hub/guides/cli" + licence: + - "MIT" + identifier: '' input: - - meta: type: map @@ -59,8 +59,8 @@ topics: type: eval description: The expression to obtain the version of the tool authors: -- "@toniher" -- "@lucacozzuto" + - "@toniher" + - "@lucacozzuto" maintainers: -- "@toniher" -- "@lucacozzuto" + - "@toniher" + - "@lucacozzuto" diff --git a/modules/nf-core/llamacpp-python/run/meta.yml b/modules/nf-core/llamacpp-python/run/meta.yml index 18607a776271..bd8ca208a075 100644 --- a/modules/nf-core/llamacpp-python/run/meta.yml +++ b/modules/nf-core/llamacpp-python/run/meta.yml @@ -1,16 +1,16 @@ name: llamacpp_python_run description: Python wrapper for running locally-hosted LLM with llama.cpp keywords: -- llm -- llama -- ai + - llm + - llama + - ai tools: -- llama-cpp-python: - description: "Python wrapper for llama.cpp LLM inference tool" - homepage: "https://llama-cpp-python.readthedocs.io/en/latest/" - licence: - - "MIT" - identifier: '' + - llama-cpp-python: + description: "Python wrapper for llama.cpp LLM inference tool" + homepage: "https://llama-cpp-python.readthedocs.io/en/latest/" + licence: + - "MIT" + identifier: '' input: - - meta: type: map @@ -62,8 +62,8 @@ topics: type: eval description: The expression to obtain the version of the tool authors: -- "@toniher" -- "@lucacozzuto" + - "@toniher" + - "@lucacozzuto" maintainers: -- "@toniher" -- "@lucacozzuto" + - "@toniher" + - "@lucacozzuto" diff --git a/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py b/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py index e9e6123544f3..4e332bca6338 100755 --- a/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py +++ b/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py @@ -11,7 +11,7 @@ # Helper to create messages from a text file def create_messages_from_textfile(textfile, system_prompt): try: - with open(textfile, "r", encoding="utf-8") as f: + with open(textfile, encoding="utf-8") as f: content = f.read() return [ {"role": "system", "content": system_prompt.strip()}, @@ -28,7 +28,7 @@ def load_messages(messages_file, system_prompt): print(f"Messages file '{messages_file}' does not exist.", file=sys.stderr) sys.exit(1) try: - with open(messages_file, "r", encoding="utf-8") as f: + with open(messages_file, encoding="utf-8") as f: content = f.read() try: return json.loads(content) @@ -111,9 +111,7 @@ def main(): parser = argparse.ArgumentParser(description="Submit a process with model.") parser.add_argument("-s", "--messages", required=True, help="JSON message") parser.add_argument("-m", "--model", required=True, help="Model used") - parser.add_argument( - "-t", "--temperature", default=0.9, type=float, help="Temperature" - ) + parser.add_argument("-t", "--temperature", default=0.9, type=float, help="Temperature") parser.add_argument("-o", "--output", default="output.txt", help="Output text") parser.add_argument("-c", "--context", default=2048, type=int, help="Context size") parser.add_argument("--chat_format", default="chatml", help="Chat format") diff --git a/modules/nf-core/llamacpp-python/run/tests/data/prompt.json b/modules/nf-core/llamacpp-python/run/tests/data/prompt.json index 7d76ad158bab..52d9ea3e2aa7 100644 --- a/modules/nf-core/llamacpp-python/run/tests/data/prompt.json +++ b/modules/nf-core/llamacpp-python/run/tests/data/prompt.json @@ -2,7 +2,6 @@ { "role": "system", "content": "A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions" - }, { "role": "user", From 5035e82beb3af788cde1960e79d607d99e7e7686 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 13:08:09 +0100 Subject: [PATCH 07/32] fix yaml for prettier --- modules/nf-core/huggingface/download/meta.yml | 78 ++++++++--------- modules/nf-core/llamacpp-python/run/meta.yml | 84 +++++++++---------- 2 files changed, 81 insertions(+), 81 deletions(-) diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index b3512b4ea075..9ca5bed5d613 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -9,55 +9,55 @@ tools: description: "HuggingFace Hub CLI interface" homepage: "https://huggingface.co/docs/huggingface_hub/guides/cli" licence: - - "MIT" - identifier: '' + - "MIT" + identifier: "" input: -- - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1' ]`- prompt_file: - - hf_repo: - type: string - description: HuggingFace repository - - hf_file: - type: string - description: HuggingFace GGUF file - - hf_home: - type: string - description: HuggingFace default cache directory -output: - output: - - meta: type: map description: | Groovy Map containing sample information - e.g. `[ id:'sample1' ]` + e.g. `[ id:'sample1' ]`- prompt_file: + - hf_repo: + type: string + description: HuggingFace repository - hf_file: - type: file - description: Downloaded HuggingFace GGUF file - ontologies: [] - versions_huggingface_hub: - - - ${task.process}: type: string - description: The name of the process - - huggingface_hub: + description: HuggingFace GGUF file + - hf_home: type: string - description: The name of the tool - - hf --version 2>&1 | awk '{print \$NF}': - type: eval - description: The expression to obtain the version of the tool + description: HuggingFace default cache directory +output: + output: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - hf_file: + type: file + description: Downloaded HuggingFace GGUF file + ontologies: [] + versions_huggingface_hub: + - - ${task.process}: + type: string + description: The name of the process + - huggingface_hub: + type: string + description: The name of the tool + - hf --version 2>&1 | awk '{print \$NF}': + type: eval + description: The expression to obtain the version of the tool topics: versions: - - - ${task.process}: - type: string - description: The name of the process - - huggingface_hub: - type: string - description: The name of the tool - - hf --version 2>&1 | awk '{print \$NF}': - type: eval - description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - huggingface_hub: + type: string + description: The name of the tool + - hf --version 2>&1 | awk '{print \$NF}': + type: eval + description: The expression to obtain the version of the tool authors: - "@toniher" - "@lucacozzuto" diff --git a/modules/nf-core/llamacpp-python/run/meta.yml b/modules/nf-core/llamacpp-python/run/meta.yml index bd8ca208a075..70d7bbf4f162 100644 --- a/modules/nf-core/llamacpp-python/run/meta.yml +++ b/modules/nf-core/llamacpp-python/run/meta.yml @@ -9,58 +9,58 @@ tools: description: "Python wrapper for llama.cpp LLM inference tool" homepage: "https://llama-cpp-python.readthedocs.io/en/latest/" licence: - - "MIT" - identifier: '' + - "MIT" + identifier: "" input: -- - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'sample1' ]`- prompt_file: - - prompt_file: - type: file - description: | - Prompt file - Structure: [ val(meta), path(prompt_file) ] - ontologies: [] - - gguf_model: - type: file - description: | - GGUF model - Structure: [ val(meta), path(gguf_model) ] - ontologies: [] -output: - output: - - meta: type: map description: | Groovy Map containing sample information - e.g. `[ id:'sample1' ]` - - "output.txt": + e.g. `[ id:'sample1' ]`- prompt_file: + - prompt_file: + type: file + description: | + Prompt file + Structure: [ val(meta), path(prompt_file) ] + ontologies: [] + - gguf_model: type: file - description: File with the output of LLM inference request + description: | + GGUF model + Structure: [ val(meta), path(gguf_model) ] ontologies: [] +output: + output: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'sample1' ]` + - "output.txt": + type: file + description: File with the output of LLM inference request + ontologies: [] versions_llama_cpp_python: - - - ${task.process}: - type: string - description: The name of the process - - llama-cpp-python: - type: string - description: The name of the tool - - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': - type: eval - description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - llama-cpp-python: + type: string + description: The name of the tool + - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': + type: eval + description: The expression to obtain the version of the tool topics: versions: - - - ${task.process}: - type: string - description: The name of the process - - llama-cpp-python: - type: string - description: The name of the tool - - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': - type: eval - description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - llama-cpp-python: + type: string + description: The name of the tool + - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': + type: eval + description: The expression to obtain the version of the tool authors: - "@toniher" - "@lucacozzuto" From 2c796de96acc5514afcb7924758686d1d952bcc8 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 13:44:02 +0100 Subject: [PATCH 08/32] fix retrieval of version for huggingface --- modules/nf-core/huggingface/download/main.nf | 2 +- modules/nf-core/huggingface/download/meta.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf index 63eef3a5bcb2..78c6211ac34f 100644 --- a/modules/nf-core/huggingface/download/main.nf +++ b/modules/nf-core/huggingface/download/main.nf @@ -10,7 +10,7 @@ process HF_DOWNLOAD { output: tuple val(meta), path(hf_file), emit: output - tuple val("${task.process}"), val("huggingface_hub"), eval("hf --version 2>&1 | awk '{print \$NF}'"), topic: versions, emit: versions_huggingface_hub + tuple val("${task.process}"), val("huggingface_hub"), eval("hf --version 2>&1 | tail -n1 | awk '{print \$NF}'"), topic: versions, emit: versions_huggingface_hub when: task.ext.when == null || task.ext.when diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index 9ca5bed5d613..a3186bce7b07 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -44,7 +44,7 @@ output: - huggingface_hub: type: string description: The name of the tool - - hf --version 2>&1 | awk '{print \$NF}': + - hf --version 2>&1 | tail -n1 | awk '{print \$NF}': type: eval description: The expression to obtain the version of the tool topics: @@ -55,7 +55,7 @@ topics: - huggingface_hub: type: string description: The name of the tool - - hf --version 2>&1 | awk '{print \$NF}': + - hf --version 2>&1 | tail -n1 | awk '{print \$NF}': type: eval description: The expression to obtain the version of the tool authors: From ff7039c53d6010eea6b8d94d7bf084820c2fb86f Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 14:02:28 +0100 Subject: [PATCH 09/32] importing nextflow.config from HF_DOWNLOAD --- modules/nf-core/llamacpp-python/run/tests/nextflow.config | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/nf-core/llamacpp-python/run/tests/nextflow.config b/modules/nf-core/llamacpp-python/run/tests/nextflow.config index 7a6b3c247728..6806a86ca3ef 100644 --- a/modules/nf-core/llamacpp-python/run/tests/nextflow.config +++ b/modules/nf-core/llamacpp-python/run/tests/nextflow.config @@ -1,6 +1,9 @@ nextflow.enable.moduleBinaries = true process { + withName: 'HF_DOWNLOAD' { + containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } + } withName: 'LLAMACPP_PYTHON_RUN' { ext.args = "--seed 42" } From fb1768c4e6621e3abcf993da4e532c35051ab796 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 26 Mar 2026 14:51:46 +0100 Subject: [PATCH 10/32] adding hf_cache for setup as well --- modules/nf-core/llamacpp-python/run/tests/main.nf.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpp-python/run/tests/main.nf.test index 469ce2d8d258..dc789505242d 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test @@ -22,7 +22,8 @@ nextflow_process { input[0] = [ [ id:'test_model' ], "ggml-org/gemma-3-1b-it-GGUF", - "gemma-3-1b-it-Q4_K_M.gguf" + "gemma-3-1b-it-Q4_K_M.gguf", + "./hf_cache" ] """ } From ac7f44cf8f7ef47f0d69da19b0f208162a32742d Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 18:47:48 +0200 Subject: [PATCH 11/32] moving HF_DOWNLOAD to HUGGINGFACE_DOWNLOAD https://nf-co.re/docs/guidelines/components/modules#naming-conventions --- modules/nf-core/huggingface/download/main.nf | 2 +- modules/nf-core/huggingface/download/tests/main.nf.test | 4 ++-- modules/nf-core/huggingface/download/tests/main.nf.test.snap | 4 ++-- modules/nf-core/huggingface/download/tests/nextflow.config | 2 +- modules/nf-core/llamacpp-python/run/tests/main.nf.test | 4 ++-- modules/nf-core/llamacpp-python/run/tests/nextflow.config | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf index 78c6211ac34f..e279195d50e6 100644 --- a/modules/nf-core/huggingface/download/main.nf +++ b/modules/nf-core/huggingface/download/main.nf @@ -1,4 +1,4 @@ -process HF_DOWNLOAD { +process HUGGINGFACE_DOWNLOAD { tag "$meta.id" label 'process_medium' diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test b/modules/nf-core/huggingface/download/tests/main.nf.test index 2173c5d32897..6f99fd1e48fd 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test +++ b/modules/nf-core/huggingface/download/tests/main.nf.test @@ -1,8 +1,8 @@ nextflow_process { - name "Test Process HF_DOWNLOAD" + name "Test Process HUGGINGFACE_DOWNLOAD" script "../main.nf" - process "HF_DOWNLOAD" + process "HUGGINGFACE_DOWNLOAD" tag "modules" tag "modules_nfcore" diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test.snap b/modules/nf-core/huggingface/download/tests/main.nf.test.snap index 5565340150b6..68a48764c0a8 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test.snap +++ b/modules/nf-core/huggingface/download/tests/main.nf.test.snap @@ -4,7 +4,7 @@ { "versions_huggingface_hub": [ [ - "HF_DOWNLOAD", + "HUGGINGFACE_DOWNLOAD", "huggingface_hub", "1.6.0" ] @@ -22,7 +22,7 @@ { "versions_huggingface_hub": [ [ - "HF_DOWNLOAD", + "HUGGINGFACE_DOWNLOAD", "huggingface_hub", "1.6.0" ] diff --git a/modules/nf-core/huggingface/download/tests/nextflow.config b/modules/nf-core/huggingface/download/tests/nextflow.config index 68a5630f57cb..93c850d839c7 100644 --- a/modules/nf-core/huggingface/download/tests/nextflow.config +++ b/modules/nf-core/huggingface/download/tests/nextflow.config @@ -1,7 +1,7 @@ nextflow.enable.moduleBinaries = true process { - withName: 'HF_DOWNLOAD' { + withName: 'HUGGINGFACE_DOWNLOAD' { containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } } } diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpp-python/run/tests/main.nf.test index dc789505242d..2aeaeb0d8add 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test @@ -15,7 +15,7 @@ nextflow_process { config "./nextflow.config" setup { - run("HF_DOWNLOAD") { + run("HUGGINGFACE_DOWNLOAD") { script "../../../huggingface/download/main.nf" process { """ @@ -33,7 +33,7 @@ nextflow_process { when { process { """ - input[0] = HF_DOWNLOAD.out.output.map { meta, model -> + input[0] = HUGGINGFACE_DOWNLOAD.out.output.map { meta, model -> [ [ id:'test_run' ], file("${moduleDir}/tests/data/prompt.json"), model ] } """ diff --git a/modules/nf-core/llamacpp-python/run/tests/nextflow.config b/modules/nf-core/llamacpp-python/run/tests/nextflow.config index 6806a86ca3ef..df1c65a4aae8 100644 --- a/modules/nf-core/llamacpp-python/run/tests/nextflow.config +++ b/modules/nf-core/llamacpp-python/run/tests/nextflow.config @@ -1,7 +1,7 @@ nextflow.enable.moduleBinaries = true process { - withName: 'HF_DOWNLOAD' { + withName: 'HUGGINGFACE_DOWNLOAD' { containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } } withName: 'LLAMACPP_PYTHON_RUN' { From 26168b7f14d568c8fabcd06788a05dab093e2177 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 18:51:02 +0200 Subject: [PATCH 12/32] Update modules/nf-core/huggingface/download/tests/main.nf.test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not so many assertions for stub test Co-authored-by: Famke Bäuerle <45968370+famosab@users.noreply.github.com> --- modules/nf-core/huggingface/download/tests/main.nf.test | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test b/modules/nf-core/huggingface/download/tests/main.nf.test index 6f99fd1e48fd..e4c0a3d94940 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test +++ b/modules/nf-core/huggingface/download/tests/main.nf.test @@ -56,10 +56,7 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert process.out.output.size() == 1 }, - { assert process.out.output[0][0] == [ id:'test_model' ] }, - { assert file(process.out.output[0][1]).name == "gemma-3-1b-it-Q4_K_M.gguf" }, - { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } + { assert snapshot(sanitizeOutput(process.out)).match() } ) } } From 6dfff97e7fe77c2c274819cd73c19acc8748d3ba Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 19:06:43 +0200 Subject: [PATCH 13/32] more detail and naming of Hugging Face --- modules/nf-core/huggingface/download/meta.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index a3186bce7b07..0b79bd03777a 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -1,12 +1,12 @@ -name: hf_download -description: Tool for downloading models from HuggingFace +name: huggingface_download +description: Command-line interface for downloading models in GGUF format from Hugging Face Hub keywords: - llm - llama - ai tools: - huggingface_hub: - description: "HuggingFace Hub CLI interface" + description: "Command-line interface for interacting with Hugging Face Hub, allowing to download, upload and interact with models and datasets" homepage: "https://huggingface.co/docs/huggingface_hub/guides/cli" licence: - "MIT" @@ -19,13 +19,13 @@ input: e.g. `[ id:'sample1' ]`- prompt_file: - hf_repo: type: string - description: HuggingFace repository + description: Hugging Face repository - hf_file: type: string - description: HuggingFace GGUF file + description: Hugging Face GGUF file - hf_home: type: string - description: HuggingFace default cache directory + description: Hugging Face default cache directory output: output: - - meta: @@ -35,7 +35,7 @@ output: e.g. `[ id:'sample1' ]` - hf_file: type: file - description: Downloaded HuggingFace GGUF file + description: Downloaded Hugging Face GGUF file ontologies: [] versions_huggingface_hub: - - ${task.process}: From 3021074572fb1ffbcbe5523de4c1a8885102684c Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 19:16:09 +0200 Subject: [PATCH 14/32] linting modules using --- modules/nf-core/huggingface/download/main.nf | 2 +- modules/nf-core/llamacpp-python/run/main.nf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf index e279195d50e6..9c9d8c4d44c5 100644 --- a/modules/nf-core/huggingface/download/main.nf +++ b/modules/nf-core/huggingface/download/main.nf @@ -1,5 +1,5 @@ process HUGGINGFACE_DOWNLOAD { - tag "$meta.id" + tag "${meta.id}" label 'process_medium' conda "${moduleDir}/environment.yml" diff --git a/modules/nf-core/llamacpp-python/run/main.nf b/modules/nf-core/llamacpp-python/run/main.nf index 5dec0f6bcf28..9468132fd9a5 100644 --- a/modules/nf-core/llamacpp-python/run/main.nf +++ b/modules/nf-core/llamacpp-python/run/main.nf @@ -1,10 +1,10 @@ process LLAMACPP_PYTHON_RUN { - tag "$meta.id" + tag "${meta.id}" label 'process_medium' label 'process_gpu' conda "${moduleDir}/environment.yml" - container "${ task.ext.use_gpu ? 'quay.io/nf-core/llama-cpp-python:0.1.9' : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5' }" + container "${task.ext.use_gpu ? 'quay.io/nf-core/llama-cpp-python:0.1.9' : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5'}" input: tuple val(meta), path(prompt_file), path(gguf_model) From 4630e5a55a728ad16e8ce7a593f25fa207b73bd6 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 20:51:50 +0200 Subject: [PATCH 15/32] generate files on the fly --- .../llamacpp-python/run/tests/main.nf.test | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpp-python/run/tests/main.nf.test index 2aeaeb0d8add..bbf9fc98817b 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test @@ -33,8 +33,22 @@ nextflow_process { when { process { """ + // Generate prompt.json with provided content + def promptFile = file('prompt.json') + promptFile.text = '''[ + { + "role": "system", + "content": "A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions" + }, + { + "role": "user", + "content": "Describe Barcelona in one paragraph" + } +] +''' + input[0] = HUGGINGFACE_DOWNLOAD.out.output.map { meta, model -> - [ [ id:'test_run' ], file("${moduleDir}/tests/data/prompt.json"), model ] + [ [ id:'test_run' ], promptFile, model ] } """ } @@ -59,10 +73,28 @@ nextflow_process { when { process { """ + // Generate prompt.json with provided content + def promptFile = file('prompt.json') + promptFile.text = '''[ + { + "role": "system", + "content": "A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions" + }, + { + "role": "user", + "content": "Describe Barcelona in one paragraph" + } +] +''' + + // Generate an empty stub_model.gguf file + def modelFile = file('stub_model.gguf') + modelFile.createNewFile() + input[0] = [ [ id:'test_run' ], - file("${moduleDir}/tests/data/prompt.json"), - file("${moduleDir}/tests/data/stub_model.gguf") + promptFile, + modelFile ] """ } From 53c782648705cfe5e6cceb57747a9e3bb7d45381 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 20:52:45 +0200 Subject: [PATCH 16/32] rmed data files for tests --- .../nf-core/llamacpp-python/run/tests/data/prompt.json | 10 ---------- .../llamacpp-python/run/tests/data/stub_model.gguf | 0 2 files changed, 10 deletions(-) delete mode 100644 modules/nf-core/llamacpp-python/run/tests/data/prompt.json delete mode 100644 modules/nf-core/llamacpp-python/run/tests/data/stub_model.gguf diff --git a/modules/nf-core/llamacpp-python/run/tests/data/prompt.json b/modules/nf-core/llamacpp-python/run/tests/data/prompt.json deleted file mode 100644 index 52d9ea3e2aa7..000000000000 --- a/modules/nf-core/llamacpp-python/run/tests/data/prompt.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - { - "role": "system", - "content": "A chat between a curious user and an artificial intelligence assistant. The assistant gives helpful, detailed, and polite answers to the user's questions" - }, - { - "role": "user", - "content": "Describe Barcelona in one paragraph" - } -] diff --git a/modules/nf-core/llamacpp-python/run/tests/data/stub_model.gguf b/modules/nf-core/llamacpp-python/run/tests/data/stub_model.gguf deleted file mode 100644 index e69de29bb2d1..000000000000 From 4156db08961a716d3432e988b8816dfb35b5d7ad Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 21:16:11 +0200 Subject: [PATCH 17/32] upgrade tests to work on the fly and updated snaps --- .../huggingface/download/tests/main.nf.test.snap | 12 ++++++++++-- .../huggingface/download/tests/nextflow.config | 2 -- .../nf-core/llamacpp-python/run/tests/main.nf.test | 2 +- .../llamacpp-python/run/tests/main.nf.test.snap | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test.snap b/modules/nf-core/huggingface/download/tests/main.nf.test.snap index 68a48764c0a8..b21e9080d8aa 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test.snap +++ b/modules/nf-core/huggingface/download/tests/main.nf.test.snap @@ -2,6 +2,14 @@ "stub - download gguf file": { "content": [ { + "output": [ + [ + { + "id": "test_model" + }, + "gemma-3-1b-it-Q4_K_M.gguf:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], "versions_huggingface_hub": [ [ "HUGGINGFACE_DOWNLOAD", @@ -11,7 +19,7 @@ ] } ], - "timestamp": "2026-03-26T08:39:57.919278809", + "timestamp": "2026-04-04T20:59:17.940382342", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" @@ -35,4 +43,4 @@ "nextflow": "25.10.4" } } -} +} \ No newline at end of file diff --git a/modules/nf-core/huggingface/download/tests/nextflow.config b/modules/nf-core/huggingface/download/tests/nextflow.config index 93c850d839c7..377fa1bb065c 100644 --- a/modules/nf-core/huggingface/download/tests/nextflow.config +++ b/modules/nf-core/huggingface/download/tests/nextflow.config @@ -1,5 +1,3 @@ -nextflow.enable.moduleBinaries = true - process { withName: 'HUGGINGFACE_DOWNLOAD' { containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpp-python/run/tests/main.nf.test index bbf9fc98817b..f7ae1c190e2a 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test @@ -89,7 +89,7 @@ nextflow_process { // Generate an empty stub_model.gguf file def modelFile = file('stub_model.gguf') - modelFile.createNewFile() + modelFile.text = '' input[0] = [ [ id:'test_run' ], diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap b/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap index 4bd263f10e6e..b417bbbbd6a1 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap @@ -11,7 +11,7 @@ ] } ], - "timestamp": "2026-03-25T18:33:08.596485421", + "timestamp": "2026-04-04T21:04:22.372671272", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" @@ -35,4 +35,4 @@ "nextflow": "25.10.4" } } -} +} \ No newline at end of file From 421603e938aa087a09af17fcb8c1e13f693501cd Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 4 Apr 2026 22:05:47 +0200 Subject: [PATCH 18/32] upgrading tests - adding new smollm3 --- .../huggingface/download/tests/main.nf.test | 37 ++++++++++++++++--- .../download/tests/main.nf.test.snap | 28 +++++++++++--- .../llamacpp-python/run/tests/main.nf.test | 6 +++ .../llamacpp-python/run/tests/nextflow.config | 2 +- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test b/modules/nf-core/huggingface/download/tests/main.nf.test index e4c0a3d94940..1ae2df9dd7e2 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test +++ b/modules/nf-core/huggingface/download/tests/main.nf.test @@ -9,13 +9,13 @@ nextflow_process { tag "huggingface" tag "huggingface/download" - test("download gguf file") { + test("download gguf file - gemma3") { when { process { """ input[0] = [ - [ id:'test_model' ], + [ id:'test_model_gemma3' ], "ggml-org/gemma-3-1b-it-GGUF", "gemma-3-1b-it-Q4_K_M.gguf", "./hf_cache" @@ -28,7 +28,7 @@ nextflow_process { assertAll( { assert process.success }, { assert process.out.output.size() == 1 }, - { assert process.out.output[0][0] == [ id:'test_model' ] }, + { assert process.out.output[0][0] == [ id:'test_model_gemma3' ] }, { assert file(process.out.output[0][1]).name == "gemma-3-1b-it-Q4_K_M.gguf" }, { assert file(process.out.output[0][1]).size() > 0 }, { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } @@ -36,7 +36,34 @@ nextflow_process { } } - test("stub - download gguf file") { + test("download gguf file - smollm3") { + + when { + process { + """ + input[0] = [ + [ id:'test_model_smollm3' ], + "unsloth/SmolLM3-3B-GGUF", + "SmolLM3-3B-UD-IQ2_XXS.gguf", + "./hf_cache" + ] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.output.size() == 1 }, + { assert process.out.output[0][0] == [ id:'test_model_smollm3' ] }, + { assert file(process.out.output[0][1]).name == "SmolLM3-3B-UD-IQ2_XXS.gguf" }, + { assert file(process.out.output[0][1]).size() > 0 }, + { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } + ) + } + } + + test("stub - download gguf file - gemma3") { options "-stub" @@ -44,7 +71,7 @@ nextflow_process { process { """ input[0] = [ - [ id:'test_model' ], + [ id:'test_model_gemma3' ], "ggml-org/gemma-3-1b-it-GGUF", "gemma-3-1b-it-Q4_K_M.gguf", "./hf_cache" diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test.snap b/modules/nf-core/huggingface/download/tests/main.nf.test.snap index b21e9080d8aa..2d90773afc25 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test.snap +++ b/modules/nf-core/huggingface/download/tests/main.nf.test.snap @@ -1,11 +1,11 @@ { - "stub - download gguf file": { + "stub - download gguf file - gemma3": { "content": [ { "output": [ [ { - "id": "test_model" + "id": "test_model_gemma3" }, "gemma-3-1b-it-Q4_K_M.gguf:md5,d41d8cd98f00b204e9800998ecf8427e" ] @@ -19,13 +19,13 @@ ] } ], - "timestamp": "2026-04-04T20:59:17.940382342", + "timestamp": "2026-04-04T22:00:17.896195894", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" } }, - "download gguf file": { + "download gguf file - gemma3": { "content": [ { "versions_huggingface_hub": [ @@ -37,7 +37,25 @@ ] } ], - "timestamp": "2026-03-26T08:38:24.630341776", + "timestamp": "2026-04-04T21:36:18.125789808", + "meta": { + "nf-test": "0.9.5", + "nextflow": "25.10.4" + } + }, + "download gguf file - smollm3": { + "content": [ + { + "versions_huggingface_hub": [ + [ + "HUGGINGFACE_DOWNLOAD", + "huggingface_hub", + "1.6.0" + ] + ] + } + ], + "timestamp": "2026-04-04T21:55:38.228583826", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpp-python/run/tests/main.nf.test index f7ae1c190e2a..3000d957a668 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test +++ b/modules/nf-core/llamacpp-python/run/tests/main.nf.test @@ -31,6 +31,9 @@ nextflow_process { } when { + params { + module_args = '--seed 42' + } process { """ // Generate prompt.json with provided content @@ -71,6 +74,9 @@ nextflow_process { options "-stub" when { + params { + module_args = '--seed 42' + } process { """ // Generate prompt.json with provided content diff --git a/modules/nf-core/llamacpp-python/run/tests/nextflow.config b/modules/nf-core/llamacpp-python/run/tests/nextflow.config index df1c65a4aae8..d36bba22b0e6 100644 --- a/modules/nf-core/llamacpp-python/run/tests/nextflow.config +++ b/modules/nf-core/llamacpp-python/run/tests/nextflow.config @@ -5,6 +5,6 @@ process { containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } } withName: 'LLAMACPP_PYTHON_RUN' { - ext.args = "--seed 42" + ext.args = params.module_args } } From af5eadd42863a5d6083a7c4290c7b3989f201c7c Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 8 Apr 2026 17:09:33 +0200 Subject: [PATCH 19/32] Update modules/nf-core/llamacpp-python/run/main.nf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit output to ${prefix} Co-authored-by: Famke Bäuerle <45968370+famosab@users.noreply.github.com> --- modules/nf-core/llamacpp-python/run/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/llamacpp-python/run/main.nf b/modules/nf-core/llamacpp-python/run/main.nf index 9468132fd9a5..2da55b50b38d 100644 --- a/modules/nf-core/llamacpp-python/run/main.nf +++ b/modules/nf-core/llamacpp-python/run/main.nf @@ -23,7 +23,7 @@ process LLAMACPP_PYTHON_RUN { llamacpp-python.py \ --model ${gguf_model} \ --messages ${prompt_file} \ - --output output.txt \ + --output ${prefix}.txt \ ${args} """ From 02d3f6dd389ae8293cecc1b820527d56c74a8c99 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 8 Apr 2026 17:09:53 +0200 Subject: [PATCH 20/32] Update modules/nf-core/llamacpp-python/run/main.nf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit output to ${prefix} Co-authored-by: Famke Bäuerle <45968370+famosab@users.noreply.github.com> --- modules/nf-core/llamacpp-python/run/main.nf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/nf-core/llamacpp-python/run/main.nf b/modules/nf-core/llamacpp-python/run/main.nf index 2da55b50b38d..5113cea63e68 100644 --- a/modules/nf-core/llamacpp-python/run/main.nf +++ b/modules/nf-core/llamacpp-python/run/main.nf @@ -30,7 +30,6 @@ process LLAMACPP_PYTHON_RUN { stub: prefix = task.ext.prefix ?: "${meta.id}" """ - touch output.txt - + touch ${prefix}.txt """ } From 297f503becbaa41ae888714c674e21acc43fd069 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 8 Apr 2026 17:10:15 +0200 Subject: [PATCH 21/32] Update modules/nf-core/llamacpp-python/run/main.nf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit output to ${prefix} Co-authored-by: Famke Bäuerle <45968370+famosab@users.noreply.github.com> --- modules/nf-core/llamacpp-python/run/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/llamacpp-python/run/main.nf b/modules/nf-core/llamacpp-python/run/main.nf index 5113cea63e68..aa1bcf48fc5b 100644 --- a/modules/nf-core/llamacpp-python/run/main.nf +++ b/modules/nf-core/llamacpp-python/run/main.nf @@ -10,7 +10,7 @@ process LLAMACPP_PYTHON_RUN { tuple val(meta), path(prompt_file), path(gguf_model) output: - tuple val(meta), path("output.txt"), emit: output + tuple val(meta), path("${prefix}.txt"), emit: output tuple val("${task.process}"), val("llama-cpp-python"), eval("python3 -c 'import llama_cpp; print(llama_cpp.__version__)'"), topic: versions, emit: versions_llama_cpp_python when: From ac61a5699d1ac746d72abda6e044c5434843aa7b Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 8 Apr 2026 17:59:44 +0200 Subject: [PATCH 22/32] Moving name of the module, script name and adapting tests and stubs --- modules/nf-core/huggingface/download/main.nf | 2 +- modules/nf-core/huggingface/download/meta.yml | 5 +++-- .../nf-core/huggingface/download/tests/nextflow.config | 2 +- .../{llamacpp-python => llamacpppython}/run/Dockerfile | 0 .../run/environment.yml | 0 .../{llamacpp-python => llamacpppython}/run/main.nf | 4 ++-- .../{llamacpp-python => llamacpppython}/run/meta.yml | 7 +++++-- .../run/resources/usr/bin/llama-cpp-python.py} | 0 .../run/tests/main.nf.test | 8 ++++---- .../run/tests/main.nf.test.snap | 0 .../run/tests/nextflow.config | 2 +- 11 files changed, 17 insertions(+), 13 deletions(-) rename modules/nf-core/{llamacpp-python => llamacpppython}/run/Dockerfile (100%) rename modules/nf-core/{llamacpp-python => llamacpppython}/run/environment.yml (100%) rename modules/nf-core/{llamacpp-python => llamacpppython}/run/main.nf (94%) rename modules/nf-core/{llamacpp-python => llamacpppython}/run/meta.yml (97%) rename modules/nf-core/{llamacpp-python/run/resources/usr/bin/llamacpp-python.py => llamacpppython/run/resources/usr/bin/llama-cpp-python.py} (100%) rename modules/nf-core/{llamacpp-python => llamacpppython}/run/tests/main.nf.test (96%) rename modules/nf-core/{llamacpp-python => llamacpppython}/run/tests/main.nf.test.snap (100%) rename modules/nf-core/{llamacpp-python => llamacpppython}/run/tests/nextflow.config (87%) diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf index 9c9d8c4d44c5..23e9364cf565 100644 --- a/modules/nf-core/huggingface/download/main.nf +++ b/modules/nf-core/huggingface/download/main.nf @@ -16,7 +16,7 @@ process HUGGINGFACE_DOWNLOAD { task.ext.when == null || task.ext.when script: - def hf_home_resolved = hf_home ?: "${workflow.projectDir}/hf_cache" + def hf_home_resolved = hf_home ?: "${workflow.workDir}/hf_cache" """ export HF_HOME="${hf_home_resolved}" export HF_HUB_CACHE=\$HF_HOME diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index 0b79bd03777a..fd1b75c8b1c3 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -1,9 +1,10 @@ name: huggingface_download description: Command-line interface for downloading models in GGUF format from Hugging Face Hub keywords: - - llm - - llama - ai + - gguf + - llama + - llm tools: - huggingface_hub: description: "Command-line interface for interacting with Hugging Face Hub, allowing to download, upload and interact with models and datasets" diff --git a/modules/nf-core/huggingface/download/tests/nextflow.config b/modules/nf-core/huggingface/download/tests/nextflow.config index 377fa1bb065c..53e3adbb13f4 100644 --- a/modules/nf-core/huggingface/download/tests/nextflow.config +++ b/modules/nf-core/huggingface/download/tests/nextflow.config @@ -1,5 +1,5 @@ process { withName: 'HUGGINGFACE_DOWNLOAD' { - containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } + containerOptions = { workflow.profile.contains('docker') ? "--volume ${workDir}/hf_cache:${workDir}/hf_cache" : '' } } } diff --git a/modules/nf-core/llamacpp-python/run/Dockerfile b/modules/nf-core/llamacpppython/run/Dockerfile similarity index 100% rename from modules/nf-core/llamacpp-python/run/Dockerfile rename to modules/nf-core/llamacpppython/run/Dockerfile diff --git a/modules/nf-core/llamacpp-python/run/environment.yml b/modules/nf-core/llamacpppython/run/environment.yml similarity index 100% rename from modules/nf-core/llamacpp-python/run/environment.yml rename to modules/nf-core/llamacpppython/run/environment.yml diff --git a/modules/nf-core/llamacpp-python/run/main.nf b/modules/nf-core/llamacpppython/run/main.nf similarity index 94% rename from modules/nf-core/llamacpp-python/run/main.nf rename to modules/nf-core/llamacpppython/run/main.nf index aa1bcf48fc5b..51da616104be 100644 --- a/modules/nf-core/llamacpp-python/run/main.nf +++ b/modules/nf-core/llamacpppython/run/main.nf @@ -1,4 +1,4 @@ -process LLAMACPP_PYTHON_RUN { +process LLAMACPPPYTHON_RUN { tag "${meta.id}" label 'process_medium' label 'process_gpu' @@ -20,7 +20,7 @@ process LLAMACPP_PYTHON_RUN { def args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" """ - llamacpp-python.py \ + llama-cpp-python.py \ --model ${gguf_model} \ --messages ${prompt_file} \ --output ${prefix}.txt \ diff --git a/modules/nf-core/llamacpp-python/run/meta.yml b/modules/nf-core/llamacpppython/run/meta.yml similarity index 97% rename from modules/nf-core/llamacpp-python/run/meta.yml rename to modules/nf-core/llamacpppython/run/meta.yml index 70d7bbf4f162..b3d66774831d 100644 --- a/modules/nf-core/llamacpp-python/run/meta.yml +++ b/modules/nf-core/llamacpppython/run/meta.yml @@ -1,9 +1,12 @@ name: llamacpp_python_run description: Python wrapper for running locally-hosted LLM with llama.cpp keywords: - - llm - - llama - ai + - inference + - llama + - llm + - local-inference + - offline-llm tools: - llama-cpp-python: description: "Python wrapper for llama.cpp LLM inference tool" diff --git a/modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py b/modules/nf-core/llamacpppython/run/resources/usr/bin/llama-cpp-python.py similarity index 100% rename from modules/nf-core/llamacpp-python/run/resources/usr/bin/llamacpp-python.py rename to modules/nf-core/llamacpppython/run/resources/usr/bin/llama-cpp-python.py diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test b/modules/nf-core/llamacpppython/run/tests/main.nf.test similarity index 96% rename from modules/nf-core/llamacpp-python/run/tests/main.nf.test rename to modules/nf-core/llamacpppython/run/tests/main.nf.test index 3000d957a668..c6f2ad9d977f 100644 --- a/modules/nf-core/llamacpp-python/run/tests/main.nf.test +++ b/modules/nf-core/llamacpppython/run/tests/main.nf.test @@ -1,8 +1,8 @@ nextflow_process { - name "Test Process LLAMACPP_PYTHON_RUN" + name "Test Process LLAMACPPPYTHON_RUN" script "../main.nf" - process "LLAMACPP_PYTHON_RUN" + process "LLAMACPPPYTHON_RUN" tag "modules" tag "modules_nfcore" @@ -62,7 +62,7 @@ nextflow_process { { assert process.success }, { assert process.out.output.size() == 1 }, { assert process.out.output[0][0] == [ id:'test_run' ] }, - { assert file(process.out.output[0][1]).name == "output.txt" }, + { assert file(process.out.output[0][1]).name == "test_run.txt" }, { assert file(process.out.output[0][1]).size() > 0 }, { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } ) @@ -111,7 +111,7 @@ nextflow_process { { assert process.success }, { assert process.out.output.size() == 1 }, { assert process.out.output[0][0] == [ id:'test_run' ] }, - { assert file(process.out.output[0][1]).name == "output.txt" }, + { assert file(process.out.output[0][1]).name == "test_run.txt" }, { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } ) } diff --git a/modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap b/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap similarity index 100% rename from modules/nf-core/llamacpp-python/run/tests/main.nf.test.snap rename to modules/nf-core/llamacpppython/run/tests/main.nf.test.snap diff --git a/modules/nf-core/llamacpp-python/run/tests/nextflow.config b/modules/nf-core/llamacpppython/run/tests/nextflow.config similarity index 87% rename from modules/nf-core/llamacpp-python/run/tests/nextflow.config rename to modules/nf-core/llamacpppython/run/tests/nextflow.config index d36bba22b0e6..5b139fd364ab 100644 --- a/modules/nf-core/llamacpp-python/run/tests/nextflow.config +++ b/modules/nf-core/llamacpppython/run/tests/nextflow.config @@ -4,7 +4,7 @@ process { withName: 'HUGGINGFACE_DOWNLOAD' { containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } } - withName: 'LLAMACPP_PYTHON_RUN' { + withName: 'LLAMACPPPYTHON_RUN' { ext.args = params.module_args } } From ca4721bd6375015dd88d6d0dc7ce243b5e8056ab Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 8 Apr 2026 18:15:55 +0200 Subject: [PATCH 23/32] update tests --- modules/nf-core/llamacpppython/run/meta.yml | 4 ++-- modules/nf-core/llamacpppython/run/tests/main.nf.test | 4 ++-- .../nf-core/llamacpppython/run/tests/main.nf.test.snap | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/nf-core/llamacpppython/run/meta.yml b/modules/nf-core/llamacpppython/run/meta.yml index b3d66774831d..52e9f4967a65 100644 --- a/modules/nf-core/llamacpppython/run/meta.yml +++ b/modules/nf-core/llamacpppython/run/meta.yml @@ -1,4 +1,4 @@ -name: llamacpp_python_run +name: llamacpppython_run description: Python wrapper for running locally-hosted LLM with llama.cpp keywords: - ai @@ -39,7 +39,7 @@ output: description: | Groovy Map containing sample information e.g. `[ id:'sample1' ]` - - "output.txt": + - ${prefix}.txt: type: file description: File with the output of LLM inference request ontologies: [] diff --git a/modules/nf-core/llamacpppython/run/tests/main.nf.test b/modules/nf-core/llamacpppython/run/tests/main.nf.test index c6f2ad9d977f..218f61f24380 100644 --- a/modules/nf-core/llamacpppython/run/tests/main.nf.test +++ b/modules/nf-core/llamacpppython/run/tests/main.nf.test @@ -6,8 +6,8 @@ nextflow_process { tag "modules" tag "modules_nfcore" - tag "llamacpp-python" - tag "llamacpp-python/run" + tag "llamacpppython" + tag "llamacpppython/run" tag "huggingface/download" test("run inference with downloaded gguf model") { diff --git a/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap b/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap index b417bbbbd6a1..8f0e320e5443 100644 --- a/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap +++ b/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap @@ -4,14 +4,14 @@ { "versions_llama_cpp_python": [ [ - "LLAMACPP_PYTHON_RUN", + "LLAMACPPPYTHON_RUN", "llama-cpp-python", "0.3.16" ] ] } ], - "timestamp": "2026-04-04T21:04:22.372671272", + "timestamp": "2026-04-08T18:13:43.62132008", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" @@ -22,14 +22,14 @@ { "versions_llama_cpp_python": [ [ - "LLAMACPP_PYTHON_RUN", + "LLAMACPPPYTHON_RUN", "llama-cpp-python", "0.3.16" ] ] } ], - "timestamp": "2026-03-25T17:23:21.997786726", + "timestamp": "2026-04-08T18:13:50.462201237", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" From d65181d858036723de05d3807907acc9e9ecbb98 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 9 Apr 2026 16:21:12 +0200 Subject: [PATCH 24/32] update task.accelerator --- modules/nf-core/llamacpppython/run/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/llamacpppython/run/main.nf b/modules/nf-core/llamacpppython/run/main.nf index 51da616104be..5d8625bfc342 100644 --- a/modules/nf-core/llamacpppython/run/main.nf +++ b/modules/nf-core/llamacpppython/run/main.nf @@ -4,7 +4,7 @@ process LLAMACPPPYTHON_RUN { label 'process_gpu' conda "${moduleDir}/environment.yml" - container "${task.ext.use_gpu ? 'quay.io/nf-core/llama-cpp-python:0.1.9' : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5'}" + container "${task.accelerator ? 'quay.io/nf-core/llama-cpp-python:0.1.9' : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5'}" input: tuple val(meta), path(prompt_file), path(gguf_model) From cd3d1b96df856c972a373880cb352dfefe58e4e3 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Thu, 9 Apr 2026 16:55:31 +0200 Subject: [PATCH 25/32] moving all assertions into the same snapshot --- .../huggingface/download/tests/main.nf.test | 24 +++++++++++-------- .../download/tests/main.nf.test.snap | 16 +++++++++++-- .../llamacpppython/run/tests/main.nf.test | 22 ++++++++++------- .../run/tests/main.nf.test.snap | 15 ++++++++++-- 4 files changed, 54 insertions(+), 23 deletions(-) diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test b/modules/nf-core/huggingface/download/tests/main.nf.test index 1ae2df9dd7e2..74cb97ec5c20 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test +++ b/modules/nf-core/huggingface/download/tests/main.nf.test @@ -27,11 +27,13 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert process.out.output.size() == 1 }, - { assert process.out.output[0][0] == [ id:'test_model_gemma3' ] }, - { assert file(process.out.output[0][1]).name == "gemma-3-1b-it-Q4_K_M.gguf" }, - { assert file(process.out.output[0][1]).size() > 0 }, - { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } + { assert snapshot( + process.out.output.size(), + process.out.output[0][0], + file(process.out.output[0][1]).name, + file(process.out.output[0][1]).size() > 0, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } ) } } @@ -54,11 +56,13 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert process.out.output.size() == 1 }, - { assert process.out.output[0][0] == [ id:'test_model_smollm3' ] }, - { assert file(process.out.output[0][1]).name == "SmolLM3-3B-UD-IQ2_XXS.gguf" }, - { assert file(process.out.output[0][1]).size() > 0 }, - { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } + { assert snapshot( + process.out.output.size(), + process.out.output[0][0], + file(process.out.output[0][1]).name, + file(process.out.output[0][1]).size() > 0, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } ) } } diff --git a/modules/nf-core/huggingface/download/tests/main.nf.test.snap b/modules/nf-core/huggingface/download/tests/main.nf.test.snap index 2d90773afc25..145bf736d334 100644 --- a/modules/nf-core/huggingface/download/tests/main.nf.test.snap +++ b/modules/nf-core/huggingface/download/tests/main.nf.test.snap @@ -27,6 +27,12 @@ }, "download gguf file - gemma3": { "content": [ + 1, + { + "id": "test_model_gemma3" + }, + "gemma-3-1b-it-Q4_K_M.gguf", + true, { "versions_huggingface_hub": [ [ @@ -37,7 +43,7 @@ ] } ], - "timestamp": "2026-04-04T21:36:18.125789808", + "timestamp": "2026-04-09T16:48:14.073310733", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" @@ -45,6 +51,12 @@ }, "download gguf file - smollm3": { "content": [ + 1, + { + "id": "test_model_smollm3" + }, + "SmolLM3-3B-UD-IQ2_XXS.gguf", + true, { "versions_huggingface_hub": [ [ @@ -55,7 +67,7 @@ ] } ], - "timestamp": "2026-04-04T21:55:38.228583826", + "timestamp": "2026-04-09T16:49:18.323499722", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" diff --git a/modules/nf-core/llamacpppython/run/tests/main.nf.test b/modules/nf-core/llamacpppython/run/tests/main.nf.test index 218f61f24380..9896bd3b7051 100644 --- a/modules/nf-core/llamacpppython/run/tests/main.nf.test +++ b/modules/nf-core/llamacpppython/run/tests/main.nf.test @@ -60,11 +60,13 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert process.out.output.size() == 1 }, - { assert process.out.output[0][0] == [ id:'test_run' ] }, - { assert file(process.out.output[0][1]).name == "test_run.txt" }, - { assert file(process.out.output[0][1]).size() > 0 }, - { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } + { assert snapshot( + process.out.output.size(), + process.out.output[0][0], + file(process.out.output[0][1]).name, + file(process.out.output[0][1]).size() > 0, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } ) } } @@ -109,10 +111,12 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert process.out.output.size() == 1 }, - { assert process.out.output[0][0] == [ id:'test_run' ] }, - { assert file(process.out.output[0][1]).name == "test_run.txt" }, - { assert snapshot(process.out.findAll { key, val -> key.startsWith('versions') }).match() } + { assert snapshot( + process.out.output.size(), + process.out.output[0][0], + file(process.out.output[0][1]).name, + process.out.findAll { key, val -> key.startsWith('versions') } + ).match() } ) } } diff --git a/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap b/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap index 8f0e320e5443..8d8ab1f81cef 100644 --- a/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap +++ b/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap @@ -1,6 +1,12 @@ { "run inference with downloaded gguf model": { "content": [ + 1, + { + "id": "test_run" + }, + "test_run.txt", + true, { "versions_llama_cpp_python": [ [ @@ -11,7 +17,7 @@ ] } ], - "timestamp": "2026-04-08T18:13:43.62132008", + "timestamp": "2026-04-09T16:40:57.888211501", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" @@ -19,6 +25,11 @@ }, "stub - run inference with json prompt": { "content": [ + 1, + { + "id": "test_run" + }, + "test_run.txt", { "versions_llama_cpp_python": [ [ @@ -29,7 +40,7 @@ ] } ], - "timestamp": "2026-04-08T18:13:50.462201237", + "timestamp": "2026-04-09T16:41:05.221151819", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" From fb8136599a61a3a760bf3804c9edcd4cb262ac88 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Sat, 11 Apr 2026 17:55:59 +0200 Subject: [PATCH 26/32] removed unneded nextflow.config for test --- modules/nf-core/huggingface/download/tests/nextflow.config | 5 ----- modules/nf-core/llamacpppython/run/tests/nextflow.config | 3 --- 2 files changed, 8 deletions(-) delete mode 100644 modules/nf-core/huggingface/download/tests/nextflow.config diff --git a/modules/nf-core/huggingface/download/tests/nextflow.config b/modules/nf-core/huggingface/download/tests/nextflow.config deleted file mode 100644 index 53e3adbb13f4..000000000000 --- a/modules/nf-core/huggingface/download/tests/nextflow.config +++ /dev/null @@ -1,5 +0,0 @@ -process { - withName: 'HUGGINGFACE_DOWNLOAD' { - containerOptions = { workflow.profile.contains('docker') ? "--volume ${workDir}/hf_cache:${workDir}/hf_cache" : '' } - } -} diff --git a/modules/nf-core/llamacpppython/run/tests/nextflow.config b/modules/nf-core/llamacpppython/run/tests/nextflow.config index 5b139fd364ab..21556318f133 100644 --- a/modules/nf-core/llamacpppython/run/tests/nextflow.config +++ b/modules/nf-core/llamacpppython/run/tests/nextflow.config @@ -1,9 +1,6 @@ nextflow.enable.moduleBinaries = true process { - withName: 'HUGGINGFACE_DOWNLOAD' { - containerOptions = { workflow.profile.contains('docker') ? "--volume ${projectDir}/hf_cache:${projectDir}/hf_cache" : '' } - } withName: 'LLAMACPPPYTHON_RUN' { ext.args = params.module_args } From dfadccbda6ff7cc82391798b4c4e4d0e4b045e12 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Mon, 13 Apr 2026 21:16:04 +0200 Subject: [PATCH 27/32] addressing some coments, such as cache_dir --- modules/nf-core/huggingface/download/main.nf | 3 +-- modules/nf-core/huggingface/download/meta.yml | 4 +++- modules/nf-core/llamacpppython/run/Dockerfile | 2 +- modules/nf-core/llamacpppython/run/meta.yml | 1 - 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf index 23e9364cf565..66678391a5fb 100644 --- a/modules/nf-core/huggingface/download/main.nf +++ b/modules/nf-core/huggingface/download/main.nf @@ -16,9 +16,8 @@ process HUGGINGFACE_DOWNLOAD { task.ext.when == null || task.ext.when script: - def hf_home_resolved = hf_home ?: "${workflow.workDir}/hf_cache" """ - export HF_HOME="${hf_home_resolved}" + export HF_HOME="${hf_home:-./hf_cache}" export HF_HUB_CACHE=\$HF_HOME hf download ${hf_repo} ${hf_file} --local-dir \$PWD """ diff --git a/modules/nf-core/huggingface/download/meta.yml b/modules/nf-core/huggingface/download/meta.yml index fd1b75c8b1c3..f961aa7458d0 100644 --- a/modules/nf-core/huggingface/download/meta.yml +++ b/modules/nf-core/huggingface/download/meta.yml @@ -1,10 +1,12 @@ name: huggingface_download description: Command-line interface for downloading models in GGUF format from Hugging Face Hub keywords: - - ai - gguf + - inference - llama - llm + - local-inference + - offline-llm tools: - huggingface_hub: description: "Command-line interface for interacting with Hugging Face Hub, allowing to download, upload and interact with models and datasets" diff --git a/modules/nf-core/llamacpppython/run/Dockerfile b/modules/nf-core/llamacpppython/run/Dockerfile index aeb89834ee1c..c26428f1f920 100644 --- a/modules/nf-core/llamacpppython/run/Dockerfile +++ b/modules/nf-core/llamacpppython/run/Dockerfile @@ -1,5 +1,5 @@ FROM nvidia/cuda:12.4.1-devel-ubuntu22.04 RUN apt-get update && apt-get install -y python3 python3-pip -RUN pip3 install llama-cpp-python \ +RUN pip3 install llama-cpp-python==0.3.16 \ --extra-index-url https://abetlen.github.io/llama-cpp-python/whl/cu124 diff --git a/modules/nf-core/llamacpppython/run/meta.yml b/modules/nf-core/llamacpppython/run/meta.yml index 52e9f4967a65..18a6d3a2a2f5 100644 --- a/modules/nf-core/llamacpppython/run/meta.yml +++ b/modules/nf-core/llamacpppython/run/meta.yml @@ -1,7 +1,6 @@ name: llamacpppython_run description: Python wrapper for running locally-hosted LLM with llama.cpp keywords: - - ai - inference - llama - llm From 1dbb3e99b1979956d8f8e8ae859d34f0fa20ff52 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Mon, 13 Apr 2026 21:29:34 +0200 Subject: [PATCH 28/32] lint didn't like, so out --- modules/nf-core/huggingface/download/main.nf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/nf-core/huggingface/download/main.nf b/modules/nf-core/huggingface/download/main.nf index 66678391a5fb..095a4d472e6f 100644 --- a/modules/nf-core/huggingface/download/main.nf +++ b/modules/nf-core/huggingface/download/main.nf @@ -17,7 +17,7 @@ process HUGGINGFACE_DOWNLOAD { script: """ - export HF_HOME="${hf_home:-./hf_cache}" + export HF_HOME="${hf_home}" export HF_HUB_CACHE=\$HF_HOME hf download ${hf_repo} ${hf_file} --local-dir \$PWD """ From bfe3bf932fb38b2949ee0f2035e1429e38ccf292 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Tue, 14 Apr 2026 23:07:12 +0200 Subject: [PATCH 29/32] script moved to work as template and corresponding changes to versions and tests --- modules/nf-core/llamacpppython/run/main.nf | 17 ++++++++--------- .../usr/bin => templates}/llama-cpp-python.py | 17 ++++++++++++++--- .../llamacpppython/run/tests/main.nf.test.snap | 16 ++++------------ 3 files changed, 26 insertions(+), 24 deletions(-) rename modules/nf-core/llamacpppython/run/{resources/usr/bin => templates}/llama-cpp-python.py (88%) diff --git a/modules/nf-core/llamacpppython/run/main.nf b/modules/nf-core/llamacpppython/run/main.nf index 5d8625bfc342..3a12334424e4 100644 --- a/modules/nf-core/llamacpppython/run/main.nf +++ b/modules/nf-core/llamacpppython/run/main.nf @@ -11,25 +11,24 @@ process LLAMACPPPYTHON_RUN { output: tuple val(meta), path("${prefix}.txt"), emit: output - tuple val("${task.process}"), val("llama-cpp-python"), eval("python3 -c 'import llama_cpp; print(llama_cpp.__version__)'"), topic: versions, emit: versions_llama_cpp_python + path "versions.yml", emit: versions_llama_cpp_python, topic: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' + args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" - """ - llama-cpp-python.py \ - --model ${gguf_model} \ - --messages ${prompt_file} \ - --output ${prefix}.txt \ - ${args} - """ + template 'llama-cpp-python.py' stub: prefix = task.ext.prefix ?: "${meta.id}" """ touch ${prefix}.txt + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + llama-cpp-python: \$(python3 -c 'import llama_cpp; print(llama_cpp.__version__)') + END_VERSIONS """ } diff --git a/modules/nf-core/llamacpppython/run/resources/usr/bin/llama-cpp-python.py b/modules/nf-core/llamacpppython/run/templates/llama-cpp-python.py similarity index 88% rename from modules/nf-core/llamacpppython/run/resources/usr/bin/llama-cpp-python.py rename to modules/nf-core/llamacpppython/run/templates/llama-cpp-python.py index 4e332bca6338..94f892368df3 100755 --- a/modules/nf-core/llamacpppython/run/resources/usr/bin/llama-cpp-python.py +++ b/modules/nf-core/llamacpppython/run/templates/llama-cpp-python.py @@ -3,6 +3,7 @@ import argparse import json import os +import shlex import sys import llama_cpp @@ -107,7 +108,7 @@ def llamacpp_python( sys.exit(1) -def main(): +def main(args_string=None): parser = argparse.ArgumentParser(description="Submit a process with model.") parser.add_argument("-s", "--messages", required=True, help="JSON message") parser.add_argument("-m", "--model", required=True, help="Model used") @@ -118,7 +119,7 @@ def main(): parser.add_argument("--seed", default=None, type=int, help="Defined seed") parser.add_argument("--verbose", action="store_true", help="Verbose output") - args = parser.parse_args() + args = parser.parse_args(shlex.split(args_string) if args_string is not None else None) llamacpp_python( messages_file=args.messages, model_file=args.model, @@ -131,5 +132,15 @@ def main(): ) +def write_versions(): + versions = {"${task.process}": {"llama-cpp-python": llama_cpp.__version__}} + with open("versions.yml", "w", encoding="utf-8") as f: + for process, pkgs in versions.items(): + f.write(f'"{process}":\\n') + for pkg, ver in pkgs.items(): + f.write(f" {pkg}: {ver}\\n") + + if __name__ == "__main__": - main() + main("--model ${gguf_model} --messages ${prompt_file} --output ${prefix}.txt ${args}") + write_versions() diff --git a/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap b/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap index 8d8ab1f81cef..a5e0744fb50e 100644 --- a/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap +++ b/modules/nf-core/llamacpppython/run/tests/main.nf.test.snap @@ -9,15 +9,11 @@ true, { "versions_llama_cpp_python": [ - [ - "LLAMACPPPYTHON_RUN", - "llama-cpp-python", - "0.3.16" - ] + "versions.yml:md5,e4e5fd3eefb4e0b1e83d8766a8b52e7c" ] } ], - "timestamp": "2026-04-09T16:40:57.888211501", + "timestamp": "2026-04-14T22:59:52.532384543", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" @@ -32,15 +28,11 @@ "test_run.txt", { "versions_llama_cpp_python": [ - [ - "LLAMACPPPYTHON_RUN", - "llama-cpp-python", - "0.3.16" - ] + "versions.yml:md5,e4e5fd3eefb4e0b1e83d8766a8b52e7c" ] } ], - "timestamp": "2026-04-09T16:41:05.221151819", + "timestamp": "2026-04-14T22:59:56.61647329", "meta": { "nf-test": "0.9.5", "nextflow": "25.10.4" From 255e7db7251a733a04e829fe59556ee37e2e10d7 Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Tue, 14 Apr 2026 23:13:22 +0200 Subject: [PATCH 30/32] adapt meta to fit versions.yml based on https://github.com/nf-core/modules/blob/master/modules/nf-core/ea-utils/gtf2bed/meta.yml --- modules/nf-core/llamacpppython/run/meta.yml | 27 +++++++-------------- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/modules/nf-core/llamacpppython/run/meta.yml b/modules/nf-core/llamacpppython/run/meta.yml index 18a6d3a2a2f5..a97172b7ad15 100644 --- a/modules/nf-core/llamacpppython/run/meta.yml +++ b/modules/nf-core/llamacpppython/run/meta.yml @@ -43,26 +43,17 @@ output: description: File with the output of LLM inference request ontologies: [] versions_llama_cpp_python: - - - ${task.process}: - type: string - description: The name of the process - - llama-cpp-python: - type: string - description: The name of the tool - - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': - type: eval - description: The expression to obtain the version of the tool + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML topics: versions: - - - ${task.process}: - type: string - description: The name of the process - - llama-cpp-python: - type: string - description: The name of the tool - - python3 -c 'import llama_cpp; print(llama_cpp.__version__)': - type: eval - description: The expression to obtain the version of the tool + - versions.yml: + type: string + description: The name of the process authors: - "@toniher" - "@lucacozzuto" From 9069b44a190b42f39bd01c66a43a59e0be57d15c Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 15 Apr 2026 10:45:17 +0200 Subject: [PATCH 31/32] adding singularity oras image following this example: https://github.com/biocorecrg/nf-core-modules/blob/4e03bf614d8338067c864d8ee38c2a4a738311aa/modules/nf-core/amulety/esm2/main.nf --- modules/nf-core/llamacpppython/run/main.nf | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/nf-core/llamacpppython/run/main.nf b/modules/nf-core/llamacpppython/run/main.nf index 3a12334424e4..0236c7cbeb9b 100644 --- a/modules/nf-core/llamacpppython/run/main.nf +++ b/modules/nf-core/llamacpppython/run/main.nf @@ -4,7 +4,11 @@ process LLAMACPPPYTHON_RUN { label 'process_gpu' conda "${moduleDir}/environment.yml" - container "${task.accelerator ? 'quay.io/nf-core/llama-cpp-python:0.1.9' : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5'}" + container "${task.accelerator + ? 'quay.io/nf-core/llama-cpp-python:0.1.9' + : (workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'oras://community.wave.seqera.io/library/llama-cpp-python:0.3.16--d6f959a4c13960c4' + : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5')}" input: tuple val(meta), path(prompt_file), path(gguf_model) @@ -19,7 +23,7 @@ process LLAMACPPPYTHON_RUN { script: args = task.ext.args ?: '' prefix = task.ext.prefix ?: "${meta.id}" - template 'llama-cpp-python.py' + template('llama-cpp-python.py') stub: prefix = task.ext.prefix ?: "${meta.id}" From ec9a159e7d8aca66e17d033d8fcbfeb870a759dc Mon Sep 17 00:00:00 2001 From: Toni Hermoso Pulido Date: Wed, 15 Apr 2026 10:58:17 +0200 Subject: [PATCH 32/32] trying to accomodate nf-core modules lint (sic) --- modules/nf-core/llamacpppython/run/main.nf | 6 +----- modules/nf-core/llamacpppython/run/meta.yml | 9 ++++++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/modules/nf-core/llamacpppython/run/main.nf b/modules/nf-core/llamacpppython/run/main.nf index 0236c7cbeb9b..d47a3ab9570d 100644 --- a/modules/nf-core/llamacpppython/run/main.nf +++ b/modules/nf-core/llamacpppython/run/main.nf @@ -4,11 +4,7 @@ process LLAMACPPPYTHON_RUN { label 'process_gpu' conda "${moduleDir}/environment.yml" - container "${task.accelerator - ? 'quay.io/nf-core/llama-cpp-python:0.1.9' - : (workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container - ? 'oras://community.wave.seqera.io/library/llama-cpp-python:0.3.16--d6f959a4c13960c4' - : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5')}" + container "${task.accelerator ? 'quay.io/nf-core/llama-cpp-python:0.1.9' : (workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? 'oras://community.wave.seqera.io/library/llama-cpp-python:0.3.16--d6f959a4c13960c4' : 'community.wave.seqera.io/library/llama-cpp-python:0.3.16--b351398cd0ea7fc5')}" input: tuple val(meta), path(prompt_file), path(gguf_model) diff --git a/modules/nf-core/llamacpppython/run/meta.yml b/modules/nf-core/llamacpppython/run/meta.yml index a97172b7ad15..d38300d9ea6a 100644 --- a/modules/nf-core/llamacpppython/run/meta.yml +++ b/modules/nf-core/llamacpppython/run/meta.yml @@ -48,12 +48,15 @@ output: description: File containing software versions pattern: "versions.yml" ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - edam: http://edamontology.org/format_3750 topics: versions: - versions.yml: - type: string - description: The name of the process + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 authors: - "@toniher" - "@lucacozzuto"