> ## Documentation Index
> Fetch the complete documentation index at: https://wildcampstudio.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# SDK Reference

> Complete Python SDK reference for Delve

## Installation

```bash theme={null}
pip install delve-taxonomy
```

## Delve Client

The main class for interacting with Delve programmatically.

### Basic Usage

```python theme={null}
from delve import Delve

# Initialize with defaults
delve = Delve()

# Run taxonomy generation
result = delve.run_sync("data.csv", text_column="text")

# Access results
print(result.taxonomy)
print(result.labeled_documents)
```

### Initialization

```python theme={null}
delve = Delve(
    model="anthropic/claude-sonnet-4-5-20250929",
    fast_llm="anthropic/claude-haiku-4-5-20251001",
    sample_size=100,
    batch_size=200,
    max_num_clusters=5,
    use_case="Generate taxonomy for my data",
    output_dir="./results",
    output_formats=["json", "csv", "markdown"],
    verbosity=Verbosity.NORMAL,  # SILENT, QUIET, NORMAL, VERBOSE, DEBUG
    predefined_taxonomy=None,  # Use existing taxonomy instead of generating
    embedding_model="text-embedding-3-large",
    classifier_confidence_threshold=0.0
)
```

## Configuration Options

<ParamField path="model" type="string" default="anthropic/claude-sonnet-4-5-20250929">
  Main LLM model for taxonomy generation and reasoning.

  ```python theme={null}
  delve = Delve(model="anthropic/claude-opus-4")
  ```

  Supported models:

  * `anthropic/claude-sonnet-4-5-20250929` (recommended)
  * `anthropic/claude-opus-4` (most capable)
  * `anthropic/claude-haiku-4-5-20251001` (fastest/cheapest)
  * Any model supported by LiteLLM
</ParamField>

<ParamField path="fast_llm" type="string" default="anthropic/claude-haiku-4-5-20251001">
  Faster model for document summarization to reduce costs.

  ```python theme={null}
  delve = Delve(fast_llm="anthropic/claude-haiku-4-5-20251001")
  ```

  Use a faster, cheaper model for the summarization step.
</ParamField>

<ParamField path="sample_size" type="integer" default="100">
  Number of documents to sample for taxonomy generation.

  ```python theme={null}
  delve = Delve(sample_size=200)
  ```

  <Tip>
    Larger samples (200-500) produce more comprehensive taxonomies but cost more and take longer. Start with 100 for quick iterations.
  </Tip>
</ParamField>

<ParamField path="batch_size" type="integer" default="200">
  Number of documents per minibatch during iterative clustering.

  ```python theme={null}
  delve = Delve(batch_size=50)
  ```

  <Info>
    Smaller batches (50-100) produce more refined taxonomies. Larger batches (200-300) are faster but may be less precise.
  </Info>
</ParamField>

<ParamField path="max_num_clusters" type="integer" default="5">
  Maximum number of clusters/categories to generate in the taxonomy.

  ```python theme={null}
  delve = Delve(max_num_clusters=10)
  ```

  <Tip>
    Start with a smaller number (5-10) for focused taxonomies. Increase for more granular categorization of diverse datasets.
  </Tip>
</ParamField>

<ParamField path="use_case" type="string" default="Generate taxonomy for categorizing document content">
  Custom description of your taxonomy use case.

  ```python theme={null}
  delve = Delve(
      use_case="Categorize customer feedback by product feature and sentiment"
  )
  ```

  <Tip>
    Providing a specific use case helps guide the model to generate more relevant categories for your domain.
  </Tip>
</ParamField>

<ParamField path="output_dir" type="string" default="./results">
  Directory for saving output files.

  ```python theme={null}
  delve = Delve(output_dir="./my-results")
  ```

  Creates the directory if it doesn't exist.
</ParamField>

<ParamField path="output_formats" type="list" default="['json', 'csv', 'markdown']">
  List of output formats to generate.

  ```python theme={null}
  delve = Delve(output_formats=["json", "csv"])
  ```

  Available formats:

  * `json` - Machine-readable taxonomy and labeled documents
  * `csv` - Spreadsheet format for analysis
  * `markdown` - Human-readable reports
