Skip to main content

serapeum openai integration

Project description

Serapeum OpenAI Provider

OpenAI integration for the Serapeum LLM framework

The serapeum-openai package provides complete OpenAI backend support for Serapeum, with two main classes covering both OpenAI APIs:

  • Completions: Chat Completions API for GPT-4o, GPT-4, GPT-3.5, and instruct models
  • Responses: Responses API for reasoning models (o3, o4-mini) with built-in tools and stateful conversations

Both classes implement the serapeum.core.llms.FunctionCallingLLM interface, making them compatible with all Serapeum orchestrators and tools.

Features

  • Chat & Completion: Sync/async support with streaming
  • Tool Calling: Function calling with automatic schema generation
  • Structured Outputs: Native JSON-schema support on compatible models, with automatic fallback to function-calling approach
  • Responses API: Built-in tools (file search, web search, code interpreter), reasoning-effort control, stateful conversations
  • Model Registry: YAML-based model metadata with automatic capability detection (context windows, JSON-schema support, function calling)
  • Retry Logic: OpenAI-specific exception classification with automatic retries for transient errors
  • Token Counting: Tiktoken integration for accurate token counting

Installation

From Source

cd libs/providers/openai
uv sync --active

From PyPI (when published)

pip install serapeum-openai

Prerequisites

You need an OpenAI API key. Set it as an environment variable:

export OPENAI_API_KEY="sk-..."

Or pass it directly when creating the LLM instance.

Quick Start

Chat Completions API

from serapeum.openai import Completions
from serapeum.core.llms import Message, MessageRole

llm = Completions(model="gpt-4o", temperature=0.7)

messages = [
    Message(role=MessageRole.USER, content="Explain quantum computing in one sentence.")
]
response = llm.chat(messages)
print(response.message.content)

Responses API

from serapeum.openai import Responses
from serapeum.core.llms import Message, MessageRole

llm = Responses(model="o3", reasoning_options={"effort": "medium"})

messages = [
    Message(role=MessageRole.USER, content="Solve this step by step: what is 2^10?")
]
response = llm.chat(messages)
print(response.message.content)

LLM Features

Streaming

from serapeum.openai import Completions
from serapeum.core.llms import Message, MessageRole

llm = Completions(model="gpt-4o")

messages = [Message(role=MessageRole.USER, content="Write a haiku about coding.")]

for chunk in llm.chat(messages, stream=True):
    print(chunk.delta, end="", flush=True)
print()

Async Operations

import asyncio
from serapeum.openai import Completions
from serapeum.core.llms import Message, MessageRole

llm = Completions(model="gpt-4o")

async def main():
    response = await llm.achat([
        Message(role=MessageRole.USER, content="Hello!")
    ])
    print(response.message.content)

    # Async streaming
    async for chunk in await llm.achat(
        [Message(role=MessageRole.USER, content="Count to 5.")],
        stream=True,
    ):
        print(chunk.delta, end="", flush=True)
    print()

asyncio.run(main())

Structured Outputs

Extract structured data using Pydantic models. On compatible models (GPT-4o and later), native JSON-schema mode is used automatically:

from pydantic import BaseModel, Field
from serapeum.openai import Completions
from serapeum.core.prompts import PromptTemplate


class Person(BaseModel):
    name: str = Field(description="Person's full name")
    age: int = Field(description="Person's age in years")
    occupation: str = Field(description="Person's job title")


llm = Completions(model="gpt-4o")

person = llm.parse(
    schema=Person,
    prompt=PromptTemplate("Extract person info from: {text}"),
    text="John Doe is a 32-year-old software engineer at Tech Corp.",
)

print(f"{person.name}, {person.age}, works as {person.occupation}")

Tool Calling

from serapeum.openai import Completions
from serapeum.core.tools import CallableTool
from serapeum.core.llms import Message, MessageRole


def get_weather(location: str, unit: str = "celsius") -> str:
    """Get current weather for a location."""
    return f"The weather in {location} is 22 {unit} and sunny."


llm = Completions(model="gpt-4o")

weather_tool = CallableTool.from_function(get_weather)
messages = [Message(role=MessageRole.USER, content="What's the weather in Paris?")]

response = llm.generate_tool_calls(
    tools=[weather_tool],
    chat_history=messages,
)

tool_calls = llm.get_tool_calls_from_response(
    response, error_on_no_tool_call=False
)
if tool_calls:
    for call in tool_calls:
        print(f"Tool: {call.tool_name}, Args: {call.tool_kwargs}")

Responses API with Built-in Tools

from serapeum.openai import Responses
from serapeum.core.llms import Message, MessageRole

llm = Responses(
    model="o3",
    reasoning_options={"effort": "medium"},
    built_in_tools=[{"type": "web_search_preview"}],
)

