From 3de980ff010e77fd4407dc1350c4e7f55b3fce94 Mon Sep 17 00:00:00 2001 From: jsonbailey Date: Thu, 7 May 2026 16:34:37 -0500 Subject: [PATCH] feat: Reorganize examples for easier navigation --- .github/workflows/ci.yml | 2 +- README.md | 56 ++++---- examples/chat_observability/README.md | 50 ------- .../chat_observability_example.py | 128 ------------------ examples/judge/README.md | 55 -------- features/judge/README.md | 36 +++++ .../judge/judge_example.py | 7 +- {examples => features}/judge/pyproject.toml | 9 +- .../managed_agent/README.md | 0 .../managed_agent/managed_agent_example.py | 7 +- .../managed_agent/pyproject.toml | 1 + .../managed_agent_graph/README.md | 0 .../managed_agent_graph_example.py | 7 +- .../managed_agent_graph/pyproject.toml | 1 + features/managed_model/README.md | 36 +++++ .../managed_model/managed_model_example.py | 7 +- .../managed_model}/pyproject.toml | 11 +- .../agent_config}/langgraph_agent/README.md | 0 .../langgraph_agent_example.py | 7 +- .../langgraph_agent/pyproject.toml | 1 + .../langgraph_multi_agent/README.md | 0 .../langgraph_multi_agent_example.py | 7 +- .../langgraph_multi_agent/pyproject.toml | 1 + .../completion_config}/bedrock/README.md | 0 .../bedrock/bedrock_example.py | 7 +- .../completion_config}/bedrock/pyproject.toml | 1 + .../completion_config}/gemini/README.md | 0 .../gemini/gemini_example.py | 7 +- .../completion_config}/gemini/pyproject.toml | 1 + .../completion_config}/langchain/README.md | 0 .../langchain/langchain_example.py | 7 +- .../langchain/pyproject.toml | 1 + .../completion_config}/openai/README.md | 0 .../openai/openai_example.py | 7 +- .../completion_config}/openai/pyproject.toml | 1 + 35 files changed, 177 insertions(+), 284 deletions(-) delete mode 100644 examples/chat_observability/README.md delete mode 100644 examples/chat_observability/chat_observability_example.py delete mode 100644 examples/judge/README.md create mode 100644 features/judge/README.md rename examples/judge/direct_judge_example.py => features/judge/judge_example.py (94%) rename {examples => features}/judge/pyproject.toml (76%) rename {examples => features}/managed_agent/README.md (100%) rename {examples => features}/managed_agent/managed_agent_example.py (94%) rename {examples => features}/managed_agent/pyproject.toml (94%) rename {examples => features}/managed_agent_graph/README.md (100%) rename {examples => features}/managed_agent_graph/managed_agent_graph_example.py (95%) rename {examples => features}/managed_agent_graph/pyproject.toml (95%) create mode 100644 features/managed_model/README.md rename examples/judge/chat_judge_example.py => features/managed_model/managed_model_example.py (93%) rename {examples/chat_observability => features/managed_model}/pyproject.toml (65%) rename {examples => getting_started/agent_config}/langgraph_agent/README.md (100%) rename {examples => getting_started/agent_config}/langgraph_agent/langgraph_agent_example.py (94%) rename {examples => getting_started/agent_config}/langgraph_agent/pyproject.toml (95%) rename {examples => getting_started/agent_config}/langgraph_multi_agent/README.md (100%) rename {examples => getting_started/agent_config}/langgraph_multi_agent/langgraph_multi_agent_example.py (97%) rename {examples => getting_started/agent_config}/langgraph_multi_agent/pyproject.toml (95%) rename {examples => getting_started/completion_config}/bedrock/README.md (100%) rename {examples => getting_started/completion_config}/bedrock/bedrock_example.py (95%) rename {examples => getting_started/completion_config}/bedrock/pyproject.toml (93%) rename {examples => getting_started/completion_config}/gemini/README.md (100%) rename {examples => getting_started/completion_config}/gemini/gemini_example.py (96%) rename {examples => getting_started/completion_config}/gemini/pyproject.toml (93%) rename {examples => getting_started/completion_config}/langchain/README.md (100%) rename {examples => getting_started/completion_config}/langchain/langchain_example.py (94%) rename {examples => getting_started/completion_config}/langchain/pyproject.toml (94%) rename {examples => getting_started/completion_config}/openai/README.md (100%) rename {examples => getting_started/completion_config}/openai/openai_example.py (93%) rename {examples => getting_started/completion_config}/openai/pyproject.toml (93%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 45b57a3..2e9f612 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: - name: Install dependencies run: | - for dir in examples/*/; do + for dir in getting_started/completion_config/*/ getting_started/agent_config/*/ features/*/; do echo "Installing $dir" poetry -C "$dir" install done diff --git a/README.md b/README.md index ea1d587..9e36997 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,36 @@ -# LaunchDarkly sample Python application +# LaunchDarkly AI SDK for Python - Examples -We've built a simple console application that demonstrates how LaunchDarkly's SDK works. - -Below, you'll find the build procedure. For more comprehensive instructions, you can visit your [Quickstart page](https://docs.launchdarkly.com/home/ai-configs/quickstart) or the [Python reference guide](https://docs.launchdarkly.com/sdk/ai/python). - -This demo requires Python 3.10 or higher. - -## Build Instructions - -This repository includes examples for `OpenAI`, `Bedrock`, `Gemini`, `LangChain`, `LangGraph`, `Judge`, and `Observability`. Depending on your preferred provider, you may have to take some additional steps. +| Package | PyPI | Docs | +| --- | --- | --- | +| [launchdarkly-server-sdk-ai](https://github.com/launchdarkly/python-server-sdk-ai/tree/main/packages/sdk/server-ai) | [![PyPI](https://img.shields.io/pypi/v/launchdarkly-server-sdk-ai)](https://pypi.org/project/launchdarkly-server-sdk-ai/) | [Reference](https://docs.launchdarkly.com/sdk/ai/python) | +| [launchdarkly-server-sdk-ai-openai](https://github.com/launchdarkly/python-server-sdk-ai/tree/main/packages/ai-providers/server-ai-openai) | [![PyPI](https://img.shields.io/pypi/v/launchdarkly-server-sdk-ai-openai)](https://pypi.org/project/launchdarkly-server-sdk-ai-openai/) | [Reference](https://docs.launchdarkly.com/sdk/ai/python) | +| [launchdarkly-server-sdk-ai-langchain](https://github.com/launchdarkly/python-server-sdk-ai/tree/main/packages/ai-providers/server-ai-langchain) | [![PyPI](https://img.shields.io/pypi/v/launchdarkly-server-sdk-ai-langchain)](https://pypi.org/project/launchdarkly-server-sdk-ai-langchain/) | [Reference](https://docs.launchdarkly.com/sdk/ai/python) | +| [launchdarkly-observability](https://github.com/launchdarkly/observability-sdk/tree/main/sdk/%40launchdarkly/observability-python) | [![PyPI](https://img.shields.io/pypi/v/launchdarkly-observability)](https://pypi.org/project/launchdarkly-observability/) | [Reference](https://docs.launchdarkly.com/sdk/observability/python) | -### General setup +Each example is a self-contained application you can run independently to explore LaunchDarkly's AI APIs hands-on. Pick one that matches your provider or use case, follow the README, and you'll be up and running in minutes. -1. [Create an AI Config](https://launchdarkly.com/docs/home/ai-configs/create) using the key specified in each example, or copy the key of existing AI Config in your LaunchDarkly project that you want to evaluate. +For more comprehensive instructions, visit the [Quickstart page](https://docs.launchdarkly.com/home/ai-configs/quickstart) or the [Python reference guide](https://docs.launchdarkly.com/sdk/ai/python). -1. Ensure you have [Poetry](https://python-poetry.org/) installed. +## Getting Started -1. Create a `.env` file in the repository root with at least your LaunchDarkly SDK key: +These examples show how to integrate LaunchDarkly AI with different providers using `completion_config` and `agent_config`. - ``` - LAUNCHDARKLY_SDK_KEY=your-launchdarkly-sdk-key - ``` +| Example | Description | +| --- | --- | +| [Bedrock](getting_started/completion_config/bedrock/) | `completion_config` with AWS Bedrock, metrics tracking | +| [Gemini](getting_started/completion_config/gemini/) | `completion_config` with Google Gemini, metrics tracking | +| [LangChain](getting_started/completion_config/langchain/) | `completion_config` with LangChain, async metrics tracking | +| [LangGraph Agent](getting_started/agent_config/langgraph_agent/) | `agent_config` with a single LangGraph ReAct agent, tool calling, metrics tracking | +| [LangGraph Multi-Agent](getting_started/agent_config/langgraph_multi_agent/) | `agent_config` with multiple LangGraph agents, custom StateGraph workflow, per-node metrics | +| [OpenAI](getting_started/completion_config/openai/) | `completion_config` with OpenAI, automatic metrics tracking | - Each example README describes the full set of environment variables needed. The `.env` file is loaded automatically when running any example. +## Features -### Examples +These examples demonstrate LaunchDarkly's managed APIs and standalone capabilities. -| Example | Description | README | -| --- | --- | --- | -| **OpenAI** | Single provider using OpenAI | [examples/openai](examples/openai/README.md) | -| **Bedrock** | Single provider using AWS Bedrock | [examples/bedrock](examples/bedrock/README.md) | -| **Gemini** | Single provider using Google Gemini | [examples/gemini](examples/gemini/README.md) | -| **LangChain** | Multiple providers via LangChain | [examples/langchain](examples/langchain/README.md) | -| **LangGraph Agent** | Single agent using LangGraph | [examples/langgraph_agent](examples/langgraph_agent/README.md) | -| **LangGraph Multi-Agent** | Multiple agents using LangGraph | [examples/langgraph_multi_agent](examples/langgraph_multi_agent/README.md) | -| **Judge** | Judge evaluation of AI responses | [examples/judge](examples/judge/README.md) | -| **Chat with Observability** | Observability plugin for AI chat monitoring | [examples/chat_observability](examples/chat_observability/README.md) | +| Example | Description | +| --- | --- | +| [Judge](features/judge/) | `create_judge` for standalone evaluation of AI responses | +| [Managed Agent](features/managed_agent/) | `create_agent` with tool calling, automatic metrics tracking, and judge evaluation | +| [Managed Agent Graph](features/managed_agent_graph/) | `create_agent_graph` with multi-node workflows, tool calling, per-node metrics, and judge evaluation | +| [Managed Model](features/managed_model/) | `create_model` with managed chat, automatic metrics tracking, and judge evaluation | diff --git a/examples/chat_observability/README.md b/examples/chat_observability/README.md deleted file mode 100644 index 452d9d1..0000000 --- a/examples/chat_observability/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# Chat with Observability (Observability Plugin Example) - -This example demonstrates how to use the LaunchDarkly observability SDK plugin to monitor AI chat operations. For more details, see the [Python SDK observability reference](https://launchdarkly.com/docs/sdk/observability/python). - -The observability plugin automatically captures and sends data to LaunchDarkly: - -- **Observability tab**: SDK operations, flag evaluations, error monitoring, logging, and distributed tracing -- **AI Config Monitoring tab**: Token usage, duration, success/error rates, and custom metadata for filtering and analysis - -View your data in the LaunchDarkly dashboard under **Observability** tabs. - -## Prerequisites - -- Python 3.10 or higher -- [Poetry](https://python-poetry.org/) installed -- A [LaunchDarkly](https://launchdarkly.com/) account and SDK key -- An API key for your AI provider (e.g., OpenAI) - -## Setup - -1. Create the following config in your LaunchDarkly project. You can use a different key by setting the environment variable in your `.env`. - - - [Create an AI Config](https://launchdarkly.com/docs/home/ai-configs/create) with a model and a system message. Default key: `sample-completion-config`. - -1. Create a `.env` file in this directory with the following variables: - - ``` - LAUNCHDARKLY_SDK_KEY=your-launchdarkly-sdk-key - LAUNCHDARKLY_AI_CONFIG_KEY=sample-completion-config - OPENAI_API_KEY=your-openai-api-key - ``` - - Optionally, set service identification: - - ``` - SERVICE_NAME=my-ai-service - SERVICE_VERSION=1.0.0 - ``` - -1. Install the required dependencies: - - ```bash - poetry install - ``` - -## Run - -```bash -poetry run chat -``` diff --git a/examples/chat_observability/chat_observability_example.py b/examples/chat_observability/chat_observability_example.py deleted file mode 100644 index 66efe00..0000000 --- a/examples/chat_observability/chat_observability_example.py +++ /dev/null @@ -1,128 +0,0 @@ -import os -import logging -from dotenv import load_dotenv -import asyncio -import ldclient -from ldclient import Context -from ldclient.config import Config -from ldai import LDAIClient, AICompletionConfigDefault -from ldobserve import ObservabilityConfig, ObservabilityPlugin - -load_dotenv() - -logging.basicConfig() -logging.getLogger('ldclient').setLevel(logging.WARNING) -logging.getLogger('httpx').setLevel(logging.WARNING) - -# Set sdk_key to your LaunchDarkly SDK key. -sdk_key = os.getenv('LAUNCHDARKLY_SDK_KEY') - -# Set config_key to the AI Config key you want to evaluate. -ai_config_key = os.getenv('LAUNCHDARKLY_AI_CONFIG_KEY', 'sample-completion-config') - -# Service configuration for observability -service_name = os.getenv('SERVICE_NAME', 'hello-python-ai-observability') -service_version = os.getenv('SERVICE_VERSION', '1.0.0') - - -async def async_main(): - if not sdk_key: - print("*** Please set the LAUNCHDARKLY_SDK_KEY env first") - exit() - - - # Initialize LaunchDarkly SDK with observability plugin - ldclient.set_config(Config( - sdk_key, - plugins=[ - ObservabilityPlugin( - ObservabilityConfig( - service_name=service_name, - service_version=service_version, - ) - ) - ] - )) - - if not ldclient.get().is_initialized(): - print("\n*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") - exit() - - aiclient = LDAIClient(ldclient.get()) - print("*** SDK successfully initialized") - - # Set up the evaluation context with custom attributes for filtering - context = ( - Context - .builder('example-user-key') - .kind('user') - .name('Sandy') - .set('environment', 'observability-demo') - .set('tier', 'premium') - .build() - ) - - try: - # Pass a default for improved resiliency when the AI config is unavailable - # or LaunchDarkly is unreachable; omit for a disabled default. - # Example: - # default = AICompletionConfigDefault( - # enabled=True, - # model={'name': 'gpt-4'}, - # provider={'name': 'openai'}, - # messages=[{'role': 'system', 'content': 'You are a helpful assistant.'}], - # ) - # chat = await aiclient.create_model(ai_config_key, context, default, {'example_type': 'observability_demo'}) - chat = await aiclient.create_model( - ai_config_key, - context, - variables={ - 'example_type': 'observability_demo', - 'session_id': 'demo-session-123', - 'feature': 'ai_chat' - } - ) - - if not chat: - print(f"*** Failed to create chat for key: {ai_config_key}") - return - - sample_question_1 = "What is feature flagging in 2 sentences?" - print(f'\nSending sample question: "{sample_question_1}"') - print("Waiting for response...") - - response_1 = await chat.run(sample_question_1) - print(f"\nModel response:\n{response_1.content}") - - sample_question_2 = "Give me a specific use case example." - print(f'\nSending follow-up question: "{sample_question_2}"') - print("Waiting for response...") - - response_2 = await chat.run(sample_question_2) - print(f"\nModel response:\n{response_2.content}") - - # Judge evaluations run asynchronously. Await them so they - # complete before the process or request ends—even if you don't need to log or use - # the results. - if response_1.evaluations is not None: - await response_1.evaluations - if response_2.evaluations is not None: - await response_2.evaluations - - print("\nDone! The AI config was evaluated with observability enabled.") - - except Exception as err: - print("Error:", err) - finally: - # Flush pending events and close the client. - ldclient.get().flush() - ldclient.get().close() - - -def main(): - """Synchronous entry point for Poetry script.""" - asyncio.run(async_main()) - - -if __name__ == "__main__": - main() diff --git a/examples/judge/README.md b/examples/judge/README.md deleted file mode 100644 index 7041c9d..0000000 --- a/examples/judge/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# Judge Examples (Judge Evaluation) - -These examples demonstrate how to use LaunchDarkly's judge functionality to evaluate AI responses for accuracy, relevance, and other metrics. - -## Prerequisites - -- Python 3.10 or higher -- [Poetry](https://python-poetry.org/) installed -- A [LaunchDarkly](https://launchdarkly.com/) account and SDK key -- API keys for the provider you want to use (OpenAI, Bedrock, or Gemini) - -## Setup - -1. Create the following configs in your LaunchDarkly project. You can use different keys by setting the environment variables in your `.env`. - - - [Create an AI Config](https://launchdarkly.com/docs/home/ai-configs/create) with a model and system message. Default key: `sample-completion-config`. - - [Create a Judge Config](https://launchdarkly.com/docs/home/ai-configs/judges) for evaluation. Default key: `sample-ai-judge`. - -1. Create a `.env` file in this directory with the following variables: - - ``` - LAUNCHDARKLY_SDK_KEY=your-launchdarkly-sdk-key - LAUNCHDARKLY_AI_CONFIG_KEY=sample-completion-config - LAUNCHDARKLY_AI_JUDGE_KEY=sample-ai-judge - ``` - - Add the API key for your chosen provider: - - ``` - OPENAI_API_KEY=your-openai-api-key - ``` - -1. Install the required dependencies: - - ```bash - poetry install - ``` - -## Run - -### Chat with automatic judge evaluation - -Uses the chat functionality which automatically evaluates responses with any judges defined in the AI config. - -```bash -poetry run chat-judge -``` - -### Direct judge evaluation - -Evaluates specific input/output pairs using a judge configuration directly. - -```bash -poetry run direct-judge -``` diff --git a/features/judge/README.md b/features/judge/README.md new file mode 100644 index 0000000..f97539e --- /dev/null +++ b/features/judge/README.md @@ -0,0 +1,36 @@ +# Judge Example (Direct Evaluation) + +This example demonstrates how to use LaunchDarkly's judge functionality to evaluate specific input/output pairs directly, without an associated chat session. + +## Prerequisites + +- Python 3.10 or higher +- [Poetry](https://python-poetry.org/) installed +- A [LaunchDarkly](https://launchdarkly.com/) account and SDK key +- API keys for the provider you want to use (OpenAI, Bedrock, or Gemini) + +## Setup + +1. Create the following config in your LaunchDarkly project. You can use a different key by setting the environment variable in your `.env`. + + - [Create a Judge Config](https://launchdarkly.com/docs/home/ai-configs/judges) for evaluation. Default key: `sample-ai-judge`. + +1. Create a `.env` file in this directory with the following variables: + + ``` + LAUNCHDARKLY_SDK_KEY=your-launchdarkly-sdk-key + LAUNCHDARKLY_AI_JUDGE_KEY=sample-ai-judge + OPENAI_API_KEY=your-openai-api-key + ``` + +1. Install the required dependencies: + + ```bash + poetry install + ``` + +## Run + +```bash +poetry run judge +``` diff --git a/examples/judge/direct_judge_example.py b/features/judge/judge_example.py similarity index 94% rename from examples/judge/direct_judge_example.py rename to features/judge/judge_example.py index 6650d32..eda5e38 100644 --- a/examples/judge/direct_judge_example.py +++ b/features/judge/judge_example.py @@ -6,6 +6,7 @@ from ldclient import Context from ldclient.config import Config from ldai import LDAIClient, AIJudgeConfigDefault +from ldobserve import ObservabilityConfig, ObservabilityPlugin load_dotenv() @@ -24,7 +25,11 @@ async def async_main(): print("*** Please set the LAUNCHDARKLY_SDK_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-judge', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") diff --git a/examples/judge/pyproject.toml b/features/judge/pyproject.toml similarity index 76% rename from examples/judge/pyproject.toml rename to features/judge/pyproject.toml index c5b1818..7eb3f7c 100644 --- a/examples/judge/pyproject.toml +++ b/features/judge/pyproject.toml @@ -5,19 +5,16 @@ description = "Hello LaunchDarkly for Python AI - Judge" authors = ["LaunchDarkly "] license = "Apache-2.0" readme = "README.md" -packages = [ - {include = "chat_judge_example.py"}, - {include = "direct_judge_example.py"}, -] +packages = [{include = "judge_example.py"}] [tool.poetry.scripts] -chat-judge = "chat_judge_example:main" -direct-judge = "direct_judge_example:main" +judge = "judge_example:main" [tool.poetry.dependencies] python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-openai = ">=0.5.0" launchdarkly-server-sdk-ai-langchain = ">=0.6.0" openai = ">=1.0.0" diff --git a/examples/managed_agent/README.md b/features/managed_agent/README.md similarity index 100% rename from examples/managed_agent/README.md rename to features/managed_agent/README.md diff --git a/examples/managed_agent/managed_agent_example.py b/features/managed_agent/managed_agent_example.py similarity index 94% rename from examples/managed_agent/managed_agent_example.py rename to features/managed_agent/managed_agent_example.py index 5ac5b48..80d5a76 100644 --- a/examples/managed_agent/managed_agent_example.py +++ b/features/managed_agent/managed_agent_example.py @@ -6,6 +6,7 @@ from ldclient import Context from ldclient.config import Config from ldai import LDAIClient, AIAgentConfigDefault +from ldobserve import ObservabilityConfig, ObservabilityPlugin load_dotenv() @@ -29,7 +30,11 @@ async def async_main(): print("*** Please set the LAUNCHDARKLY_SDK_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-managed-agent', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") diff --git a/examples/managed_agent/pyproject.toml b/features/managed_agent/pyproject.toml similarity index 94% rename from examples/managed_agent/pyproject.toml rename to features/managed_agent/pyproject.toml index ddf727c..c235f4f 100644 --- a/examples/managed_agent/pyproject.toml +++ b/features/managed_agent/pyproject.toml @@ -14,6 +14,7 @@ agent = "managed_agent_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-openai = {version = ">=0.5.0", extras = ["agents"]} launchdarkly-server-sdk-ai-langchain = ">=0.6.0" openai = ">=1.0.0" diff --git a/examples/managed_agent_graph/README.md b/features/managed_agent_graph/README.md similarity index 100% rename from examples/managed_agent_graph/README.md rename to features/managed_agent_graph/README.md diff --git a/examples/managed_agent_graph/managed_agent_graph_example.py b/features/managed_agent_graph/managed_agent_graph_example.py similarity index 95% rename from examples/managed_agent_graph/managed_agent_graph_example.py rename to features/managed_agent_graph/managed_agent_graph_example.py index 8d09452..e62683d 100644 --- a/examples/managed_agent_graph/managed_agent_graph_example.py +++ b/features/managed_agent_graph/managed_agent_graph_example.py @@ -6,6 +6,7 @@ from ldclient import Context from ldclient.config import Config from ldai import LDAIClient +from ldobserve import ObservabilityConfig, ObservabilityPlugin load_dotenv() @@ -39,7 +40,11 @@ async def async_main(): print("*** Please set the LAUNCHDARKLY_SDK_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-managed-agent-graph', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") diff --git a/examples/managed_agent_graph/pyproject.toml b/features/managed_agent_graph/pyproject.toml similarity index 95% rename from examples/managed_agent_graph/pyproject.toml rename to features/managed_agent_graph/pyproject.toml index 8eaae37..01857d4 100644 --- a/examples/managed_agent_graph/pyproject.toml +++ b/features/managed_agent_graph/pyproject.toml @@ -14,6 +14,7 @@ agent-graph = "managed_agent_graph_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-openai = {version = ">=0.5.0", extras = ["agents"]} launchdarkly-server-sdk-ai-langchain = {version = ">=0.6.0", extras = ["graph"]} openai = ">=1.0.0" diff --git a/features/managed_model/README.md b/features/managed_model/README.md new file mode 100644 index 0000000..a176bbb --- /dev/null +++ b/features/managed_model/README.md @@ -0,0 +1,36 @@ +# Managed Model Example + +This example demonstrates how to use LaunchDarkly's managed model functionality (`create_model`), which handles model creation, chat execution, and optional judge evaluation dispatch automatically. + +## Prerequisites + +- Python 3.10 or higher +- [Poetry](https://python-poetry.org/) installed +- A [LaunchDarkly](https://launchdarkly.com/) account and SDK key +- API keys for the provider you want to use (OpenAI, Bedrock, or Gemini) + +## Setup + +1. Create the following config in your LaunchDarkly project. You can use a different key by setting the environment variable in your `.env`. + + - [Create an AI Config](https://launchdarkly.com/docs/home/ai-configs/create) with a model and system message. Default key: `sample-completion-config`. + +1. Create a `.env` file in this directory with the following variables: + + ``` + LAUNCHDARKLY_SDK_KEY=your-launchdarkly-sdk-key + LAUNCHDARKLY_AI_CONFIG_KEY=sample-completion-config + OPENAI_API_KEY=your-openai-api-key + ``` + +1. Install the required dependencies: + + ```bash + poetry install + ``` + +## Run + +```bash +poetry run managed-model +``` diff --git a/examples/judge/chat_judge_example.py b/features/managed_model/managed_model_example.py similarity index 93% rename from examples/judge/chat_judge_example.py rename to features/managed_model/managed_model_example.py index 0e4a26c..45b7fc5 100644 --- a/examples/judge/chat_judge_example.py +++ b/features/managed_model/managed_model_example.py @@ -6,6 +6,7 @@ from ldclient import Context from ldclient.config import Config from ldai import LDAIClient, AICompletionConfigDefault +from ldobserve import ObservabilityConfig, ObservabilityPlugin load_dotenv() @@ -24,7 +25,11 @@ async def async_main(): print("*** Please set the LAUNCHDARKLY_SDK_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-managed-model', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") diff --git a/examples/chat_observability/pyproject.toml b/features/managed_model/pyproject.toml similarity index 65% rename from examples/chat_observability/pyproject.toml rename to features/managed_model/pyproject.toml index 4dd142c..57ee050 100644 --- a/examples/chat_observability/pyproject.toml +++ b/features/managed_model/pyproject.toml @@ -1,14 +1,14 @@ [tool.poetry] -name = "hello-python-ai-chat-observability" +name = "hello-python-ai-managed-model" version = "0.1.0" -description = "Hello LaunchDarkly for Python AI - Chat with Observability" +description = "Hello LaunchDarkly for Python AI - Managed Model" authors = ["LaunchDarkly "] license = "Apache-2.0" readme = "README.md" -packages = [{include = "chat_observability_example.py"}] +packages = [{include = "managed_model_example.py"}] [tool.poetry.scripts] -chat = "chat_observability_example:main" +managed-model = "managed_model_example:main" [tool.poetry.dependencies] python = "^3.10" @@ -17,7 +17,8 @@ launchdarkly-server-sdk-ai = ">=0.19.0" launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-openai = ">=0.5.0" launchdarkly-server-sdk-ai-langchain = ">=0.6.0" -openai = ">=0.2.0" +openai = ">=1.0.0" +langchain-openai = "^1.0.0" [build-system] requires = ["poetry-core"] diff --git a/examples/langgraph_agent/README.md b/getting_started/agent_config/langgraph_agent/README.md similarity index 100% rename from examples/langgraph_agent/README.md rename to getting_started/agent_config/langgraph_agent/README.md diff --git a/examples/langgraph_agent/langgraph_agent_example.py b/getting_started/agent_config/langgraph_agent/langgraph_agent_example.py similarity index 94% rename from examples/langgraph_agent/langgraph_agent_example.py rename to getting_started/agent_config/langgraph_agent/langgraph_agent_example.py index e91e85a..024c17d 100644 --- a/examples/langgraph_agent/langgraph_agent_example.py +++ b/getting_started/agent_config/langgraph_agent/langgraph_agent_example.py @@ -7,6 +7,7 @@ from ldai import LDAIClient from ldai.providers import LDAIMetrics from ldai_langchain import sum_token_usage_from_messages +from ldobserve import ObservabilityConfig, ObservabilityPlugin from langchain.chat_models import init_chat_model from langgraph.prebuilt import create_react_agent @@ -43,7 +44,11 @@ def main(): print("*** Please set the LAUNCHDARKLY_SDK_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-langgraph-agent', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") exit() diff --git a/examples/langgraph_agent/pyproject.toml b/getting_started/agent_config/langgraph_agent/pyproject.toml similarity index 95% rename from examples/langgraph_agent/pyproject.toml rename to getting_started/agent_config/langgraph_agent/pyproject.toml index 0e3e870..febeb78 100644 --- a/examples/langgraph_agent/pyproject.toml +++ b/getting_started/agent_config/langgraph_agent/pyproject.toml @@ -14,6 +14,7 @@ agent = "langgraph_agent_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-langchain = ">=0.6.0" langchain = "^1.0.0" langchain-core = "^1.0.0" diff --git a/examples/langgraph_multi_agent/README.md b/getting_started/agent_config/langgraph_multi_agent/README.md similarity index 100% rename from examples/langgraph_multi_agent/README.md rename to getting_started/agent_config/langgraph_multi_agent/README.md diff --git a/examples/langgraph_multi_agent/langgraph_multi_agent_example.py b/getting_started/agent_config/langgraph_multi_agent/langgraph_multi_agent_example.py similarity index 97% rename from examples/langgraph_multi_agent/langgraph_multi_agent_example.py rename to getting_started/agent_config/langgraph_multi_agent/langgraph_multi_agent_example.py index 58246cd..f319397 100644 --- a/examples/langgraph_multi_agent/langgraph_multi_agent_example.py +++ b/getting_started/agent_config/langgraph_multi_agent/langgraph_multi_agent_example.py @@ -7,6 +7,7 @@ from ldai import LDAIClient from ldai.tracker import TokenUsage from ldai_langchain import get_ai_metrics_from_response +from ldobserve import ObservabilityConfig, ObservabilityPlugin from langchain.chat_models import init_chat_model from langgraph.prebuilt import create_react_agent from langgraph.graph import StateGraph, END @@ -189,7 +190,11 @@ def main(): print("*** Please set the LAUNCHDARKLY_SDK_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-langgraph-multi-agent', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") exit() diff --git a/examples/langgraph_multi_agent/pyproject.toml b/getting_started/agent_config/langgraph_multi_agent/pyproject.toml similarity index 95% rename from examples/langgraph_multi_agent/pyproject.toml rename to getting_started/agent_config/langgraph_multi_agent/pyproject.toml index 1617b7e..6ccf126 100644 --- a/examples/langgraph_multi_agent/pyproject.toml +++ b/getting_started/agent_config/langgraph_multi_agent/pyproject.toml @@ -14,6 +14,7 @@ agent-graph = "langgraph_multi_agent_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-langchain = ">=0.6.0" langchain = "^1.0.0" langchain-core = "^1.0.0" diff --git a/examples/bedrock/README.md b/getting_started/completion_config/bedrock/README.md similarity index 100% rename from examples/bedrock/README.md rename to getting_started/completion_config/bedrock/README.md diff --git a/examples/bedrock/bedrock_example.py b/getting_started/completion_config/bedrock/bedrock_example.py similarity index 95% rename from examples/bedrock/bedrock_example.py rename to getting_started/completion_config/bedrock/bedrock_example.py index f10265b..aae970b 100755 --- a/examples/bedrock/bedrock_example.py +++ b/getting_started/completion_config/bedrock/bedrock_example.py @@ -7,6 +7,7 @@ from ldai import LDAIClient from ldai.tracker import TokenUsage from ldai.providers import LDAIMetrics +from ldobserve import ObservabilityConfig, ObservabilityPlugin import boto3 load_dotenv() @@ -49,7 +50,11 @@ def main(): print("*** Please set the LAUNCHDARKLY_AI_CONFIG_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-bedrock', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") diff --git a/examples/bedrock/pyproject.toml b/getting_started/completion_config/bedrock/pyproject.toml similarity index 93% rename from examples/bedrock/pyproject.toml rename to getting_started/completion_config/bedrock/pyproject.toml index ddf72f9..4341134 100644 --- a/examples/bedrock/pyproject.toml +++ b/getting_started/completion_config/bedrock/pyproject.toml @@ -14,6 +14,7 @@ bedrock = "bedrock_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" boto3 = ">=0.2.0" [build-system] diff --git a/examples/gemini/README.md b/getting_started/completion_config/gemini/README.md similarity index 100% rename from examples/gemini/README.md rename to getting_started/completion_config/gemini/README.md diff --git a/examples/gemini/gemini_example.py b/getting_started/completion_config/gemini/gemini_example.py similarity index 96% rename from examples/gemini/gemini_example.py rename to getting_started/completion_config/gemini/gemini_example.py index 3f2b2f8..3445ea1 100644 --- a/examples/gemini/gemini_example.py +++ b/getting_started/completion_config/gemini/gemini_example.py @@ -6,6 +6,7 @@ from ldclient.config import Config from ldai import LDAIClient, LDMessage from ldai.tracker import TokenUsage +from ldobserve import ObservabilityConfig, ObservabilityPlugin from google import genai from google.genai import types from typing import List, Optional, Tuple @@ -98,7 +99,11 @@ def main(): print("*** Please set the GOOGLE_API_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-gemini', + )) + ])) aiclient = LDAIClient(ldclient.get()) if not ldclient.get().is_initialized(): diff --git a/examples/gemini/pyproject.toml b/getting_started/completion_config/gemini/pyproject.toml similarity index 93% rename from examples/gemini/pyproject.toml rename to getting_started/completion_config/gemini/pyproject.toml index ebd1bcd..3082b27 100644 --- a/examples/gemini/pyproject.toml +++ b/getting_started/completion_config/gemini/pyproject.toml @@ -14,6 +14,7 @@ gemini = "gemini_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" google-genai = "^1.30.0" [build-system] diff --git a/examples/langchain/README.md b/getting_started/completion_config/langchain/README.md similarity index 100% rename from examples/langchain/README.md rename to getting_started/completion_config/langchain/README.md diff --git a/examples/langchain/langchain_example.py b/getting_started/completion_config/langchain/langchain_example.py similarity index 94% rename from examples/langchain/langchain_example.py rename to getting_started/completion_config/langchain/langchain_example.py index 8f09121..427a3d8 100644 --- a/examples/langchain/langchain_example.py +++ b/getting_started/completion_config/langchain/langchain_example.py @@ -7,6 +7,7 @@ from ldclient.config import Config from ldai import LDAIClient from ldai_langchain import get_ai_metrics_from_response +from ldobserve import ObservabilityConfig, ObservabilityPlugin from langchain.chat_models import init_chat_model load_dotenv() @@ -37,7 +38,11 @@ async def async_main(): print("*** Please set the LAUNCHDARKLY_AI_CONFIG_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-langchain', + )) + ])) if not ldclient.get().is_initialized(): print("*** SDK failed to initialize. Please check your internet connection and SDK credential for any typo.") exit() diff --git a/examples/langchain/pyproject.toml b/getting_started/completion_config/langchain/pyproject.toml similarity index 94% rename from examples/langchain/pyproject.toml rename to getting_started/completion_config/langchain/pyproject.toml index e416120..cfcf97f 100644 --- a/examples/langchain/pyproject.toml +++ b/getting_started/completion_config/langchain/pyproject.toml @@ -14,6 +14,7 @@ langchain = "langchain_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-langchain = ">=0.6.0" langchain = "^1.0.0" langchain-core = "^1.0.0" diff --git a/examples/openai/README.md b/getting_started/completion_config/openai/README.md similarity index 100% rename from examples/openai/README.md rename to getting_started/completion_config/openai/README.md diff --git a/examples/openai/openai_example.py b/getting_started/completion_config/openai/openai_example.py similarity index 93% rename from examples/openai/openai_example.py rename to getting_started/completion_config/openai/openai_example.py index 8d6c2e8..20749ff 100755 --- a/examples/openai/openai_example.py +++ b/getting_started/completion_config/openai/openai_example.py @@ -6,6 +6,7 @@ from ldclient.config import Config from ldai import LDAIClient from ldai_openai import get_ai_metrics_from_response +from ldobserve import ObservabilityConfig, ObservabilityPlugin from openai import OpenAI load_dotenv() @@ -30,7 +31,11 @@ def main(): print("*** Please set the LAUNCHDARKLY_AI_CONFIG_KEY env first") exit() - ldclient.set_config(Config(sdk_key)) + ldclient.set_config(Config(sdk_key, plugins=[ + ObservabilityPlugin(ObservabilityConfig( + service_name='hello-python-ai-openai', + )) + ])) aiclient = LDAIClient(ldclient.get()) if not ldclient.get().is_initialized(): diff --git a/examples/openai/pyproject.toml b/getting_started/completion_config/openai/pyproject.toml similarity index 93% rename from examples/openai/pyproject.toml rename to getting_started/completion_config/openai/pyproject.toml index a56bbe5..92f33f2 100644 --- a/examples/openai/pyproject.toml +++ b/getting_started/completion_config/openai/pyproject.toml @@ -14,6 +14,7 @@ openai = "openai_example:main" python = "^3.10" python-dotenv = ">=1.0.0" launchdarkly-server-sdk-ai = ">=0.19.0" +launchdarkly-observability = ">=0.1.0" launchdarkly-server-sdk-ai-openai = ">=0.5.0" openai = ">=1.0.0"