We are going to build a research paper curator that fetches the latest LLM papers from arXiv and uses an Oxlo.ai model to summarize, categorize, and rank them by relevance to your interests. It is a small Python script that saves hours of scrolling through abstracts. If you are a developer or researcher trying to stay current, this tool gives you a filtered, readable digest every morning.
What you'll need
- Python 3.10 or newer
- An Oxlo.ai API key from https://portal.oxlo.ai
- The OpenAI SDK:
pip install openai - The
arxivlibrary to fetch papers:pip install arxiv
Step 1: Fetch recent LLM papers
First we need raw material. I use the arXiv API to pull the last 50 submissions tagged with "large language models" or related terms. This gives us titles, abstracts, and links.
import arxiv
def truncate(text, limit=800):
return text if len(text) <= limit else text[:limit] + "..."
def fetch_papers(max_results=50):
search = arxiv.Search(
query="cat:cs.CL AND (large language model OR LLM OR transformer OR reasoning)",
sort_by=arxiv.SortCriterion.SubmittedDate,
max_results=max_results,
)
papers = []
for result in search.results():
papers.append({
"title": result.title,
"abstract": truncate(result.summary),
"url": result.entry_id,
"published": result.published.isoformat(),
})
return papers
papers = fetch_papers()
print(f"Fetched {len(papers)} papers")
Step 2: Define the curator prompt
The system prompt turns the model into a technical editor. It enforces JSON output so we can parse rankings and summaries reliably.
SYSTEM_PROMPT = """You are a senior ML research engineer curating papers for a team of busy developers.
You receive a JSON list of papers. Return a JSON object with a single key "curated".
The value is a list of at most 8 papers, sorted by relevance to practitioners building with LLMs today.
For each paper include:
- title: exact title
- url: exact url
- relevance_score: integer 1-10
- category: one of [Architecture, Training, Reasoning, Agents, Evaluation, Multimodal, Safety, Other]
- one_sentence_summary: what the paper does, plain English, no hype
- why_it_matters: one sentence on practical impact for developers
Only return valid JSON. Do not wrap it in markdown fences."""
Step 3: Rank and filter with Oxlo.ai
Now we batch the abstracts into one prompt. I use Llama 3.3 70B because it handles long context well, and Oxlo.ai charges per request, not per token, so sending a large block of text is cheap.
import json
from openai import OpenAI
client = OpenAI(base_url="https://api.oxlo.ai/v1", api_key="YOUR_OXLO_API_KEY")
def curate_papers(papers):
user_message = json.dumps({"papers": papers}, ensure_ascii=False)
response = client.chat.completions.create(
model="llama-3.3-70b",
messages=[
{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_message},
],
)
return json.loads(response.choices[0].message.content)
curated = curate_papers(papers)
print(json.dumps(curated, indent=2))
Step 4: Generate a markdown digest
Parsing JSON is useful, but I want a readable file. I pass the curated JSON back to the model and ask for a short Markdown report with code snippets where relevant.
FORMAT_PROMPT = """You are a technical writer. Convert the provided JSON list of curated papers into a clean Markdown document.
Use level-3 headings for paper titles.
Include a bullet list with category, score, and why_it_matters.
Add a short paragraph summarizing the paper's approach.
If the paper introduces a new architecture or technique, include a tiny Python or pseudo-code snippet that captures the core idea.
Return only Markdown, no JSON."""
def generate_digest(curated_json):
user_message = json.dumps(curated_json, ensure_ascii=False)
response = client.chat.completions.create(
model="qwen-3-32b",
messages=[
{"role": "system", "content": FORMAT_PROMPT},
{"role": "user", "content": user_message},
],
)
return response.choices[0].message.content
digest = generate_digest(curated)
with open("llm_papers_digest.md", "w", encoding="utf-8") as f:
f.write(digest)
print("Saved digest to llm_papers_digest.md")
Step 5: Filter by your interests
I usually only care about agents and reasoning. I add a lightweight filter so the digest only keeps papers matching my tags.
MY_TAGS = {"Agents", "Reasoning", "Architecture"}
def filter_by_tags(curated, tags):
kept = [p for p in curated["curated"] if p["category"] in tags]
return {"curated": kept}
filtered = filter_by_tags(curated, MY_TAGS)
digest = generate_digest(filtered)
with open("llm_papers_digest_filtered.md", "w", encoding="utf-8") as f:
f.write(digest)
print(f"Filtered digest saved with {len(filtered['curated'])} papers")
Run it
Putting it together, the full script fetches papers, curates them, and writes two files. Here is a complete run with example output truncated for brevity.
python curator.py
# Fetched 50 papers
# Saved digest to llm_papers_digest.md
# Filtered digest saved with 5 papers
Example excerpt from llm_papers_digest.md:
### Chain-of-Thought Reasoning in Multimodal Agents
- **Category:** Reasoning
- **Relevance:** 9/10
- **Why it matters:** Shows how to reuse text-based CoT templates for vision-language models without retraining.
This paper introduces a routing mechanism that selects between visual and textual reasoning pathways based on confidence scores. The core idea is a lightweight gating function.
def route(input_tensor, text_gate, vision_gate):
if text_gate(input_tensor) > vision_gate(input_tensor):
return text_reasoner(input_tensor)
return vision_reasoner(input_tensor)
Next steps
Swap llama-3.3-70b for kimi-k2.6 if you want stronger reasoning during curation, or use deepseek-v3.2 on the free tier to prototype at zero cost. You could also schedule this script with cron and email the digest to your team.
Oxlo.ai's request-based pricing means you pay the same flat rate whether you send ten short abstracts or a full batch of fifty long ones. That makes this kind of long-context batch processing trivial to run daily without token-meter anxiety. Check the details at https://oxlo.ai/pricing.
Top comments (0)