Metadata-Version: 2.4
Name: contractex
Version: 0.5.0
Summary: Processing layer for legal document AI: chunking, extraction, provenance, privacy enforcement and evaluation
Author-email: Alexander Hepburn <hello@quietsignalslab.com>
License: Apache-2.0
Project-URL: Documentation, https://quietsignalslab.com/contractex/docs/
Project-URL: Homepage, https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library
Project-URL: Repository, https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library
Project-URL: Issues, https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/issues
Project-URL: Changelog, https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/blob/main/CHANGELOG.md
Keywords: legal-tech,contract-analysis,llm,privacy,pii-redaction,provenance,evaluation,cuad
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Legal Industry
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.9.0
Requires-Dist: pypdfium2>=4.30
Requires-Dist: python-docx>=1.1.0
Requires-Dist: pyyaml>=6.0.0
Provides-Extra: openai
Requires-Dist: openai>=1.50.0; extra == "openai"
Provides-Extra: anthropic
Requires-Dist: anthropic<1.0,>=0.39.0; extra == "anthropic"
Provides-Extra: google
Requires-Dist: google-genai>=1.0.0; extra == "google"
Provides-Extra: ollama
Requires-Dist: ollama>=0.1.0; extra == "ollama"
Provides-Extra: langchain
Requires-Dist: langchain>=0.3.0; extra == "langchain"
Requires-Dist: langchain-community>=0.3.0; extra == "langchain"
Provides-Extra: privacy
Requires-Dist: presidio-analyzer>=2.2.0; extra == "privacy"
Requires-Dist: cryptography>=41.0.0; extra == "privacy"
Provides-Extra: ocr
Requires-Dist: pytesseract>=0.3.10; extra == "ocr"
Requires-Dist: pillow>=10.0.0; extra == "ocr"
Provides-Extra: network
Requires-Dist: requests>=2.31.0; extra == "network"
Provides-Extra: export
Requires-Dist: pandas>=2.2.0; extra == "export"
Requires-Dist: openpyxl>=3.1.0; extra == "export"
Provides-Extra: spacy
Requires-Dist: spacy>=3.7.0; extra == "spacy"
Provides-Extra: storage
Requires-Dist: psycopg2-binary>=2.9.9; extra == "storage"
Requires-Dist: pgvector>=0.3.0; extra == "storage"
Provides-Extra: rag
Requires-Dist: sentence-transformers>=2.0.0; extra == "rag"
Provides-Extra: graph
Requires-Dist: networkx>=3.0.0; extra == "graph"
Requires-Dist: neo4j>=5.0.0; extra == "graph"
Requires-Dist: rdflib>=7.0.0; extra == "graph"
Provides-Extra: all
Requires-Dist: contractex[anthropic,export,google,graph,langchain,network,ocr,ollama,openai,privacy,rag,spacy,storage]; extra == "all"
Provides-Extra: dev
Requires-Dist: pytest>=8.0.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
Requires-Dist: black==24.10.0; extra == "dev"
Requires-Dist: ruff>=0.1.0; extra == "dev"
Requires-Dist: mypy>=1.8.0; extra == "dev"
Requires-Dist: types-requests>=2.31.0; extra == "dev"
Requires-Dist: types-PyYAML>=6.0.0; extra == "dev"
Requires-Dist: cryptography>=41.0.0; extra == "dev"
Requires-Dist: pillow>=10.0.0; extra == "dev"
Requires-Dist: psycopg2-binary>=2.9.9; extra == "dev"
Requires-Dist: requests>=2.31.0; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs<2,>=1.5.0; extra == "docs"
Requires-Dist: mkdocs-material>=9.5.0; extra == "docs"
Requires-Dist: mkdocstrings[python]>=0.24; extra == "docs"
Requires-Dist: mkdocs-autorefs>=0.5; extra == "docs"
Requires-Dist: mkdocs-minify-plugin>=0.7; extra == "docs"
Dynamic: license-file

# Contractex

[![PyPI](https://img.shields.io/pypi/v/contractex)](https://pypi.org/project/contractex/)
[![Python](https://img.shields.io/pypi/pyversions/contractex)](https://pypi.org/project/contractex/)
[![Tests](https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/actions/workflows/tests.yml/badge.svg)](https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/actions/workflows/tests.yml)
[![License](https://img.shields.io/badge/license-Apache%202.0-blue)](https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/blob/main/LICENSE)

Contractex is a Python library for legal document intelligence: the
processing layer for chunking, extraction, retrieval, privacy enforcement and
quality measurement that legal AI products are built on.

This project aims to democratise legal tech by building a transparent
open-source library that changes who within the legal field gets to benefit
from the latest developments in machine learning and AI.

```bash
pip install contractex
```

**Documentation: [quietsignalslab.com/contractex/docs](https://quietsignalslab.com/contractex/docs/)**

## What it does

- Parses contracts deterministically: sections, defined terms,
  cross-references.
- Extracts parties, clauses and terms with the model you choose: a local model
  through Ollama, or OpenAI, Anthropic or Google.
- Traces an extracted value back to character offsets in the source.
- Enforces a privacy profile on every model call.
- Measures quality with an evaluation harness and CI gates.

## What it refuses to do

- Put the text of a `secret` document into any model prompt.
- Send a `restricted` document to anything but a local model.
- Send `confidential` text to a model without redacting the personal data it
  detects.
- Pick a model vendor for you, or install one's SDK unless you ask for it.

```python
from contractex import LegalDoc
from contractex.privacy import PrivacyBlockedError, PrivacyProfile
from contractex.tasks import TaskRegistry

doc = LegalDoc(
    full_text="Board minutes: acquire Acme Corp for $4.2bn. Contact 415-555-0132.",
    privacy_profile=PrivacyProfile(sensitivity="secret"),
)
pipeline = TaskRegistry.default().build_pipeline(
    ["pii_detection", "summarization"],
    task_kwargs={"summarization": {"llm_provider": "llama3.1:8b"}},  # a local Ollama model
)
try:
    pipeline.run(doc)
except PrivacyBlockedError:
    print("blocked before any prompt reached the model")
```

```text
blocked before any prompt reached the model
```

## Measured, not claimed

Generated by `python -m benchmarks` and checked in CI.  Methodology and
limitations are in the [benchmarks documentation](https://quietsignalslab.com/contractex/docs/benchmarks/).

<!-- benchmarks:start -->
| Measured on | Result |
|---|---|
| Gold clause spans kept in one chunk (102 CUAD contracts, 512-token chunks) | clause aware 98.9% · semantic 95.5% · fixed window 88.6% |
| Verbatim values traced to the right place in the source | 97.2% |
| Privacy routing checks (4 sensitivity levels × 2 providers × 4 entry points) | 32 of 32 pass |
<!-- benchmarks:end -->

## Limits

Without [Presidio](https://microsoft.github.io/presidio/) (`contractex[privacy]`),
names are not detected.  Scanned PDFs need OCR (`contractex[ocr]`).  Patterns
for chunking, citations and personal data are English-centric.  The full list
is on the [Limitations](https://quietsignalslab.com/contractex/docs/limitations/)
page.

## Project

[Changelog](https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/blob/main/CHANGELOG.md) ·
[Contributing](https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/blob/main/CONTRIBUTING.md) ·
[Security](https://github.com/Quiet-Signals-Lab/Contractex-Legal-Tech-Library/blob/main/SECURITY.md) ·
Apache License 2.0 · maintained by [Quiet Signals Lab](https://quietsignalslab.com)
