Skip to main content

Context0 SDK — one import, all calls logged

Project description

llm-observatory

Drop-in LLM observability for Python. One import change, all calls logged automatically.

Install

pip install llm-observatory

Usage

from llm_observatory import configure, OpenAI

configure(api_key="your-api-key", base_url="https://your-endpoint.com")

client = OpenAI(api_key="sk-...")
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)

Supports OpenAI, AsyncOpenAI, AzureOpenAI, AsyncAzureOpenAI, Anthropic, and AsyncAnthropic.

Wrapping third-party clients

Already using another LLM wrapper (e.g. Langfuse)? Use wrap() to add Context0 observability on top of any OpenAI- or Anthropic-compatible client — no need to change your existing setup:

from langfuse.openai import OpenAI as LangfuseOpenAI
from llm_observatory import configure, wrap

configure(api_key="your-api-key", base_url="https://your-endpoint.com")

client = wrap(LangfuseOpenAI(api_key="sk-..."))

# Both Langfuse AND Context0 capture this call
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "Hello"}],
)

wrap() works with any client that has a .chat (OpenAI-shaped) or .messages (Anthropic-shaped) interface. If the client is already a Context0 wrapper, it's returned as-is — no double-wrapping.

Tracing

Group related LLM calls into traces to see your full pipeline as a tree.

@observe decorator

Automatically creates a trace (top-level) or span (nested). Captures function args as input and return value as output.

import llm_observatory as obs

client = obs.OpenAI()

@obs.observe
def retrieve_docs(query: str):
    return vector_db.search(query)

@obs.observe
def rag_pipeline(question: str):
    docs = retrieve_docs(question)       # child span
    response = client.chat.completions.create(  # auto-captured as generation
        model="gpt-4o",
        messages=[{"role": "user", "content": f"{docs}\n\n{question}"}],
    )
    return response.choices[0].message.content

Options:

  • @obs.observe(name="custom-name") — override the span name (default: function name)
  • @obs.observe(capture_input=False) — don't log args (for sensitive data)
  • @obs.observe(capture_output=False) — don't log return value

Works with both sync and async functions.

Context managers

Use trace() and span() for inline code blocks that aren't standalone functions:

with obs.trace(name="rag-pipeline", input={"query": q}) as t:
    with obs.span(name="vector-search") as s:
        results = search(q)
        s.set_output(results)

    response = client.chat.completions.create(model="gpt-4o", messages=[...])
    t.set_output(response.choices[0].message.content)

Mix freely — @observe and with span() compose within the same trace.

Cross-service propagation

Pass trace context across services (e.g., API to SQS worker) via W3C traceparent:

# Producer — get traceparent inside a trace
with obs.trace(name="api-request"):
    traceparent = obs.get_current_traceparent()
    sqs.send_message(Body=json.dumps({"traceparent": traceparent, ...}))

# Consumer — restore context
msg = json.loads(sqs_message["Body"])
with obs.trace(name="worker", traceparent=msg["traceparent"]):
    client.chat.completions.create(...)  # appears as child in same trace

Use obs.emit_completed_span() to backfill spans with explicit start/end times (e.g., queue wait duration).

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

llm_observatory-0.2.0.tar.gz (36.2 kB view details)

Uploaded Source

Built Distribution

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

llm_observatory-0.2.0-py3-none-any.whl (20.1 kB view details)

Uploaded Python 3

File details

Details for the file llm_observatory-0.2.0.tar.gz.

File metadata

  • Download URL: llm_observatory-0.2.0.tar.gz
  • Upload date:
  • Size: 36.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.10

File hashes

Hashes for llm_observatory-0.2.0.tar.gz
Algorithm Hash digest
SHA256 f2001fcb6de757cd86620a50378f9a6629d58b558916351078cc826a98082272
MD5 fd0e8baef2393d032d7b940eb7f18dc1
BLAKE2b-256 02acd0f22df2ad5cbbd0a1e8dbeec846a65f1a0d3b88ea522f01270ee72d97df

See more details on using hashes here.

File details

Details for the file llm_observatory-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for llm_observatory-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d2220d46232e5e87a3e20e161b008d70ba3ff307456cae1682a546bfd9b8a031
MD5 5e310abf22b0d19019b9e1add5c1fb0c
BLAKE2b-256 b351b953e3b37ee33bbf7c7524156b5bca283deefc61eef0ceb00350afab9574

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