From cff8c8c0cf3ee9f23552fd5456c629c618505e7a Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 14 May 2026 08:49:50 -0500 Subject: [PATCH 1/3] fix: Modernize server-ai package and provider READMEs to current SDK - packages/sdk/server-ai/README.md, packages/ai-providers/server-ai-openai/README.md, packages/ai-providers/server-ai-langchain/README.md - Replace nonexistent `from ldai import init` / `init(ld_client)` with `from ldai import LDAIClient` / `LDAIClient(ld_client)` in both provider READMEs - Update server-ai README: model.invoke() -> model.run() and .message.content -> .content; remove nonexistent model.get_messages(); replace nonexistent LangChainProvider class with create_langchain_model + bare get_ai_metrics_from_response; swap track_metrics_of / track_metrics_of_async arg order to (extractor, callable); canonicalize from ldai.providers.types -> from ldai.providers + from ldai.tracker - Fix LangChain README: align manual-runner example to import LangChainModelRunner that it actually uses - Fix `result.metrics.tokens` -> `result.metrics.usage` in both provider READMEs (Python LDAIMetricSummary uses .usage; the input LDAIMetrics dataclass uses .tokens - asymmetric) Refs AIC-2383 Co-Authored-By: Claude Opus 4.7 (1M context) --- .../server-ai-langchain/README.md | 10 ++++---- .../ai-providers/server-ai-openai/README.md | 6 ++--- packages/sdk/server-ai/README.md | 24 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/ai-providers/server-ai-langchain/README.md b/packages/ai-providers/server-ai-langchain/README.md index da52fa37..f1bc8f50 100644 --- a/packages/ai-providers/server-ai-langchain/README.md +++ b/packages/ai-providers/server-ai-langchain/README.md @@ -37,12 +37,12 @@ pip install langchain-google-genai ```python import asyncio from ldclient import LDClient, Config, Context -from ldai import init +from ldai import LDAIClient from ldai.models import AICompletionConfigDefault, ModelConfig, ProviderConfig # Initialize LaunchDarkly client ld_client = LDClient(Config("your-sdk-key")) -ai_client = init(ld_client) +ai_client = LDAIClient(ld_client) context = Context.builder("user-123").build() @@ -84,11 +84,11 @@ if model: ### Using the runner directly If you need to construct a runner manually (e.g. for testing), you can use -`LangChainRunnerFactory` from the `ldai_langchain` package: +`LangChainModelRunner` from the `ldai_langchain` package: ```python from langchain_openai import ChatOpenAI -from ldai_langchain import LangChainRunnerFactory +from ldai_langchain import LangChainModelRunner llm = ChatOpenAI(model="gpt-4", temperature=0.7) runner = LangChainModelRunner(llm) @@ -126,7 +126,7 @@ model = await ai_client.create_model("ai-config-key", context) if model: result = await model.run("Explain feature flags.") # Metrics are tracked automatically; access them via result.metrics - print(result.metrics.tokens) + print(result.metrics.usage) ``` ### Static Utility Methods diff --git a/packages/ai-providers/server-ai-openai/README.md b/packages/ai-providers/server-ai-openai/README.md index 18a6a57a..c555ae09 100644 --- a/packages/ai-providers/server-ai-openai/README.md +++ b/packages/ai-providers/server-ai-openai/README.md @@ -24,12 +24,12 @@ pip install launchdarkly-server-sdk-ai-openai ```python import asyncio from ldclient import LDClient, Config, Context -from ldai import init +from ldai import LDAIClient from ldai.models import AICompletionConfigDefault, ModelConfig, ProviderConfig # Initialize LaunchDarkly client ld_client = LDClient(Config("your-sdk-key")) -ai_client = init(ld_client) +ai_client = LDAIClient(ld_client) context = Context.builder("user-123").build() @@ -112,7 +112,7 @@ model = await ai_client.create_model("ai-config-key", context) if model: result = await model.run("Explain feature flags.") # Metrics are tracked automatically; access them via result.metrics - print(result.metrics.tokens) + print(result.metrics.usage) ``` ### Static Utility Methods diff --git a/packages/sdk/server-ai/README.md b/packages/sdk/server-ai/README.md index 38eb89e9..b49ba0e2 100644 --- a/packages/sdk/server-ai/README.md +++ b/packages/sdk/server-ai/README.md @@ -123,15 +123,15 @@ async def main(): ) if model: - # Simple conversation flow - metrics are automatically tracked by invoke() - response1 = await model.invoke('I need help with my order') - print(response1.message.content) + # Simple conversation flow - metrics are automatically tracked by run() + response1 = await model.run('I need help with my order') + print(response1.content) - response2 = await model.invoke("What's the status?") - print(response2.message.content) + response2 = await model.run("What's the status?") + print(response2.content) # Access conversation history - messages = model.get_messages() + messages = model.get_config().messages print(f'Conversation has {len(messages)} messages') asyncio.run(main()) @@ -146,21 +146,20 @@ For more control, you can use the configuration directly with AI providers. We r ```python import asyncio from ldai import LDAIClient, AICompletionConfigDefault, ModelConfig -from ldai.providers.types import LDAIMetrics, TokenUsage -from ldai_langchain import LangChainProvider +from ldai_langchain import create_langchain_model, get_ai_metrics_from_response async def main(): ai_config = ai_client.completion_config(ai_config_key, context, default) # Create LangChain model from configuration - llm = await LangChainProvider.create_langchain_model(ai_config) + llm = create_langchain_model(ai_config) # Use with tracking (sync invoke). Mint a tracker once per AI run. tracker = ai_config.create_tracker() response = tracker.track_metrics_of( + get_ai_metrics_from_response, lambda: llm.invoke(messages), - lambda result: LangChainProvider.get_ai_metrics_from_response(result) ) print('AI Response:', response.content) @@ -173,7 +172,8 @@ asyncio.run(main()) ```python import asyncio from ldai import LDAIClient, AICompletionConfigDefault, ModelConfig -from ldai.providers.types import LDAIMetrics, TokenUsage +from ldai.providers import LDAIMetrics +from ldai.tracker import TokenUsage async def main(): ai_config = ai_client.completion_config(ai_config_key, context, default) @@ -200,8 +200,8 @@ async def main(): # Mint a tracker once per AI run. tracker = ai_config.create_tracker() result = await tracker.track_metrics_of_async( + map_custom_provider_metrics, call_custom_provider, - map_custom_provider_metrics ) print('AI Response:', result.content) From d62ee1d34722adffe4457eccf2d90f60b178e9da Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 14 May 2026 11:03:58 -0500 Subject: [PATCH 2/3] fix: Restore result.metrics.tokens in provider README quick-start examples MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LDAIMetricSummary's token field is `tokens`, not `usage` (verified at packages/sdk/server-ai/src/ldai/tracker.py — the `@property def tokens` on LDAIMetricSummary). The earlier change to `.usage` was a regression based on an unverified asymmetry claim; reverting. Refs AIC-2383 Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/ai-providers/server-ai-langchain/README.md | 2 +- packages/ai-providers/server-ai-openai/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ai-providers/server-ai-langchain/README.md b/packages/ai-providers/server-ai-langchain/README.md index f1bc8f50..aaecf39c 100644 --- a/packages/ai-providers/server-ai-langchain/README.md +++ b/packages/ai-providers/server-ai-langchain/README.md @@ -126,7 +126,7 @@ model = await ai_client.create_model("ai-config-key", context) if model: result = await model.run("Explain feature flags.") # Metrics are tracked automatically; access them via result.metrics - print(result.metrics.usage) + print(result.metrics.tokens) ``` ### Static Utility Methods diff --git a/packages/ai-providers/server-ai-openai/README.md b/packages/ai-providers/server-ai-openai/README.md index c555ae09..7a877d1a 100644 --- a/packages/ai-providers/server-ai-openai/README.md +++ b/packages/ai-providers/server-ai-openai/README.md @@ -112,7 +112,7 @@ model = await ai_client.create_model("ai-config-key", context) if model: result = await model.run("Explain feature flags.") # Metrics are tracked automatically; access them via result.metrics - print(result.metrics.usage) + print(result.metrics.tokens) ``` ### Static Utility Methods From cc7dc8a0f1b34541c3026b008142bfb911cb8abd Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 14 May 2026 11:16:43 -0500 Subject: [PATCH 3/3] fix: Drop misleading "conversation history" example from server-ai README `ManagedModel.get_config().messages` returns the configured/templated system messages from the AI Config, not the conversation history the model accumulated across run() calls. Drop the block rather than imply otherwise. Refs AIC-2383 Co-Authored-By: Claude Opus 4.7 (1M context) --- packages/sdk/server-ai/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/sdk/server-ai/README.md b/packages/sdk/server-ai/README.md index b49ba0e2..3ee83e5f 100644 --- a/packages/sdk/server-ai/README.md +++ b/packages/sdk/server-ai/README.md @@ -129,10 +129,6 @@ async def main(): response2 = await model.run("What's the status?") print(response2.content) - - # Access conversation history - messages = model.get_config().messages - print(f'Conversation has {len(messages)} messages') asyncio.run(main()) ```