-
Notifications
You must be signed in to change notification settings - Fork 3.4k
feat: Add comprehensive OpenAI base URL configuration support #585
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
orestesgarcia
wants to merge
18
commits into
coleam00:main
from
orestesgarcia:feature/externalized-openai-base-url
Closed
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
5577ae8
feat: Add comprehensive OpenAI base URL configuration support
orestesgarcia 39f753a
fix: Address PR review feedback for OpenAI base URL configuration
orestesgarcia e06fbc6
Update python/src/agents/agent_provider_config.py
orestesgarcia 6db9b19
Update python/src/agents/base_agent.py
orestesgarcia c4cf1c7
Update python/src/agents/agent_provider_config.py
orestesgarcia c462c18
Update python/src/agents/agent_provider_config.py
orestesgarcia 1091e1b
docs: Add OpenAI base URL configuration documentation
orestesgarcia f7fcf77
feat: Centralize OpenAI client configuration across all services
orestesgarcia a4e1689
docs: Update documentation to reflect centralized OpenAI configuration
orestesgarcia 9da7379
Update docs/docs/api-reference.mdx
orestesgarcia 8b71633
Update docs/docs/rag.mdx
orestesgarcia 54d29a3
Update python/src/agents/agent_provider_config.py
orestesgarcia efb5f20
Update python/src/server/services/llm_provider_service.py
orestesgarcia 2f26bf6
fix: Improve error logging in LLM provider service
orestesgarcia 1a770ce
feat: Improve error handling and observability in base agent
orestesgarcia 3c53fde
feat: Improve private host detection for HTTP URL warnings
orestesgarcia 58a9e13
feat: Add configurable timeouts and retries to OpenAI clients
orestesgarcia 8604252
Update docs/docs/rag.mdx
orestesgarcia File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,131 @@ | ||
| """ | ||
| Agent Provider Configuration | ||
|
|
||
| Handles OpenAI provider configuration for PydanticAI agents. | ||
| Enables custom base_url configuration for OpenAI-compatible endpoints. | ||
| """ | ||
|
|
||
| import logging | ||
| import os | ||
|
|
||
| from pydantic_ai.models.openai import OpenAIChatModel | ||
| from pydantic_ai.providers.openai import OpenAIProvider | ||
|
|
||
| logger = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| async def get_configured_openai_model(model_name: str) -> OpenAIChatModel | str: | ||
| """ | ||
| Get a configured OpenAI model for PydanticAI agents. | ||
|
|
||
| If OPENAI_BASE_URL is configured in the system, returns an OpenAIChatModel | ||
| with a custom OpenAIProvider. Otherwise, returns the standard model string | ||
| format that PydanticAI handles automatically. | ||
|
|
||
| Args: | ||
| model_name: The model name (e.g., "gpt-4o", "gpt-4o-mini") | ||
|
|
||
| Returns: | ||
| Either an OpenAIChatModel with custom provider or a model string | ||
| """ | ||
| try: | ||
| # Try to get base URL from credential service | ||
| base_url = await _get_openai_base_url() | ||
|
|
||
| if base_url: | ||
| # Get API key | ||
| api_key = await _get_openai_api_key() | ||
| if not api_key: | ||
| logger.warning("OPENAI_BASE_URL is configured but no API key found, falling back to default") | ||
| return f"openai:{model_name}" | ||
|
|
||
| # Create custom provider with base_url | ||
| provider = OpenAIProvider( | ||
| base_url=base_url, | ||
| api_key=api_key | ||
| ) | ||
|
|
||
| logger.info(f"Creating OpenAI model {model_name} with custom base URL: {base_url}") | ||
| return OpenAIChatModel(model_name, provider=provider) | ||
| else: | ||
| # No custom base URL, use standard string format | ||
| logger.debug(f"Using default OpenAI configuration for model: {model_name}") | ||
| return f"openai:{model_name}" | ||
|
|
||
| except Exception as e: | ||
| logger.error(f"Error configuring OpenAI model: {e}") | ||
| # Fallback to standard string format | ||
| return f"openai:{model_name}" | ||
|
|
||
|
orestesgarcia marked this conversation as resolved.
orestesgarcia marked this conversation as resolved.
Outdated
|
||
|
|
||
| async def _get_openai_base_url() -> str | None: | ||
| """Get OpenAI base URL from credential service.""" | ||
| try: | ||
| # Import here to avoid circular imports | ||
| from ..server.services.credential_service import credential_service | ||
|
|
||
| # Get RAG settings which contain OPENAI_BASE_URL | ||
| rag_settings = await credential_service.get_credentials_by_category("rag_strategy") | ||
| base_url = rag_settings.get("OPENAI_BASE_URL") | ||
|
|
||
| if base_url: | ||
| logger.debug(f"Found OPENAI_BASE_URL in settings: {base_url}") | ||
| return base_url | ||
| else: | ||
| # Check environment variable as fallback | ||
| env_base_url = os.getenv("OPENAI_BASE_URL") | ||
| if env_base_url: | ||
| logger.debug(f"Found OPENAI_BASE_URL in environment: {env_base_url}") | ||
| return env_base_url | ||
|
|
||
|
orestesgarcia marked this conversation as resolved.
Outdated
|
||
| return None | ||
|
|
||
| except Exception as e: | ||
| logger.debug(f"Could not get OPENAI_BASE_URL from settings: {e}") | ||
| # Try environment variable as fallback | ||
| return os.getenv("OPENAI_BASE_URL") | ||
|
|
||
|
|
||
| async def _get_openai_api_key() -> str | None: | ||
| """Get OpenAI API key from credential service.""" | ||
| try: | ||
| # Import here to avoid circular imports | ||
| from ..server.services.credential_service import credential_service | ||
|
|
||
| # Try to get from credential service first | ||
| api_key = await credential_service.get_credential("OPENAI_API_KEY", decrypt=True) | ||
| if api_key: | ||
| logger.debug("Found OPENAI_API_KEY in credential service") | ||
| return api_key | ||
|
|
||
| # Fallback to environment variable | ||
| env_api_key = os.getenv("OPENAI_API_KEY") | ||
| if env_api_key: | ||
| logger.debug("Found OPENAI_API_KEY in environment") | ||
| return env_api_key | ||
|
|
||
| return None | ||
|
|
||
| except Exception as e: | ||
| logger.debug(f"Could not get OPENAI_API_KEY from settings: {e}") | ||
| # Try environment variable as fallback | ||
| return os.getenv("OPENAI_API_KEY") | ||
|
|
||
|
|
||
| def get_configured_openai_model_sync(model_name: str) -> str: | ||
| """ | ||
| Synchronous version that returns model string format. | ||
|
|
||
| Since we can't easily call async functions from sync contexts, | ||
| this returns the standard model string format and relies on | ||
| PydanticAI's automatic configuration. | ||
|
|
||
| Args: | ||
| model_name: The model name (e.g., "gpt-4o", "gpt-4o-mini") | ||
|
|
||
| Returns: | ||
| Model string in "openai:model" format | ||
| """ | ||
| # For synchronous contexts, we use the standard format | ||
| # PydanticAI will handle OpenAI configuration automatically | ||
| return f"openai:{model_name}" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.