Llama-ChemLink-Parser-8B-MTYS

ChemLink is a LoRA fine-tune of tokyotech-llm/Llama-3.1-Swallow-8B-Instruct-v0.3 for extracting chemical measurement values (MW, IC50, EC50, Yield) from scientific literature, with compound-name linkage for PubChem grounding and Graph RAG integration.


Background and Motivation

Target environment: CPU-only local hardware, no GPU required.

Chemical and pharmaceutical researchers frequently operate under security policies that prohibit cloud API usage. This model is designed to run on a standard CPU workstation (e.g., Core i7 / 24 GB RAM) via Ollama in GGUF format, suitable for overnight batch processing in network-restricted or air-gapped environments.

A critical requirement in this setting is compound-name linkage: downstream pipelines (PubChem grounding, Graph RAG) need to know not just the measurement value, but which chemical compound it belongs to. This requires the model to output a compound_name field alongside each extracted value.

Two prompt conditions were evaluated:

  • Condition A (no instruction): prompt requests only type / value / unit; compound_name is not requested.
  • Condition B (with instruction): prompt explicitly requests compound_name in addition to type / value / unit.

ChemLink outputs compound_name under both conditions. All comparison models output 0% compound_name without explicit instruction (Condition A).


Key Capability

ChemLink outputs compound_name alongside each extracted value under both prompt conditions, without dependence on explicit instruction.

{
  "chemical_entities": [
    {
      "compound_name": "linezolid",
      "measurements": [
        {"type": "Molecular Weight", "value": 337.35, "unit": "g/mol"}
      ]
    }
  ]
}

This stability reduces the risk of pipeline failures where a measurement value is extracted but cannot be linked to its source compound β€” a risk that depends on prompt design when using baseline models.


Model Overview

Item Detail
Developer MitzMitz / Ingenta AI
Base model tokyotech-llm/Llama-3.1-Swallow-8B-Instruct-v0.3
Training tool unsloth + TRL (SFTTrainer)
Quantization 4-bit NF4 (QLoRA)
LoRA config r=16, alpha=32, dropout=0, bias=none
Max seq length 2048
Local deployment Ollama (GGUF q5_K_M) β€” CPU only, no GPU required
Supported languages Japanese, English
License Llama 3.1 Community License

Usage

Local CPU Inference (Ollama β€” Primary Use Case)

# γƒ’γƒ‡γƒ«η™»ιŒ²
ollama create llama-chemlink-parser-8b-mtys -f Modelfile

# ζŽ¨θ«–
ollama run llama-chemlink-parser-8b-mtys

Modelfile example (Llama 3.1 chat template):

FROM ./Llama-3.1-Swallow-8B-Instruct-v0.3.Q5_K_M.gguf

TEMPLATE """{{ if .System }}<|start_header_id|>system<|end_header_id|>

{{ .System }}<|eot_id|>{{ end }}<|start_header_id|>user<|end_header_id|>

{{ .Prompt }}<|eot_id|><|start_header_id|>assistant<|end_header_id|>

{{ .Response }}<|eot_id|>"""

PARAMETER temperature 0
PARAMETER num_ctx 2048
PARAMETER num_predict 256

Inference (Colab / GPU)

import torch, json, re
from unsloth import FastLanguageModel
from google.colab import userdata

HF_TOKEN = userdata.get('HF_TOKEN')

SYSTEM_PROMPT = (
    "You are a chemical data extraction assistant. "
    "Extract measurements from the given text and return a JSON object. "
    "The object must have a 'chemical_entities' array. "
    "Each element must have: compound_name (string), "
    "measurements (array of objects with type/value/unit). "
    "If no target measurement is found, return {\"chemical_entities\": []}. "
    "Output only the JSON object, no explanation."
)

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name     = "MitzMitz/Llama-ChemLink-Parser-8B-MTYS",
    max_seq_length = 2048,
    dtype          = None,
    load_in_4bit   = True,
    token          = HF_TOKEN,
)
FastLanguageModel.for_inference(model)

def extract(text):
    messages = [
        {"role": "system", "content": SYSTEM_PROMPT},
        {"role": "user",   "content": text},
    ]
    input_ids = tokenizer.apply_chat_template(
        messages, tokenize=True,
        add_generation_prompt=True, return_tensors="pt"
    ).to("cuda")
    with torch.no_grad():
        output = model.generate(
            input_ids, max_new_tokens=256,
            temperature=0.0, do_sample=False,
            pad_token_id=tokenizer.eos_token_id,
        )
    return tokenizer.decode(
        output[0][input_ids.shape[1]:], skip_special_tokens=True
    ).strip()

print(extract("The compound linezolid has a molecular weight of 337.35 g/mol."))

Training Configuration

Parameter Value
per_device_train_batch_size 1
gradient_accumulation_steps 16
num_train_epochs 2
learning_rate 2e-4
warmup_steps 10
lr_scheduler_type cosine
fp16 / bf16 auto-detected
optimizer adamw_8bit (unsloth default)
save_strategy steps (save_steps=20)

Training Data

File Total MW IC50 EC50 Yield Negative Source
phase6_train_mix 3,763 2,283 717 0 44 719 PubChem / ChEMBL / ORD
additional_ec50_yield 2,534 0 0 1,000 1,000 534 ChEMBL / ORD
additional_yield_table 621 0 0 0 500 121 ORD
additional_mw_unit_fix 120 84 16 0 0 20 PubChem
additional_phase5 740 17 115 22 425 161 ChEMBL / ORD / PubChem
Total 7,778 2,384 848 1,022 1,969 1,555

