Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 158 additions & 0 deletions packages/opentelemetry-instrumentation-alephalpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,164 @@ from opentelemetry.instrumentation.alephalpha import AlephAlphaInstrumentor
AlephAlphaInstrumentor().instrument()
```

---

## Beginner-friendly walkthrough

This section walks you through tracing your first Aleph Alpha LLM call from scratch.

### Prerequisites

Install the required packages:

```bash
pip install opentelemetry-instrumentation-alephalpha \
aleph_alpha_client \
opentelemetry-sdk
```

You need an **Aleph Alpha API token**. Sign up at <https://app.aleph-alpha.com> and create a token in your account settings.

### Step 1 – Set up OpenTelemetry

Before instrumenting anything you need an OpenTelemetry `TracerProvider` that knows where to export spans. The simplest option for local development is to print spans to the console:

```python
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter

# Create a provider that prints spans to stdout
provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)
```

### Step 2 – Instrument the Aleph Alpha client

```python
from opentelemetry.instrumentation.alephalpha import AlephAlphaInstrumentor

AlephAlphaInstrumentor().instrument()
```

After this single call every subsequent Aleph Alpha API request is automatically wrapped in an OpenTelemetry span — no further code changes are needed.

### Step 3 – Make an LLM call

```python
import os
from aleph_alpha_client import Client, CompletionRequest, Prompt

client = Client(token=os.environ["AA_TOKEN"])

request = CompletionRequest(
prompt=Prompt.from_text("Explain observability in one sentence."),
maximum_tokens=100,
)
response = client.complete(request, model="luminous-base")
print(response.completions[0].completion)
```

### Complete minimal example

```python
"""
Minimal Aleph Alpha tracing example.

Requirements:
pip install opentelemetry-instrumentation-alephalpha aleph_alpha_client opentelemetry-sdk

Environment:
export AA_TOKEN=<your-aleph-alpha-api-token>
"""

import os

# 1. Set up OpenTelemetry (console exporter for local development)
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import SimpleSpanProcessor, ConsoleSpanExporter

provider = TracerProvider()
provider.add_span_processor(SimpleSpanProcessor(ConsoleSpanExporter()))
trace.set_tracer_provider(provider)

# 2. Instrument the Aleph Alpha client
from opentelemetry.instrumentation.alephalpha import AlephAlphaInstrumentor

AlephAlphaInstrumentor().instrument()

# 3. Make a completion request — the span is captured automatically
from aleph_alpha_client import Client, CompletionRequest, Prompt

client = Client(token=os.environ["AA_TOKEN"])
request = CompletionRequest(
prompt=Prompt.from_text("Explain observability in one sentence."),
maximum_tokens=100,
)
response = client.complete(request, model="luminous-base")
print("Response:", response.completions[0].completion)
```

### Expected trace output

When you run the example above you will see a JSON span printed to the console. The key attributes are:

| Attribute | Description | Example value |
|---|---|---|
| `gen_ai.system` | The LLM provider | `"AlephAlpha"` |
| `llm.request.type` | The type of LLM call | `"completion"` |
| `gen_ai.request.model` | The model used | `"luminous-base"` |
| `gen_ai.prompt.0.content` | The prompt text (if content tracing is enabled) | `"Explain observability…"` |
| `gen_ai.completion.0.content` | The model's reply (if content tracing is enabled) | `"Observability is…"` |
| `gen_ai.usage.input_tokens` | Number of prompt tokens consumed | `8` |
| `gen_ai.usage.output_tokens` | Number of generated tokens | `42` |
| `llm.usage.total_tokens` | Total tokens (input + output) | `50` |

### Using the Traceloop SDK (recommended)

For production use, the [Traceloop SDK](https://pypi.org/project/traceloop-sdk/) handles provider setup, instrumentation, and exporting for you:

```bash
pip install traceloop-sdk opentelemetry-instrumentation-alephalpha aleph_alpha_client
```

```python
import os
from aleph_alpha_client import Client, CompletionRequest, Prompt
from traceloop.sdk import Traceloop
from traceloop.sdk.decorators import task, workflow

# Initialise – instruments all supported LLM libraries automatically
Traceloop.init(app_name="my_alephalpha_app")

client = Client(token=os.environ["AA_TOKEN"])


@task(name="complete_prompt")
def complete_prompt(text: str) -> str:
request = CompletionRequest(
prompt=Prompt.from_text(text),
maximum_tokens=100,
)
response = client.complete(request, model="luminous-base")
return response.completions[0].completion


@workflow(name="main_workflow")
def main():
answer = complete_prompt("Explain observability in one sentence.")
print("Answer:", answer)


