DEV Community

shashank ms
shashank ms

Posted on

Applying LLMs to Biology and Bioinformatics

We are building a command-line bioinformatics assistant that ingests a raw DNA sequence, finds open reading frames with local Python logic, and uses an LLM to interpret the peptides and answer a research question. It is aimed at biologists and bioinformatics students who need quick sequence insights without writing a full analysis pipeline from scratch.

What you'll need

Step 1: Set up the Oxlo.ai client

Import the OpenAI SDK and point it at Oxlo.ai. Because Oxlo.ai is fully OpenAI-compatible, this single client handles everything.

from openai import OpenAI

client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")

Step 2: Build a minimal DNA toolkit

Before calling the model, we need real biological data to ground the response. I will implement transcription, translation, and a simple ORF scanner with the standard codon table. No external bioinformatics libraries are required.

CODON_TABLE = {
    'UUU': 'F', 'UUC': 'F', 'UUA': 'L', 'UUG': 'L',
    'UCU': 'S', 'UCC': 'S', 'UCA': 'S', 'UCG': 'S',
    'UAU': 'Y', 'UAC': 'Y', 'UAA': '*', 'UAG': '*',
    'UGU': 'C', 'UGC': 'C', 'UGA': '*', 'UGG': 'W',
    'CUU': 'L', 'CUC': 'L', 'CUA': 'L', 'CUG': 'L',
    'CCU': 'P', 'CCC': 'P', 'CCA': 'P', 'CCG': 'P',
    'CAU': 'H', 'CAC': 'H', 'CAA': 'Q', 'CAG': 'Q',
    'CGU': 'R', 'CGC': 'R', 'CGA': 'R', 'CGG': 'R',
    'AUU': 'I', 'AUC': 'I', 'AUA': 'I', 'AUG': 'M',
    'ACU': 'T', 'ACC': 'T', 'ACA': 'T', 'ACG': 'T',
    'AAU': 'N', 'AAC': 'N', 'AAA': 'K', 'AAG': 'K',
    'AGU': 'S', 'AGC': 'S', 'AGA': 'R', 'AGG': 'R',
    'GUU': 'V', 'GUC': 'V', 'GUA': 'V', 'GUG': 'V',
    'GCU': 'A', 'GCC': 'A', 'GCA': 'A', 'GCG': 'A',
    'GAU': 'D', 'GAC': 'D', 'GAA': 'E', 'GAG': 'E',
    'GGU': 'G', 'GGC': 'G', 'GGA': 'G', 'GGG': 'G',
}

def transcribe(dna: str) -> str:
    return dna.upper().replace('T', 'U')

def translate(rna: str) -> str:
    protein = []
    for i in range(0, len(rna) - 2, 3):
        codon = rna[i:i + 3]
        protein.append(CODON_TABLE.get(codon, '?'))
    return ''.join(protein)

def find_orfs(dna: str, min_protein_len: int = 30):
    rna = transcribe(dna)
    orfs = []
    for frame in range(3):
        seq = rna[frame:]
        protein = translate(seq)
        start = 0
        while start < len(protein):
            if protein[start] == 'M':
                stop = protein.find('*', start)
                if stop == -1:
                    break
                segment = protein[start:stop]
                if len(segment) >= min_protein_len:
                    dna_start = frame + start * 3
                    dna_end = frame + stop * 3 + 3
                    orfs.append({
                        "frame": frame + 1,
                        "dna_start": dna_start,
                        "dna_end": dna_end,
                        "length_aa": len(segment),
                        "sequence": segment
                    })
                start = stop + 1
            else:
                start += 1
    return orfs

Step 3: Write the system prompt

The system prompt constrains the model to act as a bioinformatics assistant and keeps the output structured and concise.

SYSTEM_PROMPT = """You are a bioinformatics research assistant.
The user will provide a DNA sequence, a list of open reading frames (ORFs) detected by a local script, and a specific research question.

Your job is to:
1. Summarize each ORF with its length and frame position.
2. Predict possible protein families or functional domains based on the peptide sequences.
3. Answer the user's research question using the sequence evidence.
4. Suggest one follow-up experiment or database search.

Keep your answer concise. Use bullet points. If you are uncertain, say so."""

Step 4: Create the analysis agent

This function runs the local ORF finder, packages the results as JSON, and sends them to Oxlo.ai. I use kimi-k2.6 because its reasoning and coding strengths handle structured biological data accurately.

import json

def analyze_sequence(dna: str, question: str) -> str:
    orfs = find_orfs(dna, min_protein_len=20)

    context = {
        "dna_length": len(dna),
        "orfs_found": len(orfs),
        "orfs": orfs,
        "user_question": question
    }

    user_message = json.dumps(context, indent=2)

    response = client.chat.completions.create(
        model="kimi-k2.6",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_message},
        ],
    )

    return response.choices[0].message.content

Step 5: Add a CLI entrypoint

Finally, I will add a main block with a sample beta-globin fragment and a research question so we can run the script immediately.

if __name__ == "__main__":
    sample_dna = (
        "ATGGTGCACCTGACTCCTGAGGAGAAGTCTGCCGTTACTGCCCTGTGGGGCAAGGTG"
        "AACGTGGATGAAGTTGGTGGTGAGGCCCTGGGCAGGTTGGTATCAAGGTTACAAGAC"
        "AGGTTTAAGGAGACCAATAGAAACTGGGCATGTGGAGACAGAGAAGACTCTTGGGTT"
        "TCTGATAGGCACTGACTCTCTCTGCCTATTGGTCTATTTTCCCACCCTTAGGCTGCT"
        "GGTGGTCTACCCTTGGACCCAGAGGTTCTTTGAGTCCTTTGGGGATCTGTCCACTCC"
        "TGATGCTGTTATGGGCAACCCTAAGGTGAAGGCTCATGGCAAGAAAGTGCTCGGTGC"
        "CTTTAGTGATGGCCTGGCTCACCTGGACAACCTCAAGGGCACCTTTGCCACACTGAG"
        "TGAGCTGCACTGTGACAAGCTGCACGTGGATCCTGAGAACTTCAGGCTCCTGGGCAA"
        "TATGATCGTGAT"
    )

    question = (
        "Does this sequence contain a known globin family motif, "
        "and what is the likely function of the longest ORF?"
    )

    print(analyze_sequence(sample_dna, question))

Run it

Save the script as bio_agent.py, export your API key, and run it.

$ export OXLO_API_KEY="sk-..."
$ python bio_agent.py

- ORF 1 (frame 1, 147 aa): Matches a classic globin fold. The peptide contains conserved histidine residues consistent with heme coordination.
- ORF 2 (frame 1, 44 aa): Short fragment with no clear functional domain match.

Answer: The longest ORF is consistent with beta-globin and likely functions in oxygen transport.

Follow-up: Run BLASTp against the NCBI nr database to confirm the exact subfamily and check for pathogenic variants.

Next steps

Two concrete ways to extend this assistant:

  1. Integrate the NCBI E-utilities API to fetch real taxonomy and literature context before sending data to the model.
  2. Add reverse-complement ORF scanning and benchmark the pipeline on long genomic contigs. Because Oxlo.ai uses flat per-request pricing, cost stays predictable even when you feed in long sequences that would inflate token bills elsewhere. See https://oxlo.ai/pricing for plan details.

Top comments (0)