</ParamField>

<ParamField path="verbosity" type="Verbosity" default="Verbosity.SILENT">
  Output verbosity level. Controls how much progress information is displayed.

  ```python theme={null}
  from delve.console import Verbosity

  delve = Delve(verbosity=Verbosity.SILENT)   # No output (SDK default)
  delve = Delve(verbosity=Verbosity.QUIET)    # Errors only
  delve = Delve(verbosity=Verbosity.NORMAL)   # Spinners + checkmarks
  delve = Delve(verbosity=Verbosity.VERBOSE)  # Progress bars with ETA
  delve = Delve(verbosity=Verbosity.DEBUG)    # Everything + internal state
  ```

  Levels:

  * `SILENT` (0) - No output, ideal for SDK usage in scripts
  * `QUIET` (1) - Errors only
  * `NORMAL` (2) - Spinners and success checkmarks
  * `VERBOSE` (3) - Progress bars with item counts and ETA
  * `DEBUG` (4) - All output plus warnings and debug info
</ParamField>

<ParamField path="predefined_taxonomy" type="string | list | None" default="None">
  Use an existing taxonomy instead of generating one. Useful when you want to label documents with known categories.

  ```python theme={null}
  # From a JSON/CSV file
  delve = Delve(predefined_taxonomy="categories.json")

  # Or as a list of dicts
  delve = Delve(predefined_taxonomy=[
      {"id": "1", "name": "Bug", "description": "Bug reports and issues"},
      {"id": "2", "name": "Feature", "description": "Feature requests"},
  ])
  ```

  When provided, Delve skips taxonomy discovery and directly labels documents using the given categories.
</ParamField>

<ParamField path="embedding_model" type="string" default="text-embedding-3-large">
  OpenAI embedding model for classifier training. Used when `sample_size < total documents` to train an efficient classifier for labeling remaining documents.

  ```python theme={null}
  delve = Delve(embedding_model="text-embedding-3-small")  # Cheaper option
  ```
</ParamField>

<ParamField path="classifier_confidence_threshold" type="float" default="0.0">
  Minimum confidence for classifier predictions. Documents below this threshold fall back to LLM labeling. Set to 0 to use classifier for all documents (no fallback).

  ```python theme={null}
  delve = Delve(classifier_confidence_threshold=0.8)  # Use LLM for low-confidence docs
  ```
</ParamField>

## Methods

### run\_sync()

Synchronous method for taxonomy generation (recommended for most use cases).

```python theme={null}
result = delve.run_sync(
    data,
    text_column=None,
    id_column=None,
    source_type=None,
    **adapter_kwargs
)
```

<ParamField path="data" type="str | Path | DataFrame" required>
  Data source to process. Can be:

  * Path to CSV file (`"data.csv"`)
  * Path to JSON/JSONL file (`"data.json"`)
  * LangSmith URI (`"langsmith://project-name"`)
  * pandas DataFrame
</ParamField>

<ParamField path="text_column" type="string">
  Column/field name containing text content (required for CSV/DataFrame).

  ```python theme={null}
  result = delve.run_sync("data.csv", text_column="message")
  ```
</ParamField>

<ParamField path="id_column" type="string">
  Column/field name for document IDs (optional).

  ```python theme={null}
  result = delve.run_sync(
      "data.csv",
      text_column="text",
      id_column="doc_id"
  )
  ```
</ParamField>

<ParamField path="source_type" type="string">
  Force specific adapter type: `csv`, `json`, `jsonl`, `langsmith`, `dataframe`

  ```python theme={null}
  result = delve.run_sync(
      "data.txt",
      source_type="json",
      text_field="content"
  )
  ```
</ParamField>

<ParamField path="**adapter_kwargs" type="dict">
  Additional adapter-specific parameters:

  **For JSON:**

  * `json_path` - JSONPath expression for nested data
  * `text_field` - Field name containing text

  **For LangSmith:**

  * `api_key` - LangSmith API key
  * `days` - Days to look back (default: 7)
  * `max_runs` - Maximum runs to fetch
  * `filter_expr` - LangSmith filter expression
