Skip to content

methzen/ObservAI

Repository files navigation

ObservAI

PyPI License Python Versions

Lightweight SDK for capturing and buffering LLM calls (OpenAI for now) for audit, compliance, and analytics.

Why ObservAI?

LLMs like ChatGPT are powerful but opaque. ObservAI adds transparency and observability to your AI systems by:

  • Capturing every prompt/response made to OpenAI
  • Logging metadata such as latency, timestamp, route, and user
  • Supporting crash-safe local buffering with SQLite
  • Sending logs to a remote collector or local file
  • Providing optional background flushing with low overhead

Ideal for:

  • Auditing LLM usage
  • Debugging hallucinations or failure cases
  • Proving compliance (e.g., GDPR, HIPAA)
  • Generating analytics on prompt effectiveness

Features

  • Capture prompts/responses from OpenAI automatically
  • SQLite fallback for crash resilience
  • Easy integration with openai SDK
  • Local log file or remote collector
  • Optional background flushing

Installation

pip install observai

Quick Start

import observai as oai

# initialize with defaults (no background flusher)
oai.init(
    user_id="alice@example.com",
    log_path="observai_events.log",
    endpoint="http://localhost:9000/events/batch",
    headers={"X-Observai-Key": "dev-secret-key"},
    flush_interval=2.0,
    background=True,  # enables automatic flush
)

# optionally tag with a user id if not set above
oai.set_user("alice@example.com")

# ... then anywhere in your code, whenever you call OpenAI:
from openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY")
resp = client.chat.completions.create(
    model="gpt-4",
    messages=[{"role":"user","content":"Hello"}]
)

# at process exit we auto‐flush; you can also manually:
oai.flush(final=True)

Adding Custom Metadata with Decorators

You can attach custom metadata to each OpenAI request captured by ObservAI using the observai_context decorator. This is useful for tagging requests with experiment IDs, user actions, or any business context you want to track.

Usage

Import the decorator:

from observai.core.decorators import observai_context

Static Metadata

Attach a fixed dictionary of metadata to all calls of a function:

@observai_context(metadata={"experiment": "A"})
def my_function():
    # Your OpenAI call here
    pass

Dynamic Metadata

Attach metadata that depends on the function's arguments:

def dynamic_metadata(*args, **kwargs):
    return {"user_action": kwargs.get("action", "unknown")}

@observai_context(metadata_func=dynamic_metadata)
def another_function(action):
    # Your OpenAI call here
    pass

Example

@observai_context({"metadata": 1})
def call_openai():
    response = openai.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": "Hello there monkey ?"}],
    )
    print("Assistant:", response.choices[0].message.content)

How it works

  • The decorator injects your metadata into the ObservAI context for the duration of the function call.
  • This metadata will appear in the metadata field of each captured event (see observai_events.log or your collector endpoint).
  • Works with both synchronous and asynchronous functions.

Configuration

You can override defaults in init():

Parameter Default Description
log_path "observai_events.log" Local fallback file for JSON-lines dumps
truncate 500 Max chars for prompt/response (None = no truncation)
flush_interval 2.0 Seconds between auto flushes
db_path "observai_buffer.sqlite" SQLite path for crash-safe buffering
endpoint https://collector.example.com/events/batch HTTP endpoint for batch POST'ing events
headers {} HTTP headers to include on each POST
background False Whether to spawn the background thread

Adapters

By default, ObservAI auto-detects and patches all supported SDKs (currently: OpenAI).

An adapter patches a third-party SDK (like OpenAI) to automatically intercept API calls.

To explicitly specify only the OpenAI adapter:

from observai.adapters.openai import OpenAIChatAdapter

observai.init(adapters=[OpenAIChatAdapter()])

✅ Compatible with openai>=1.0.0

Packaging & Tests

What gets captured?

For each LLM call:

  • API route (e.g. chat.completions.create)
  • Model name
  • Input prompt (truncated if configured)
  • Output response (truncated if configured)
  • Latency (ms)
  • Timestamp
  • User ID (if configured)
  • SHA256 hash of prompt + response

Flush Modes

  • flush(final=True) sends events to the configured collector endpoint.
  • flush(final=False) writes events to a local JSON-lines fallback file.
  • Auto-flush mode (enabled via background=True) periodically calls flush() in a background thread.
  • All buffered events are flushed on process exit via atexit.

Roadmap

  • Anthropic adapters ??

About

No description, website, or topics provided.

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages