Skip to content

Commit 1fa3d6a

Browse files
jsonbaileyclaude
andcommitted
docs: update OpenAI provider README to new Runner protocol API
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 078b3bc commit 1fa3d6a

1 file changed

Lines changed: 156 additions & 38 deletions

File tree

  • packages/ai-providers/server-ai-openai

packages/ai-providers/server-ai-openai/README.md

Lines changed: 156 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -23,64 +23,182 @@ pip install launchdarkly-server-sdk-ai-openai
2323

2424
```python
2525
import asyncio
26-
from ldai import AIClient
27-
from ldai_openai import OpenAIProvider
26+
from ldclient import LDClient, Config, Context
27+
from ldai import init
28+
from ldai.models import AICompletionConfigDefault, ModelConfig, ProviderConfig
29+
30+
# Initialize LaunchDarkly client
31+
ld_client = LDClient(Config("your-sdk-key"))
32+
ai_client = init(ld_client)
33+
34+
context = Context.builder("user-123").build()
2835

2936
async def main():
30-
# Initialize the AI client
31-
ai_client = AIClient(ld_client)
32-
33-
# Get AI config. Pass a default for improved resiliency when the flag is unavailable or
34-
# LaunchDarkly is unreachable; omit for a disabled default. Example:
35-
# from ldai.models import AICompletionConfigDefault, LDMessage, ModelConfig, ProviderConfig
36-
# default = AICompletionConfigDefault(
37-
# enabled=True,
38-
# model=ModelConfig("gpt-4"),
39-
# provider=ProviderConfig("openai"),
40-
# messages=[LDMessage(role="system", content="You are a helpful assistant.")]
41-
# )
42-
# ai_config = ai_client.config("my-ai-config-key", context, default)
43-
ai_config = ai_client.config("my-ai-config-key", context)
44-
45-
# Create an OpenAI provider from the config
46-
provider = await OpenAIProvider.create(ai_config)
47-
48-
# Invoke the model
49-
response = await provider.invoke_model(ai_config.messages)
50-
print(response.message.content)
37+
# Create a ManagedModel backed by the OpenAI provider
38+
model = await ai_client.create_model(
39+
"ai-config-key",
40+
context,
41+
AICompletionConfigDefault(
42+
enabled=True,
43+
model=ModelConfig("gpt-4"),
44+
provider=ProviderConfig("openai"),
45+
),
46+
)
47+
48+
if model:
49+
result = await model.run("Hello, how are you?")
50+
print(result.content)
5151

5252
asyncio.run(main())
5353
```
5454

55-
## Features
55+
## Usage
56+
57+
### Using `create_model` (recommended)
58+
59+
The recommended entry point is `LDAIClient.create_model`, which evaluates a
60+
LaunchDarkly AI config flag, selects the OpenAI runner automatically, and
61+
returns a `ManagedModel` that wraps the runner:
62+
63+
```python
64+
model = await ai_client.create_model("ai-config-key", context)
65+
66+
if model:
67+
result = await model.run("What is feature flagging?")
68+
print(result.content)
69+
```
70+
71+
### Using the runner directly
72+
73+
If you need to construct a runner manually (e.g. for testing), you can use
74+
`OpenAIRunnerFactory` from the `ldai_openai` package:
75+
76+
```python
77+
from ldai_openai import OpenAIRunnerFactory
78+
79+
factory = OpenAIRunnerFactory() # uses OPENAI_API_KEY from environment
80+
runner = factory.create_model(ai_config)
81+
82+
result = await runner.run("Hello!")
83+
print(result.content)
84+
```
85+
86+
### Structured Output
87+
88+
Pass a JSON schema dict as `output_type` to request structured output:
89+
90+
```python
91+
response_structure = {
92+
"type": "object",
93+
"properties": {
94+
"sentiment": {"type": "string", "enum": ["positive", "negative", "neutral"]},
95+
"confidence": {"type": "number"},
96+
},
97+
"required": ["sentiment", "confidence"],
98+
}
99+
100+
result = await runner.run(messages, output_type=response_structure)
101+
print(result.parsed) # {"sentiment": "positive", "confidence": 0.95}
102+
```
103+
104+
### Tracking Metrics
105+
106+
`ManagedModel.run()` automatically tracks metrics via the associated
107+
`LDAIConfigTracker`. For manual tracking, use the tracker directly:
108+
109+
```python
110+
model = await ai_client.create_model("ai-config-key", context)
111+
112+
if model:
113+
result = await model.run("Explain feature flags.")
114+
# Metrics are tracked automatically; access them via result.metrics
115+
print(result.metrics.usage)
116+
```
117+
118+
### Static Utility Methods
119+
120+
The `ldai_openai` helper module provides several utility functions:
121+
122+
#### Converting Messages
123+
124+
```python
125+
from ldai.models import LDMessage
126+
from ldai_openai import convert_messages_to_openai
127+
128+
messages = [
129+
LDMessage(role="system", content="You are helpful."),
130+
LDMessage(role="user", content="Hello!"),
131+
]
132+
133+
openai_messages = convert_messages_to_openai(messages)
134+
```
135+
136+
#### Extracting Metrics
56137

