Metadata-Version: 2.4
Name: factivelabs
Version: 0.1.0
Summary: Official Python SDK for FactiveLabs fact-checking API
Author-email: FactiveLabs <jonasphilliplee@gmail.com>
License: MIT
Project-URL: Homepage, https://factivelabs.com
Project-URL: Documentation, https://factivelabs.com/api/docs
Project-URL: Repository, https://github.com/jonasphilliplee/claimcheck
Project-URL: Issues, https://github.com/jonasphilliplee/claimcheck/issues
Keywords: fact-checking,verification,claims,api
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.20; extra == "dev"
Requires-Dist: pytest-cov>=4.0; extra == "dev"
Requires-Dist: black>=22.0; extra == "dev"
Requires-Dist: isort>=5.0; extra == "dev"
Requires-Dist: mypy>=0.990; extra == "dev"
Dynamic: license-file

# FactiveLabs Python SDK

Official Python client for the [FactiveLabs](https://factivelabs.com) fact-checking API.

## Installation

```bash
pip install factivelabs
```

## Quick Start

### Sync Client

```python
from factivelabs import FactiveLabs

client = FactiveLabs(api_key="YOUR_API_KEY")
result = client.verify(content="The Earth is flat", mode="text")

for claim in result.claims:
    print(f"{claim.verdict}: {claim.text}")
```

### Async Client

```python
from factivelabs import AsyncFactiveLabs
import asyncio

async def main():
    client = AsyncFactiveLabs(api_key="YOUR_API_KEY")
    result = await client.verify(content="The Earth is flat", mode="text")
    
    for claim in result.claims:
        print(f"{claim.verdict}: {claim.text}")
    
    await client.close()

asyncio.run(main())
```

## Features

- **Sync and Async clients** - Use whichever fits your workflow
- **Fact verification** - Check claims against reliable sources
- **Claim extraction** - Extract claims from documents without verification
- **Batch processing** - Verify up to 100 items in one request
- **File support** - Verify PDFs, DOCX, XLSX, and text files
- **Streaming responses** - Get real-time verification progress
- **Type hints** - Full type annotations for IDE autocomplete
- **Automatic retries** - Built-in retry logic with exponential backoff

## Usage Examples

### Verify Content

```python
client = FactiveLabs(api_key="YOUR_API_KEY")

# Verify text
result = client.verify(
    content="Climate change is real and human-caused",
    mode="text",
    max_claims=50
)

print(f"Found {len(result.claims)} claims")
for claim in result.claims:
    print(f"  {claim.verdict}: {claim.text}")
    if claim.sources:
        for source in claim.sources:
            print(f"    Source: {source.title} ({source.domain})")
```

### Extract Claims

```python
# Extract claims without verification
result = client.extract(
    content="Your document text here",
    max_claims=2000
)

print(f"Extracted {result.claims_count} claims")
```

### Extract Plain Text

```python
# Free endpoint to extract clean text from documents
result = client.extract_text(file="document.pdf")
print(result.text)
print(f"Title: {result.title}")
```

### Analyze Document Structure

```python
# Analyze sections and get skip recommendations
result = client.analyze_structure(file="report.docx")

for section in result.sections:
    print(f"{section.title}: {section.word_count} words")
    if section.skip_recommended:
        print("  (Skip recommended)")
```

### Batch Verification

```python
items = [
    {"content": "Claim 1", "content_type": "text"},
    {"content": "Claim 2", "content_type": "text"},
    {"content": "Claim 3", "content_type": "text"},
]

batch = client.batch_verify(items)
print(f"Batch {batch.batch_id}: {batch.total} items")

# Poll for results
import time
while True:
    job_status = client.get_job(batch.jobs[0].id)
    if job_status.status == "complete":
        print("Batch complete!")
        break
    time.sleep(1)
```

### Streaming Responses

```python
# Stream verification results as they arrive
stream = client.verify(
    content="Your content here",
    stream=True,
    mode="text"
)

for event in stream:
    print(f"Event: {event['event']}")
    print(f"Data: {event['data']}")
```

### File Verification

```python
# Automatically detects file type and encodes file
result = client.verify_file("document.pdf")

for claim in result.claims:
    print(f"{claim.verdict}: {claim.text}")
```

## Response Objects

### VerifyResponse

```python
result = client.verify(content="...")

# Access verdict counts
print(f"Confirmed: {result.counts.confirmed}")
print(f"Disputed: {result.counts.disputed}")
print(f"Inconclusive: {result.counts.inconclusive}")

# Access individual claims
for claim in result.claims:
    claim.text              # The claim text
    claim.verdict          # confirmed/disputed/inconclusive/skipped
    claim.summary          # Human-readable summary
    claim.explanation      # Detailed explanation
    claim.corrected_text   # Corrected version if applicable
    claim.sources          # List of sources
    claim.categories       # Claim categories
    claim.verified_by      # Verification method/source
```

## Error Handling

```python
from factivelabs import (
    FactiveLabs,
    AuthenticationError,
    RateLimitError,
    ValidationError,
    APIError,
)

client = FactiveLabs(api_key="YOUR_API_KEY")

try:
    result = client.verify(content="...")
except AuthenticationError:
    print("Invalid API key")
except RateLimitError:
    print("Rate limit exceeded, retrying...")
except ValidationError as e:
    print(f"Invalid request: {e}")
except APIError as e:
    print(f"API error {e.status_code}: {e}")
```

## Context Manager Usage

```python
# Sync client
with FactiveLabs(api_key="YOUR_API_KEY") as client:
    result = client.verify(content="...")

# Async client
async with AsyncFactiveLabs(api_key="YOUR_API_KEY") as client:
    result = await client.verify(content="...")
```

## Configuration

### Custom Base URL

```python
client = FactiveLabs(
    api_key="YOUR_API_KEY",
    base_url="https://custom.factivelabs.com"
)
```

### Custom Timeout

```python
# Default is 120 seconds for verify, 30 seconds for other endpoints
client = FactiveLabs(
    api_key="YOUR_API_KEY",
    timeout=300.0  # 5 minutes
)
```

## API Documentation

For complete API documentation, visit [docs.factivelabs.com](https://docs.factivelabs.com).

## License

MIT License - see LICENSE file for details.

## Support

For issues, questions, or feedback, please visit:
- GitHub Issues: https://github.com/factivelabs/factivelabs-python/issues
- Email: support@factivelabs.com
- Website: https://factivelabs.com
