Skip to content

Adapters

Adapters turn provider SDK clients into lemmas CompleteFn / EmbedFn callables. Lemmas's core has zero provider dependencies; each adapter is opt-in via extras (e.g. pip install lemmas[openai]).

OpenAI

from openai import OpenAI
from lemmas.adapters import openai_complete, openai_embed

complete = openai_complete(OpenAI(), model="gpt-4o-mini",
                            temperature=0.7, max_tokens=1024)
embed    = openai_embed(OpenAI(), model="text-embedding-3-small")

Anthropic

from anthropic import Anthropic
from lemmas.adapters import anthropic_complete

complete = anthropic_complete(Anthropic(), model="claude-haiku-4-5-20251001",
                                temperature=0.3, max_tokens=512)

The adapter lifts your role: "system" messages into Anthropic's top-level system parameter for you.

Gemini

import google.generativeai as genai
genai.configure(api_key=...)
from lemmas.adapters import gemini_complete

# Either pass the module (we'll construct the model)...
complete = gemini_complete(genai, model="gemini-1.5-flash")
# ...or pass a pre-built GenerativeModel.
complete = gemini_complete(genai.GenerativeModel("gemini-1.5-flash"))

Groq

from groq import Groq
from lemmas.adapters import groq_complete

complete = groq_complete(Groq(), model="llama-3.1-8b-instant")

OpenAI-compatible URL (zero SDK)

For vLLM, llama.cpp's server, Together, Fireworks, DeepSeek, Perplexity, LM Studio, Ollama (/v1 mode), Anyscale, or any homegrown OpenAI-shaped endpoint:

from lemmas.adapters import openai_compatible_complete, openai_compatible_embed

complete = openai_compatible_complete(
    base_url="http://localhost:8000",   # vLLM default
    api_key="",                          # often unused for local
    model="meta-llama/Llama-3.1-8B-Instruct",
    temperature=0.7,
)
embed = openai_compatible_embed(
    base_url="http://localhost:11434",  # Ollama
    model="nomic-embed-text",
)

This adapter uses urllib directly -- no SDK dependency.

Test stubs

For unit tests and offline demos:

from lemmas.adapters import echo_complete, varying_echo_complete

stub  = echo_complete()                                      # deterministic
cycle = varying_echo_complete(["A", "B", "C"])              # round-robins

Roll your own

Three lines:

def my_complete(messages: list[dict]) -> str:
    response = my_client.chat(messages=messages)
    return response.text

That's the whole interface.