Skip to main content

Automatic cost tracking and observability for LLM applications

Project description

LLM Observe SDK

Automatic cost tracking and observability for LLM applications

Track costs, tokens, latency, and errors for OpenAI, Anthropic, and other LLM providers with just 2 lines of code.

PyPI version Python Versions License: MIT

Features

  • โœ… Auto-instrumentation - No code changes needed beyond initialization
  • ๐Ÿ“Š Real-time tracking - Costs, tokens, latency, errors
  • ๐Ÿ” Hierarchical tracing - Track agents, tools, and workflows
  • ๐Ÿ‘ฅ Customer attribution - Track costs per end-user
  • ๐ŸŽฏ Zero overhead - Async buffering, sub-millisecond impact
  • ๐Ÿ”’ Privacy-first - Optional prompt/response capture
  • ๐Ÿš€ Production-ready - Battle-tested, scalable architecture

Supported Providers

  • OpenAI (GPT-4, GPT-3.5, embeddings, images, audio, etc.)
  • Pinecone (vector database operations)
  • More coming soon! (Anthropic, Cohere, etc.)

Quick Start

1. Install

pip install llmobserve

2. Get Your API Key

Sign up at llmobserve.com to get your API key.

3. Add 2 Lines of Code

from llmobserve import observe
from openai import OpenAI

# Initialize observability
observe(
    collector_url="https://api.llmobserve.com",
    api_key="llmo_sk_your_key_here"
)

# Use OpenAI as normal - all calls are tracked automatically!
client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Hello!"}]
)

That's it! ๐ŸŽ‰ View your costs and metrics at app.llmobserve.com

Advanced Usage

Track Agents & Workflows

Automatic Tracking (Zero Config):

from llmobserve import observe
from langchain.agents import AgentExecutor

observe(
    collector_url="https://api.llmobserve.com",
    api_key="llmo_sk_your_key_here"
)

# Agent tracking happens automatically - no manual labeling needed!
agent = AgentExecutor(...)
result = agent.run("query")  # Automatically tracked as agent

Manual Labeling (Optional, for Better UX):

from llmobserve import observe, section

observe(
    collector_url="https://api.llmobserve.com",
    api_key="llmo_sk_your_key_here"
)

# Hierarchical tracking (optional - improves dashboard UX)
with section("agent:research_assistant"):
    with section("tool:web_search"):
        # Your search logic
        results = search_web(query)
    
    with section("tool:summarize"):
        # Your summarization logic
        summary = summarize(results)

Key Points:

  • โœ… Costs are always tracked via HTTP interception (works everywhere)
  • โœ… Framework agents auto-tracked (LangChain, CrewAI, AutoGen, LlamaIndex)
  • โœ… Manual labeling is optional (improves dashboard UX but not required)
  • โœ… Untracked costs still shown (labeled as "untracked" in dashboard)

Dashboard shows:

agent:research_assistant    $0.50  (10 calls)
โ”œโ”€ tool:web_search          $0.002  [ok]
โ””โ”€ tool:summarize           $0.001  [ok]
untracked                   $0.10   (5 calls)  โ† Costs without agent labels

Track Costs Per Customer

from llmobserve import observe, set_customer_id

observe(
    collector_url="https://api.llmobserve.com",
    api_key="llmo_sk_your_key_here"
)

# Set customer ID for cost attribution
set_customer_id("customer_xyz")

# All subsequent API calls are attributed to this customer
client = OpenAI()
response = client.chat.completions.create(...)

Decorator Style

from llmobserve import trace

@trace(agent="customer_support")
async def handle_support_request(message: str):
    # All OpenAI calls inside are automatically tracked
    response = await client.chat.completions.create(...)
    return response

Framework Integration

FastAPI

from fastapi import FastAPI
from llmobserve import ObservabilityMiddleware, observe

app = FastAPI()
app.add_middleware(ObservabilityMiddleware)

observe(
    collector_url="https://api.llmobserve.com",
    api_key="llmo_sk_your_key_here"
)

@app.post("/chat")
async def chat(request: Request):
    # Context is auto-reset per request
    # All OpenAI calls are tracked
    response = await client.chat.completions.create(...)
    return response

Flask

from flask import Flask
from llmobserve import flask_before_request, observe

app = Flask(__name__)
app.before_request(flask_before_request)

observe(
    collector_url="https://api.llmobserve.com",
    api_key="llmo_sk_your_key_here"
)