Negative samples (1,555 records, 20.0%) contain [] as output, representing texts where no target measurement exists.

Data licenses:

  • ORD: CC-BY-SA 4.0
  • ChEMBL: CC-BY-SA 3.0 (EMBL-EBI)
  • PubChem: Public Domain (NCBI/NIH)

Evaluation

Evaluation Dataset

Indicator n (chemfmt evaluation) Source
MW 125 per model PubChem (PMID-verified)
Yield 125 per model ORD (PMID-verified)
IC50 125 per model ChEMBL β†’ PubMed Abstract
EC50 125 per model ChEMBL β†’ PubMed Abstract

Evaluation used true_eval_all_pmid_clean.jsonl (2,963 records total; PMID-verified, zero training data contamination). 500 samples per model per condition (125 per indicator, stratified, RANDOM_SEED=42).

Local CPU / Ollama Evaluation (q5_K_M GGUF)

Prompt format: chemical_entities structured output. Parameters: temperature=0.0, num_predict=256, num_ctx=2048.

MW extraction β€” Condition A (no instruction):

Model MW parsed (n/125) compound_name PubChem resolved MW accuracy*
ChemLink q5_K_M 124/125 100% 60.5% 100%
Swallow-base q5_K_M 124/125 100%† 60.5% 100%
Mistral-7B q5_K_M 123/125 0% β€” 100%

MW extraction β€” Condition B (with compound_name instruction):

Model MW parsed (n/125) compound_name PubChem resolved MW accuracy*
ChemLink q5_K_M 125/125 100% 64.8% 100%
Swallow-base q5_K_M 125/125 100% 64.0% 100%
Mistral-7B q5_K_M 67/125 ⚠️ 100%‑ 47.8% 100%

* MW accuracy = fraction of extracted values within Β±1% of gold-standard truth value.
† Swallow-base compound_name output under Condition A is an artifact of the Ollama chat template (see Limitations); this behaviour is not observed in the Colab/GPU evaluation of the same base model.
⚠️ Mistral-7B Condition B: low n (67/125) due to chemical_entities format incompatibility causing truncation or empty outputs (see Limitations).

Colab GPU / NF4 Reference Results

Parameters: temperature=0.0, max_new_tokens=256.

MW extraction:

Model Condition MW parsed (n/125) compound_name PubChem resolved
ChemLink NF4 no instruction 123/125 100% 59.3%
ChemLink NF4 with instruction 120/125 100% 63.3%
Swallow-base no instruction 123/125 0% β€”
Swallow-base with instruction 124/125 100% 64.5%
Mistral-7B no instruction 112/125 0% β€”
Mistral-7B with instruction 32/125 ⚠️ 100%‑ 68.8%‑

‑ When values were successfully extracted.

PubChem Grounding Summary

Of all compound names output by ChemLink (Condition A, local CPU, MW):

  • PubChem resolution rate: ~60–65%
  • Non-resolved names are typically IUPAC systematic names, synthesis intermediates, or proprietary codes not registered in PubChem.

Limitations

compound_name in real abstracts: Real PubMed abstracts often use codes ("compound 3", "2b") rather than IUPAC names. The model outputs whatever name appears in the source text; PubChem grounding success depends on name quality.

Mistral-7B format incompatibility: Mistral-7B-Instruct-v0.2 produced valid MW extractions in only 25–51% of cases under the chemical_entities prompt format, compared to >95% for ChemLink and Swallow-base. This is attributed to the [INST] chat template being incompatible with longer structured JSON output, causing truncation. Mistral-7B is not recommended for chemical_entities format inference.

Swallow-base Ollama Condition A artifact: Swallow-base q5_K_M showed unexpected compound_name output under Condition A (no instruction) via Ollama, which was not observed in the same model evaluated via Colab/GPU. This is attributed to a difference in chat template handling between Ollama and apply_chat_template. The Colab result (0% compound_name) is considered more reliable.

IC50 / EC50: Across all models evaluated, IC50/EC50 correct-extraction rates were below 2%. This reflects a limitation of the unified structured-output evaluation protocol, not a model-specific capability gap.

Inference environment differences: Colab GPU: temperature=0.0, max_new_tokens=256, apply_chat_template. Local Ollama: temperature=0.0, num_predict=256, Modelfile TEMPLATE. Cross-environment comparisons should account for these differences.


Intended Use

  • Automated extraction of MW / Yield from chemical literature in network-restricted, CPU-only local environments
  • Compound-name to measurement-value association for PubChem grounding and Graph RAG pipelines
  • Overnight batch processing on CPU-only hardware without cloud API dependency

Out-of-Scope Use

  • Medical diagnosis or legal judgment
  • Domains outside chemistry and chemical biology
  • IC50/EC50 extraction (see Limitations)

Base Model Reference

Model License
tokyotech-llm/Llama-3.1-Swallow-8B-Instruct-v0.3 Llama 3.1 Community License
meta-llama/Llama-3.1-8B-Instruct Llama 3.1 Community License

License

Licensed under the Llama 3.1 Community License. Copyright (C) Meta Platforms, Inc. All Rights Reserved.


Framework Versions

Library Version
unsloth 2026.5.2
PEFT 0.19.1
Transformers 5.5.0
PyTorch 2.10.0
TRL 0.24.0
Datasets 4.3.0
Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. πŸ™‹ Ask for provider support