Skip to main content

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 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)

Source distribution for fj-llm 0.8.0
File Size Uploaded Provenance
fj_llm-0.8.0.tar.gz 15.4 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for fj-llm 0.8.0
File Interpreter ABI Platform
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.

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