Docs / Documents & embeddings

Documents & embeddings

OCR, embeddings, and a full PDF → RAG recipe.

Beyond chat models, Cobble hosts the pieces you need to make documents searchable and answerable: four OCR models and five embedding models. Both are billed from your wallet at per-page and per-token rates — they don't touch your plan window.

OCR: documents in, text out

Four models, one decision — accuracy versus cost:

ModelBatch sizePricePick it when
GLM-OCR200 pages$0.08/1K pagesDefault for clean printed documents
DeepSeek OCR2250 pages$0.08/1K pagesMixed layouts, tables
Nemotron OCR v2300 pages$0.08/1K pagesLarge batches, throughput-first
Chandra OCR500 pages$4/1K pagesHard documents: handwriting, degraded scans, complex layouts

Start with a $0.08 model; escalate pages that come back garbled to Chandra rather than running everything through it.

<!-- TODO before publishing: sync request example with the real OCR endpoint shape (see api-reference.md TODO). -->

Embeddings: text in, vectors out

ModelContextPricePick it when
nomic/nomic-embed-1.58K$0.01/1MDefault — strong general retrieval, cheap
qwen/qwen3-embedding-0.6b32K$0.01/1MLong chunks, multilingual
qwen/qwen3-embedding-8b32K$0.01/1MHighest retrieval quality
ibm/granite-embedding-97m8K$0.09/1MLatency-critical lookups
ibm/granite-embedding-311m8K$0.1/1MEnterprise/compliance-flavored stacks

One rule that outranks model choice: embed your documents and your queries with the same model. Vectors from different models live in different spaces; mixing them silently breaks retrieval.

python
vectors = client.embeddings.create(
    model="nomic/nomic-embed-1.5",
    input=chunks,          # list of strings
).data

Recipe: PDF → searchable knowledge base

The full pipeline, using only Cobble endpoints plus a vector store of your choice:

python
# 1. OCR the document (wallet, per page)
text = cobble_ocr("contract.pdf", model="glm/glm-ocr")

# 2. Chunk — start simple: ~800 tokens per chunk, 100 overlap
chunks = chunk(text, size=800, overlap=100)

# 3. Embed the chunks (wallet, $0.01/1M tokens)
vectors = client.embeddings.create(model="nomic/nomic-embed-1.5", input=chunks)

# 4. Store in your vector DB (pgvector, Qdrant, Chroma...)
db.upsert(zip(chunks, vectors))

# 5. At question time: embed the query, retrieve, generate (plan window)
hits = db.search(embed(question), top_k=8)
answer = client.chat.completions.create(
    model="qwen/qwen3.5-122b-a10b",
    messages=[
        {"role": "system", "content": "Answer from the provided context. Cite which excerpt supports each claim."},
        {"role": "user", "content": f"Context:\n{format(hits)}\n\nQuestion: {question}"},
    ],
)

Cost intuition for a 1,000-page archive: ~$0.08 to OCR, roughly a cent to embed, and question-answering runs inside your plan window. The expensive part of RAG isn't the pipeline — it's doing it somewhere that meters every step.

Coming soon: a hosted reranker to slot between retrieval and generation, and managed knowledge endpoints that run this whole pipeline for you. The recipe above future-proofs cleanly — the reranker drops in between steps 5's retrieve and generate.