Skip to main content
โšก Calmops

Deep Research AI Tools: Perplexity, OpenAI Deep Research, and Building Your Own

Introduction

AI research tools can compress hours of literature review into minutes. But they vary enormously in quality โ€” some hallucinate sources, others miss key information, and most require knowing how to prompt them effectively. This guide covers the practical side: which tools work for what, how to use them well, and how to build your own research agent.

The Research Tool Landscape

Tool Best For Cost Sources
Perplexity Pro Quick research with citations $20/month Real-time web
OpenAI Deep Research Comprehensive multi-hour reports $200/month (ChatGPT Pro) Real-time web
Claude + web search Analytical synthesis API pricing Real-time web
Elicit Academic papers Free/paid Semantic Scholar
Custom LangChain agent Your specific use case API costs Configurable

Perplexity: Fast Research with Citations

Perplexity is the best tool for quick, cited research. Every claim links to a source.

Effective Prompting

# BAD: vague question
"Tell me about Kubernetes"

# GOOD: specific research question
"What are the main differences between Kubernetes 1.28 and 1.29?
Focus on breaking changes and new features. Include official changelog sources."

# GOOD: comparative research
"Compare the performance benchmarks of PostgreSQL 16 vs MySQL 8.0 for OLTP workloads.
Include recent (2024-2026) benchmark studies."

# GOOD: technical deep dive
"What are the current best practices for implementing RAG with large document collections?
Focus on chunking strategies and retrieval optimization. Cite recent papers."

Using Perplexity API

import httpx
import json

def perplexity_research(query: str, model: str = "llama-3.1-sonar-large-128k-online") -> dict:
    """Query Perplexity API for research with citations."""

    response = httpx.post(
        "https://api.perplexity.ai/chat/completions",
        headers={
            "Authorization": f"Bearer {PERPLEXITY_API_KEY}",
            "Content-Type": "application/json",
        },
        json={
            "model": model,
            "messages": [
                {
                    "role": "system",
                    "content": "You are a research assistant. Provide accurate, well-cited information. Always include specific sources."
                },
                {
                    "role": "user",
                    "content": query
                }
            ],
            "return_citations": True,
            "search_recency_filter": "month",  # only recent sources
        },
        timeout=30,
    )

    data = response.json()
    return {
        "answer": data["choices"][0]["message"]["content"],
        "citations": data.get("citations", []),
    }

# Usage
result = perplexity_research(
    "What are the latest developments in WebAssembly WASI 0.2? "
    "Include specific features and adoption status."
)

print(result["answer"])
print("\nSources:")
for i, citation in enumerate(result["citations"], 1):
    print(f"  [{i}] {citation}")

OpenAI Deep Research: Comprehensive Reports

Deep Research (available in ChatGPT Pro) runs for 5-30 minutes, searches hundreds of sources, and produces detailed reports. Use it for:

  • Competitive analysis
  • Technology evaluation
  • Literature review
  • Market research

Prompting for Deep Research

# Template for comprehensive research
"Research [TOPIC] comprehensively. I need:

1. Current state of the technology/field (2025-2026)
2. Key players and their approaches
3. Technical comparison of main options
4. Adoption trends and real-world usage
5. Known limitations and open problems
6. Expert opinions and community consensus

Focus on technical accuracy. Include specific version numbers, benchmark data,
and cite primary sources (official docs, papers, GitHub repos) over blog posts."
Quick Perplexity search (seconds):
  โœ“ "What's the latest version of React?"
  โœ“ "How do I configure nginx for HTTP/2?"
  โœ“ "What does error X mean in Kubernetes?"

Deep Research (5-30 minutes):
  โœ“ "Evaluate vector databases for our RAG system (Pinecone vs Weaviate vs Qdrant)"
  โœ“ "Research the current state of LLM fine-tuning approaches"
  โœ“ "Comprehensive analysis of Rust vs Go for systems programming in 2026"

Building a Custom Research Agent

For domain-specific research, build your own agent with LangChain:

# pip install langchain langchain-openai tavily-python
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain.tools import tool
import httpx

# Tool 1: Web search
search_tool = TavilySearchResults(
    max_results=5,
    search_depth="advanced",
    include_answer=True,
    include_raw_content=True,
)

# Tool 2: Fetch specific URLs
@tool
def fetch_url(url: str) -> str:
    """Fetch and return the content of a specific URL."""
    try:
        response = httpx.get(url, timeout=10, follow_redirects=True)
        # Return first 3000 chars to avoid token overflow
        return response.text[:3000]
    except Exception as e:
        return f"Error fetching URL: {e}"

# Tool 3: Search academic papers
@tool
def search_papers(query: str) -> str:
    """Search Semantic Scholar for academic papers on a topic."""
    response = httpx.get(
        "https://api.semanticscholar.org/graph/v1/paper/search",
        params={
            "query": query,
            "limit": 5,
            "fields": "title,abstract,year,authors,citationCount,url"
        },
        timeout=10,
    )
    papers = response.json().get("data", [])
    results = []
    for p in papers:
        authors = ", ".join([a["name"] for a in p.get("authors", [])[:3]])
        results.append(
            f"Title: {p['title']}\n"
            f"Authors: {authors} ({p.get('year', 'N/A')})\n"
            f"Citations: {p.get('citationCount', 0)}\n"
            f"Abstract: {p.get('abstract', 'N/A')[:300]}...\n"
            f"URL: {p.get('url', 'N/A')}\n"
        )
    return "\n---\n".join(results) if results else "No papers found"

# Create the research agent
llm = ChatOpenAI(model="gpt-4o", temperature=0)

