Python: [BREAKING] Standardize model selection on model (#4999)

* Refactor Anthropic model option and provider clients

Rename the Anthropic client model option from model_id to model, add provider-specific Anthropic wrappers for Foundry, Bedrock, and Vertex, and expose them through the Anthropic, Foundry, Amazon, and Google namespaces. Update core option handling, docs, samples, and tests accordingly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix Anthropic skills sample typing

Cast the Anthropic beta client to Any in the skills sample so the pre-commit sample pyright check no longer fails on beta skills and files endpoints that are not exposed by the current SDK stubs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* undo sample mypy

* Retry CI after transient external failures

Retrigger PR validation after an unrelated Copilot review workflow SAML failure and a transient external tau2 git fetch failure in the Windows Python test setup.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review feedback on model option merging

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address Anthropic compatibility review feedback

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* moved all to `model`

* fixes for azure ai search

* Python: standardize remaining sample env var names

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Python: fix foundry-local pyright compatibility

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* updated env vars in cicd

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Eduard van Valkenburg
2026-04-01 21:00:18 +02:00
committed by GitHub
Unverified
parent 95550dd0dc
commit 6acab3d1d6
184 changed files with 1749 additions and 1025 deletions
@@ -391,7 +391,7 @@ class EntityDiscovery:
source=source, # IMPORTANT: Pass the source parameter
tools=[str(tool) for tool in (tools_list or [])],
instructions=instructions,
model_id=model,
model=model,
chat_client_type=chat_client_type,
context_provider=context_provider_list,
middleware=middlewares_list,
@@ -846,7 +846,7 @@ class EntityDiscovery:
description=description,
tools=tools_union,
instructions=instructions,
model_id=model,
model=model,
chat_client_type=chat_client_type,
context_provider=context_provider_list,
middleware=middlewares_list,
@@ -770,9 +770,9 @@ class MessageMapper:
from .models._openai_custom import AgentCompletedEvent, AgentFailedEvent, AgentStartedEvent
try:
# Get model name from request or use 'devui' as default
# Get model from request or use 'devui' as default
request_obj = context.get("request")
model_name = request_obj.model if request_obj and request_obj.model else "devui"
model = request_obj.model if request_obj and request_obj.model else "devui"
if isinstance(event, AgentStartedEvent):
execution_id = f"agent_{uuid4().hex[:12]}"
@@ -783,7 +783,7 @@ class MessageMapper:
id=f"resp_{execution_id}",
object="response",
created_at=float(time.time()),
model=model_name,
model=model,
output=[],
status="in_progress",
parallel_tool_calls=False,
@@ -818,7 +818,7 @@ class MessageMapper:
id=f"resp_{execution_id}",
object="response",
created_at=float(time.time()),
model=model_name,
model=model,
output=[],
status="failed",
error=response_error,
@@ -865,16 +865,16 @@ class MessageMapper:
# Return proper OpenAI event objects
events: list[Any] = []
# Get model name from request or use 'devui' as default
# Get model from request or use 'devui' as default
request_obj = context.get("request")
model_name = request_obj.model if request_obj and request_obj.model else "devui"
model = request_obj.model if request_obj and request_obj.model else "devui"
# Create a full Response object with all required fields
response_obj = Response(
id=f"resp_{workflow_id}",
object="response",
created_at=float(time.time()),
model=model_name,
model=model,
output=[], # Empty output list initially
status="in_progress",
# Required fields with safe defaults
@@ -989,9 +989,9 @@ class MessageMapper:
# Import Response and ResponseError types
from openai.types.responses import Response, ResponseError
# Get model name from request or use 'devui' as default
# Get model from request or use 'devui' as default
request_obj = context.get("request")
model_name = request_obj.model if request_obj and request_obj.model else "devui"
model = request_obj.model if request_obj and request_obj.model else "devui"
# Extract error message from WorkflowErrorDetails
if details:
@@ -1013,7 +1013,7 @@ class MessageMapper:
id=f"resp_{workflow_id}",
object="response",
created_at=float(time.time()),
model=model_name,
model=model,
output=[],
status="failed",
error=response_error,
@@ -20,7 +20,7 @@ class RequestRecord(TypedDict):
entity_id: str
executor: str
input: Any
model_id: str
model: str
stream: bool
execution_time: NotRequired[float]
status: NotRequired[str]
@@ -91,7 +91,7 @@ class SessionManager:
logger.debug(f"Closed session: {session_id}")
def add_request_record(
self, session_id: str, entity_id: str, executor_name: str, request_input: Any, model_id: str
self, session_id: str, entity_id: str, executor_name: str, request_input: Any, model: str
) -> str:
"""Add a request record to a session.
@@ -100,7 +100,7 @@ class SessionManager:
entity_id: ID of the entity being executed
executor_name: Name of the executor
request_input: Input for the request
model_id: Model name
model: Model name
Returns:
Request ID
@@ -115,7 +115,7 @@ class SessionManager:
"entity_id": entity_id,
"executor": executor_name,
"input": request_input,
"model_id": model_id,
"model": model,
"stream": True,
}
session["requests"].append(request_record)
@@ -163,7 +163,7 @@ class SessionManager:
"timestamp": req["timestamp"].isoformat(),
"entity_id": req["entity_id"],
"executor": req["executor"],
"model": req["model_id"],
"model": req["model"],
"input_length": len(str(req["input"])) if req["input"] else 0,
"execution_time": req.get("execution_time"),
"status": req.get("status", "unknown"),
@@ -59,13 +59,13 @@ def extract_agent_metadata(entity_object: Any) -> dict[str, Any]:
chat_opts = entity_object.default_options
chat_opts_dict = _string_key_dict(chat_opts)
if chat_opts_dict is not None:
model_id = chat_opts_dict.get("model_id")
if model_id:
metadata["model"] = model_id
elif hasattr(chat_opts, "model_id") and chat_opts.model_id:
metadata["model"] = chat_opts.model_id
if metadata["model"] is None and hasattr(entity_object, "client") and hasattr(entity_object.client, "model_id"):
metadata["model"] = entity_object.client.model_id
model = chat_opts_dict.get("model")
if model:
metadata["model"] = model
elif hasattr(chat_opts, "model") and chat_opts.model:
metadata["model"] = chat_opts.model
if metadata["model"] is None and hasattr(entity_object, "client") and hasattr(entity_object.client, "model"):
metadata["model"] = entity_object.client.model
# Try to get chat client type
if hasattr(entity_object, "client"):
@@ -44,7 +44,7 @@ class EntityInfo(BaseModel):
# Agent-specific fields (optional, populated when available)
instructions: str | None = None
model_id: str | None = None
model: str | None = None
chat_client_type: str | None = None
context_provider: list[str] | None = None
middleware: list[str] | None = None
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -37,7 +37,7 @@ OPENAI_CHAT_MODEL="gpt-4o-mini"
# Or for Azure OpenAI
AZURE_OPENAI_ENDPOINT="your-endpoint"
AZURE_OPENAI_DEPLOYMENT_NAME="your-deployment-name"
AZURE_OPENAI_MODEL="your-deployment-name"
```
## 4. Test DevUI
@@ -247,7 +247,7 @@ services:
# Or Azure OpenAI
- AZURE_OPENAI_API_KEY=\${AZURE_OPENAI_API_KEY}
- AZURE_OPENAI_ENDPOINT=\${AZURE_OPENAI_ENDPOINT}
- AZURE_OPENAI_DEPLOYMENT_NAME=\${AZURE_OPENAI_DEPLOYMENT_NAME}
- AZURE_OPENAI_MODEL=\${AZURE_OPENAI_MODEL}
# Optional: Enable instrumentation
- ENABLE_INSTRUMENTATION=\${ENABLE_INSTRUMENTATION:-false}
ports:
@@ -78,7 +78,7 @@ export const SAMPLE_ENTITIES: SampleEntity[] = [
required: true,
},
{
name: "AZURE_OPENAI_DEPLOYMENT_NAME",
name: "AZURE_OPENAI_MODEL",
description: "Name of the deployed model in Azure OpenAI",
required: true,
example: "gpt-4o",
@@ -151,7 +151,7 @@ async def test_credential_cleanup() -> None:
# Create mock chat client with credential
mock_client = Mock()
mock_client.async_credential = mock_credential
mock_client.model_id = "test-model"
mock_client.model = "test-model"
mock_client.function_invocation_configuration = None
# Create agent with mock client
@@ -184,7 +184,7 @@ async def test_credential_cleanup_error_handling() -> None:
# Create mock chat client with credential
mock_client = Mock()
mock_client.async_credential = mock_credential
mock_client.model_id = "test-model"
mock_client.model = "test-model"
mock_client.function_invocation_configuration = None
# Create agent with mock client
@@ -219,7 +219,7 @@ async def test_multiple_credential_attributes() -> None:
mock_client = Mock()
mock_client.credential = mock_cred1
mock_client.async_credential = mock_cred2
mock_client.model_id = "test-model"
mock_client.model = "test-model"
mock_client.function_invocation_configuration = None
# Create agent with mock client