# Quber - Advanced Table Extraction and Inference System

Quber extracts tables and structure from financial PDFs and uses LLM analysis to
understand them. A vision model locates each table on the page, Camelot reads the
values inside that region from the PDF's own text layer, and a second vision pass
corrects the structure under guards that reject any number the page does not
carry.

## Overview

The hard part is not parsing a clean table. It is answering two questions on a
crowded page: where is each table, and what exactly does it contain, with a
guarantee that no number was invented and no row silently dropped. Quber splits
that across three components and trusts each only for what it does well.

| Component | Decides | Why it is trusted for this |
| --- | --- | --- |
| Vision over a gridded page image | Which tables exist and the region each occupies | It sees the page as a reader does, including tables with no ruled lines |
| Camelot over the PDF text layer | The cell values inside a region | Whatever lands in a cell came from the document's own text layer |
| Vision over a cropped table image | Column layout, headers, titles, footnotes | Structure is visible on the page and absent from the text layer |

The default extraction engine is Set-of-Mark, named for the visual-prompting
technique it applies: a labelled grid is drawn over the page and the model
answers by reading printed labels rather than predicting coordinates.
`docs/SET_OF_MARK_EXTRACTION_GRAPH.pdf` is the engineering reference for it.

## Key Features

- **Region-constrained extraction** so one table cannot shatter into several
  grids, nor several merge into one.
- **Value guards** that discard a structure correction rather than emit a figure
  with no source in the grid or the page text.
- **Cell-level provenance**: every cell of a finished table records how it was
  produced and whether its coordinates were measured.
- **Nothing dropped silently**: a region that yields no grid is still emitted
  with its identity, and a page the locator cannot read stops the run.
- **Multi-provider LLM support** through PydanticAI (Anthropic, OpenAI, Groq,
  Gemini, VertexAI, Bedrock, Mistral, Ollama).
- **Retrieval playground**: a web app that ingests a document and answers
  questions about it with cell-level citations.

## Installation

### Prerequisites
- Python 3.13+
- API key for at least one LLM provider (Anthropic, OpenAI, Groq, etc.)
- Docker (optional, only to build the cloud-job or RunPod images)

### Setup

```bash
# Install with uv (recommended)
uv sync

# Or with pip
pip install -e .

# Set up environment variables for your chosen provider(s)
export ANTHROPIC_API_KEY="your-key-here"  # For Anthropic Claude
export OPENAI_API_KEY="your-key-here"     # For OpenAI GPT models
export GROQ_API_KEY="your-key-here"       # For Groq
export GEMINI_API_KEY="your-key-here"     # For Google Gemini
# See 'quber models' command for all providers
```

Keys may also go in a `.env` file in the project root, which is read
automatically (see `src/quber/settings/__init__.py`).

## Usage

### Command-Line Interface

Quber provides a comprehensive CLI with three main commands:

#### 1. Analyze a Single Document

```bash
# Basic analysis with default settings
quber analyze documents/TMUS_Q225_991.pdf

# Specify output files and model
quber analyze documents/TMUS_Q225_991.pdf \
    --output output/analysis.json \
    --summary output/summary.md \
    --model claude-3-5-sonnet-20241022

# Use a specific provider and model
quber analyze documents/report.pdf \
    --provider anthropic \
    --model claude-3-5-haiku-latest \
    --max-concurrent 10 \
    --verbose

# Use OpenAI instead of Anthropic
quber analyze documents/report.pdf \
    --provider openai \
    --model gpt-4o-mini
```

#### 2. Batch Process Multiple Documents

```bash
# Process all PDFs in a directory
quber batch documents/

# Custom output directory and pattern
quber batch documents/ \
    --output-dir results/ \
    --pattern "*.pdf" \
    --provider groq \
    --model llama-3.1-8b-instant

# Process with specific settings
quber batch reports/ \
    --max-concurrent 8 \
    --provider anthropic \
    --model claude-3-5-haiku-latest
```

#### 3. Database Management