prompt = ChatPromptTemplate.from_messages([
    ("system", """You are a thorough research assistant. When researching a topic:
1. Search for recent information (prioritize 2024-2026 sources)
2. Look for multiple perspectives and sources
3. Verify claims across multiple sources
4. Distinguish between facts, opinions, and speculation
5. Always cite your sources with URLs
6. Note when information is uncertain or conflicting

Be comprehensive but concise. Focus on actionable insights."""),
    ("human", "{input}"),
    MessagesPlaceholder(variable_name="agent_scratchpad"),
])

tools = [search_tool, fetch_url, search_papers]
agent = create_openai_tools_agent(llm, tools, prompt)
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,
    max_iterations=10,
    handle_parsing_errors=True,
)

# Run research
result = agent_executor.invoke({
    "input": """Research the current state of AI code generation tools in 2026.
    I need:
    1. Top tools (GitHub Copilot, Cursor, Devin, etc.) and their capabilities
    2. Benchmark comparisons if available
    3. Pricing and adoption data
    4. Developer sentiment and real-world effectiveness
    5. Recent developments (last 6 months)"""
})

print(result["output"])

Multi-Step Research Pipeline

For complex research that requires synthesis across many sources:

from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

llm = ChatOpenAI(model="gpt-4o", temperature=0)

# Step 1: Generate research questions
question_generator = ChatPromptTemplate.from_template("""
Given this research topic: {topic}

Generate 5 specific research questions that would comprehensively cover this topic.
Focus on questions that have factual, verifiable answers.
Format as a numbered list.
""") | llm | StrOutputParser()

# Step 2: Research each question
researcher = ChatPromptTemplate.from_template("""
Research this specific question: {question}

Context: This is part of a larger research project on: {topic}

Provide a detailed, factual answer with specific data points, examples, and sources.
Be precise and cite specific sources where possible.
""") | llm | StrOutputParser()

# Step 3: Synthesize findings
synthesizer = ChatPromptTemplate.from_template("""
You have researched the following topic: {topic}

Here are the findings from multiple research questions:
{findings}

Synthesize these findings into a comprehensive research report that:
1. Identifies key themes and patterns
2. Highlights areas of consensus and disagreement
3. Notes gaps in the research
4. Provides actionable conclusions
5. Lists the most important sources

Format as a structured report with clear sections.
""") | llm | StrOutputParser()

async def deep_research(topic: str) -> str:
    """Multi-step research pipeline."""

    # Generate questions
    questions_text = await question_generator.ainvoke({"topic": topic})
    questions = [q.strip() for q in questions_text.split("\n") if q.strip() and q[0].isdigit()]

    # Research each question in parallel
    import asyncio
    tasks = [
        researcher.ainvoke({"question": q, "topic": topic})
        for q in questions[:5]  # limit to 5 questions
    ]
    findings_list = await asyncio.gather(*tasks)

    # Format findings
    findings = "\n\n".join([
        f"Q: {q}\nA: {a}"
        for q, a in zip(questions, findings_list)
    ])

    # Synthesize
    report = await synthesizer.ainvoke({
        "topic": topic,
        "findings": findings
    })

    return report

# Usage
import asyncio
report = asyncio.run(deep_research(
    "The current state of WebAssembly for server-side computing in 2026"
))
print(report)

Evaluating Research Quality

Not all AI research is equal. Check for these quality signals:

def evaluate_research_quality(research_output: str, sources: list[str]) -> dict:
    """Evaluate the quality of AI-generated research."""

    llm = ChatOpenAI(model="gpt-4o", temperature=0)

    evaluation_prompt = ChatPromptTemplate.from_template("""
    Evaluate this research output for quality:

    RESEARCH OUTPUT:
    {output}

    CITED SOURCES:
    {sources}

    Rate each dimension 1-5 and explain:
    1. Source quality (are sources authoritative? recent? primary?)
    2. Factual accuracy (are specific claims verifiable?)
    3. Completeness (are major aspects covered?)
    4. Bias (is the analysis balanced?)
    5. Recency (is information current for 2025-2026?)

    Also flag any:
    - Potential hallucinations (claims without sources)
    - Outdated information
    - Missing important perspectives

    Format as JSON.
    """)

    result = (evaluation_prompt | llm | StrOutputParser()).invoke({
        "output": research_output[:3000],
        "sources": "\n".join(sources[:10])
    })

    return result

# Red flags in AI research:
RED_FLAGS = [
    "According to recent studies...",  # vague citation
    "Experts say...",                  # no specific expert named
    "It is widely believed...",        # no source
    "Research shows...",               # no specific research cited
    "As of my knowledge cutoff...",    # outdated info warning
]

Practical Research Workflows

For Technical Evaluation

1. Start with Perplexity: "What are the main [technology] options in 2026?"
   โ†’ Get overview and identify key players

2. Deep Research: "Comprehensive comparison of [option A] vs [option B] for [use case]"
   โ†’ Get detailed analysis

3. Verify with primary sources:
   - Official documentation
   - GitHub issues/discussions
   - Recent conference talks (YouTube)
   - HN/Reddit discussions

4. Synthesize with Claude/GPT-4o:
   "Given these findings [paste], what would you recommend for [specific context]?"

For Staying Current

# Automated daily research digest
import schedule
import time

def daily_research_digest(topics: list[str]) -> str:
    """Generate daily digest of developments in your areas."""

    results = []
    for topic in topics:
        result = perplexity_research(
            f"What are the most important developments in {topic} in the last 7 days? "
            f"Focus on releases, papers, and significant announcements."
        )
        results.append(f"## {topic}\n{result['answer']}\n")

    return "\n".join(results)

# Run daily
topics = ["LLM research", "Kubernetes", "Rust ecosystem", "WebAssembly"]
digest = daily_research_digest(topics)

Resources

Comments