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

# SDK Quickstart

> Build a knowledge base, query it, and chat from Python.

This quickstart creates a small support knowledge base, stores it in Qdrant, retrieves the matching chunk, and asks an LLM for a grounded answer. It uses inline Markdown for the first smoke test, then shows the same SDK workflow with documents, websites, and REST API sources.

## 1. Install

```bash theme={null}
pip install "ragrails[store-qdrant]"
export VOYAGE_API_KEY="..."
export OPENAI_API_KEY="..."
docker run -p 6333:6333 qdrant/qdrant
```

For website extraction:

```bash theme={null}
pip install "ragrails[url,store-qdrant]"
ragrails setup-url --browser chromium
```

## 2. Configure

```python theme={null}
from ragrails import RagRails

rag = RagRails(
    collection="support",
    vector_store={"provider": "qdrant", "url": "http://localhost:6333"},
    embedding={"provider": "voyage", "model": "voyage-3"},
    llm={"provider": "openai", "model": "gpt-4o-mini"},
)
```

## 3. Ingest

`ingest()` runs extraction, chunking, embedding, and storage.

```python theme={null}
ingested = rag.ingest(
    markdown=(
        "# Refund policy\n\n"
        "Customers can request a refund within 30 days of purchase. "
        "Refunds are returned to the original payment method within 5 business days."
    ),
)

print({
    "sources": ingested.sources,
    "chunks": ingested.chunks,
    "embedded": ingested.embedded,
    "stored": ingested.stored,
    "failed": ingested.failed,
})
```

Use the same ingest workflow with other source types:

<CodeGroup>
  ```python Documents theme={null}
  rag.ingest(docs=["files/refund-policy.pdf"])
  rag.ingest(docs={"folder": "files/policies"})
  ```

  ```python Website theme={null}
  rag.setup_url(browser="chromium")
  rag.ingest(urls="https://example.com/help/refunds")
  rag.ingest(urls={"url": "https://example.com/docs", "mode": "full", "max_pages": 25})
  ```

  ```python REST API theme={null}
  rag.ingest(api={"url": "https://api.example.com/refund-policy", "title": "Refund policy"})
  ```
</CodeGroup>

## 4. Query

```python theme={null}
result = rag.query("How long do I have to request a refund?", retrieval={"top_k": 5})

for chunk in result.items:
    print(chunk.score, chunk.text[:200])
```

## 5. Chat

```python theme={null}
result = rag.chat("How long do I have to request a refund?", history=[])
print(result.answer)
history = result.history
```

Expected answer:

```text theme={null}
You can request a refund within 30 days of purchase.
```

<Tip>Chat is stateless. Store the returned `history` and pass it to the next turn.</Tip>

## Next

<CardGroup cols={2}>
  <Card title="Ingest" icon="package-plus" href="/usage/sdk/ingest">Learn the full SDK ingest workflow.</Card>
  <Card title="Query" icon="search-check" href="/usage/sdk/query">Search and chat over the stored knowledge base.</Card>
  <Card title="Overview" icon="route" href="/usage/sdk/pipeline-overview">See every SDK pipeline stage.</Card>
  <Card title="Extraction" icon="file-input" href="/usage/sdk/extraction">Use documents, websites, and APIs.</Card>
</CardGroup>
