Metadata-Version: 2.4
Name: faqai
Version: 0.3.0
Summary: Official Python SDK for FAQai.app — turn documents into production-ready RAG datasets.
Project-URL: Homepage, https://faqai.app
Project-URL: Documentation, https://faqai.app/docs/api
Project-URL: Source, https://github.com/faqai/faqai-python
Author-email: FAQai <support@faqai.app>
License: MIT
Keywords: ai,datasets,embeddings,faqai,llm,rag,vector-database
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
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
Requires-Dist: requests>=2.25
Description-Content-Type: text/markdown

# FAQai Python SDK

Official Python client for [FAQai.app](https://faqai.app) — turn any document
into production-ready RAG datasets (Canonical Q&A, Query Variants, Evaluation,
Adversarial, and RAG Chunks) and export to 16 formats including Pinecone,
Qdrant, pgvector, Chroma, Weaviate, Milvus, LanceDB, and Upstash.

**Large files just work.** Uploads above ~4 MB are automatically routed through
the FAQai upload proxy, so you never hit the serverless 4.5 MB body limit and
never see a `413` — up to your plan's 25 MB maximum, in a single call.

## Install

```bash
pip install faqai
```

## Quickstart

```python
from faqai import FaqaiClient

client = FaqaiClient("faq_your_api_key")  # or set FAQAI_API_KEY

# Upload (any size up to your plan limit) and wait for processing
doc = client.upload("large-report.pdf", wait=True)
print(doc["status"])  # "completed"

# List generated datasets
datasets = client.list_datasets(doc["id"])
for ds in datasets["datasets"]:
    print(ds["dataset_type"], ds["item_count"])

# Export a dataset for your vector DB
ds_id = datasets["datasets"][0]["id"]
client.export(ds_id, "pinecone", path="pinecone.json")

# Search your generated Q&A
hits = client.search("refund policy", dataset_type="canonical_qa")
print(hits["total"])

# Coverage report
print(client.coverage(ds_id)["coverage_percent"])
```

## Ingesting from a URL or website

No file needed — point FAQai at a public web page, or crawl a whole
same-domain site (discovered via its sitemap, or a breadth-first walk if there
is none). Crawling honors `robots.txt` and your plan's per-crawl page cap
(Free 5, Basic 50, Starter 150, Pro 500). Only static HTML is read, so
JavaScript-rendered pages may yield little content.

```python
# Single page
doc = client.ingest_url("https://example.com/docs/faq", wait=True)

# Crawl a site (up to 50 same-domain pages), steer generation, and wait
site = client.ingest_url(
    "https://example.com/",
    crawl=True,
    max_pages=50,
    generation_context="customer_support_bot",
    wait=True,
)
print(site.get("crawl"))  # {discovered, capped_to, estimated_pages, mode}
```

## Configuration

| Argument / env var                         | Default                | Purpose                          |
| ------------------------------------------ | ---------------------- | -------------------------------- |
| `api_key` / `FAQAI_API_KEY`                | —                      | Your `faq_...` API key (required) |
| `base_url` / `FAQAI_BASE_URL`              | `https://faqai.app`    | API base URL                     |
| `upload_proxy_url` / `FAQAI_UPLOAD_PROXY_URL` | FAQai production proxy | Large-file upload proxy URL    |
| `timeout`                                  | `60`                   | Per-request timeout (seconds)    |
| `max_retries`                              | `3`                    | Retries for 429/5xx with backoff |

## Error handling

All failures raise a `FaqaiError` (or a subclass: `AuthenticationError`,
`PermissionError_`, `NotFoundError`, `PayloadTooLargeError`, `RateLimitError`,
`TimeoutError_`). Each carries `.status`, `.code`, and `.response_body`.

```python
from faqai import FaqaiClient, RateLimitError

client = FaqaiClient()
try:
    client.upload("doc.pdf")
except RateLimitError as e:
    print("Slow down:", e.message)
```

## How large-file uploads work

Files ≤ 4 MB are sent directly to `POST /api/v1/documents`. Larger files are
sent to the FAQai upload proxy (a Supabase Edge Function), which performs the
3-step presigned upload flow on your behalf and returns the same document
record. You don't need to change anything — it's automatic.

## License

MIT