messages = [
    Message(role=MessageRole.USER, content="What happened in tech news today?")
]
response = llm.chat(messages)
print(response.message.content)

Configuration

Completions (Chat Completions API)

from serapeum.openai import Completions

llm = Completions(
    model="gpt-4o",                       # Required: model name
    temperature=0.7,                       # Sampling temperature (0.0-2.0)
    max_tokens=1024,                       # Max tokens to generate
    logprobs=None,                         # Return log probabilities (None/True/False)
    top_logprobs=0,                        # Number of top logprobs per token (0-20)
    strict=False,                          # Strict JSON-schema mode
    reasoning_effort=None,                 # For O1 models: "low"/"medium"/"high"/etc.
    modalities=None,                       # Output modalities, e.g. ["text", "audio"]
    audio_config=None,                     # Audio output config (voice, format, etc.)
    api_key="sk-...",                      # API key (or OPENAI_API_KEY env)
    api_base=None,                         # Custom API base URL
    timeout=60.0,                          # Request timeout in seconds
    default_headers=None,                  # Additional HTTP headers
    additional_kwargs={},                  # Extra API parameters
)

Responses (Responses API)

from serapeum.openai import Responses

llm = Responses(
    model="o3",                            # Required: model name
    temperature=0.1,                       # Sampling temperature (omitted when reasoning_options set)
    top_p=1.0,                             # Nucleus sampling (omitted when reasoning_options set)
    max_output_tokens=None,                # Max output tokens
    reasoning_options={"effort": "medium"},# Reasoning effort control for O1 models
    include=None,                          # Additional output fields, e.g. ["reasoning.encrypted_content"]
    instructions=None,                     # System-level instructions
    built_in_tools=None,                   # Built-in tools list
    store=False,                           # Store responses server-side
    track_previous_responses=False,        # Stateful conversation tracking (forces store=True)
    truncation="disabled",                 # Input truncation strategy
    user=None,                             # End-user identifier for abuse monitoring
    call_metadata=None,                    # Metadata forwarded in the "metadata" field
    strict=False,                          # Strict JSON-schema mode
    context_window=None,                   # Manual context-window override in tokens
    api_key="sk-...",                      # API key (or OPENAI_API_KEY env)
    api_base=None,                         # Custom API base URL
    timeout=60.0,                          # Request timeout
)

Package Layout

src/serapeum/openai/
├── __init__.py              # Lazy imports (Completions, Responses)
├── llm/
│   ├── chat_completions.py  # Completions class (Chat Completions API)
│   ├── responses.py         # Responses class (Responses API)
│   └── base/
│       ├── client.py        # SDK client lifecycle and credentials
│       ├── model.py         # Model metadata and tokenizer
│       └── structured.py    # Native JSON-schema structured output
├── data/
│   ├── models.py            # Model query functions and constants
│   └── models.yaml          # Model registry (context windows, capabilities)
├── parsers/
│   ├── chat_parsers.py      # Chat completion response parsers
│   ├── formatters.py        # Message format converters
│   └── response_parsers.py  # Responses API output parsers
├── retry.py                 # OpenAI-specific retry logic
└── utils.py                 # Credential resolution, constants

Testing

# All tests (from repo root)
python -m pytest libs/providers/openai/tests

# Skip end-to-end tests (don't require API key)
python -m pytest libs/providers/openai/tests -m "not e2e"

# Only unit tests
python -m pytest libs/providers/openai/tests -m unit

Note: End-to-end tests require a valid OPENAI_API_KEY environment variable.

Links

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

serapeum_openai-0.1.0.tar.gz (65.0 kB view details)

Uploaded Source

Built Distribution

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

serapeum_openai-0.1.0-py3-none-any.whl (72.6 kB view details)

Uploaded Python 3

File details

Details for the file serapeum_openai-0.1.0.tar.gz.

File metadata

  • Download URL: serapeum_openai-0.1.0.tar.gz
  • Upload date:
  • Size: 65.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.13

File hashes

Hashes for serapeum_openai-0.1.0.tar.gz
Algorithm Hash digest
SHA256 1e993600d8381ef4517b7357a96be4b2ed09fc2229d7e0ed4b9827645783ce6f
MD5 fd86ff9838af0c8cde70f4dda961be99
BLAKE2b-256 d91324205ea9bfcb3531147e9a34856217c14c2174347e994d402ca2feaed3f7

See more details on using hashes here.

File details

Details for the file serapeum_openai-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for serapeum_openai-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8f79ccdd9258b2f11872f1b4546f7d320a53d3575b80d18b70570de70a36d0fb
MD5 34eb1eafe3fa4f082963f2c85f8d6221
BLAKE2b-256 ecbfec043c12bee4d7378d4f6565b5a2f4198e2258dc04c5e8dc689e73921380

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