```bash
# Initialize database schema
quber db init

# Import a single JSON file
quber db import-json output/TMUS_Q225_991_analysis.json

# Import all JSON files from a directory
quber db import-dir output/

# View database statistics
quber db stats

# See all database commands
quber db --help
```

For detailed database setup and usage, see [Database Setup Guide](docs/DATABASE_SETUP.md).

#### 4. List Available Models

```bash
# Show all available providers and models
quber models

# Show models for a specific provider
quber models --provider anthropic

# Show all models (including extended lists)
quber models --all
```

### Development/Testing

```bash
# Parse a PDF to a document model without any LLM analysis
uv run quber document <pdf> -o output/
```

## Architecture

### Core components

| Module | Responsibility |
| --- | --- |
| `src/quber/cli.py` | The command-line interface. Its module docstring is the contract for how the four pipeline commands hand artifacts to each other. |
| `src/quber/core/extractors/set_of_mark/` | The default table engine: the extraction graph, per-table capture, grounding, and status inspection. |
| `src/quber/core/parsers/` | The document parse path, producing a `DoclingDocument`. |
| `src/quber/core/fusion/` | Merges the document parse and the table extraction into one document. |
| `src/quber/core/figures/` | Reads charts and image-printed tables that carry no text layer. |
| `src/quber/agents/` | The LLM agent roles, each a Protocol with a real implementation and a mock. |
| `src/quber/playground/` | The retrieval web app: ingestion, embedding, retrieval, and the answering UI. |

### The pipeline

Four commands compose, handing work to each other through files named after the
source document, so one stage's `--output-dir` is the next stage's input.

1. `quber document` parses the PDF and writes the document model.
2. `quber table` extracts the tables with the Set-of-Mark engine.
3. `quber fuse` merges those two into one unified document.
4. `quber figure` reads the imagery and enriches the parse it is handed.

`quber playground` serves the answering app, which runs those stages as
subprocesses when a document is uploaded. Run `quber --help` for the full
command list; that output is authoritative and this file does not restate it.

## Advanced Features

### Header Consolidation Rules

Headers are consolidated when:
- They appear consecutively (no intervening content)
- They are at the same hierarchical level
- No tables, images, or text blocks separate them

Example:
```
H2: Financial Statements
H2: Consolidated Balance Sheet
H2: (Unaudited)
→ "Financial Statements ^ Consolidated Balance Sheet ^ (Unaudited)"
```

### Context Hierarchy

LLM receives three levels of context:

1. **Page Context** (2000 chars):
   - Document headers, company names
   - Section titles, report types
   - Page-level metadata

2. **Procedural Headers**:
   - Immediately preceding headers
   - Consolidated based on rules
   - Preserves original structure

3. **Table Preview**:
   - First 10 rows of table
   - Column headers and structure
   - Sample data values

### Output Formats

#### JSON Structure
```json
{
  "document": "TMUS_992_Q423.pdf",
  "extraction_date": "2024-09-26T15:00:00",
  "total_tables": 15,
  "tables": [{
    "table_id": 0,
    "page": 17,
    "procedural_title": "Consolidated Balance Sheets",
    "headers": ["Financial Tables", "T-Mobile US, Inc.", "Consolidated Balance Sheets"],
    "llm_title": "T-Mobile US, Inc. Consolidated Balance Sheets (Unaudited)",
    "llm_description": "Quarterly balance sheet showing assets, liabilities...",
    "table_markdown": "| Assets | Q3 2023 | Q4 2023 |...",
    "metadata": {
      "rows": 45,
      "cols": 3,
      "first_cell": "Assets"
    }
  }]
}
```

#### Markdown Summary
- Procedural extraction details
- LLM-generated insights
- Table previews as rendered tables
- Comprehensive metadata

## Configuration

### Model Providers and Default Models

