|
1 | 1 | """ |
2 | | -Example: Programmatic Configuration for Openlayer Tracing |
| 2 | +Example: Configuring the Openlayer Tracer |
3 | 3 |
|
4 | | -This example demonstrates how to configure Openlayer tracing programmatically |
5 | | -using the configure() function, instead of relying on environment variables. |
| 4 | +Demonstrates the three ways to configure the tracer and how they compose: |
| 5 | + 1. Environment variables (canonical for deployments) |
| 6 | + 2. init() — programmatic, idempotent, merges on repeated calls |
| 7 | + 3. Per-decorator override via @trace(inference_pipeline_id=...) |
| 8 | +
|
| 9 | +Precedence (highest first): |
| 10 | + decorator argument > init() > environment variable > default |
| 11 | +
|
| 12 | +Also shows the deprecated configure() alias, kept for backward compatibility. |
6 | 13 | """ |
7 | 14 |
|
8 | 15 | import os |
9 | 16 | import openai |
10 | | -from openlayer.lib import configure, trace, trace_openai |
| 17 | +from openlayer.lib import init, configure, get_tracer_config, trace, trace_openai |
11 | 18 |
|
12 | 19 |
|
13 | 20 | def example_environment_variables(): |
14 | | - """Traditional approach using environment variables.""" |
| 21 | + """Canonical deployment path — env vars only, no code changes needed.""" |
15 | 22 | print("=== Environment Variables Approach ===") |
16 | 23 |
|
17 | | - # Set environment variables (traditional approach) |
18 | 24 | os.environ["OPENLAYER_API_KEY"] = "your_openlayer_api_key_here" |
19 | 25 | os.environ["OPENLAYER_INFERENCE_PIPELINE_ID"] = "your_pipeline_id_here" |
20 | 26 | os.environ["OPENAI_API_KEY"] = "your_openai_api_key_here" |
21 | 27 |
|
22 | | - # Use the @trace decorator |
23 | 28 | @trace() |
24 | 29 | def generate_response(query: str) -> str: |
25 | | - """Generate a response using OpenAI.""" |
26 | | - # Configure OpenAI client and trace it |
27 | 30 | client = trace_openai(openai.OpenAI()) |
28 | | - |
29 | 31 | response = client.chat.completions.create( |
30 | 32 | model="gpt-3.5-turbo", |
31 | 33 | messages=[{"role": "user", "content": query}], |
32 | 34 | max_tokens=100, |
33 | 35 | ) |
34 | 36 | return response.choices[0].message.content |
35 | 37 |
|
36 | | - # Test the function |
37 | | - result = generate_response("What is machine learning?") |
38 | | - print(f"Response: {result}") |
| 38 | + print(f"Response: {generate_response('What is machine learning?')}") |
39 | 39 |
|
40 | 40 |
|
41 | | -def example_programmatic_configuration(): |
42 | | - """New approach using programmatic configuration.""" |
43 | | - print("\n=== Programmatic Configuration Approach ===") |
| 41 | +def example_programmatic_init(): |
| 42 | + """Programmatic configuration via init() — preferred for notebooks/apps.""" |
| 43 | + print("\n=== Programmatic init() ===") |
44 | 44 |
|
45 | | - # Configure Openlayer programmatically |
46 | | - configure( |
| 45 | + init( |
47 | 46 | api_key="your_openlayer_api_key_here", |
48 | 47 | inference_pipeline_id="your_pipeline_id_here", |
49 | | - # base_url="https://api.openlayer.com/v1" # Optional: custom base URL |
| 48 | + # base_url="https://onprem.example.com", # Optional, for on-prem deployments |
50 | 49 | ) |
51 | 50 |
|
52 | | - # Set OpenAI API key |
53 | 51 | os.environ["OPENAI_API_KEY"] = "your_openai_api_key_here" |
54 | 52 |
|
55 | | - # Use the @trace decorator (no environment variables needed for Openlayer) |
56 | 53 | @trace() |
57 | | - def generate_response_programmatic(query: str) -> str: |
58 | | - """Generate a response using OpenAI with programmatic configuration.""" |
59 | | - # Configure OpenAI client and trace it |
| 54 | + def generate_response(query: str) -> str: |
60 | 55 | client = trace_openai(openai.OpenAI()) |
61 | | - |
62 | 56 | response = client.chat.completions.create( |
63 | 57 | model="gpt-3.5-turbo", |
64 | 58 | messages=[{"role": "user", "content": query}], |
65 | 59 | max_tokens=100, |
66 | 60 | ) |
67 | 61 | return response.choices[0].message.content |
68 | 62 |
|
69 | | - # Test the function |
70 | | - result = generate_response_programmatic("What is deep learning?") |
71 | | - print(f"Response: {result}") |
| 63 | + print(f"Response: {generate_response('What is deep learning?')}") |
| 64 | + |
| 65 | + |
| 66 | +def example_init_merges_on_repeat(): |
| 67 | + """init() is idempotent and merges — safe to call multiple times.""" |
| 68 | + print("\n=== init() Merge Semantics ===") |
| 69 | + |
| 70 | + init(api_key="key-A", inference_pipeline_id="pipeline-A") |
| 71 | + # Later in the program, override just one knob — the rest is preserved. |
| 72 | + init(inference_pipeline_id="pipeline-B") |
| 73 | + |
| 74 | + cfg = get_tracer_config() # API key is redacted in the returned dict |
| 75 | + print(f"Resolved config: api_key={cfg['api_key']}, pipeline_id={cfg['inference_pipeline_id']}") |
| 76 | + # api_key=***, pipeline_id=pipeline-B |
72 | 77 |
|
73 | 78 |
|
74 | 79 | def example_per_decorator_override(): |
75 | | - """Example showing how to override pipeline ID per decorator.""" |
76 | | - print("\n=== Per-Decorator Pipeline ID Override ===") |
| 80 | + """The @trace decorator can override the configured pipeline per-call.""" |
| 81 | + print("\n=== Per-Decorator Override ===") |
77 | 82 |
|
78 | | - # Configure default settings |
79 | | - configure( |
80 | | - api_key="your_openlayer_api_key_here", |
81 | | - inference_pipeline_id="default_pipeline_id", |
82 | | - ) |
| 83 | + init(api_key="your_openlayer_api_key_here", inference_pipeline_id="default_pipeline_id") |
83 | 84 |
|
84 | | - # Function using default pipeline ID |
85 | 85 | @trace() |
86 | 86 | def default_pipeline_function(query: str) -> str: |
87 | 87 | return f"Response to: {query}" |
88 | 88 |
|
89 | | - # Function using specific pipeline ID (overrides default) |
90 | 89 | @trace(inference_pipeline_id="specific_pipeline_id") |
91 | 90 | def specific_pipeline_function(query: str) -> str: |
92 | 91 | return f"Specific response to: {query}" |
93 | 92 |
|
94 | | - # Test both functions |
95 | | - default_pipeline_function("Question 1") # Uses default_pipeline_id |
96 | | - specific_pipeline_function("Question 2") # Uses specific_pipeline_id |
| 93 | + default_pipeline_function("Question 1") # default_pipeline_id |
| 94 | + specific_pipeline_function("Question 2") # specific_pipeline_id |
97 | 95 |
|
98 | | - print("Both functions executed with different pipeline IDs") |
99 | 96 |
|
| 97 | +def example_mixed_env_and_init(): |
| 98 | + """Env var for API key, init() for pipeline — both honored via resolver.""" |
| 99 | + print("\n=== Mixed (Env Var + init()) ===") |
100 | 100 |
|
101 | | -def example_mixed_configuration(): |
102 | | - """Example showing mixed environment and programmatic configuration.""" |
103 | | - print("\n=== Mixed Configuration Approach ===") |
104 | | - |
105 | | - # Set API key via environment variable |
106 | 101 | os.environ["OPENLAYER_API_KEY"] = "your_openlayer_api_key_here" |
107 | | - |
108 | | - # Set pipeline ID programmatically |
109 | | - configure(inference_pipeline_id="programmatic_pipeline_id") |
| 102 | + init(inference_pipeline_id="programmatic_pipeline_id") |
110 | 103 |
|
111 | 104 | @trace() |
112 | 105 | def mixed_config_function(query: str) -> str: |
113 | | - """Function using mixed configuration.""" |
114 | 106 | return f"Mixed config response to: {query}" |
115 | 107 |
|
116 | | - # Test the function |
117 | | - result = mixed_config_function("What is the best approach?") |
118 | | - print(f"Response: {result}") |
| 108 | + print(f"Response: {mixed_config_function('What is the best approach?')}") |
| 109 | + |
| 110 | + |
| 111 | +def example_deprecated_configure(): |
| 112 | + """configure() is kept for backward compatibility but is deprecated. |
| 113 | +
|
| 114 | + It now merges (rather than replacing) state and emits a DeprecationWarning |
| 115 | + on each call. New code should use init() instead. |
| 116 | + """ |
| 117 | + print("\n=== Deprecated configure() (still works) ===") |
| 118 | + |
| 119 | + configure( |
| 120 | + api_key="your_openlayer_api_key_here", |
| 121 | + inference_pipeline_id="your_pipeline_id_here", |
| 122 | + ) |
119 | 123 |
|
120 | 124 |
|
121 | 125 | if __name__ == "__main__": |
122 | 126 | print("Openlayer Tracing Configuration Examples") |
123 | 127 | print("=" * 50) |
124 | | - |
125 | | - # Note: Replace the placeholder API keys and IDs with real values |
126 | | - print( |
127 | | - "Note: Replace placeholder API keys and pipeline IDs with real values before running." |
128 | | - ) |
129 | | - print() |
| 128 | + print("Note: Replace placeholder API keys and pipeline IDs with real values.\n") |
130 | 129 |
|
131 | 130 | try: |
132 | | - # Run examples (these will fail without real API keys) |
133 | 131 | example_environment_variables() |
134 | | - example_programmatic_configuration() |
| 132 | + example_programmatic_init() |
| 133 | + example_init_merges_on_repeat() |
135 | 134 | example_per_decorator_override() |
136 | | - example_mixed_configuration() |
137 | | - |
| 135 | + example_mixed_env_and_init() |
| 136 | + example_deprecated_configure() |
138 | 137 | except Exception as e: |
139 | 138 | print(f"Example failed (expected with placeholder keys): {e}") |
140 | 139 | print("\nTo run this example successfully:") |
141 | 140 | print("1. Replace placeholder API keys with real values") |
142 | 141 | print("2. Replace pipeline IDs with real Openlayer pipeline IDs") |
143 | | - print("3. Ensure you have valid OpenAI and Openlayer accounts") |
0 commit comments