Skip to content

Conversation

marlenezw
Copy link
Contributor

Description

This PR adds support for passing a callable function as the openai_api_key parameter in ChatOpenAI, OpenAI, and OpenAIEmbeddings classes. This enhancement enables dynamic API key retrieval at runtime, which is needed for Azure OpenAI's new v1 API with Microsoft Entra ID (formerly Azure AD) token-based authentication.

Context: Azure OpenAI v1 API Evolution

As outlined in this Azure OpenAI API version lifecycle documentation, Azure OpenAI introduced a v1 API (Generally Available as of August 2025) that brings several improvements. The most relevant here:

  • Unified OpenAI client: Use the standard OpenAI() client instead of Azure-specific clients
  • Native token-based authentication: The v1 API adds automatic token refresh support directly to the OpenAI() client, removing the dependency on separate Azure clients.

Key Use Case: Microsoft Entra ID Authentication

The v1 API documentation specifically shows that Microsoft Entra ID authentication now works by passing a token provider callable directly to the api_key parameter:

from openai import OpenAI
from azure.identity import DefaultAzureCredential, get_bearer_token_provider

token_provider = get_bearer_token_provider(
    DefaultAzureCredential(), "https://cognitiveservices.azure.com/.default"
)

client = OpenAI(  
    base_url="https://YOUR-RESOURCE-NAME.openai.azure.com/openai/v1/",  
    api_key=token_provider  # Callable that handles automatic token refresh
)

This PR enables LangChain to support this pattern. Previously, LangChain only accepted static strings or [SecretStr] parameter, which prevented users from being able to use an Azure credential.

Changes Made

Updated the code in the OpenAI Base, LLMs and Emeddings files to contain this code:

api_key_value = None
if self.openai_api_key is not None:
    if isinstance(self.openai_api_key, SecretStr):
        api_key_value = self.openai_api_key.get_secret_value()
    elif callable(self.openai_api_key):
        api_key_value = self.openai_api_key()

I also added an environmental check to see if the user is using a key from Azure OpenAI instead of one from OpenAI

openai_api_key: SecretStr | None | Callable[[], str] = Field(
    alias="api_key",
    default_factory=secret_from_env(
        ["OPENAI_API_KEY", "AZURE_OPENAI_API_KEY"], 
        default=None
    ),
)

Added tests to the unit tests secret testing file.

Enhancement to support Azure OpenAI v1 API authentication patterns

Dependencies
None - uses existing dependencies

@github-actions github-actions bot added security integration Related to a provider partner package integration labels Oct 16, 2025
@marlenezw marlenezw force-pushed the openai_apikey_callable branch from 386a4e4 to 1dd0e14 Compare October 16, 2025 18:48
@marlenezw marlenezw changed the title OpenAI apikey callable feat(openai): add callable support for openai_api_key parameter Oct 16, 2025
Copy link

codspeed-hq bot commented Oct 16, 2025

CodSpeed Performance Report

Merging #33532 will degrade performances by 18.61%

Comparing marlenezw:openai_apikey_callable (f13e521) with master (a47386f)1

Summary

❌ 4 regressions
✅ 2 untouched
⏩ 28 skipped2

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Benchmarks breakdown

Mode Benchmark BASE HEAD Change
Instrumentation test_stream_time 937.4 ms 1,151.6 ms -18.61%
Instrumentation test_stream_time 937.1 ms 1,150.9 ms -18.57%
Instrumentation test_init_time 10.6 ms 12 ms -11.63%
Instrumentation test_init_time 10.7 ms 12 ms -11.52%

Footnotes

  1. No successful run was found on master (557fc9a) during the generation of this report, so a47386f was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 28 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@marlenezw
Copy link
Contributor Author

Tests passing! cc @ccurme and @mdrxy. This PR addresses the issue we discussed in Slack to add in support for a callable in OpenAI for the new v1 API. Note this is the same in OpenAI client code here https://github.com/openai/openai-python/blob/ebf32212f7bf5bec6b24cc2276ac0d9a28dd63bb/src/openai/_client.py#L102

Copy link
Collaborator

@ccurme ccurme left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for this!

@ccurme ccurme self-assigned this Oct 17, 2025
@marlenezw
Copy link
Contributor Author

Hi @ccurme, would be awesome to get this merged before the v1 announcement if possible! We'd like to add these updates about EntraID to the MSFT Learn docs

@ccurme ccurme requested a review from Copilot October 20, 2025 19:32
@ccurme
Copy link
Collaborator

ccurme commented Oct 20, 2025

I think there's a configuration issue with codspeed, same errors are coming up on an unrelated PR that just adds a unit test: https://github.com/langchain-ai/langchain/pull/33134/checks?check_run_id=53206813137

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR enables dynamic API key retrieval in OpenAI integration classes by allowing callable functions to be passed as the openai_api_key parameter. This change is necessary to support Azure OpenAI's v1 API authentication pattern using Microsoft Entra ID tokens, which require automatic token refresh via callable token providers.

Key Changes:

  • Modified type signatures to accept Callable[[], str] in addition to SecretStr | None
  • Added runtime type checking to handle both SecretStr and callable API key types
  • Added unit tests verifying callable API key functionality

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
libs/partners/openai/langchain_openai/llms/base.py Updated BaseOpenAI to accept callable API keys and handle extraction logic
libs/partners/openai/langchain_openai/embeddings/base.py Updated OpenAIEmbeddings to accept callable API keys and handle extraction logic
libs/partners/openai/langchain_openai/chat_models/base.py Updated BaseChatOpenAI to accept callable API keys and handle extraction logic
libs/partners/openai/tests/unit_tests/test_secrets.py Added parametrized test verifying callable API key support across all three classes

@marlenezw
Copy link
Contributor Author

No worries, feel free to add the changes when you've confirmed. I'll check back in tomorrow

@ccurme
Copy link
Collaborator

ccurme commented Oct 20, 2025

@marlenezw I'll get this across, it increased in scope somewhat to support the async case but I think it's mostly done. Will come back tomorrow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature integration Related to a provider partner package integration security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants