Skip to main content
Open-Judge Logo

Holistic Evaluation, Quality Rewards: Driving Application Excellence

🌟 If you find OpenJudge helpful, please give us a Star! 🌟

Python 3.10+ PyPI Documentation Website Try Online PawBench

🌐 Website | 🚀 Try Online | 📖 Documentation | 🤝 Contributing | 🐾 PawBench | 中文

OpenJudge is an open-source evaluation framework for AI applications (e.g., AI agents or chatbots) designed to evaluate quality and drive continuous application optimization.

In practice, application excellence depends on a trustworthy evaluation workflow: Collect test data → Define graders → Run evaluation at scale → Analyze weaknesses → Iterate quickly.

OpenJudge provides ready-to-use graders and supports generating scenario-specific rubrics (as graders), making this workflow simpler, more professional, and easy to integrate into your workflow. It can also convert grading results into reward signals to help you fine-tune and optimize your application.

🚀 Try it now! Visit openjudge.me/app to use graders online — no installation required. Test built-in graders, build custom rubrics, and explore evaluation results directly in your browser.


📑 Table of Contents


News

  • 2026-06-17 - 🐾 PawBench v1.0 - A Model × Harness co-evaluation benchmark for agentic AI: 150 tasks · 9 models · 3 harnesses, with public prompts, graders, task labels, submissions, and leaderboard slices. 👉 GitHub | Leaderboard

  • 2026-04-07 - 🔒 Skill Graders - 5 new LLM-based graders for evaluating AI Agent Skill packages: threat analysis (AITech taxonomy), declaration alignment, completeness, relevance, and design quality. 👉 Documentation | Cookbook

  • 2026-03-10 - 🛠️ New Skills - Claude authenticity verification, find skills combo, and more. 👉 Browse Skills

  • 2026-02-12 - 📚 Reference Hallucination Arena - Benchmark for evaluating LLM academic reference hallucination. 👉 Documentation | 📊 Leaderboard

  • 2026-01-27 - 🆕 Paper Review - Automatically review academic papers using LLM-powered evaluation. 👉 Documentation

  • 2026-01-27 - 🖥️ OpenJudge UI - A Streamlit-based visual interface for grader testing and Auto Arena. 👉 Try Online | Run locally: streamlit run ui/app.py


✨ Key Features

📦 Systematic & Quality-Assured Grader Library

Access 50+ production-ready graders featuring a comprehensive taxonomy, rigorously validated for reliable performance.

🎯 General

Focus: Semantic quality, functional correctness, structural compliance

Key Graders:

  • Relevance - Semantic relevance scoring
  • Similarity - Text similarity measurement
  • Syntax Check - Code syntax validation
  • JSON Match - Structure compliance

🤖 Agent

Focus: Agent lifecycle, tool calling, memory, plan feasibility, trajectory quality

Key Graders:

  • Tool Selection - Tool choice accuracy
  • Memory - Context preservation
  • Plan - Strategy feasibility
  • Trajectory - Path optimization

🖼️ Multimodal

Focus: Image-text coherence, visual generation quality, image helpfulness

Key Graders:

  • Image Coherence - Visual-text alignment
  • Text-to-Image - Generation quality
  • Image Helpfulness - Image contribution
  • 🌐 Multi-Scenario Coverage: Extensive support for diverse domains including Agent, text, code, math, and multimodal tasks. 👉 Explore Supported Scenarios
  • 🔄 Holistic Agent Evaluation: Beyond final outcomes, we assess the entire lifecycle—including trajectories, Memory, Reflection, and Tool Use. 👉 Agent Lifecycle Evaluation
  • ✅ Quality Assurance: Every grader comes with benchmark datasets and pytest integration for validation. 👉 View Benchmark Datasets

🛠️ Flexible Grader Building Methods

Choose the build method that fits your requirements:

  • Customization: Clear requirements, but no existing grader? If you have explicit rules or logic, use our Python interfaces or Prompt templates to quickly define your own grader. 👉 Custom Grader Development Guide
  • Zero-shot Rubrics Generation: Not sure what criteria to use, and no labeled data yet? Just provide a task description and optional sample queries—the LLM will automatically generate evaluation rubrics for you. Ideal for rapid prototyping when you want to get started immediately. 👉 Zero-shot Rubrics Generation Guide
  • Data-driven Rubrics Generation: Ambiguous requirements, but have few examples? Use the GraderGenerator to automatically summarize evaluation Rubrics from your annotated data, and generate a llm-based grader. 👉 Data-driven Rubrics Generation Guide
  • Training Judge Models: Massive data and need peak performance? Use our training pipeline to train a dedicated Judge Model. This is ideal for complex scenarios where prompt-based grading falls short.👉 Train Judge Models

