Skip to main content

A zero‑dependency wrapper that turns any OpenAI‑compatible endpoint into a hackable one‑liner.

Project description

LLMAID

A zero‑dependency wrapper that turns any OpenAI‑compatible endpoint into a one‑liner.


This README features a quick start guide, and simple examples for main features. Do checkout other documentation as needed:

## Installation

pip install llmaid

Environment‑variable fallback

LLMAid will look for these variables at import time—pass arguments only when you want to override them.

Variable Purpose Default
LLMAID_BASE_URL Backend URL http://127.0.0.1:17434
LLMAID_SECRET Auth key / token (none)
LLMAID_MODEL Model name mistral-large-v0.1

More in Public API Reference.


Quick start

One‑liner

# import your environment variables before using llmaid
from llmaid import llmaid

llmaid().completion("You are a hello machine, only say hello!")
# -> "hello!"

Manual configuration

from llmaid import llmaid

hello_machine = llmaid(
    base_url="https://openrouter.ai/api/v1",
    secret="<your-secret>",
    model="mistral-large-v0.1",
)

hello_machine.completion("You are a hello machine, only say hello!")
# -> "hello!"

Cloning instances

Need a new instance with different config? llmaid is callable:

  • settings can be overridden at call time, e.g. base_url, secret, model, etc.
  • the call returns a clone with merged settings from the instance that was called.
# point the same instance at another model just for this call
hello_machine(
    model="qwen-2.5b-instruct"
).completion("You are a hello machine, only say hello!")
# -> "hello!"

# or save a derived clone for later
another_machine = hello_machine(
    base_url="https://another-backend.ai/api/v1",
    secret="<another-secret>",
    model="deepseek-2.7b-instruct"
)

Prompt templating

You can use prompt templates to create reusable prompts with placeholders for parameters. This allows you to define a prompt once and fill in the parameters dynamically when making completions.

# import your environment variables before using llmaid
from llmaid import llmaid

anything_machine = llmaid().prompt_template("You are a {{role}} machine, only say {{action}}!")
# you can also use llmaid().system_prompt(...) as an alias for prompt_template

anything_machine.completion(role="hello", action="hello")  # -> "hello!"
anything_machine.completion(role="goodbye", action="goodbye")  # -> "goodbye!"

# Derive a new independant llmaid instance with a different prompt and same settings on the fly
doer = anything_machine.prompt_template(
    "You are a {{role}}. Do your best to {{action}}!"
)

doer.completion("Why is the sky blue?", role="scientist", action="explain")

llmaid.completion() supports any number of positional and keyword arguments.

  • Positional arguments are joined with a newline character and appended to the end of the prompt template.
  • Keyword arguments are used to fill in the placeholders in the prompt template.

Here is an example to illustrate this:

doer.completion(
    "Why is the sky blue?",
    "No really, why?",
    role="scientist",
    action="explain"
)
# will result in following prompt being passed to the LLM backend:
"""
You are a scientist. Do your best to explain!
Why is the sky blue?
No really, why?
"""

Note from the author: I have designed llmaid with text completion in mind rather than chat completion. Which explains the logic illustrated above. I do plan to add chat completion support in the future. Also checkout the chat history handling example below.


Streaming responses

Minimum working example using asyncio.

# prepare your environment variables before using llmaid
import asyncio, llmaid

async def main():
    anything_machine = llmaid().prompt_template("You are a {{role}} machine, only say {{action}}!")

    async for token in anything_machine.stream(role="hello", action="hello"):
        print(token, end="", flush=True)

asyncio.run(main())

Async support

All LLMAid completion methods have an async counterpart that can be used with await:

  • completion(input: str, **kwargs) -> str - synchronous completion method that returns the full response as a string.
  • acompletion(input: str, **kwargs) -> str - asynchronous completion method that returns the full response as a string. You can use it with await.
  • stream(input: str, **kwargs) -> AsyncIterator[str] - asynchronous streaming method that returns an async iterator yielding response tokens as they arrive. You can use it with async for.


More Examples

Advance prompt templating

You don't have to pass llmaid.completion any arguments at all, it all depends on how you set up your prompt template.

# import your environment variables before using llmaid
from llmaid import llmaid

spanish_translator = llmaid().prompt_template("""You are a master spanish translator.
Translate Any text you're given without any explanation or comments.

The text that follow right after the triple dash is the text you should translate to spanish.
---""")
spanish_translator.completion("The sky is blue because of the way the Earth's atmosphere scatters light from the sun.")
# -> "El cielo es azul debido a la forma en que la atmósfera de la Tierra dispersa la luz del sol."

Also, you can use only keyword arguments, but still have a user input in the prompt template.