@app.route("/chat")
def chat():
    # Context is auto-reset per request
    response = client.chat.completions.create(...)
    return response

What Gets Tracked

For every LLM API call:

  • โœ… Costs - Calculated using latest pricing
  • โœ… Tokens - Input, output, and cached tokens
  • โœ… Latency - Request duration in milliseconds
  • โœ… Status - Success, error, timeout, etc.
  • โœ… Model - Which model was used
  • โœ… Provider - OpenAI, Anthropic, etc.
  • โœ… Section/Agent - Hierarchical context
  • โœ… Customer ID - For cost attribution
  • โœ… Timestamps - When the call was made
  • โš ๏ธ Prompts/Responses - Optional (disabled by default)

Configuration

Environment Variables

# Disable observability
LLMOBSERVE_DISABLED=1

# Enable content capture (prompts/responses)
ALLOW_CONTENT_CAPTURE=true

Custom Flush Interval

observe(
    collector_url="https://api.llmobserve.com",
    api_key="llmo_sk_your_key_here",
    flush_interval_ms=1000  # Flush every 1 second (default: 500ms)
)

Dashboard Features

Visit app.llmobserve.com to view:

  • ๐Ÿ’ฐ Cost Overview - Total spend, trends, by provider/model
  • ๐Ÿ“Š Run Details - Individual request breakdowns
  • ๐ŸŽฏ Agent Analytics - Which agents/workflows cost the most
  • ๐Ÿ‘ฅ Customer Breakdown - Cost per end-user
  • ๐Ÿšจ Alerts - Cost spikes, errors, anomalies
  • ๐Ÿ“ˆ Insights - Auto-detected inefficiencies

Self-Hosting

Want to run your own instance?

git clone https://github.com/yourusername/llmobserve
cd llmobserve

# Start collector API
cd collector
pip install -r requirements.txt
uvicorn main:app --port 8000

# Start dashboard
cd ../web
npm install
npm run dev

See DEPLOYMENT.md for production deployment guide.

Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Your App      โ”‚
โ”‚  + llmobserve   โ”‚  โ† Auto-instruments OpenAI & Pinecone
โ”‚     SDK         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚ POST /events
         โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  Collector API  โ”‚  โ† FastAPI + PostgreSQL
โ”‚   (Backend)     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
         โ”‚ GET /runs, /stats
         โ†“
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Dashboard     โ”‚  โ† Next.js + Clerk
โ”‚   (Frontend)    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

FAQ

Q: Does this slow down my app? A: No. Events are buffered asynchronously with sub-millisecond overhead.

Q: Are my prompts/responses sent to your servers? A: No, by default only metadata is sent (tokens, cost, latency). Set ALLOW_CONTENT_CAPTURE=true to enable content logging.

Q: Can I use this in production? A: Yes! It's production-ready and tested at scale.

Q: What about other LLM providers? A: Anthropic, Cohere, and others coming soon! Request support via GitHub issues.

Q: How much does it cost? A: Free tier includes 10K tracked API calls/month. See pricing.

Contributing

We welcome contributions! See CONTRIBUTING.md.

License

MIT License - see LICENSE

Support


Made with โค๏ธ by the LLM Observe team

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

llmobserve-0.3.0.tar.gz (107.2 kB view details)

Uploaded Source

Built Distribution

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

llmobserve-0.3.0-py3-none-any.whl (130.8 kB view details)

Uploaded Python 3

File details

Details for the file llmobserve-0.3.0.tar.gz.

File metadata

  • Download URL: llmobserve-0.3.0.tar.gz
  • Upload date:
  • Size: 107.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for llmobserve-0.3.0.tar.gz
Algorithm Hash digest
SHA256 d34f8efbf25572ee0dfe9ed6db84a4b927de9bbb4ec071f28142d79c71ac2c2f
MD5 e50a208420db589c443f53a7822a3222
BLAKE2b-256 babc99b6797aa583bec6706f690da54a148498c8eb248f98ab8354c3949139a0

See more details on using hashes here.

File details

Details for the file llmobserve-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: llmobserve-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 130.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for llmobserve-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 7fff7de2d8042141dd8f2299ad8c39672eb490f91192273657752477ae6e10cc
MD5 ec39b9dae9702626ea68dd09e101e1f2
BLAKE2b-256 e9aae9574b98039b4c9b904af199ca34526adada6139055b477486fe1c6c574d

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