pypaya-llm-client
One small client for every OpenAI-compatible LLM server — local or hosted — with images and audio as plain message parts.
Most "LLM client" code differs between providers only in the base URL. This library leans into that: one class, preset shorthands for the common servers, and multimodal input handled the way the chat protocol actually works — as content parts in a message list. ~330 lines, one required dependency (openai).
Install
pip install pypaya-llm-client
# with in-memory PIL image support:
pip install pypaya-llm-client[pil]
Quick start
from pypaya_llm_client import LLMClient
# Local model via Ollama
client = LLMClient(base_url="ollama", model="gemma4:latest")
print(client.chat("What is a neural network?").content)
# Same code, hosted via OpenRouter
client = LLMClient(base_url="openrouter", model="qwen/qwen3-vl-30b-a3b-instruct",
api_key="sk-or-...")
Preset base URLs (KNOWN_BACKENDS): ollama, lmstudio, vllm, llamacpp, openrouter, openai — or pass any full URL.
Images and audio
Modalities are just content-part types; pass file paths, raw bytes, or PIL images:
reply = client.chat("What text is on the button in the bottom-left?",
images=["screenshot.png"])
reply = client.chat("How many beeps do you hear?", audios=["alert.wav"])
Audio requires an audio-capable (omni) model. Note from real testing: an "audio input" flag does not guarantee audio understanding — pick models known to comprehend your kind of audio, and verify with a cheap test of your own.
Multi-turn conversations, mixed modalities
from pypaya_llm_client import LLMClient, build_user_message
client = LLMClient(base_url="openrouter", model="google/gemini-2.5-flash", api_key="...")
messages = [{"role": "system", "content": "You are analyzing a GUI test session."}]
messages.append(build_user_message("The session ID is ALPHA-7. Confirm."))
messages.append({"role": "assistant", "content": client.chat_messages(messages).content})
messages.append(build_user_message("New screen and new alert sound attached. "
"How many beeps, what does the orange button say, "
"and what was the session ID?",
images=[screenshot], audios=[alert_wav_bytes]))
print(client.chat_messages(messages).content) # e.g. "2, DEPLOY, ALPHA-7"
Metrics for free
Every call returns an LLMResponse with content, model, duration_ms, prompt_tokens, completion_tokens — enough to track latency and cost without extra instrumentation.
Per-call overrides
client.chat("Say OK.", model="qwen/qwen3-vl-8b-instruct", max_tokens=10)
Useful for model ladders (try a cheap model, fall back to a stronger one) without constructing new clients.
API surface
LLMClient(base_url, model, api_key, temperature, timeout, max_tokens).chat(prompt, *, system, images, audios, model, max_tokens) -> LLMResponse.chat_messages(messages, *, model, max_tokens) -> LLMResponse.is_available() -> bool— probe the serverbuild_user_message(text, images, audios) -> dict— build one OpenAI-format messageencode_image_base64(path | bytes | PIL.Image),get_image_media_type(...)
Tests
pytest
The suite runs fully offline — no server, no API key, no network.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pypaya_llm_client-0.1.0.tar.gz.
File metadata
- Download URL: pypaya_llm_client-0.1.0.tar.gz
- Upload date:
- Size: 7.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65648f90bdd509a956818c3c0277ff36a5709b68a0648e81693e6868cd368638
|
|
| MD5 |
dda60d8b297413290a648122128cf0a7
|
|
| BLAKE2b-256 |
46d7a5ffcdb2c4dfbddd9a1bcc556dcfbd76b9b0d15cb453c27729a3fc4122cf
|
File details
Details for the file pypaya_llm_client-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pypaya_llm_client-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1811073c650b035b7a0f0581a67c4d60e049a4ea1ca9e1bc758b3bb14d864f0
|
|
| MD5 |
00aa8818491897b21df9933d1e4926dc
|
|
| BLAKE2b-256 |
f7dc4ae92c8c2db6328932c3283ed51600c41f035443e93798ffa0966166b8c5
|