main()
```

A richer version of this example (with `@workflow` / `@task` decorators) can be found in [`packages/sample-app/sample_app/alephalpha_example.py`](../../sample-app/sample_app/alephalpha_example.py).

---

## Privacy

**By default, this instrumentation logs prompts, completions, and embeddings to span attributes**. This gives you a clear visibility into how your LLM application is working, and can make it easy to debug and evaluate the quality of the outputs.
Expand Down
3 changes: 3 additions & 0 deletions packages/sample-app/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ dependencies = [
"fastmcp>=2.12.3,<3",
"agno>=2.4.0,<3",
"voyageai>=0.3.7",
"aleph_alpha_client>=7.1.0,<8",
"opentelemetry-instrumentation-alephalpha",
"opentelemetry-instrumentation-openai",
"opentelemetry-instrumentation-haystack",
"opentelemetry-instrumentation-pinecone",
Expand Down Expand Up @@ -84,6 +86,7 @@ opentelemetry-instrumentation-agno = { path = "../opentelemetry-instrumentation-
opentelemetry-instrumentation-anthropic = { path = "../opentelemetry-instrumentation-anthropic", editable = true }
opentelemetry-instrumentation-bedrock = { path = "../opentelemetry-instrumentation-bedrock", editable = true }
opentelemetry-instrumentation-voyageai = { path = "../opentelemetry-instrumentation-voyageai", editable = true }
opentelemetry-instrumentation-alephalpha = { path = "../opentelemetry-instrumentation-alephalpha", editable = true }
traceloop-sdk = { path = "../traceloop-sdk", editable = true }

[dependency-groups]
Expand Down
114 changes: 114 additions & 0 deletions packages/sample-app/sample_app/alephalpha_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""
Beginner-friendly example: LLM tracing with Aleph Alpha and OpenLLMetry
========================================================================

This script shows, step by step, how to:
1. Initialise the Traceloop SDK (which sets up the OpenTelemetry tracer).
2. Instrument the Aleph Alpha client so every completion call is traced
automatically.
3. Make a basic text-completion request.
4. Observe the trace that is captured.

Prerequisites
-------------
Install the required packages::

pip install traceloop-sdk opentelemetry-instrumentation-alephalpha aleph_alpha_client python-dotenv

Set the environment variables (or create a .env file)::

AA_TOKEN=<your-aleph-alpha-api-token>
TRACELOOP_API_KEY=<your-traceloop-api-key> # optional – omit to print traces locally

Expected trace
--------------
After running this script you should see a single span exported with:

- span name : "alephalpha.completion"
- gen_ai.system : "AlephAlpha"
- llm.request.type : "completion"
- gen_ai.request.model: "luminous-base"
- gen_ai.prompt.0.content : <your prompt text>
- gen_ai.completion.0.content : <the model's reply>
- gen_ai.usage.input_tokens : <number of prompt tokens>
- gen_ai.usage.output_tokens : <number of generated tokens>
- llm.usage.total_tokens : input + output tokens
"""

import os

from aleph_alpha_client import Client, CompletionRequest, Prompt
from dotenv import load_dotenv
from traceloop.sdk import Traceloop
from traceloop.sdk.decorators import task, workflow

# ---------------------------------------------------------------------------
# Step 1 – Load environment variables from a .env file (if present)
# ---------------------------------------------------------------------------
load_dotenv()

# ---------------------------------------------------------------------------
# Step 2 – Initialise Traceloop / OpenTelemetry
#
# Traceloop.init() sets up an OpenTelemetry TracerProvider and automatically
# instruments every supported LLM library that is installed, including the
# Aleph Alpha client. No additional call to AlephAlphaInstrumentor is needed
# when using the SDK.
#
# If TRACELOOP_API_KEY is set the traces are sent to Traceloop's cloud.
# Otherwise they are printed to stdout (great for local development).
# ---------------------------------------------------------------------------
Traceloop.init(app_name="alephalpha_beginner_example")

# ---------------------------------------------------------------------------
# Step 3 – Create the Aleph Alpha client
# ---------------------------------------------------------------------------
aleph_alpha_client = Client(token=os.environ["AA_TOKEN"])

# ---------------------------------------------------------------------------
# Step 4 – Define a traced task that performs a single completion
#
# The @task decorator wraps the function in an OpenTelemetry span named
# "generate_joke". The AlephAlpha instrumentation automatically adds a
# child span "alephalpha.completion" containing all LLM-specific attributes.
# ---------------------------------------------------------------------------
@task(name="generate_joke")
def generate_joke(prompt_text: str) -> str:
"""Send a prompt to Aleph Alpha and return the generated completion."""
request = CompletionRequest(
prompt=Prompt.from_text(prompt_text),
maximum_tokens=200,
)
response = aleph_alpha_client.complete(request, model="luminous-base")
completion = response.completions[0].completion
print(f"\nCompletion received:\n{completion}\n")
return completion


# ---------------------------------------------------------------------------
# Step 5 – Define a top-level workflow that calls the task
#
# The @workflow decorator creates the root span for this execution. All
# child spans (tasks, LLM calls) are nested inside it, giving you a clear
# view of the full execution tree in your tracing backend.
# ---------------------------------------------------------------------------
@workflow(name="joke_generator")
def joke_generator():
"""Top-level workflow: ask the model for a joke and print it."""
prompt = "Tell me a short, funny joke about observability."
print(f"Prompt: {prompt}")
joke = generate_joke(prompt)
return joke


# ---------------------------------------------------------------------------
# Step 6 – Run the workflow
# ---------------------------------------------------------------------------
if __name__ == "__main__":
print("=" * 60)
print("Aleph Alpha LLM Tracing – Beginner Example")
print("=" * 60)
result = joke_generator()
print("=" * 60)
print("Done! Check your Traceloop dashboard (or stdout) for the trace.")
print("=" * 60)