🔌 Easy Integration

Using mainstream observability platforms like LangSmith or Langfuse? We offer seamless integration to enhance their evaluators and automated evaluation capabilities. We also provide integrations with training frameworks like VERL for RL training. 👉 See Integrations for details

🌐 Online Playground

Explore OpenJudge without writing a single line of code. Our online platform at openjudge.me/app lets you:

  • Test graders interactively — select a built-in grader, input your data, and see results instantly
  • Build custom rubrics — use the zero-shot generator to create graders from task descriptions
  • View leaderboards — compare model performance across evaluation benchmarks at openjudge.me/leaderboard

📥 Installation

💡 Don't want to install anything? Try OpenJudge online — use graders directly in your browser, no setup needed.

pip install py-openjudge

💡 More installation methods can be found in the Quickstart Guide.


🚀 Quickstart

📚 Complete Quickstart can be found in the Quickstart Guide.

Simple Example

A simple example to evaluate a single response:

import asyncio
from openjudge.models import OpenAIChatModel
from openjudge.graders.common.relevance import RelevanceGrader

async def main():
    # 1️⃣ Create model client
    model = OpenAIChatModel(model="qwen3-32b")
    # 2️⃣ Initialize grader
    grader = RelevanceGrader(model=model)
    # 3️⃣ Prepare data
    data = {
        "query": "What is machine learning?",
        "response": "Machine learning is a subset of AI that enables computers to learn from data.",
    }
    # 4️⃣ Evaluate
    result = await grader.aevaluate(**data)
    print(f"Score: {result.score}")   # Score: 4
    print(f"Reason: {result.reason}")

if __name__ == "__main__":
    asyncio.run(main())

Evaluate LLM Applications with Built-in Graders

Use multiple built-in graders to comprehensively evaluate your LLM application: 👉 Explore All built-in graders

Business Scenario: Evaluating an e-commerce customer service agent that handles order inquiries. We assess the agent's performance across three dimensions: relevance, hallucination, and tool selection.

import asyncio
from openjudge.models import OpenAIChatModel
from openjudge.graders.common import RelevanceGrader, HallucinationGrader
from openjudge.graders.agent.tool.tool_selection import ToolSelectionGrader
from openjudge.runner import GradingRunner
from openjudge.runner.aggregator import WeightedSumAggregator
from openjudge.analyzer.statistical import DistributionAnalyzer

TOOL_DEFINITIONS = [
    {"name": "query_order", "description": "Query order status and logistics information", "parameters": {"order_id": "str"}},
    {"name": "query_logistics", "description": "Query detailed logistics tracking", "parameters": {"order_id": "str"}},
    {"name": "estimate_delivery", "description": "Estimate delivery time", "parameters": {"order_id": "str"}},
]
# Prepare your dataset
dataset = [{
    "query": "Where is my order ORD123456?",
    "response": "Your order ORD123456 has arrived at the Beijing distribution center and is expected to arrive tomorrow.",
    "context": "Order ORD123456: Arrived at Beijing distribution center, expected to arrive tomorrow.",
    "tool_definitions": TOOL_DEFINITIONS,
    "tool_calls": [{"name": "query_order", "arguments": {"order_id": "ORD123456"}}],
    # ... more test cases
}]
async def main():
    # 1️⃣ Initialize judge model
    model = OpenAIChatModel(model="qwen3-max")
    # 2️⃣ Configure multiple graders
    grader_configs = {
        "relevance": {"grader": RelevanceGrader(model=model), "mapper": {"query": "query", "response": "response"}},
        "hallucination": {"grader": HallucinationGrader(model=model), "mapper": {"query": "query", "response": "response", "context": "context"}},
        "tool_selection": {"grader": ToolSelectionGrader(model=model), "mapper": {"query": "query", "tool_definitions": "tool_definitions", "tool_calls": "tool_calls"}},
    }
    # 3️⃣ Set up aggregator for overall score
    aggregator = WeightedSumAggregator(name="overall_score", weights={"relevance": 0.3, "hallucination": 0.4, "tool_selection": 0.3})
    # 4️⃣ Run evaluation
    results = await GradingRunner(grader_configs=grader_configs, aggregators=[aggregator], max_concurrency=5).arun(dataset)
    # 5️⃣ Generate evaluation report
    overall_stats = DistributionAnalyzer().analyze(dataset, results["overall_score"])
    print(f"{'Overall Score':<20} | {overall_stats.mean:>15.2f}")

if __name__ == "__main__":
    asyncio.run(main())

