Guaranteed 15% off your current AI inference bill for team spending up to $20000 / month.

Book a call →
Back to Blogs
Engineering

Building Academic Writing Tools with LLMs: A Step-by-Step Guide

We will build a command-line academic writing assistant that refines draft paragraphs, tightens arguments, and normalizes citations. It is meant for...

Building Academic Writing Tools with LLMs: A Step-by-Step Guide

We will build a command-line academic writing assistant that refines draft paragraphs, tightens arguments, and normalizes citations. It is meant for researchers and graduate students who want clean prose without manually editing every section. Because the tool sends full drafts to Oxlo.ai, its flat per-request pricing keeps costs predictable even when chapters grow long, which makes iterative rewriting practical.

What you'll need

Python 3.10 or newer installed locally. The OpenAI Python SDK, which you install with pip install openai. An Oxlo.ai API key from https://portal.oxlo.ai. A rough draft paragraph saved as a text file so you have material to test against. I also assume you are comfortable running Python scripts from a terminal. If you are on macOS or Linux, your system Python is likely sufficient. Windows users should use Python from the Microsoft Store or python.org to avoid path issues.

Step 1: Configure the Oxlo.ai client

Oxlo.ai exposes a fully OpenAI-compatible endpoint, so the official SDK drops in without custom adapters or new abstractions. I store my key in an environment variable to keep secrets out of source control. The client initialization is standard, and once this object exists, every subsequent call follows the exact same pattern you would use with any OpenAI-compatible provider. There are no cold starts on popular models, so the first request after opening your laptop returns as fast as any other.

import os
from openai import OpenAI

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

Step 2: Write the academic editor system prompt

The system prompt is where I encode tone, constraints, and failure modes. I want formal academic English, stronger topic sentences, and explicit flags for vague language. I also instruct the model to preserve citations and avoid adding commentary outside the text itself. Keeping the prompt in a module-level constant makes A/B testing easy. You can swap versions without touching the request logic.

SYSTEM_PROMPT = """You are an academic editor. Your job is to improve drafts for clarity, concision, and formal tone suitable for journal submission. Follow these rules:
- Remove passive voice where it weakens the argument.
- Strengthen topic sentences.
- Flag vague quantifiers like "many" or "some" by replacing them with precise language or marking them with [VAGUE].
- Preserve all original citations and technical terminology exactly.
- Output only the revised text. Do not include meta-commentary, greetings, or summaries.
"""

Step 3: Build the paragraph refinement function

I wrap the API call in a helper that accepts the draft and optional instructions, such as "make the argument more direct" or "shorten to 150 words." I keep the instructions parameter open because different journals and disciplines have different style expectations. A physics methods section needs different tightening than a humanities literature review. I use Llama 3.3 70B on Oxlo.ai because it is a strong general-purpose model that handles long-context academic prose reliably. Because Oxlo.ai charges per request rather than per token, sending a multi-page draft costs the same as a single sentence. That matters when you are iterating on full chapters and do not want usage to scale with input length. You can see the exact rates on the pricing page.

def refine_paragraph(draft, instructions=""):
    user_content = f"Instructions: {instructions}\n\nDraft:\n{draft}"
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": user_content},
        ],
    )
    return response.choices[0].message.content

Step 4: Add a citation formatting helper

Next I add a second helper that normalizes inline citations. It takes the refined text and converts references to a target style, such as APA or MLA, without altering the surrounding prose. I route this to DeepSeek V3.2 on Oxlo.ai, which is available on a free tier and handles structured formatting tasks efficiently. Separating prose refinement from citation formatting improves reliability because each prompt is more focused and less likely to invent or drop references while rewriting sentences. By routing formatting to a separate model, I treat the pipeline like a microservice: each stage can be swapped independently if Oxlo.ai adds a newer reasoning or coding model later.

def format_citations(text, style="APA"):
    prompt = (
        f"Convert all inline citations in the following text to {style} format. "
        f"Do not change any wording, arguments, or structure outside the citations.\n\n{text}"
    )
    response = client.chat.completions.create(
        model="deepseek-v3.2",
        messages=[
            {"role": "system", "content": "You are a precise citation formatter."},
            {"role": "user", "content": prompt},
        ],
    )
    return response.choices[0].message.content

Step 5: Assemble the CLI tool

Finally, I wire the two helpers into a small script that reads a file, runs prose refinement, then formats citations, and writes the result to disk. I use argparse so I can pass instructions from the terminal without editing code between runs. Writing to a file instead of stdout makes it easy to diff versions with git or your editor. I also set encoding to utf-8 so mathematical symbols and diacritics survive the round trip. If you plan to run this on a directory of files, you could wrap the call in a try/except block and log failures, but for a single draft the simple path is enough.

import argparse

def process_draft(file_path, instructions):
    with open(file_path, "r", encoding="utf-8") as f:
        draft = f.read()

    print("Refining prose...")
    refined = refine_paragraph(draft, instructions)

    print("Formatting citations...")
    final = format_citations(refined, style="APA")

    out_path = "output.txt"
    with open(out_path, "w", encoding="utf-8") as f:
        f.write(final)

    print(f"Done. Saved to {out_path}")
    return final

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Academic writing assistant")
    parser.add_argument("file", help="Path to draft text file")
    parser.add_argument("--instructions", default="", help="Extra guidance for the editor")
    args = parser.parse_args()

    process_draft(args.file, args.instructions)

Run it

I create a file named draft.txt with a rough paragraph full of weak hedges and inconsistent citations.

There are many studies that show machine learning can be used for climate prediction. Smith et al. (2020) said it helps, and some others found similar things. It is believed that this approach will be very useful in the future.

Then I run the tool from the terminal.

python academic_writer.py draft.txt --instructions "Strengthen the claim and remove hedging."

The output is written to output.txt. The model tightened the prose, removed passive constructions, and left the citation intact for the formatter. The result looks like this.

Machine learning has emerged as a robust methodology for climate prediction. Smith et al. (2020) demonstrated significant improvements in predictive accuracy, and subsequent studies have replicated these findings. This approach offers substantial utility for future climate modeling.

I always read the output before submitting, because even strong models can over-smooth nuanced arguments. The tool is an editor, not a replacement for your judgment. If your draft contains vague quantifiers, you will see [VAGUE] markers in the output so you can decide whether to add precise figures or qualifiers.

Next steps

Two directions I would take next. First, integrate a Zotero or Mendeley API lookup so the tool can verify citations against a live reference library instead of trusting raw text. Second, add a multi-turn revision loop where the model asks clarifying questions about ambiguous claims before rewriting, which improves accuracy on technical drafts. Another option is to expose the pipeline as a FastAPI endpoint so your lab mates can submit drafts through a simple web form instead of the command line. All of these patterns are cheap to experiment with on Oxlo.ai because the flat per-request pricing does not penalize long prompts or back-and-forth messages. You can start iterating immediately without worrying about token counters.

Ready to build with Oxlo.ai?

Get started building high-performance AI inference applications today.

Get started
Ox Assistant
Online
OxBot
OxBot

Hi there! Try our cost calculator to see what you'd save with Oxlo.ai.