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

# Quickstart

> Turn a CSV of inputs and correct outputs into an optimized prompt, and see the score change on held-out rows.

Use this when you already have a CSV of inputs and correct outputs for one repeatable LLM job. The steps below create a task, upload the rows, run prompt optimization, and print the score change.

## Install

```bash theme={null}
pip install apprentice-sdk
```

LangChain support is optional. Install it only if you plan to capture from a LangChain app or pass a LangChain prompt:

```bash theme={null}
pip install "apprentice-sdk[langchain]"
```

## Set your keys

```bash theme={null}
export APPRENTICE_API_KEY="ap_live_..."
export APPRENTICE_BASE_URL="https://your-backend"
```

Create the API key once in the console. The client also reads these two values from the environment, so you can leave them out of your code.

## Run it

```python theme={null}
import os
from apprentice import Apprentice

client = Apprentice(
    api_key=os.environ["APPRENTICE_API_KEY"],
    base_url=os.environ["APPRENTICE_BASE_URL"],
)

client.tasks.create("invoice-json", metric="json_f1")
client.datasets.upload(
    "invoice-json",
    path="golden.csv",
    input_col="input",
    output_col="output",
    prompt="Extract the invoice fields as a JSON object.",
)

report = client.optimize("invoice-json").wait().report()
print(report.baseline_score, "->", report.optimized_score)
print(report.optimized_prompt)
```

`golden.csv` needs an `input` column and an `output` column. For a JSON task, the `output` is the exact JSON you want back.

## What you get

`report.baseline_score` and `report.optimized_score` are field-level scores on rows the optimizer held out, so treat the result as proof for this dataset, not a universal benchmark. `report.optimized_prompt` is the rewritten instruction you can paste back into your app.

<Note>
  If `optimized_score` does not beat `baseline_score`, that is a real result, not a failure of the tool. Add cleaner verified rows, or pick a metric that fits the task, then run again. We never report a gain that is not there.
</Note>

## Next

<CardGroup cols={2}>
  <Card title="JSON extraction, end to end" icon="brackets-curly" href="/how-to/json-extraction">
    The same flow with a real dataset and the optimized prompt pulled back into code.
  </Card>

  <Card title="Capture from LangChain" icon="plug" href="/how-to/capture-langchain">
    Build the dataset from your live traffic instead of a CSV.
  </Card>
</CardGroup>

Model replacement comes after this first prompt win. It is described on pages marked **Building** until the public flow ships.