Build Custom Graders for Your Scenario

Zero-shot Rubric Generation

Generate a custom grader from task description without labeled data: 👉 Zero-shot Rubrics Generation Guide

When to use: Quick prototyping when you have no labeled data but can clearly describe your task.

import asyncio
from openjudge.generator.simple_rubric import SimpleRubricsGenerator, SimpleRubricsGeneratorConfig
from openjudge.models import OpenAIChatModel

async def main():
    # 1️⃣ Configure generator
    config = SimpleRubricsGeneratorConfig(
        grader_name="customer_service_grader",
        model=OpenAIChatModel(model="qwen3-max"),
        task_description="E-commerce AI customer service primarily handles order inquiry tasks (such as logistics status and ETA) while focusing on managing customer emotions.",
        min_score=1,
        max_score=3,
    )
    # 2️⃣ Generate grader
    generator = SimpleRubricsGenerator(config)
    grader = await generator.generate(dataset=[], sample_queries=[])
    # 3️⃣ View generated rubrics
    print("Generated Rubrics:", grader.kwargs.get("rubrics"))
    # 4️⃣ Use the grader
    result = await grader.aevaluate(
        query="My order is delayed, what should I do?",
        response="I understand your concern. Let me check your order status..."
    )
    print(f"\nScore: {result.score}/3\nReason: {result.reason}")

if __name__ == "__main__":
    asyncio.run(main())

Data-driven Rubric Generation

Learn evaluation criteria from labeled examples: 👉 Data-driven Rubrics Generation Guide

When to use: You have labeled data and need high-accuracy graders for production use, especially when evaluation criteria are implicit.

import asyncio
from openjudge.generator.iterative_rubric.generator import IterativeRubricsGenerator, IterativePointwiseRubricsGeneratorConfig
from openjudge.models import OpenAIChatModel
from openjudge.models.schema.prompt_template import LanguageEnum

# Prepare labeled dataset (simplified example, recommend 10+ samples in practice)
labeled_dataset = [
    {"query": "My order hasn't arrived after 10 days, I want to complain!", "response": "I sincerely apologize for the delay. I completely understand your frustration! Your order was delayed due to weather conditions, but it has now resumed shipping and is expected to arrive tomorrow. I've marked it for priority delivery.", "label_score": 5},
    {"query": "Where is my package? I need it urgently!", "response": "I understand your urgency! Your package is currently out for delivery and is expected to arrive before 2 PM today. The delivery driver's contact number is 138xxxx.", "label_score": 5},
    {"query": "Why hasn't my order arrived yet? I've been waiting for days!", "response": "Your order is expected to arrive the day after tomorrow.", "label_score": 2},
    {"query": "The logistics hasn't updated in 3 days, is it lost?", "response": "Hello, your package is not lost. It's still in transit, please wait patiently.", "label_score": 3},
    # ... more labeled examples
]

async def main():
    # 1️⃣ Configure generator
    config = IterativePointwiseRubricsGeneratorConfig(
        grader_name="customer_service_grader_v2", model=OpenAIChatModel(model="qwen3-max"),
        min_score=1, max_score=5,
        enable_categorization=True, categories_number=5,  # Enable categorization, Aggregate into 5 themes
    )
    # 2️⃣ Generate grader from labeled data
    generator = IterativeRubricsGenerator(config)
    grader = await generator.generate(labeled_dataset)
    # 3️⃣ View learned rubrics
    print("\nLearned Rubrics from Labeled Data:\n",grader.kwargs.get("rubrics", "No rubrics generated"))
    # 4️⃣ Evaluate new samples
    test_cases = [
        {"query": "My order hasn't moved in 5 days, can you check? I'm a bit worried", "response": "I understand your concern! Let me check immediately: Your package is currently at XX distribution center. Due to recent high order volume, there's a slight delay, but it's expected to arrive the day after tomorrow. I'll proactively contact you if there are any issues."},
        {"query": "Why is this delivery so slow? I'm waiting to use it!", "response": "Checking, please wait."},
    ]
    print("\n" + "=" * 70, "\nEvaluation Results:\n", "=" * 70)
    for i, case in enumerate(test_cases):
        result = await grader.aevaluate(query=case["query"], response=case["response"])
        print(f"\n[Test {i+1}]\n  Query: {case['query']}\n  Response: {case['response']}\n  Score: {result.score}/5\n  Reason: {result.reason[:200]}...")

if __name__ == "__main__":
    asyncio.run(main())

🔗 Integrations

Seamlessly connect OpenJudge with mainstream observability and training platforms:

