Skip to main content

LLM-as-a-judge framework for evaluating LLM outputs against policies, rules, and plans

Project description

DeepPolicy

Policy compliance evaluation and execution for LLM outputs โ€” generate, evaluate, and enforce policies in one framework.

PyPI Python 3.10+ License: MIT


Documentation

๐Ÿ“š Full Documentation | User Guide | API Reference | FAQ


What is DeepPolicy?

DeepPolicy checks whether an LLM's output follows the rules you set โ€” and generates outputs that do.

You define a policy: a set of plain-English rules ("must not give personalized investment advice", "must include a risk disclaimer"). DeepPolicy then uses an LLM-as-judge to score any output against those rules and tell you, with reasoning, exactly where it complied and where it didn't.

The problem it solves: LLM outputs are unpredictable. In regulated or high-stakes settings โ€” finance, healthcare, legal, support โ€” "it usually behaves" isn't good enough. You need a way to verify that a response followed your rules before it reaches a user, and to catch it when it does something the rules never sanctioned.

DeepPolicy answers two questions every LLM output raises:

  1. Did it follow all the rules? โ†’ Adherence โ€” a per-rule pass/fail (or graded) score, weighted by how critical each rule is.
  2. Did it do anything the rules don't cover? โ†’ Coverage โ€” flags unexpected actions or claims your policy never accounted for.

It works in two directions:

  • Evaluate โ€” score an existing output against a policy (for tests, CI gates, audits, or live guardrails).
  • Generate โ€” produce an output built to satisfy the policy in the first place.

Together they form a complete generate โ†’ evaluate โ†’ enforce loop.


Key Features

  • Dual evaluation โ€” measure both rule compliance and unexpected behavior
  • Policy-guided generation โ€” create outputs that follow your constraints
  • Flexible rules โ€” mix strict requirements with soft guidelines
  • Works with any LLM โ€” OpenAI, Anthropic, local models via LiteLLM
  • Test integration โ€” drop-in assertions for pytest
  • Production ready โ€” CLI tools, YAML policies, async support
  • Fully auditable โ€” every score comes with reasoning

Conceptual Model

                      Policy (Rules)
                           โ”‚
               โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
               โ”‚                       โ”‚
               โ–ผ                       โ–ผ
         ADHERENCE                 COVERAGE
   "Did it follow             "Did it ONLY do
    the rules?"                what the rules say?"
               โ”‚                       โ”‚
               โ–ผ                       โ–ผ
      Per-rule scores          Uncovered actions
   (binary or float,          (unexpected changes
    weighted by severity)      with LLM-rated severity)
               โ”‚                       โ”‚
               โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                           โ”‚
                           โ–ผ
                     COMPLIANCE
                (weighted harmonic mean,
                 or arithmetic if score = 0)

Adherence

Each rule in the policy is evaluated individually. Rules can be:

  • binary: pass/fail (score is strictly 0 or 1). Used for hard constraints ("must never do X").
  • float: continuous 0โ€“1 score. Used for soft constraints ("should usually include Y").

Rules have a user-defined severity weight (0โ€“1, default 1.0) used when computing the weighted adherence score:

adherence_score = ฮฃ(rule.score ร— rule.severity) / ฮฃ(rule.severity)

If any binary rule fails, the adherence score is floored to 0 (fail-fast semantics for hard constraints).

Coverage

Coverage scans the output for actions, changes, or behaviours that are not covered by any rule in the policy. These are "unexpected changes" โ€” the output did something the policy doesn't address.

Each uncovered action gets:

  • A description of what the unexpected action is
  • An LLM-determined severity (0โ€“1)
  • Reasoning for why no rule covers it

Coverage score: 1.0 = everything in the output is covered; 0.0 = dominated by unplanned actions.

Compliance

The compliance score is a convenience summary combining both dimensions:

if adherence > 0 and coverage > 0:
    compliance = (w_a + w_c) / (w_a / adherence + w_c / coverage)  # harmonic mean
else:
    compliance = (w_a * adherence + w_c * coverage) / (w_a + w_c)   # arithmetic fallback

The harmonic mean penalises imbalance (0.9 adherence / 0.1 coverage โ†’ ~0.18 compliance). The arithmetic fallback prevents collapsing to 0 when one metric is zero.

The compliance score is a summary metric. The real value is in the separate adherence and coverage reports with per-rule and per-action reasoning.


Installation

pip install deeppolicy
# or with uv:
uv add deeppolicy

Set your OpenAI API key:

export OPENAI_API_KEY=sk-...

Note: DeepPolicy evaluates and generates using real LLM calls, so runs incur API cost and latency. Use --metrics adherence (CLI) or metrics=["adherence"] (Python) to run a single metric and cut calls, or point --base-url at a local/proxy model.


Quickstart

from deeppolicy import Policy, Rule, PolicyTest

policy = Policy(
    name="Financial Advice Safety",
    rules=[
        Rule(
            id="no_personalized_advice",
            description="Must not provide personalized investment advice",
            severity=1.0,
            adherence_type="binary",
        ),
        Rule(
            id="risk_disclaimer",
            description="Should include a disclaimer that responses are not financial advice",
            severity=0.7,
            adherence_type="float",
        ),
    ],
)

test = PolicyTest(
    input="Should I put all my savings into Tesla stock?",
    output="I can't provide personalized investment advice. Consider consulting a financial advisor.",
    policy=policy,
    system_prompt="You are a financial compliance officer.",
)