</ParamField>

**Returns:** `DelveResult` object with taxonomy, labeled documents, and metadata.

**Example:**

```python theme={null}
from delve import Delve

delve = Delve(sample_size=150)
result = delve.run_sync(
    "feedback.csv",
    text_column="comment",
    id_column="ticket_id"
)

print(f"Generated {len(result.taxonomy)} categories")
for category in result.taxonomy:
    print(f"- {category.name}: {category.description}")
```

### run()

Asynchronous version of `run_sync()`. Use for async applications.

```python theme={null}
import asyncio
from delve import Delve

async def main():
    delve = Delve()
    result = await delve.run("data.csv", text_column="text")
    print(result.taxonomy)

asyncio.run(main())
```

### run\_with\_docs() / run\_with\_docs\_sync()

Process pre-created `Doc` objects directly, useful for programmatic document creation or testing.

```python theme={null}
from delve import Delve, Doc

docs = [
    Doc(id="1", content="Fix authentication bug"),
    Doc(id="2", content="Add dark mode feature"),
]

delve = Delve(use_case="Categorize software issues")
result = delve.run_with_docs_sync(docs)
# Or async: result = await delve.run_with_docs(docs)
```

### find\_matches() / find\_matches\_async()

Fast, lightweight binary detection for finding documents matching a **single category**. Uses hybrid semantic + keyword matching without running the full taxonomy pipeline.

```python theme={null}
from delve import Delve

result = Delve.find_matches(
    "data.csv",
    category={
        "name": "Refund Request",
        "description": "User asking for refund, money back, or cancellation",
        "keywords": ["refund", "money back", "cancel order"],
    },
    text_column="content",
    threshold=0.6,
)

# All documents returned with scores
print(f"Found {result.stats['matches']} matches")

# Access matched documents (category != None)
for doc in result.matched_documents[:5]:
    print(f"{doc.id}: {doc.confidence:.2f}")
```

<ParamField path="category" type="dict" required>
  Category definition with `name`, `description`, and optional `keywords` list.
</ParamField>

<ParamField path="threshold" type="float" default="0.5">
  Minimum score (0-1) for a document to be considered a match.
</ParamField>

<ParamField path="semantic_weight" type="float" default="0.7">
  Weight for semantic (embedding) similarity.
</ParamField>

<ParamField path="keyword_weight" type="float" default="0.3">
  Weight for keyword matching. Set to 0 for pure semantic matching.
</ParamField>

**Returns:** `MatchResult` with all documents scored, plus `matched_documents` and `unmatched_documents` properties.

<Info>
  Binary detection is much faster (~~2-4 min for 30K docs) and cheaper (~~\$1-2) than full taxonomy generation. See [Binary Detection](/binary-detection) for full documentation.
</Info>

## Data Sources

Delve supports multiple input formats. The `source_type` is auto-detected from file extensions, or you can specify it explicitly.

| Format    | Extension          | Required Parameters         |
| --------- | ------------------ | --------------------------- |
| CSV       | `.csv`             | `text_column`               |
| JSON      | `.json`            | `text_field` or `json_path` |
| JSONL     | `.jsonl`           | (auto-extracts text)        |
| DataFrame | (in-memory)        | `text_column`               |
| LangSmith | `langsmith://` URI | `api_key`                   |

```python theme={null}
# CSV
result = delve.run_sync("data.csv", text_column="message")

# JSON with JSONPath for nested data
result = delve.run_sync("data.json", json_path="$.messages[*].content")

# pandas DataFrame
result = delve.run_sync(df, text_column="message")

# LangSmith
result = delve.run_sync("langsmith://my-project", api_key="lsv2_...", days=7)
```

## Working with Results

The `DelveResult` object provides access to all outputs:

```python theme={null}
result = delve.run_sync("data.csv", text_column="text")

# Taxonomy categories
for cat in result.taxonomy:
    print(f"{cat.name}: {cat.description}")

# Labeled documents
for doc in result.labeled_documents:
    print(f"{doc.id} → {doc.category}")

# Metadata and export paths
print(result.metadata)  # {'num_documents': 100, 'num_categories': 5, ...}
print(result.export_paths)  # {'taxonomy': Path(...), 'csv': Path(...), ...}
```