spanish_translator2 = spanish_translator.prompt_template(
    "Translate this text to spanish: {{user_input}}",
)

spanish_translator2.completion(user_input="The sky is blue because of the way the Earth's atmosphere scatters light from the sun.")
# -> "El cielo es azul debido a la forma en que la atmósfera de la Tierra dispersa la luz del sol."

Handling chat history

As a text-completion first module, LLMAid does not have built-in chat history management (yet), but you can easily implement it using the prompt templating feature. Here's a simple example:

# import your environment variables before using llmaid
from llmaid import llmaid

helpful_assistant = llmaid().prompt_template("""
    You are a helpful assistant. You will be given a chat history and the next user input.
    Your task is to respond to the user input based on your knowledge and taking into account the chat history.

    Chat history:
    {{chat_history}}
    End of chat history.

    User input:
    {{user_input}}
    End of user input.

    Your response should be concise and relevant to the user input.
    Only refer to the chat history if it is relevant to the user input.
""")

chat_history = [
    "User: What is the capital of France?",
    "Assistant: The capital of France is Paris.",
].join("\n")

response = helpful_assistant.completion(
    chat_history=chat_history,
    user_input="How old are you?"
)
# -> "I am an AI and do not have an age like humans do, but I can provide more information about Paris or any other topic you are interested in."

Advanced prompt management

Prompt files can become lengthy and cumbersome to manage when modularizing your prompts. LLMAid supports concatenating multiple prompt files together, allowing you to split your prompts into smaller, manageable pieces.

# import your environment variables before using llmaid
from pathlib import Path
from llmaid import llmaid

scientist_summary = llmaid(prompt_template_dir=Path("./prompts")).prompt_template(
    "scientist_prompt.txt",  # roles/contexts can be split up
    "summary_prompt.txt"      # and concatenated in order
)

scientist_summary.completion("Why is the sky blue?")
# -> "The sky appears blue due to the scattering of sunlight by the Earth's atmosphere. This phenomenon is known as Rayleigh scattering, which causes shorter wavelengths of light (blue) to be scattered more than longer wavelengths (red)."

Feature matrix

Feature Status Notes
Synchronous completion completion()
Asynchronous completion await acompletion()
Streaming tokens async for ... in stream()
Prompt templating (Jinja‑like) File or inline strings
Prompt directories & concatenation Pass multiple paths
Environment‑variable config Zero‑code setup
Exponential back‑off & retry Built‑in, configurable
Easy logging and debugging 🕗 Planned
Output‑format enforcement 🕗 Planned (JSON/YAML/XML)
Output critic and validation 🕗 Planned (guards, quality control...)
Built-in chat history handling 🕗 Planned
Pydantic template validation 🕗 Planned
File attachments 🕗 Planned
Tools / agent actions 🕗 Planned
MCP support Considering

Other todos for later

  • quickstart video in terminal
  • auto deploy to PyPI with github actions

License

LLMAid is released under the MIT License—see the LICENSE file for full text.


Building for PyPI

To build LLMAid for PyPI, run the following commands in the root directory of the project:

rm -rf dist
.venv/bin/pip install --upgrade build
.venv/bin/python -m build
.venv/bin/pip install --upgrade twine
.venv/bin/twine upload dist/*

About

I built LLMAid because I kept rewriting the same boilerplate for different OpenAI‑compatible backends. The goals are:

  • Simplicity – no runtime dependencies, no hidden magic.
  • Flexibility – override anything at call‑time.
  • Speed – prototype in one import.

Full reference documentation is available

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llmaid-0.1.1.tar.gz (42.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llmaid-0.1.1-py3-none-any.whl (18.3 kB view details)

Uploaded Python 3

File details

Details for the file llmaid-0.1.1.tar.gz.

File metadata

  • Download URL: llmaid-0.1.1.tar.gz
  • Upload date:
  • Size: 42.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for llmaid-0.1.1.tar.gz
Algorithm Hash digest
SHA256 b530c5fd4afb60669ffa6410f6a1c0ff9f6b0945a7b7e2c5c58cda1d341c4242
MD5 899d032280203e0bb206203bb0447e1f
BLAKE2b-256 990096d1ac7e01a3e1f88bdf31e7755ebd826d8d0edd677087cadc95e7cc7758

See more details on using hashes here.

File details

Details for the file llmaid-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: llmaid-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 18.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.13

File hashes

Hashes for llmaid-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 884bec4888c58a990a69b51b66d361a3d22f87c677774a69f6fe4e0e5baef298
MD5 553be0b8fd0ec815505f8995ae0884af
BLAKE2b-256 3e7695b94ba2495d6d0f2f8208f2e5e35799d695b14f41fbc99c0ec97fd97181

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page