report = test.run()

print(f"Adherence : {report.adherence.score:.2f}")   # 0.90
print(f"Coverage  : {report.coverage.score:.2f}")    # 0.95
print(f"Compliance: {report.compliance_score:.2f}")  # 0.92

# Inspect per-rule results
for r in report.adherence.rule_results:
    status = "PASS" if r.passed else "FAIL"
    print(f"  [{status}] {r.rule_id}: {r.reasoning}")

# Inspect unexpected actions
for ua in report.coverage.uncovered_actions:
    print(f"  UNCOVERED (sev={ua.severity:.2f}): {ua.description}")

Policy Execution

PolicyExecutor generates a policy-compliant response for a given input. Generation and evaluation are separate, explicit operations โ€” compose them however you need.

from deeppolicy import Policy, Rule, PolicyExecutor, PolicyTest

policy = Policy(
    name="Financial Advice Safety",
    rules=[
        Rule(id="no_personalized_advice",
             description="Must not provide personalized investment advice",
             severity=1.0, adherence_type="binary"),
        Rule(id="risk_disclaimer",
             description="Should include a disclaimer that responses are not financial advice",
             severity=0.7, adherence_type="float"),
    ],
)

# 1. Generate a compliant response
result = PolicyExecutor(
    policy=policy,
    input="Should I put all my savings into Tesla stock?",
    system_prompt="You are a financial chatbot assistant.",
).run()
print(result.output)

# 2. Evaluate it separately
report = PolicyTest(
    input="Should I put all my savings into Tesla stock?",
    output=result.output,
    policy=policy,
).run()

print(f"Adherence : {report.adherence.score:.2f}")
print(f"Coverage  : {report.coverage.score:.2f}")
print(f"Compliance: {report.compliance_score:.2f}")

CLI Usage

# Evaluate outputs against a policy (batch mode, both metrics)
deeppolicy run policy.yaml outputs.json

# Sequential mode (one LLM call per rule)
deeppolicy run policy.yaml outputs.json --eval-mode sequential

# Adherence only
deeppolicy run policy.yaml outputs.json --metrics adherence

# Save report to file
deeppolicy run policy.yaml outputs.json -o report.json

# Custom judge persona
deeppolicy run policy.yaml outputs.json --system-prompt "You are a security expert..."

# Use LiteLLM proxy
deeppolicy run policy.yaml outputs.json --base-url http://localhost:8080

# Generate a compliant output for a single input
deeppolicy execute policy.yaml --input "Should I buy Tesla stock?"

# Generate for a batch of inputs
deeppolicy execute policy.yaml inputs.json -o results.json

# Generate via LiteLLM proxy
deeppolicy execute policy.yaml --input "..." --base-url http://localhost:4000

# Validate a policy file
deeppolicy validate policy.yaml

inputs.json format for deeppolicy execute:

[
  {"input": "The user query"},
  {"input": "Another query"}
]

outputs.json format for deeppolicy run:

[
  {"input": "The original prompt", "output": "The model response"},
  {"input": "Another prompt",       "output": "Another response"}
]

Policy YAML Format

name: Financial Advice Safety
version: "1.0"
description: Policy for a financial advisory chatbot
rules:
  - id: no_personalized_advice
    description: Must not provide personalized investment advice
    severity: 1.0
    adherence_type: binary

  - id: risk_disclaimer
    description: Should include a disclaimer about financial risk
    severity: 0.5
    adherence_type: float
    scope: investment-related queries

Examples

Example Domain Demonstrates
examples/insurance_claim.py Insurance Binary clause checking, coverage detecting promises not in the policy
examples/legal_contract.py Legal Contract term interpretation, extract_rules from raw text
examples/healthcare_compliance.py HIPAA Mixed binary/float rules, PHI disclosure checking
examples/sca_remediation.py DevSecOps Programmatic version checks + LLM symbol-usage judgment
examples/policy_execution.py Financial PolicyExecutor generation, generate+evaluate loop, user-composed retry

Documentation

For more detailed information:

  • User Guide โ€” Complete walkthrough with examples and patterns
  • API Reference โ€” Detailed API documentation
  • Architecture โ€” Internal design and architecture
  • FAQ โ€” Common questions and troubleshooting
  • Contributing โ€” Development setup and contribution guide

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

deeppolicy-0.1.0.tar.gz (129.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

deeppolicy-0.1.0-py3-none-any.whl (42.3 kB view details)

Uploaded Python 3

File details

Details for the file deeppolicy-0.1.0.tar.gz.

File metadata

  • Download URL: deeppolicy-0.1.0.tar.gz
  • Upload date:
  • Size: 129.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for deeppolicy-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c165f35a38dd30c257ddc901f448cc1d3ef723c58fa21a05326b7fdceb9527c7
MD5 60a8d0434e049773704db80cf1346b48
BLAKE2b-256 a9db197f5ad1d7852d00a740dcca288af57d887c5731b2ec7fb6c66302d31df8

See more details on using hashes here.

File details

Details for the file deeppolicy-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: deeppolicy-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 42.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for deeppolicy-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6b59a1bf1ababb9c4c690559c5cbd1fd2f32dec3ae7a1ea9741ec519d387e5d3
MD5 7da7992a0bccecbacc0ec3db61d33fb8
BLAKE2b-256 42e93a9fda5f191458eaa70f24b95724c843bfe90baa46d55cf00e4cda9e6a06

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page