fj-llm
Lightweight, config-driven Python client for multiple LLM providers. One interface, any provider — no provider SDK required.
Install
pip install fj-llm
Providers
| Provider | Config key | Env var |
|---|---|---|
| OpenAI | openai |
OPENAI_API_KEY |
| Anthropic | anthropic |
ANTHROPIC_API_KEY |
| DeepSeek | deepseek |
DEEPSEEK_API_KEY |
google |
GOOGLE_API_KEY |
Configuration
On first use, a default config is created at ~/.config/fj_llm/config.yaml. Edit it to add your API keys and define model aliases:
models:
gpt-best:
provider: openai
model_name: gpt-4o
api_key_env: OPENAI_API_KEY
base_url: https://api.openai.com/v1
max_tokens: 4000
temperature: 0.1
pricing:
input_per_1m_tokens: 2.50
output_per_1m_tokens: 10.00
fallback: gpt-light # optional: alias to use on quota exhaustion
gpt-light:
provider: openai
model_name: gpt-4o-mini
api_key_env: OPENAI_API_KEY
base_url: https://api.openai.com/v1
max_tokens: 4000
temperature: 0.1
pricing:
input_per_1m_tokens: 0.15
output_per_1m_tokens: 0.60
defaults:
retry_attempts: 3
retry_delay: 1.0
timeout: 30
For openai_compatible models that need extra request headers (e.g. a self-hosted endpoint behind Cloudflare Access), add headers_env, mapping each header name to the env var holding its value. A missing env var fails the request, which triggers fallback if set:
my-local:
provider: openai_compatible
# ...
headers_env:
CF-Access-Client-Id: CF_ACCESS_MODEL_A_CLIENT_ID
CF-Access-Client-Secret: CF_ACCESS_MODEL_A_CLIENT_SECRET
For a self-hosted openai_compatible endpoint that swaps models, set model_name: auto. fj_llm asks the endpoint which model it is serving (GET {base_url}/models, sent with the same auth headers), caches the answer, and asks again once if a request fails because that model is gone. The real model name is reported in response.model.
For Cloud Functions or other environments without filesystem access, set the FJ_LLM_CONFIG environment variable to a JSON string of the same structure.
Usage
from fj_llm import LLMClient
client = LLMClient()
response = client.query("gpt-best", "Summarise this in one sentence.", context=long_text)
if response.success:
print(response.content)
print(f"Cost: ${response.cost:.6f}")
else:
print(f"Error: {response.error}")
Cost logging
Every successful call is appended as a JSONL record to ~/.local/share/fj_llm/costs.jsonl. Override the path via the FJ_LLM_COST_LOG env var, or set cost_log in the config file.
CLI
llm-query gpt-best "What is the capital of France?"
License
MIT
Metadata
Release files for fj-llm 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| fj_llm-0.8.0.tar.gz | 15.4 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| fj_llm-0.8.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 26.5 kB
Release files / fj_llm-0.8.0.tar.gz
| Download URL | fj_llm-0.8.0.tar.gz |
|---|---|
| Size | 15.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0794f3822b6dc64fddb5d81277dbd250e176adaa1b4c9ce97bba356b36074335
|
|
BLAKE2b-256 checksum How to use checksums |
65e32a3c13f837f0623f353066742e230abc9725ad137997758b8d75a1d8d10a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Release files / fj_llm-0.8.0-py3-none-any.whl
| Download URL | fj_llm-0.8.0-py3-none-any.whl |
|---|---|
| Size | 11.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7498c33c9bfd8c4dae6f1727a45f87ae44b4a4e67265ebf5604343039b195130
|
|
BLAKE2b-256 checksum How to use checksums |
10bbd98f791bc71e4b6dc5f4e86a8683d76e67469b075356c99e443cf67bead3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.17
|
Security for fj-llm 0.8.0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.