nirikshaai 0.0.1.dev1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nirikshaai-0.0.1.dev1/PKG-INFO +563 -0
- nirikshaai-0.0.1.dev1/README.md +524 -0
- nirikshaai-0.0.1.dev1/nirikshaai/__init__.py +208 -0
- nirikshaai-0.0.1.dev1/nirikshaai/_logger.py +27 -0
- nirikshaai-0.0.1.dev1/nirikshaai/_otel.py +252 -0
- nirikshaai-0.0.1.dev1/nirikshaai/baggage.py +66 -0
- nirikshaai-0.0.1.dev1/nirikshaai/eval.py +131 -0
- nirikshaai-0.0.1.dev1/nirikshaai/middleware.py +42 -0
- nirikshaai-0.0.1.dev1/nirikshaai/pii.py +61 -0
- nirikshaai-0.0.1.dev1/nirikshaai/prompt.py +144 -0
- nirikshaai-0.0.1.dev1/nirikshaai/serverless.py +63 -0
- nirikshaai-0.0.1.dev1/nirikshaai/span.py +116 -0
- nirikshaai-0.0.1.dev1/nirikshaai.egg-info/PKG-INFO +563 -0
- nirikshaai-0.0.1.dev1/nirikshaai.egg-info/SOURCES.txt +22 -0
- nirikshaai-0.0.1.dev1/nirikshaai.egg-info/dependency_links.txt +1 -0
- nirikshaai-0.0.1.dev1/nirikshaai.egg-info/requires.txt +30 -0
- nirikshaai-0.0.1.dev1/nirikshaai.egg-info/top_level.txt +1 -0
- nirikshaai-0.0.1.dev1/pyproject.toml +107 -0
- nirikshaai-0.0.1.dev1/setup.cfg +4 -0
- nirikshaai-0.0.1.dev1/tests/test_baggage.py +33 -0
- nirikshaai-0.0.1.dev1/tests/test_logger.py +23 -0
- nirikshaai-0.0.1.dev1/tests/test_pii.py +45 -0
- nirikshaai-0.0.1.dev1/tests/test_serverless.py +44 -0
- nirikshaai-0.0.1.dev1/tests/test_span.py +51 -0
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nirikshaai
|
|
3
|
+
Version: 0.0.1.dev1
|
|
4
|
+
Summary: NirikshaAI Python SDK — full-stack observability via OpenTelemetry
|
|
5
|
+
License: Apache-2.0
|
|
6
|
+
Keywords: observability,opentelemetry,tracing,metrics,logs,apm
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
10
|
+
Requires-Python: >=3.9
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: opentelemetry-sdk>=1.24
|
|
13
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.24
|
|
14
|
+
Provides-Extra: all
|
|
15
|
+
Requires-Dist: opentelemetry-instrumentation-django>=0.45b0; extra == "all"
|
|
16
|
+
Requires-Dist: opentelemetry-instrumentation-flask>=0.45b0; extra == "all"
|
|
17
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi>=0.45b0; extra == "all"
|
|
18
|
+
Requires-Dist: opentelemetry-instrumentation-starlette>=0.45b0; extra == "all"
|
|
19
|
+
Requires-Dist: opentelemetry-instrumentation-requests>=0.45b0; extra == "all"
|
|
20
|
+
Requires-Dist: opentelemetry-instrumentation-urllib3>=0.45b0; extra == "all"
|
|
21
|
+
Requires-Dist: opentelemetry-instrumentation-aiohttp-client>=0.45b0; extra == "all"
|
|
22
|
+
Requires-Dist: opentelemetry-instrumentation-grpc>=0.45b0; extra == "all"
|
|
23
|
+
Requires-Dist: opentelemetry-instrumentation-sqlalchemy>=0.45b0; extra == "all"
|
|
24
|
+
Requires-Dist: opentelemetry-instrumentation-psycopg2>=0.45b0; extra == "all"
|
|
25
|
+
Requires-Dist: opentelemetry-instrumentation-pymongo>=0.45b0; extra == "all"
|
|
26
|
+
Requires-Dist: opentelemetry-instrumentation-redis>=0.45b0; extra == "all"
|
|
27
|
+
Requires-Dist: opentelemetry-instrumentation-celery>=0.45b0; extra == "all"
|
|
28
|
+
Provides-Extra: llm
|
|
29
|
+
Requires-Dist: opentelemetry-instrumentation-openai>=0.27b0; extra == "llm"
|
|
30
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic>=0.27b0; extra == "llm"
|
|
31
|
+
Requires-Dist: opentelemetry-instrumentation-langchain>=0.27b0; extra == "llm"
|
|
32
|
+
Provides-Extra: dev
|
|
33
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=5.0; extra == "dev"
|
|
36
|
+
Requires-Dist: ruff>=0.4.0; extra == "dev"
|
|
37
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
38
|
+
Requires-Dist: coverage[toml]>=7.5; extra == "dev"
|
|
39
|
+
|
|
40
|
+
# NirikshaAI Python SDK
|
|
41
|
+
|
|
42
|
+
[](https://github.com/san-data-systems/niriksha-sdk-python/actions/workflows/ci.yml)
|
|
43
|
+
[](https://pypi.org/project/nirikshaai/)
|
|
44
|
+
[](https://pypi.org/project/nirikshaai/)
|
|
45
|
+
[](LICENSE)
|
|
46
|
+
|
|
47
|
+
The official Python SDK for [NirikshaAI](https://nirikshaai.com) — AI-native observability for logs, metrics, traces, and LLM/agent telemetry.
|
|
48
|
+
|
|
49
|
+
Under the hood this is a thin wrapper around the [OpenTelemetry Python SDK](https://opentelemetry.io/docs/languages/python/). It configures OTLP exporters, wires up auto-instrumentation, and exposes NirikshaAI-specific helpers (evals, prompt management). You can use the standard OTEL API at any time alongside it.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Table of Contents
|
|
54
|
+
|
|
55
|
+
- [Installation](#installation)
|
|
56
|
+
- [Quick Start](#quick-start)
|
|
57
|
+
- [LLM Applications](#llm-applications)
|
|
58
|
+
- [Configuration Reference](#configuration-reference)
|
|
59
|
+
- [Auto-Instrumented Libraries](#auto-instrumented-libraries)
|
|
60
|
+
- [Using the Standard OTEL API](#using-the-standard-otel-api)
|
|
61
|
+
- [Logging Integration](#logging-integration)
|
|
62
|
+
- [Eval Submission](#eval-submission)
|
|
63
|
+
- [Prompt Management](#prompt-management)
|
|
64
|
+
- [Framework Examples](#framework-examples)
|
|
65
|
+
- [Environment Variables](#environment-variables)
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Installation
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install nirikshaai
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
To include automatic instrumentation for common web frameworks and infrastructure libraries (Django, Flask, FastAPI, SQLAlchemy, Redis, etc.):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install "nirikshaai[all]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
To also include automatic instrumentation for LLM libraries (OpenAI, Anthropic, LangChain, etc.):
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install "nirikshaai[all,llm]"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Minimum Python version:** 3.9
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
## Quick Start
|
|
92
|
+
|
|
93
|
+
Two lines is all it takes to start sending traces, metrics, and logs to NirikshaAI from any Python service:
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
import nirikshaai
|
|
97
|
+
|
|
98
|
+
nirikshaai.init(
|
|
99
|
+
endpoint="https://app.niriksha.ai",
|
|
100
|
+
otlp_endpoint="grpc-ingest.niriksha.ai:443", # SaaS: OTLP gateway is separate from the REST API
|
|
101
|
+
api_key="nai_...",
|
|
102
|
+
service_name="my-service",
|
|
103
|
+
)
|
|
104
|
+
# That's it — traces, metrics, and logs now flow to NirikshaAI
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Your `api_key` is a project-scoped key (prefixed `nai_`). It encodes which org and project your telemetry belongs to — you do not need to pass org or project IDs separately.
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## LLM Applications
|
|
112
|
+
|
|
113
|
+
Enable LLM instrumentation with the `enable_llm` flag. When set, the SDK automatically patches supported LLM client libraries so that every API call creates a standard OpenTelemetry span with token counts, model name, and (optionally) prompt/completion content.
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
import nirikshaai
|
|
117
|
+
|
|
118
|
+
nirikshaai.init(
|
|
119
|
+
endpoint="https://app.niriksha.ai",
|
|
120
|
+
api_key="nai_...",
|
|
121
|
+
service_name="my-ai-service",
|
|
122
|
+
enable_llm=True, # Auto-instruments OpenAI, Anthropic, LangChain, etc.
|
|
123
|
+
capture_prompts=False, # Set True only if PII controls are in place
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
import openai # auto-instrumented — every call creates an OTEL span
|
|
127
|
+
|
|
128
|
+
client = openai.OpenAI()
|
|
129
|
+
response = client.chat.completions.create(
|
|
130
|
+
model="gpt-4o",
|
|
131
|
+
messages=[{"role": "user", "content": "Summarise this document."}],
|
|
132
|
+
)
|
|
133
|
+
# A LLM span is emitted automatically — no extra code needed
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
> **Privacy note:** `capture_prompts=False` is the default. Setting it to `True` will capture the full text of prompts and completions as span attributes (`llm.input.messages` / `llm.output.messages`). Only enable this if you have appropriate data governance and PII controls in place.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Configuration Reference
|
|
141
|
+
|
|
142
|
+
All parameters are passed to `nirikshaai.init()`.
|
|
143
|
+
|
|
144
|
+
| Parameter | Type | Default | Description |
|
|
145
|
+
|---|---|---|---|
|
|
146
|
+
| `endpoint` | `str` | *(required)* | NirikshaAI REST/control-plane base URL. SaaS: `https://app.niriksha.ai`. Private Cloud: `https://niriksha.internal` |
|
|
147
|
+
| `api_key` | `str` | *(required)* | Project-scoped API key with `nai_` prefix |
|
|
148
|
+
| `service_name` | `str` | `"my-service"` | Value of the `service.name` OTEL resource attribute |
|
|
149
|
+
| `environment` | `str` | `"production"` | Value of the `deployment.environment` OTEL resource attribute |
|
|
150
|
+
| `enable_metrics` | `bool` | `True` | Export OTLP metrics on a 60-second periodic interval |
|
|
151
|
+
| `enable_logs` | `bool` | `True` | Attach an OTLP log handler to the root Python `logging` logger |
|
|
152
|
+
| `enable_llm` | `bool` | `False` | Auto-instrument supported LLM client libraries (opt-in) |
|
|
153
|
+
| `capture_prompts` | `bool` | `False` | Capture `llm.input/output.messages` span attributes (PII risk) |
|
|
154
|
+
| `otlp_port` | `int` | `4317` | OTLP gRPC port. Ignored when `otlp_endpoint` is set. |
|
|
155
|
+
| `otlp_endpoint` | `str` | `None` | Override the gRPC OTLP address (`host:port`, no scheme). SaaS: `grpc-ingest.niriksha.ai:443` |
|
|
156
|
+
| `insecure` | `bool` | `False` | Send gRPC without TLS. Use when TLS is terminated at an ingress. |
|
|
157
|
+
| `tls_skip_verify` | `bool` | `False` | Use TLS but skip server certificate validation. Dev/staging only. |
|
|
158
|
+
| `ca_cert_file` | `str` | `None` | Path to a PEM CA certificate for verifying the gateway TLS cert. |
|
|
159
|
+
| `disable_instrumentations` | `list[str]` | `[]` | Library names to skip during auto-instrumentation (e.g. `["django"]`) |
|
|
160
|
+
|
|
161
|
+
### Private Cloud examples
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
# TLS with trusted certificate (system roots)
|
|
165
|
+
nirikshaai.init(
|
|
166
|
+
endpoint="https://niriksha.internal",
|
|
167
|
+
otlp_endpoint="niriksha.internal:4317",
|
|
168
|
+
api_key="nai_...",
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
# Custom / self-signed CA
|
|
172
|
+
nirikshaai.init(
|
|
173
|
+
endpoint="https://niriksha.internal",
|
|
174
|
+
otlp_endpoint="niriksha.internal:4317",
|
|
175
|
+
api_key="nai_...",
|
|
176
|
+
ca_cert_file="/etc/ssl/niriksha-ca.crt",
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Skip TLS verification (dev/staging only)
|
|
180
|
+
nirikshaai.init(
|
|
181
|
+
endpoint="https://niriksha.internal",
|
|
182
|
+
otlp_endpoint="niriksha.internal:4317",
|
|
183
|
+
api_key="nai_...",
|
|
184
|
+
tls_skip_verify=True,
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# Plaintext gRPC (TLS terminated at ingress)
|
|
188
|
+
nirikshaai.init(
|
|
189
|
+
endpoint="https://niriksha.internal",
|
|
190
|
+
otlp_endpoint="niriksha.internal:4317",
|
|
191
|
+
api_key="nai_...",
|
|
192
|
+
insecure=True,
|
|
193
|
+
)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Auto-Instrumented Libraries
|
|
199
|
+
|
|
200
|
+
### General (always enabled when the package is installed)
|
|
201
|
+
|
|
202
|
+
| Library | What's captured |
|
|
203
|
+
|---|---|
|
|
204
|
+
| `django` | HTTP requests and responses, middleware timing, view names |
|
|
205
|
+
| `flask` | Routes, request timing, status codes |
|
|
206
|
+
| `fastapi` | Routes, request timing, async support, response codes |
|
|
207
|
+
| `starlette` | Routes, middleware, ASGI lifecycle |
|
|
208
|
+
| `requests` | Outbound HTTP calls, method, URL, status code |
|
|
209
|
+
| `urllib3` | Low-level HTTP connections and retries |
|
|
210
|
+
| `aiohttp` | Async HTTP client calls |
|
|
211
|
+
| `grpc` | gRPC server and client calls, method names |
|
|
212
|
+
| `sqlalchemy` | SQL queries and transaction timing (values are not captured) |
|
|
213
|
+
| `psycopg2` | PostgreSQL query timing and operation type |
|
|
214
|
+
| `asyncpg` | Async PostgreSQL query timing |
|
|
215
|
+
| `pymongo` | MongoDB operation type, collection, database |
|
|
216
|
+
| `redis` | Redis command name (values are not captured) |
|
|
217
|
+
| `celery` | Task name, queue, execution state, retry count |
|
|
218
|
+
|
|
219
|
+
### LLM (requires `enable_llm=True`)
|
|
220
|
+
|
|
221
|
+
| Library | What's captured |
|
|
222
|
+
|---|---|
|
|
223
|
+
| `openai` | Chat completions, embeddings, model name, token usage (prompt + completion) |
|
|
224
|
+
| `anthropic` | Messages API calls, model name, token usage |
|
|
225
|
+
| `langchain` | Chain invocations, individual tool call spans, retrieval steps |
|
|
226
|
+
| `llama_index` | Query engine spans, retrieval spans, synthesiser spans |
|
|
227
|
+
| `mistralai` | Chat completions, model name, token usage |
|
|
228
|
+
| `google-generativeai` | Gemini API calls, model name, token usage |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Using the Standard OTEL API
|
|
233
|
+
|
|
234
|
+
`nirikshaai.init()` configures the global OpenTelemetry providers. You can use the standard OTEL API directly at any point after calling `init()`:
|
|
235
|
+
|
|
236
|
+
```python
|
|
237
|
+
from opentelemetry import trace, metrics
|
|
238
|
+
|
|
239
|
+
tracer = trace.get_tracer("my-service")
|
|
240
|
+
meter = metrics.get_meter("my-service")
|
|
241
|
+
|
|
242
|
+
# Custom span
|
|
243
|
+
with tracer.start_as_current_span("process-order") as span:
|
|
244
|
+
span.set_attribute("order.id", order_id)
|
|
245
|
+
span.set_attribute("order.total", total)
|
|
246
|
+
span.set_attribute("order.currency", "USD")
|
|
247
|
+
result = fulfil_order(order_id)
|
|
248
|
+
span.set_attribute("order.status", result.status)
|
|
249
|
+
|
|
250
|
+
# Custom counter
|
|
251
|
+
order_counter = meter.create_counter(
|
|
252
|
+
"orders.processed",
|
|
253
|
+
description="Number of orders processed",
|
|
254
|
+
unit="{order}",
|
|
255
|
+
)
|
|
256
|
+
order_counter.add(1, {"status": "success", "region": "us-east"})
|
|
257
|
+
|
|
258
|
+
# Custom histogram (useful for latency)
|
|
259
|
+
latency_histogram = meter.create_histogram(
|
|
260
|
+
"order.processing.duration",
|
|
261
|
+
description="Time to process an order",
|
|
262
|
+
unit="ms",
|
|
263
|
+
)
|
|
264
|
+
latency_histogram.record(142.5, {"order_type": "express"})
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## Logging Integration
|
|
270
|
+
|
|
271
|
+
When `enable_logs=True` (the default), the SDK attaches an OTLP log handler to Python's root logger. All log records emitted through the standard `logging` module are automatically exported to NirikshaAI, with trace and span IDs attached so log lines are correlated to their parent trace.
|
|
272
|
+
|
|
273
|
+
```python
|
|
274
|
+
import logging
|
|
275
|
+
|
|
276
|
+
logger = logging.getLogger("my-service")
|
|
277
|
+
|
|
278
|
+
# Structured extra fields are forwarded as log record attributes
|
|
279
|
+
logger.info("Order processed", extra={"order_id": "abc123", "amount": 99.99})
|
|
280
|
+
logger.warning("Inventory low", extra={"sku": "WIDGET-001", "remaining": 3})
|
|
281
|
+
logger.error("Payment failed", extra={"error_code": "CARD_DECLINED", "order_id": "abc123"})
|
|
282
|
+
|
|
283
|
+
# Exception info is captured automatically
|
|
284
|
+
try:
|
|
285
|
+
process_payment(order)
|
|
286
|
+
except PaymentError as exc:
|
|
287
|
+
logger.exception("Unhandled payment error", extra={"order_id": order.id})
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Logs are exported in batches over OTLP gRPC to the same endpoint as traces and metrics.
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## Eval Submission
|
|
295
|
+
|
|
296
|
+
Submit evaluation results for LLM responses. Evals are linked to a specific trace so results appear in the NirikshaAI LLM Traces view alongside the originating span.
|
|
297
|
+
|
|
298
|
+
### Single eval
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
import nirikshaai
|
|
302
|
+
|
|
303
|
+
nirikshaai.submit_eval(
|
|
304
|
+
trace_id="your-otel-trace-id", # hex trace ID from the OTEL span context
|
|
305
|
+
metric_name="faithfulness",
|
|
306
|
+
score=0.92, # float in [0, 1]
|
|
307
|
+
label="pass", # "pass" | "fail" | any custom label
|
|
308
|
+
explanation="Response accurately reflects the source documents",
|
|
309
|
+
eval_type="llm_judge", # "llm_judge" | "rule_based" | "human"
|
|
310
|
+
)
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Batch eval
|
|
314
|
+
|
|
315
|
+
```python
|
|
316
|
+
nirikshaai.submit_evals_batch([
|
|
317
|
+
{
|
|
318
|
+
"trace_id": "abc123...",
|
|
319
|
+
"metric_name": "toxicity",
|
|
320
|
+
"score": 0.02,
|
|
321
|
+
"label": "pass",
|
|
322
|
+
"eval_type": "rule_based",
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"trace_id": "abc123...",
|
|
326
|
+
"metric_name": "relevance",
|
|
327
|
+
"score": 0.87,
|
|
328
|
+
"label": "pass",
|
|
329
|
+
"eval_type": "llm_judge",
|
|
330
|
+
"explanation": "Response addresses the user's question directly",
|
|
331
|
+
},
|
|
332
|
+
])
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Obtaining the trace ID from an active span
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
from opentelemetry import trace
|
|
339
|
+
|
|
340
|
+
with tracer.start_as_current_span("llm-call") as span:
|
|
341
|
+
ctx = span.get_span_context()
|
|
342
|
+
trace_id = format(ctx.trace_id, "032x") # 32-character hex string
|
|
343
|
+
|
|
344
|
+
response = client.chat.completions.create(...)
|
|
345
|
+
|
|
346
|
+
# Submit eval referencing this trace
|
|
347
|
+
nirikshaai.submit_eval(
|
|
348
|
+
trace_id=trace_id,
|
|
349
|
+
metric_name="faithfulness",
|
|
350
|
+
score=judge(response),
|
|
351
|
+
label="pass",
|
|
352
|
+
)
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
## Prompt Management
|
|
358
|
+
|
|
359
|
+
Fetch versioned prompt templates from the NirikshaAI prompt vault. Variable substitution is performed server-side before the rendered text is returned.
|
|
360
|
+
|
|
361
|
+
### Fetch the latest deployed version
|
|
362
|
+
|
|
363
|
+
```python
|
|
364
|
+
prompt = nirikshaai.get_prompt("customer-support-system")
|
|
365
|
+
print(prompt["text"]) # Rendered prompt text
|
|
366
|
+
print(prompt["version"]) # Active version number
|
|
367
|
+
print(prompt["name"])
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Fetch a specific version with variable substitution
|
|
371
|
+
|
|
372
|
+
```python
|
|
373
|
+
prompt = nirikshaai.get_prompt(
|
|
374
|
+
"product-description",
|
|
375
|
+
version=3,
|
|
376
|
+
variables={
|
|
377
|
+
"product_name": "Widget Pro",
|
|
378
|
+
"category": "Electronics",
|
|
379
|
+
"price": "$49.99",
|
|
380
|
+
},
|
|
381
|
+
)
|
|
382
|
+
print(prompt["text"]) # All {{variables}} replaced server-side
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### List all available prompts
|
|
386
|
+
|
|
387
|
+
```python
|
|
388
|
+
prompts = nirikshaai.list_prompts()
|
|
389
|
+
for p in prompts:
|
|
390
|
+
print(f"{p['name']} (v{p['version']}) — {p['description']}")
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Framework Examples
|
|
396
|
+
|
|
397
|
+
### Django
|
|
398
|
+
|
|
399
|
+
Call `nirikshaai.init()` in your `settings.py` (or in an `AppConfig.ready()` method). Auto-instrumentation is applied globally once at startup.
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
# myproject/settings.py
|
|
403
|
+
import nirikshaai
|
|
404
|
+
|
|
405
|
+
nirikshaai.init(
|
|
406
|
+
endpoint="https://app.niriksha.ai",
|
|
407
|
+
api_key="nai_...",
|
|
408
|
+
service_name="django-app",
|
|
409
|
+
environment="production",
|
|
410
|
+
)
|
|
411
|
+
|
|
412
|
+
INSTALLED_APPS = [
|
|
413
|
+
# ... your apps
|
|
414
|
+
]
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### Flask
|
|
418
|
+
|
|
419
|
+
```python
|
|
420
|
+
from flask import Flask
|
|
421
|
+
import nirikshaai
|
|
422
|
+
|
|
423
|
+
# init() before creating the Flask app
|
|
424
|
+
nirikshaai.init(
|
|
425
|
+
endpoint="https://app.niriksha.ai",
|
|
426
|
+
api_key="nai_...",
|
|
427
|
+
service_name="flask-app",
|
|
428
|
+
)
|
|
429
|
+
|
|
430
|
+
app = Flask(__name__)
|
|
431
|
+
|
|
432
|
+
@app.route("/orders/<order_id>")
|
|
433
|
+
def get_order(order_id):
|
|
434
|
+
# This route is automatically traced — no extra code needed
|
|
435
|
+
order = db.get_order(order_id)
|
|
436
|
+
return {"id": order_id, "status": order.status}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### FastAPI
|
|
440
|
+
|
|
441
|
+
```python
|
|
442
|
+
from fastapi import FastAPI
|
|
443
|
+
import nirikshaai
|
|
444
|
+
|
|
445
|
+
nirikshaai.init(
|
|
446
|
+
endpoint="https://app.niriksha.ai",
|
|
447
|
+
api_key="nai_...",
|
|
448
|
+
service_name="fastapi-app",
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
app = FastAPI()
|
|
452
|
+
|
|
453
|
+
@app.get("/orders/{order_id}")
|
|
454
|
+
async def get_order(order_id: str):
|
|
455
|
+
# Async routes are fully supported — traced automatically
|
|
456
|
+
order = await db.get_order(order_id)
|
|
457
|
+
return {"id": order_id, "status": order.status}
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
### Celery
|
|
461
|
+
|
|
462
|
+
```python
|
|
463
|
+
from celery import Celery
|
|
464
|
+
import nirikshaai
|
|
465
|
+
|
|
466
|
+
nirikshaai.init(
|
|
467
|
+
endpoint="https://app.niriksha.ai",
|
|
468
|
+
api_key="nai_...",
|
|
469
|
+
service_name="celery-worker",
|
|
470
|
+
)
|
|
471
|
+
|
|
472
|
+
app = Celery("tasks", broker="redis://localhost:6379/0")
|
|
473
|
+
|
|
474
|
+
@app.task
|
|
475
|
+
def send_notification(user_id: str, message: str):
|
|
476
|
+
# Every task invocation is automatically traced
|
|
477
|
+
# The task name, queue, and retry count appear as span attributes
|
|
478
|
+
notify(user_id, message)
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### LLM application with eval feedback loop
|
|
482
|
+
|
|
483
|
+
```python
|
|
484
|
+
import nirikshaai
|
|
485
|
+
from opentelemetry import trace
|
|
486
|
+
|
|
487
|
+
nirikshaai.init(
|
|
488
|
+
endpoint="https://app.niriksha.ai",
|
|
489
|
+
api_key="nai_...",
|
|
490
|
+
service_name="rag-service",
|
|
491
|
+
enable_llm=True,
|
|
492
|
+
)
|
|
493
|
+
|
|
494
|
+
import openai
|
|
495
|
+
|
|
496
|
+
client = openai.OpenAI()
|
|
497
|
+
tracer = trace.get_tracer("rag-service")
|
|
498
|
+
|
|
499
|
+
def answer_question(question: str) -> str:
|
|
500
|
+
with tracer.start_as_current_span("answer-question") as span:
|
|
501
|
+
span.set_attribute("question.length", len(question))
|
|
502
|
+
|
|
503
|
+
# LLM call is auto-instrumented — a child span is created
|
|
504
|
+
response = client.chat.completions.create(
|
|
505
|
+
model="gpt-4o",
|
|
506
|
+
messages=[
|
|
507
|
+
{"role": "system", "content": "You are a helpful assistant."},
|
|
508
|
+
{"role": "user", "content": question},
|
|
509
|
+
],
|
|
510
|
+
)
|
|
511
|
+
answer = response.choices[0].message.content
|
|
512
|
+
|
|
513
|
+
# Record trace ID for eval submission
|
|
514
|
+
ctx = span.get_span_context()
|
|
515
|
+
trace_id = format(ctx.trace_id, "032x")
|
|
516
|
+
|
|
517
|
+
# Async eval — run your judge independently and post the result
|
|
518
|
+
score = run_faithfulness_judge(question, answer)
|
|
519
|
+
nirikshaai.submit_eval(
|
|
520
|
+
trace_id=trace_id,
|
|
521
|
+
metric_name="faithfulness",
|
|
522
|
+
score=score,
|
|
523
|
+
label="pass" if score >= 0.8 else "fail",
|
|
524
|
+
eval_type="llm_judge",
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
return answer
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Environment Variables
|
|
533
|
+
|
|
534
|
+
You can configure the SDK through standard OpenTelemetry environment variables instead of (or in addition to) passing arguments to `init()`. Environment variables take lower precedence than explicit arguments.
|
|
535
|
+
|
|
536
|
+
| Variable | Equivalent `init()` parameter |
|
|
537
|
+
|---|---|
|
|
538
|
+
| `OTEL_SERVICE_NAME` | `service_name` |
|
|
539
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Derived from `endpoint` + `otlp_port` |
|
|
540
|
+
| `OTEL_EXPORTER_OTLP_HEADERS` | Set to `X-API-Key=nai_your_key` |
|
|
541
|
+
| `OTEL_RESOURCE_ATTRIBUTES` | Use to set `deployment.environment` and other attributes |
|
|
542
|
+
|
|
543
|
+
Example shell setup:
|
|
544
|
+
|
|
545
|
+
```bash
|
|
546
|
+
export OTEL_SERVICE_NAME=my-service
|
|
547
|
+
export OTEL_EXPORTER_OTLP_ENDPOINT=http://your-nirikshaai:4317
|
|
548
|
+
export OTEL_EXPORTER_OTLP_HEADERS="X-API-Key=nai_your_key"
|
|
549
|
+
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment=production"
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
Then call `init()` with no arguments (the SDK will read the environment):
|
|
553
|
+
|
|
554
|
+
```python
|
|
555
|
+
import nirikshaai
|
|
556
|
+
nirikshaai.init()
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## License
|
|
562
|
+
|
|
563
|
+
Apache 2.0 — see [LICENSE](LICENSE).
|