57-
- Full integration with OpenAI's chat completions API
58-
- Automatic token usage tracking
59-
- Support for structured output (JSON schema)
60-
- Static utility methods for custom integrations
138+
```python
139+
from ldai_openai import get_ai_metrics_from_response
140+
141+
# After getting a response from OpenAI
142+
metrics = get_ai_metrics_from_response(response)
143+
print(f"Success: {metrics.success}")
144+
print(f"Tokens used: {metrics.usage.total if metrics.usage else 'N/A'}")
145+
```
61146

62147
## API Reference
63148

64-
### OpenAIProvider
149+
### OpenAIRunnerFactory
150+
151+
`OpenAIRunnerFactory` is an `AIProvider` that creates runners from LaunchDarkly AI configs.
65152

66153
#### Constructor
67154

68155
```python
69-
OpenAIProvider(client: OpenAI, model_name: str, parameters: Dict[str, Any], logger: Optional[Any] = None)
156+
OpenAIRunnerFactory(client: Optional[AsyncOpenAI] = None)
70157
```
71158

72-
#### Static Methods
159+
If `client` is omitted, an `AsyncOpenAI` client is created using `OPENAI_API_KEY` from the environment.
73160

74-
- `create(ai_config: AIConfigKind, logger: Optional[Any] = None) -> OpenAIProvider` - Factory method to create a provider from an AI config
75-
- `get_ai_metrics_from_response(response: Any) -> LDAIMetrics` - Extract metrics from an OpenAI response
161+
#### Methods
76162

77-
#### Instance Methods
163+
- `create_model(config) -> OpenAIModelRunner` — Create a runner for chat completions from an AI config.
164+
- `create_agent(config, tools=None) -> OpenAIAgentRunner` — Create a runner for an OpenAI agent (experimental).
165+
- `get_client() -> AsyncOpenAI` — Return the underlying `AsyncOpenAI` client.
78166

79-
- `invoke_model(messages: List[LDMessage]) -> ChatResponse` - Invoke the model with messages
80-
- `invoke_structured_model(messages: List[LDMessage], response_structure: Dict[str, Any]) -> StructuredResponse` - Invoke the model with structured output
81-
- `get_client() -> OpenAI` - Get the underlying OpenAI client
167+
### OpenAIModelRunner
168+
169+
`OpenAIModelRunner` implements the `Runner` protocol for OpenAI chat completions.
170+
171+
#### Constructor
172+
173+
```python
174+
OpenAIModelRunner(client: AsyncOpenAI, model_name: str, parameters: Dict[str, Any])
175+
```
176+
177+
#### Methods
178+
179+
- `run(input, output_type=None) -> RunnerResult` — Run the model with a string prompt or list of `LDMessage` objects. Pass `output_type` (JSON schema dict) for structured output.
180+
181+
### OpenAIAgentRunner
182+
183+
> [!CAUTION]
184+
> This feature is experimental and should NOT be considered ready for production use.
185+
> It may change or be removed without notice.
186+
187+
`OpenAIAgentRunner` implements the `Runner` protocol using the OpenAI Agents SDK
188+
(`openai-agents`). Requires `pip install openai-agents`.
189+
190+
#### Methods
191+
192+
- `run(input, output_type=None) -> RunnerResult` — Run the agent with the given input. The tool-calling loop is handled internally. Returns `RunnerResult` with `content`, `metrics` (including `tool_calls`), and `raw`.
193+
194+
## Documentation
195+
196+
For full documentation, please refer to the [LaunchDarkly AI SDK documentation](https://docs.launchdarkly.com/sdk/ai/python).
197+
198+
## Contributing
199+
200+
See [CONTRIBUTING.md](../../../CONTRIBUTING.md) in the repository root.
82201

83202
## License
84203

85204
Apache-2.0
86-

0 commit comments

Comments
 (0)