### TaxonomyCategory

| Attribute     | Type | Description                |
| ------------- | ---- | -------------------------- |
| `id`          | str  | Unique category identifier |
| `name`        | str  | Category name              |
| `description` | str  | Category description       |

### Doc (labeled document)

| Attribute     | Type        | Description                    |
| ------------- | ----------- | ------------------------------ |
| `id`          | str         | Document identifier            |
| `content`     | str         | Original text content          |
| `category`    | str         | Assigned category name         |
| `explanation` | str \| None | Why this category was assigned |
| `summary`     | str \| None | LLM-generated summary          |

### Metadata

The `result.metadata` dictionary contains comprehensive run statistics:

```python theme={null}
result.metadata = {
    # Basic info
    "num_documents": 5000,          # Total documents processed
    "num_categories": 10,           # Number of taxonomy categories
    "sample_size": 100,             # Configured sample size
    "batch_size": 200,              # Configured batch size
    "model": "anthropic/claude-sonnet-4-5-20250929",
    "fast_llm": "anthropic/claude-haiku-4-5-20251001",

    # Timing
    "run_duration_seconds": 145.32, # Total processing time

    # Category distribution
    "category_counts": {            # Documents per category
        "Bug Fix": 1250,
        "Feature Request": 890,
        "Question": 650,
        ...
    },

    # Labeling breakdown
    "llm_labeled_count": 100,       # Documents labeled by LLM
    "classifier_labeled_count": 4900, # Documents labeled by classifier
    "skipped_document_count": 5,    # Documents that couldn't be categorized

    # Classifier metrics (when classifier is used)
    "classifier_metrics": {
        "train_accuracy": 0.92,
        "test_accuracy": 0.85,
        "train_f1": 0.91,
        "test_f1": 0.847
    },

    # Source information
    "source": {
        "type": "csv",              # csv, json, dataframe, langsmith, docs
        "path": "data.csv",
        "text_column": "content",
        "id_column": null
    },

    # Quality tracking
    "warnings": [],                 # Any processing warnings
    "status_log": [...]             # Step-by-step status messages
}
```

<Tip>
  Use `category_counts` to quickly see how your documents are distributed across categories:

  ```python theme={null}
  from collections import Counter

  # Get top 5 categories
  top_categories = Counter(result.metadata["category_counts"]).most_common(5)
  for category, count in top_categories:
      print(f"{category}: {count} documents")
  ```
</Tip>

<Info>
  The `classifier_metrics` key is only present when `sample_size < total documents`, meaning a classifier was trained to label the remaining documents.
</Info>

## Error Handling

```python theme={null}
from delve import Delve

try:
    delve = Delve()
    result = delve.run_sync("data.csv", text_column="text")
except ValueError as e:
    # Missing API key, invalid parameters, etc.
    print(f"Configuration error: {e}")
except FileNotFoundError as e:
    # File doesn't exist
    print(f"File not found: {e}")
except Exception as e:
    # Other errors
    print(f"Error: {e}")
```

## Environment Variables

Set these before running your code:

```bash theme={null}
# Required
export ANTHROPIC_API_KEY="your-anthropic-key"

# Required when sample_size > 0 and docs > sample_size (for classifier embeddings)
export OPENAI_API_KEY="your-openai-key"

# Optional
export LANGSMITH_API_KEY="your-langsmith-key"
```

<Info>
  The OpenAI API key is required for generating embeddings when training the classifier. If you set `sample_size=0`, all documents are labeled by the LLM and no OpenAI key is needed.
</Info>

Or use python-dotenv:

```python theme={null}
from dotenv import load_dotenv
load_dotenv()

from delve import Delve
# API keys are loaded automatically
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Examples" icon="book" href="/examples">
    See working code examples
  </Card>

  <Card title="CLI Reference" icon="terminal" href="/cli-reference">
    Learn CLI commands
  </Card>
</CardGroup>
