SPB Git forge

spb/doc-api

Public
2commits 1branches 0releases
15.7 MBsize
maindefault branch
14 days agolast push
Python 88.3% TypeScript 7.6% Shell 4.1%
3.4 KB · 61 lines python
Raw Blame History
1"""Documents with the Python SDK: (1) a generated 1-page PDF as a base64 document block, (2) a text/plain document2block, (3) count_tokens for an image to see the visual-token cost, (4) the `transformations.oversized_image`3field on an image block.4STATUS: LIVE_VERIFIED 2026-09-18 (claude-haiku-4-5-20251001): PDF answer "Green" (~1.6k input tokens), text doc "Green",5count_tokens(1x1 PNG + 'Describe.') = 15, transformations accepted. ≈$0.002.6Run: .venv/bin/python examples/anthropic/vision/pdf_and_text_document.py7"""8from __future__ import annotations910import base6411import os12import struct13import sys14import zlib15from pathlib import Path1617sys.path.insert(0, str(Path(__file__).resolve().parents[3]))18from scripts import live  # noqa: E4021920import anthropic  # noqa: E4022122MODEL = os.environ.get("ANTHROPIC_MODEL", "claude-haiku-4-5-20251001")23client = anthropic.Anthropic(max_retries=1)24Q = {"type": "text", "text": "What color is grass? One word."}252627def tiny_pdf(text: str) -> bytes:28    stream = f"BT /F1 18 Tf 40 750 Td ({text}) Tj ET".encode()29    objs = [b"<< /Type /Catalog /Pages 2 0 R >>", b"<< /Type /Pages /Kids [3 0 R] /Count 1 >>",30            b"<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>",31            b"<< /Length %d >>\nstream\n" % len(stream) + stream + b"\nendstream", b"<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>"]32    out, offs = b"%PDF-1.4\n", []33    for i, o in enumerate(objs, 1):34        offs.append(len(out)); out += f"{i} 0 obj\n".encode() + o + b"\nendobj\n"35    xref = len(out)36    out += f"xref\n0 {len(objs)+1}\n0000000000 65535 f \n".encode() + b"".join(f"{o:010d} 00000 n \n".encode() for o in offs)37    return out + f"trailer\n<< /Size {len(objs)+1} /Root 1 0 R >>\nstartxref\n{xref}\n%%EOF\n".encode()383940def tiny_png() -> str:41    def chunk(t, d):42        return struct.pack(">I", len(d)) + t + d + struct.pack(">I", zlib.crc32(t + d) & 0xFFFFFFFF)43    png = b"\x89PNG\r\n\x1a\n" + chunk(b"IHDR", struct.pack(">IIBBBBB", 1, 1, 8, 2, 0, 0, 0)) + chunk(b"IDAT", zlib.compress(b"\x00\xff\x00\x00")) + chunk(b"IEND", b"")44    return base64.b64encode(png).decode()454647def ask(label: str, block: dict, cost: float) -> None:48    m = client.messages.create(model=MODEL, max_tokens=10, messages=[{"role": "user", "content": [block, Q]}])49    print(f"{label}: {m.content[0].text!r} input_tokens={m.usage.input_tokens}")50    live.log_request("anthropic", "POST", "/v1/messages", 200, cost, f"example vision/pdf_and_text_document.py {label} {MODEL}")515253ask("pdf base64", {"type": "document", "source": {"type": "base64", "media_type": "application/pdf",54                                                  "data": base64.b64encode(tiny_pdf("The sky is blue. Grass is green.")).decode()}, "title": "Colors"}, 0.0016)55ask("text/plain", {"type": "document", "source": {"type": "text", "media_type": "text/plain", "data": "Grass is green."}}, 0.0001)56img = {"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": tiny_png()}}57cnt = client.messages.count_tokens(model=MODEL, messages=[{"role": "user", "content": [img, {"type": "text", "text": "Describe."}]}])58print("count_tokens(1x1 PNG + 'Describe.') =", cnt.input_tokens)59live.log_request("anthropic", "POST", "/v1/messages/count_tokens", 200, 0, "example vision/pdf_and_text_document.py count_tokens image")60ask("image + transformations", {**img, "transformations": {"oversized_image": "error"}}, 0.00004)61