Skip to main content

thinchat

check PyPI Python License

English | 한국어

A thin, unified client for four LLM providers — claude, openai, gemini, ollama.

Name a provider, then call it. Every client offers completion — whole, streamed, or JSON-structured — and, where the provider has one, embeddings, each with an async twin. No gateway, no router, no cost tracking: just the calls, over the openai and anthropic SDKs.

1. Install

pip install thinchat

Requires Python 3.11+. Both provider SDKs (openai and anthropic) come with it, so every provider works out of the box; each is imported lazily the first time you construct its client.

2. Use

from thinchat import make_client

llm = make_client("claude")                     # key from CLAUDE_API_KEY
print(llm.complete("Say hi in one word."))
print(llm.complete("Name a color.", system="Answer in one word."))   # system= steers the generation verbs

# Structured output: you invent the schema; the model fills a JSON object into that shape.
# It steers generation but is not validated locally, so check the returned fields yourself.
review = llm.parse(
    "Analyze the sentiment: 'Fast shipping and great quality.'",
    schema={"type": "object",
            "properties": {"sentiment": {"type": "string"}, "score": {"type": "number"}},
            "required": ["sentiment"]},
)
print(review["sentiment"])

# Streaming.
for chunk in make_client("claude").stream("Count to five."):
    print(chunk, end="")

# Embeddings (openai / gemini / ollama; Claude has none).
vectors = make_client("openai").embed(["hello", "world"])

Every verb has an async twin — acomplete, astream, aparse, aembed:

llm = make_client("claude")
text = await llm.acomplete("Summarize in one line: ...")

3. Providers

provider key env embeddings
claude CLAUDE_API_KEY no
openai OPENAI_API_KEY yes
gemini GEMINI_API_KEY yes
ollama none (local) yes

openai, gemini, and ollama speak the same OpenAI-compatible API, so one SDK serves all three; only the base URL, key, and default models differ. Ollama runs locally (OLLAMA_HOST, default http://localhost:11434) and needs no key.

Each provider takes the settings it exposes under the same name, sent only when you set them: max_tokens (reply length), temperature / top_p (sampling), and timeout in seconds / max_retries (the HTTP client) — e.g. make_client("claude", temperature=0.2, timeout=30). An unset value leaves the provider's own default in place, except max_tokens, which Anthropic requires and so defaults to 4096 for claude (the OpenAI-compatible providers omit it, letting the model decide).

Keys are read from the environment. Set them once in your shell profile (~/.bashrc, ~/.zshrc) so every session picks them up — thinchat is a library and never imposes a file location of its own:

export CLAUDE_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
export GEMINI_API_KEY="..."          # ollama runs locally and needs no key

Or pass a key explicitly, which overrides the environment:

llm = make_client("claude", api_key="sk-ant-...", model="claude-haiku-4-5-20251001")

4. Capabilities

A client whose provider lacks a capability raises UnsupportedError. The capabilities are completion, streaming, structured_output, and embeddings; check first with supports:

make_client("claude").supports("embeddings")   # False

5. Errors

Everything thinchat raises on purpose derives from ThinchatError, so one except handles the package's failures:

  • UnknownProviderError — the name isn't one of the four providers.
  • ProviderUnavailableError — the provider's SDK isn't installed, or no API key is set.
  • UnsupportedError — the provider lacks the capability (e.g. embeddings on Claude).
  • LLMError — the API call failed, or the reply was empty or malformed.
  • RateLimitError — a 429 rate limit after the SDK's own retries. It is a subclass of LLMError, so existing handlers still catch it, and its retry_after is how many seconds to wait before trying again (from the server's Retry-After), or None when the server did not give one.

The vendor SDK performs the actual backoff through max_retries, honoring Retry-After; thinchat adds no retry loop.

from thinchat import make_client, RateLimitError

with make_client("gemini") as llm:
    try:
        print(llm.complete("Say hi."))
    except RateLimitError as e:
        print(f"rate limited; wait {e.retry_after} seconds")

6. Lifecycle

A client holds an HTTP connection pool. For a one-off script you can ignore it; for a server that builds a client per request, close it so connections do not leak — use it as a context manager, or call close() / aclose():

with make_client("claude") as llm:
    llm.complete("...")                 # sync: closes the pool on exit

async with make_client("claude") as llm:
    await llm.acomplete("...")          # async: closes the async pool too

close() frees the sync pool; if you drove async verbs, release with aclose() or async with so the async pool is closed as well.

7. How it works

flowchart LR
  M["make_client(provider)"] --> C["Client<br/>openai-compatible · or claude"]
  C --> V["complete · stream · parse · embed<br/>(+ a-prefixed async twins)"]
  V --> S{{"vendor SDK"}}
  S -->|ok| O(["str · dict · list float · stream"])
  S -->|"SDK / transport error"| E(["LLMError<br/>RateLimitError for 429"])

make_client looks the provider up in one factory map: openai/gemini/ollama share a single class over the openai SDK (they differ only in data); claude has its own over anthropic. A call builds the request, hits the SDK, and either extracts the reply or maps the failure to LLMError, using RateLimitError for a 429 after the SDK's retries.

8. License

MIT

Metadata

Release files for thinchat 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for thinchat 0.1.3
File Size Uploaded
thinchat-0.1.3.tar.gz 33.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for thinchat 0.1.3
File Interpreter ABI Platform
thinchat-0.1.3-py3-none-any.whl Python 3 none any Details

Total release size: 56.5 kB

Release files / thinchat-0.1.3.tar.gz

Download URL thinchat-0.1.3.tar.gz
Size 33.7 kB
Tags Source
SHA-256 checksum
How to use checksums
0e49115a222dcdc606b2b6f281440480ab0dbfe101c8fa37073a3ec750488adc
BLAKE2b-256 checksum
How to use checksums
d9a3b55a9ae19ebb7aef8e9fe6ded3c81386fc6404366d06b30d7ff2ed5a7e4c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.

Transparency log

Release files / thinchat-0.1.3-py3-none-any.whl

Download URL thinchat-0.1.3-py3-none-any.whl
Size 22.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b37173b51ac5057c82c7c013aa25cd119bd910adb63921b5fb30f68395bf3d28
BLAKE2b-256 checksum
How to use checksums
7f870ea4016fbdad8f16cffd8274ac437185cb4148e8192e242465b0a5029b9c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 1, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

This release

0.1.3 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page