5a558eb09e
TypeScript SDK Compatibility V1.x E2E Tests / Select Node version matrix (push) Has been cancelled
TypeScript SDK Compatibility V1.x E2E Tests / TypeScript SDK Compatibility V1.x E2E Tests Node ${{matrix.node_version}} (push) Has been cancelled
TypeScript SDK E2E Tests / TypeScript SDK E2E Tests Node ${{matrix.node_version}} (push) Has been cancelled
Opik Optimizer - E2E Tests / build-opik (push) Has been cancelled
TypeScript SDK Compatibility V1.x E2E Tests / build-opik (push) Has been cancelled
Python SDK E2E Tests / Select Python version matrix (push) Has been cancelled
Python SDK E2E Tests / Python SDK E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Python SDK E2E Tests / build-opik (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / Select Python version matrix (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / Python SDK Compatibility V1.x E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Python SDK Compatibility V1.x E2E Tests / build-opik (push) Has been cancelled
TypeScript SDK E2E Tests / Select Node version matrix (push) Has been cancelled
TypeScript SDK E2E Tests / build-opik (push) Has been cancelled
Opik Optimizer - E2E Tests / Opik Optimizer E2E Tests Python ${{matrix.python_version}} (push) Has been cancelled
Opik Optimizer - E2E Tests / Opik Optimizer Integration Smoke Tests (push) Has been cancelled
🐙 Code Quality / detect (push) Has been cancelled
🐙 Code Quality / lint (${{ matrix.leg.name }}) (push) Has been cancelled
🐙 Code Quality / summary (push) Has been cancelled
TypeScript SDK Library Integration Tests / Check Secrets (push) Has been cancelled
TypeScript SDK Library Integration Tests / opik-vercel (Vercel AI SDK / eve) (push) Has been cancelled
SDK Library Integration Tests Runner / Check Secrets (push) Has been cancelled
SDK Library Integration Tests Runner / Missed OpenAI API Key Warning (push) Has been cancelled
SDK Library Integration Tests Runner / Build (push) Has been cancelled
SDK Library Integration Tests Runner / openai_tests (push) Has been cancelled
SDK Library Integration Tests Runner / langchain_tests (push) Has been cancelled
SDK Library Integration Tests Runner / langchain_legacy_tests (push) Has been cancelled
SDK Library Integration Tests Runner / llama_index_tests (push) Has been cancelled
SDK Library Integration Tests Runner / anthropic_tests (push) Has been cancelled
SDK Library Integration Tests Runner / mistral_tests (push) Has been cancelled
SDK Library Integration Tests Runner / groq_tests (push) Has been cancelled
SDK Library Integration Tests Runner / aisuite_tests (push) Has been cancelled
SDK Library Integration Tests Runner / haystack_tests (push) Has been cancelled
SDK Library Integration Tests Runner / dspy_tests (push) Has been cancelled
SDK Library Integration Tests Runner / crewai_v0_tests (push) Has been cancelled
SDK Library Integration Tests Runner / crewai_v1_tests (push) Has been cancelled
SDK Library Integration Tests Runner / genai_tests (push) Has been cancelled
SDK Library Integration Tests Runner / adk_tests (push) Has been cancelled
SDK Library Integration Tests Runner / adk_legacy_1_3_0_tests (push) Has been cancelled
SDK Library Integration Tests Runner / evaluation_metrics_tests (push) Has been cancelled
SDK Library Integration Tests Runner / bedrock_tests (push) Has been cancelled
SDK Library Integration Tests Runner / litellm_tests (push) Has been cancelled
SDK Library Integration Tests Runner / harbor_tests (push) Has been cancelled
SDK Library Integration Tests Runner / Slack Notification (push) Has been cancelled
Lint Opik Helm Chart / render-equality (push) Has been cancelled
Opik Optimizer - Unit Tests / Opik Optimizer Unit Tests Python ${{matrix.python_version}} (push) Has been cancelled
Python BE E2E Tests / Python BE E2E (push) Has been cancelled
Python Backend Tests / run-python-backend-tests (push) Has been cancelled
Python SDK Unit Tests / Python SDK Unit Tests ${{matrix.python_version}} (push) Has been cancelled
Release Drafter / update_release_draft (push) Has been cancelled
SDK E2E Libraries Integration Tests / Check Secrets (push) Has been cancelled
SDK E2E Libraries Integration Tests / Missed OpenAI API Key Warning (push) Has been cancelled
SDK E2E Libraries Integration Tests / build-opik (push) Has been cancelled
SDK E2E Libraries Integration Tests / E2E Lib Integration Python ${{matrix.python_version}} (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-gemini) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-langchain) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-openai) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-otel) (push) Has been cancelled
TypeScript SDK Integration Build & Publish / build-and-publish (opik-vercel) (push) Has been cancelled
TypeScript SDK Build & Publish / build-and-publish (push) Has been cancelled
TypeScript SDK Unit Tests / Test on Node ${{ matrix.node-version }} (push) Has been cancelled
Backend Tests / discover-tests (push) Has been cancelled
Backend Tests / ${{ matrix.name }} (push) Has been cancelled
Build and Publish SDK / build-and-publish (push) Has been cancelled
Build Opik Docker Images / set-version (push) Has been cancelled
Build Opik Docker Images / build-backend (push) Has been cancelled
Build Opik Docker Images / build-sandbox-executor-python (push) Has been cancelled
Build Opik Docker Images / build-python-backend (push) Has been cancelled
Build Opik Docker Images / build-frontend (push) Has been cancelled
Build Opik Docker Images / create-git-tag (push) Has been cancelled
ClickHouse Migration Cluster Check / validate-clickhouse-migrations (push) Has been cancelled
Docs - Publish / run (push) Has been cancelled
E2E Tests - Post Merge (v2) / 🧪 E2E v2 Tests (${{ github.event.inputs.tier || 't1' }}) (push) Has been cancelled
E2E Tests - Post Merge (v2) / 📢 Slack Notification (push) Has been cancelled
Frontend Unit Tests / Test on Node 20 (push) Has been cancelled
Guardrails E2E Tests / Select Python version matrix (push) Has been cancelled
Guardrails E2E Tests / Guardrails E2E Tests ${{matrix.python_version}} (push) Has been cancelled
Guardrails E2E Tests / 📢 Slack Notification (push) Has been cancelled
Guardrails Backend Unit Tests / Guardrails Backend Unit Tests (push) Has been cancelled
Guardrails Backend Unit Tests / 📢 Slack Notification (push) Has been cancelled
Lint Opik Helm Chart / lint-helm-chart (Helm v3.21.0) (push) Has been cancelled
Lint Opik Helm Chart / lint-helm-chart (Helm v4.2.0) (push) Has been cancelled
Lint Opik Helm Chart / unittest-helm-chart (push) Has been cancelled
353 lines
13 KiB
Plaintext
353 lines
13 KiB
Plaintext
---
|
|
description: Start here to integrate Opik into your LlamaIndex-based genai application
|
|
for end-to-end LLM observability, unit testing, and optimization.
|
|
headline: Llama Index | Opik Documentation
|
|
og:description: Build powerful LLM applications using LlamaIndex to easily connect,
|
|
structure, and query your diverse data sources.
|
|
og:site_name: Opik Documentation
|
|
og:title: 'Llama Index: Build LLM Apps with Opik Frameworks'
|
|
title: Observability for LlamaIndex with Opik
|
|
---
|
|
|
|
[LlamaIndex](https://github.com/run-llama/llama_index) is a flexible data framework for building LLM applications:
|
|
|
|
LlamaIndex is a "data framework" to help you build LLM apps. It provides the following tools:
|
|
|
|
- Offers data connectors to ingest your existing data sources and data formats (APIs, PDFs, docs, SQL, etc.).
|
|
- Provides ways to structure your data (indices, graphs) so that this data can be easily used with LLMs.
|
|
- Provides an advanced retrieval/query interface over your data: Feed in any LLM input prompt, get back retrieved context and knowledge-augmented output.
|
|
- Allows easy integrations with your outer application framework (e.g. with LangChain, Flask, Docker, ChatGPT, anything else).
|
|
|
|
## Account Setup
|
|
|
|
[Comet](https://www.comet.com/site?from=llm&utm_source=opik&utm_medium=colab&utm_content=llamaindex&utm_campaign=opik) provides a hosted version of the Opik platform, [simply create an account](https://www.comet.com/signup?from=llm&utm_source=opik&utm_medium=colab&utm_content=llamaindex&utm_campaign=opik) and grab your API Key.
|
|
|
|
> You can also run the Opik platform locally, see the [installation guide](https://www.comet.com/docs/opik/self-host/overview/?from=llm&utm_source=opik&utm_medium=colab&utm_content=llamaindex&utm_campaign=opik) for more information.
|
|
|
|
## Getting Started
|
|
|
|
### Installation
|
|
|
|
To use the Opik integration with LlamaIndex, you'll need to have both the `opik` and `llama_index` packages installed. You can install them using pip:
|
|
|
|
```bash
|
|
pip install opik llama-index llama-index-agent-openai llama-index-llms-openai llama-index-callbacks-opik
|
|
```
|
|
|
|
### Configuring Opik
|
|
|
|
Configure the Opik Python SDK for your deployment type. See the [Python SDK Configuration guide](/tracing/advanced/sdk_configuration) for detailed instructions on:
|
|
|
|
- **CLI configuration**: `opik configure`
|
|
- **Code configuration**: `opik.configure()`
|
|
- **Self-hosted vs Cloud vs Enterprise** setup
|
|
- **Configuration files** and environment variables
|
|
|
|
### Configuring LlamaIndex
|
|
|
|
In order to use LlamaIndex, you will need to configure your LLM provider API keys. For this example, we'll use OpenAI. You can [find or create your API keys in these pages](https://platform.openai.com/settings/organization/api-keys):
|
|
|
|
You can set them as environment variables:
|
|
|
|
```bash
|
|
export OPENAI_API_KEY="YOUR_API_KEY"
|
|
```
|
|
|
|
Or set them programmatically:
|
|
|
|
```python
|
|
import os
|
|
import getpass
|
|
|
|
if "OPENAI_API_KEY" not in os.environ:
|
|
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
|
|
```
|
|
|
|
## Using the Opik integration
|
|
|
|
To use the Opik integration with LLamaIndex, you can use the `set_global_handler` function from the LlamaIndex package to set the global tracer:
|
|
|
|
```python
|
|
from llama_index.core import global_handler, set_global_handler
|
|
|
|
set_global_handler("opik")
|
|
opik_callback_handler = global_handler
|
|
```
|
|
|
|
Now that the integration is set up, all the LlamaIndex runs will be traced and logged to Opik.
|
|
|
|
Alternatively, you can configure the callback handler directly for more control:
|
|
|
|
```python
|
|
from llama_index.core import Settings
|
|
from llama_index.core.callbacks import CallbackManager
|
|
from opik.integrations.llama_index import LlamaIndexCallbackHandler
|
|
|
|
# Basic setup
|
|
opik_callback = LlamaIndexCallbackHandler()
|
|
|
|
# Or with optional parameters
|
|
opik_callback = LlamaIndexCallbackHandler(
|
|
project_name="my-llamaindex-project", # Set custom project name
|
|
skip_index_construction_trace=True # Skip tracking index construction
|
|
)
|
|
|
|
Settings.callback_manager = CallbackManager([opik_callback])
|
|
```
|
|
|
|
The `skip_index_construction_trace` parameter is useful when you want to track only query operations and not the index construction phase (particularly for large document sets or pre-built indexes)
|
|
|
|
## Example
|
|
|
|
To showcase the integration, we will create a new a query engine that will use Paul Graham's essays as the data source.
|
|
|
|
**First step:**
|
|
Configure the Opik integration:
|
|
|
|
```python
|
|
import os
|
|
from llama_index.core import global_handler, set_global_handler
|
|
|
|
# Set project name for better organization
|
|
os.environ["OPIK_PROJECT_NAME"] = "llamaindex-integration-demo"
|
|
|
|
set_global_handler("opik")
|
|
opik_callback_handler = global_handler
|
|
```
|
|
|
|
**Second step:**
|
|
Download the example data:
|
|
|
|
```python
|
|
import os
|
|
import requests
|
|
|
|
# Create directory if it doesn't exist
|
|
os.makedirs('./data/paul_graham/', exist_ok=True)
|
|
|
|
# Download the file using requests
|
|
url = 'https://raw.githubusercontent.com/run-llama/llama_index/main/docs/examples/data/paul_graham/paul_graham_essay.txt'
|
|
response = requests.get(url)
|
|
with open('./data/paul_graham/paul_graham_essay.txt', 'wb') as f:
|
|
f.write(response.content)
|
|
```
|
|
|
|
**Third step:**
|
|
|
|
Configure the OpenAI API key:
|
|
|
|
```python
|
|
import os
|
|
import getpass
|
|
|
|
if "OPENAI_API_KEY" not in os.environ:
|
|
os.environ["OPENAI_API_KEY"] = getpass.getpass("Enter your OpenAI API key: ")
|
|
```
|
|
|
|
**Fourth step:**
|
|
|
|
We can now load the data, create an index and query engine:
|
|
|
|
```python
|
|
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader
|
|
|
|
documents = SimpleDirectoryReader("./data/paul_graham").load_data()
|
|
index = VectorStoreIndex.from_documents(documents)
|
|
query_engine = index.as_query_engine()
|
|
|
|
response = query_engine.query("What did the author do growing up?")
|
|
print(response)
|
|
```
|
|
|
|
Given that the integration with Opik has been set up, all the traces are logged to the Opik platform:
|
|
|
|
<Frame>
|
|
<img src="/img/cookbook/llamaIndex_cookbook.png" />
|
|
</Frame>
|
|
|
|
## Using with the @track Decorator
|
|
|
|
The LlamaIndex integration seamlessly works with Opik's `@track` decorator. When you call LlamaIndex operations inside a tracked function, the LlamaIndex traces will automatically be attached as child spans to your existing trace.
|
|
|
|
```python
|
|
import opik
|
|
from llama_index.core import global_handler, set_global_handler
|
|
from llama_index.llms.openai import OpenAI
|
|
from llama_index.core.llms import ChatMessage
|
|
|
|
# Configure Opik integration
|
|
set_global_handler("opik")
|
|
opik_callback_handler = global_handler
|
|
|
|
@opik.track()
|
|
def my_llm_application(user_query: str):
|
|
"""Process user query with LlamaIndex"""
|
|
llm = OpenAI(model="gpt-3.5-turbo")
|
|
messages = [
|
|
ChatMessage(role="system", content="You are a helpful assistant."),
|
|
ChatMessage(role="user", content=user_query),
|
|
]
|
|
|
|
response = llm.chat(messages)
|
|
return response.message.content
|
|
|
|
# Call the tracked function
|
|
result = my_llm_application("What is the capital of France?")
|
|
print(result)
|
|
```
|
|
|
|
In this example, Opik will create a trace for the `my_llm_application` function, and all LlamaIndex operations (like the LLM chat call) will appear as nested spans within this trace, giving you a complete view of your application's execution.
|
|
|
|
## Using with Manual Trace Creation
|
|
|
|
You can also manually create traces using `opik.start_as_current_trace()` and have LlamaIndex operations nested within:
|
|
|
|
```python
|
|
import opik
|
|
from llama_index.core import global_handler, set_global_handler
|
|
from llama_index.llms.openai import OpenAI
|
|
from llama_index.core.llms import ChatMessage
|
|
|
|
# Configure Opik integration
|
|
set_global_handler("opik")
|
|
opik_callback_handler = global_handler
|
|
|
|
# Create a manual trace
|
|
with opik.start_as_current_trace(name="user_query_processing"):
|
|
llm = OpenAI(model="gpt-3.5-turbo")
|
|
messages = [
|
|
ChatMessage(role="user", content="Explain quantum computing in simple terms"),
|
|
]
|
|
|
|
response = llm.chat(messages)
|
|
print(response.message.content)
|
|
```
|
|
|
|
This approach is useful when you want more control over trace naming and want to group multiple LlamaIndex operations under a single trace.
|
|
|
|
## Tracking LlamaIndex Workflows
|
|
|
|
LlamaIndex workflows are multi-step processing pipelines for LLM applications. To track workflow executions in Opik, you can manually decorate your workflow steps and use `opik.start_as_current_span()` to wrap the workflow execution.
|
|
|
|
### Basic Workflow Tracking
|
|
|
|
You can use `@opik.track()` to decorate your workflow steps and `opik.start_as_current_span()` to track the workflow execution:
|
|
|
|
```python
|
|
import opik
|
|
from llama_index.core.workflow import Workflow, StartEvent, StopEvent, step, Event
|
|
from llama_index.core import Settings
|
|
from llama_index.core.callbacks import CallbackManager
|
|
from llama_index.core import global_handler, set_global_handler
|
|
|
|
# Configure Opik integration for LLM calls within steps
|
|
set_global_handler("opik")
|
|
|
|
class QueryEvent(Event):
|
|
"""Event for passing query through workflow."""
|
|
query: str
|
|
|
|
class MyRAGWorkflow(Workflow):
|
|
"""Simple RAG workflow with tracked steps."""
|
|
|
|
@step
|
|
@opik.track()
|
|
async def retrieve_context(self, ev: StartEvent) -> QueryEvent:
|
|
"""Retrieve relevant context for the query."""
|
|
query = ev.get("query", "")
|
|
# Your retrieval logic here
|
|
context = f"Context for: {query}"
|
|
return QueryEvent(query=f"{context} | {query}")
|
|
|
|
@step
|
|
@opik.track()
|
|
async def generate_response(self, ev: QueryEvent) -> StopEvent:
|
|
"""Generate final response using the context."""
|
|
# Your generation logic here
|
|
result = f"Response based on: {ev.query}"
|
|
return StopEvent(result=result)
|
|
|
|
# Create workflow instance
|
|
workflow = MyRAGWorkflow()
|
|
|
|
# Use start_as_current_span to track workflow execution
|
|
with opik.start_as_current_span(
|
|
name="rag_workflow_execution",
|
|
input={"query": "What are the key features?"},
|
|
project_name="llama-index-workflows"
|
|
) as span:
|
|
result = await workflow.run(query="What are the key features?")
|
|
span.update(output={"result": result})
|
|
|
|
print(result)
|
|
opik.flush_tracker() # Ensure all traces are sent
|
|
```
|
|
|
|
In this example:
|
|
- Each workflow step is decorated with `@opik.track()` to create spans
|
|
- The `@step` decorator is placed before `@opik.track()` to ensure LlamaIndex can properly discover the workflow steps
|
|
- `opik.start_as_current_span()` tracks the overall workflow execution
|
|
- LLM calls within steps are automatically tracked via the global Opik handler
|
|
- All workflow steps appear as nested spans within the workflow trace
|
|
|
|
<Tip>
|
|
If you're certain the workflow is a top-level call and want to create only a trace without an additional span, you can use `opik.start_as_current_trace()` instead of `opik.start_as_current_span()`. However, `start_as_current_span()` is more flexible as it works in both standalone and nested contexts.
|
|
</Tip>
|
|
|
|
### Best Practices
|
|
|
|
1. **Decorate all workflow steps** with `@opik.track()` to capture each step as a span
|
|
2. **Decorator order matters**: Place `@step` before `@opik.track()` so LlamaIndex's workflow engine can properly discover and execute steps
|
|
3. **Use `opik.start_as_current_span()`** to wrap workflow execution - it works in both standalone and nested contexts
|
|
4. **Configure the global handler** to automatically track LLM calls within steps
|
|
5. **Use descriptive names** for spans to make debugging easier
|
|
6. **Always call `opik.flush_tracker()`** at the end to ensure all traces are sent
|
|
7. **Include input/output** in span updates for better debugging
|
|
|
|
## Token Usage in Streaming Responses
|
|
|
|
When using streaming chat responses with OpenAI models (e.g., `llm.stream_chat()`), you need to explicitly enable token usage tracking by configuring the `stream_options` parameter:
|
|
|
|
```python
|
|
from llama_index.llms.openai import OpenAI
|
|
from llama_index.core.llms import ChatMessage
|
|
from llama_index.core import global_handler, set_global_handler
|
|
|
|
# Configure Opik integration
|
|
set_global_handler("opik")
|
|
|
|
# Configure OpenAI LLM with stream_options to include usage information
|
|
llm = OpenAI(
|
|
model="gpt-3.5-turbo",
|
|
additional_kwargs={
|
|
"stream_options": {"include_usage": True}
|
|
}
|
|
)
|
|
|
|
messages = [
|
|
ChatMessage(role="user", content="Tell me a short joke")
|
|
]
|
|
|
|
# Token usage will now be tracked in streaming responses
|
|
response = llm.stream_chat(messages)
|
|
for chunk in response:
|
|
print(chunk.delta, end="", flush=True)
|
|
```
|
|
|
|
<Note>
|
|
Without setting `stream_options={'include_usage': True}`, streaming responses from OpenAI models will not include token usage information in Opik traces. This is a requirement of OpenAI's streaming API.
|
|
</Note>
|
|
|
|
## Cost Tracking
|
|
|
|
The Opik integration with LlamaIndex automatically tracks token usage and cost for all supported LLM models used within LlamaIndex applications.
|
|
|
|
Cost information is automatically captured and displayed in the Opik UI, including:
|
|
- Token usage details
|
|
- Cost per request based on model pricing
|
|
- Total trace cost
|
|
|
|
<Tip>
|
|
View the complete list of supported models and providers on the [Supported Models](/tracing/advanced/cost_tracking) page.
|
|
</Tip>
|