| Provider | Default Model | Environment Variable |
|----------|--------------|---------------------|
| Anthropic | claude-3-5-haiku-latest | ANTHROPIC_API_KEY |
| OpenAI | gpt-4o-mini | OPENAI_API_KEY |
| Groq | llama-3.1-8b-instant | GROQ_API_KEY |
| Gemini | gemini-1.5-flash | GEMINI_API_KEY |
| VertexAI | gemini-1.5-flash | GOOGLE_APPLICATION_CREDENTIALS |
| Bedrock | anthropic.claude-3-5-haiku-20241022-v1:0 | AWS_ACCESS_KEY_ID |
| Mistral | mistral-small-latest | MISTRAL_API_KEY |
| Ollama | llama3.2 | (local, no key needed) |

### CLI Parameters
- `--provider` - Choose model provider (auto-detected if not specified)
- `--model` - Specify exact model to use (uses provider default if not specified)
- `--max-concurrent` - Number of parallel table analyses (default: 5)
- `--output` - Output JSON file path
- `--summary` - Output markdown summary path
- `--verbose` - Enable detailed logging

## Performance Considerations

### Concurrent Processing
- Tables within a document are analyzed concurrently (default: 5 simultaneous)
- Adjust `--max-concurrent` based on your API rate limits and system resources
- Higher concurrency speeds up processing but may hit rate limits

### API Rate Limits
- Each provider has different rate limits
- Groq and Ollama typically allow higher throughput
- Anthropic and OpenAI may require lower concurrency for large batches

## Documentation

- **[CLAUDE.md](./CLAUDE.md)** - Conventions for working in this repository
- **[docs/](./docs/)** - Engineering references and workflow specifications
- **[docs/development/](./docs/development/)** - Setup guides

## Development

### Quick Start for Developers

**[Development Documentation](./docs/development/)** - Start here for setup guides!
- [GitHub Setup Guide](./docs/development/GITHUB_SETUP.md) - Secrets, API keys, project management
- [Issue and PR Workflow](./docs/GITHUB_WORKFLOW_SPEC.md) - Branches, PRs, evidence requirements

### Running Tests
```bash
# Test with the CLI
quber analyze documents/TMUS_992_Q423.pdf --verbose

# Test batch processing
quber batch documents/ --output-dir test_output/

# Check available models
quber models
```

### Project Structure
```
quber/
├── src/quber/
│   ├── cli.py              # Command-line interface; the pipeline contract
│   ├── agents/             # LLM agent roles, their Protocols and mocks
│   ├── core/
│   │   ├── extractors/     # Table engines; set_of_mark is the default
│   │   ├── parsers/        # Document parse to DoclingDocument
│   │   ├── fusion/         # Merges the parse and the table extraction
│   │   └── figures/        # Charts and image-printed tables
│   ├── playground/         # Retrieval web app
│   ├── processors/         # Table inference and LLM analysis
│   ├── settings/           # Configuration and model selection
│   └── db/                 # Postgres and pgvector access
├── docs/                   # Design records and engineering references
├── experiments/            # Prototypes, not part of the package
├── documents/              # Sample PDFs
└── tests/
```

## Troubleshooting

### Common Issues

**No API Keys Found**
```bash
# Check which providers are available
quber models

# Set the appropriate environment variable
export ANTHROPIC_API_KEY="your-key-here"
```

**Rate Limit Errors**
- Reduce `--max-concurrent` to a lower value (e.g., 2 or 3)
- Switch to a different provider with higher limits
- Use Groq or Ollama for higher throughput

**Model Not Found**
```bash
# List all available models for your provider
quber models --provider anthropic --all

# Use any model name directly, even if not in the default list
quber analyze document.pdf --model claude-3-opus-20240229
```

**Poor Table Titles**
- Try a more capable model (e.g., claude-3-5-sonnet vs claude-3-5-haiku)
- Check if the PDF has extractable text (not just images)
- Enable verbose mode to see what context is being extracted

## License

Proprietary - All rights reserved. This is a closed-source commercial project.

## Acknowledgments

- [IBM Docling](https://github.com/DS4SD/docling) - Document AI foundation
- [PydanticAI](https://github.com/pydantic/pydantic-ai) - Structured LLM outputs
- [Anthropic Claude](https://www.anthropic.com) - Advanced language understanding
