This is a model with 1M parameters using the qwen3 architecture. It was trained on midi melodies from projectlosangeles/Monster-MIDI-Dataset formated to text. It uses utf-8 as text tokenizer. In this format, each new song is separated by a star "*", so we can use that as a prompt when generating from the model: Note: due to the model's size, it is not made for generating coherent music.

import torch
from transformers import Qwen3ForCausalLM

repo = "qwrt/Melodimodell-1M"
device = "cuda" if torch.cuda.is_available() else "cpu"
model = Qwen3ForCausalLM.from_pretrained(repo).to(device)

prompt="*"
new_tokens=2048-len(prompt)

seed = torch.tensor(list(prompt.encode()), dtype=torch.long)[None].to(device)
out = model.generate(seed, max_new_tokens=new_tokens,
                                     do_sample=True, temperature=0.8)
text_formated_midi=bytes(out[0].tolist()).decode("utf-8", errors="replace")
print(text_formated_midi)

Note that the model was trained on a context length of 2048, predictions from text with more context degrades in quality very quickly.

To convert this output to a midi, use the following code. Here we cut out if the model generated more than one song, indicated by a "*".

import mido
from huggingface_hub import hf_hub_download
import importlib.util

file_path = hf_hub_download(
    repo_id="qwrt/Monster_textmidis_filtered",
    filename="stringtomidi.py",
    repo_type="dataset"
)


spec = importlib.util.spec_from_file_location("parse_custom",file_path)
modul = importlib.util.module_from_spec(spec)
spec.loader.exec_module(modul)

generated_songs=text_formated_midi.split("*")
generated_songs.pop(0) #remove the first since it is an empty string
first_song=generated_songs[0]

if(len(generated_songs)==1): #remove the last incomplete note of an unfinished melody
    all_notes=first_song.split(" ")
    all_notes.pop()
    first_song=" ".join(all_notes)

events = modul.parse_custom(first_song)
modul.build_midi(events, "example.mid")

To prompt the model, you can use this code to convert a midi to a string:

file_path = hf_hub_download(
    repo_id="qwrt/Monster_textmidis_filtered",
    filename="miditostring.py",
    repo_type="dataset"
)


spec = importlib.util.spec_from_file_location("midi_to_string",file_path)
modul = importlib.util.module_from_spec(spec)
spec.loader.exec_module(modul)


midi_file = r"example.mid"
output_file = "output.txt"

# Standard: Filtrera trummor + begränsa ackord till max 5 noter vid exakt samma tidpunkt
result = modul.midi_to_string(midi_file, output_file,
                        filter_drums=True,
                        filter_non_piano=False,
                        max_chord_notes=10)

You can then use this text as a starting prompt:

f=open("output.txt")
prompt="*\n"+f.read()[:200]
new_tokens=1024-len(prompt)

seed = torch.tensor(list(prompt.encode()), dtype=torch.long)[None].to(device)
out = model.generate(seed, max_new_tokens=new_tokens,
                                     do_sample=True, temperature=0.8)
text_formated_midi=bytes(out[0].tolist()).decode("utf-8", errors="replace")
print(text_formated_midi)
Downloads last month
-
Safetensors
Model size
1.16M params
Tensor type
BF16
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support