Category Platform Status Documentation
Observability LangSmith ✅ Available 👉 LangSmith Integration Guide
Langfuse ✅ Available 👉 Langfuse Integration Guide
Other frameworks 🔵 Planned —
Training verl ✅ Available 👉 VERL Integration Guide
Trinity-RFT 🔵 Planned —

💬 Have a framework you'd like us to prioritize? Open an Issue!


🌍 Ecosystem

OpenJudge is the foundation of a growing evaluation ecosystem. These projects share OpenJudge's philosophy of evaluation-driven optimization while targeting specific verticals.

🐾 PawBench — Model × Harness Co-Evaluation Benchmark

The same model can behave very differently depending on which agent runtime (harness) it runs inside. PawBench evaluates the model and the harness together, keeping enough metadata to analyze both dimensions independently:

$$\text{Agent Performance} = f(\text{Model}, \text{Harness})$$

Dimension Coverage
Tasks 150 tasks from 6 sources (ClawEval, QwenClawBench, PinchBench, SkillsBench, WildClawBench, self-built)
Models 9 models (Qwen, Claude, GLM, etc.)
Harnesses 3 harnesses (QwenPaw, OpenClaw, Hermes)
Task labels 5 dimensions: scenario, capability, complexity, modality, environment

Key findings from v1.0: harness design alone can shift a model's score by 10+ points — a gap comparable to many model upgrades. PawBench provides slice diagnostics to pinpoint whether regressions come from the model, the harness, or the grader. 👉 GitHub | Leaderboard | Documentation


🤝 Contributing

We love your input! We want to make contributing to OpenJudge as easy and transparent as possible.

🎨 Adding New Graders — Have domain-specific evaluation logic? Share it with the community! 🐛 Reporting Bugs — Found a glitch? Help us fix it by opening an issue 📝 Improving Docs — Clearer explanations or better examples are always welcome 💡 Proposing Features — Have ideas for new integrations? Let's discuss!

📖 See full Contributing Guidelines for coding standards and PR process.


💬 Community

Join our DingTalk group to connect with the community:

DingTalk QR Code

Migration Guide (v0.1.x → v0.2.0)

OpenJudge was previously distributed as the legacy package rm-gallery (v0.1.x). Starting from v0.2.0, it is published as py-openjudge and the Python import namespace is openjudge.

OpenJudge v0.2.0 is NOT backward compatible with v0.1.x. If you are currently using v0.1.x, choose one of the following paths:

  • Stay on v0.1.x (legacy): keep using the old package
pip install rm-gallery

We preserved the source code of v0.1.7 (the latest v0.1.x release) in the v0.1.7-legacy branch.

If you run into migration issues, please open an issue with your minimal repro and current version.


📄 Citation

If you use OpenJudge in your research, please cite:

@software{
  title  = {OpenJudge: A Unified Framework for Holistic Evaluation and Quality Rewards},
  author = {The OpenJudge Team},
  url    = {https://github.com/agentscope-ai/OpenJudge},
  month  = {07},
  year   = {2025}
}

Made with ❤️ by the OpenJudge Team

🌐 Website · 🚀 Try Online · ⭐ Star Us · 🐛 Report Bug · 💡 Request Feature

Metadata

Release files for py-openjudge 0.2.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-openjudge 0.2.5
File Size Uploaded Provenance Actions
py_openjudge-0.2.5.tar.gz 942.1 kB Without provenance Details for py_openjudge-0.2.5.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for py-openjudge 0.2.5
File Interpreter ABI Platform Actions
py_openjudge-0.2.5-py3-none-any.whl Python 3 none any Details for py_openjudge-0.2.5-py3-none-any.whl

Total release size: 2.3 MB

Release files / py_openjudge-0.2.5.tar.gz

Download URL py_openjudge-0.2.5.tar.gz
Size 942.1 kB
Tags Source
SHA-256 checksum
How to use checksums
88b858f2988aec2a82693239f92d656f883bf95953303631daa3be2bd35ac5a1
BLAKE2b-256 checksum
How to use checksums
c6efcd5ed8438104932d6111d2033a9b4e1289bb4cdb1308f0756ecb3f2e76dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / py_openjudge-0.2.5-py3-none-any.whl

Download URL py_openjudge-0.2.5-py3-none-any.whl
Size 1.4 MB
Tags Python 3
SHA-256 checksum
How to use checksums
f608add66cb370abdcead3c78eb2fa23ccb093b1daf59567a18f978199041a5d
BLAKE2b-256 checksum
How to use checksums
a3355816d33a3364610b20800ef336794ef3946a3aa743f0e2c475b97185ae08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for py-openjudge 0.2.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page