Skip to content

Conversation

@ehaca
Copy link
Contributor

@ehaca ehaca commented Apr 6, 2025

Hello folks,
I had some time and started drafting a possible implementation for this issue: #960.
There's still lots of work to do, but I was feeling kind of insecure about my approach and wanted to get some (both general and concrete) feedback if possible before investing more time on it :)

My main questions are:

  1. Is the idea about creating yet another extra something of your liking?
  2. The Pycharm typing issue about
 def __init__(
        self,
        model_name: AnthropicModelName,
        *,
        # breaking this in multiple lines breaks pycharm type recognition. However, I was unable to stop ruff from
        # doing it - # fmt: skip etc didn't work  :(
        provider: Literal['anthropic', 'anthropic-vertex']
        | Provider[AsyncAnthropicVertex]
        | Provider[AsyncAnthropic] =  # fmt: skip
        'anthropic',
    ):
  1. Now I am getting some static typing errors for test_init in tests/models/test_anthropic.py, how should I handle this?

Thank you very much for your feedback and help and have a nice day :)

@ehaca ehaca mentioned this pull request Apr 6, 2025
Comment on lines +120 to +125
# breaking this in multiple lines breaks pycharm type recognition. However, I was unable to stop ruff from
# doing it - # fmt: skip etc didn't work :(
provider: Literal['anthropic', 'anthropic-vertex']
| Provider[AsyncAnthropicVertex]
| Provider[AsyncAnthropic] = # fmt: skip
'anthropic',
Copy link
Member

Choose a reason for hiding this comment

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

I think you need to do # fmt: off and # fmt: on after.

instance of `Provider[AsyncAnthropic]`. If not provided, the other parameters will be used.
provider: The provider to use for the Anthropic API. Can be either the string 'anthropic',
'anthropic-vertex', or an instance of Provider[AsyncAnthropic] or Provider[AsyncAnthropicVertex].
Defaults to 'anthropic'.

Choose a reason for hiding this comment

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

Maybe you should also add an entry to the KnownModelName literal at models/__init__.py

Comment on lines +76 to +79
elif provider == 'anthropic-vertex':
from .anthropic_vertex import AnthropicVertexProvider

return AnthropicVertexProvider()
Copy link
Member

Choose a reason for hiding this comment

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

This is tricky. If you want google-vertex:<anthropic-model>, the agent should be able to infer this provider instead of the other... Maybe the provider should offer different clients depending on the model?

Right now, the GoogleVertexProvider is a generic on the client, which currently is httpx.AsyncClient. What the provider can offer a client via method?

class GoogleVertexProvider(Provider):
    def get_client(self, tp: type[T]) -> T:
        if isinstance(tp, httpx.AsyncClient):
            return self.httpx_client
        elif isinstance(tp, AsyncAnthropicVertex):
            return self.anthropic_client
        else:
            raise ValueError('not supported')

Copy link

Choose a reason for hiding this comment

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

@Kludex really want to see this happen - I would propose the following options:

  1. Kick out VertexAI to its own top level provider - e.g. Bedrock - and let the VertexAI model class handle Anthropic/Mistral/Llama/Gemini VertexAI providers. This would be pretty clean, as the string would be google-vertex: <model name> which should route to the hypothetical VertexAI model class instead of a GeminiModel class.
  2. Have routing logic based on google-vertex: <model> that would be responsible for routing to Pydantic-supported model types - e.g. it may only support Mistral/Gemini/Anthropic.
  3. Change the naming convention for VertexAI Gemini models from google-vertexai to gemini-vertexai to support a model-provider model name format.

Personally, I like number 1 as I think it would be the cleanest from a top-level abstraction standpoint.

@DouweM DouweM closed this Apr 30, 2025
@Kludex Kludex reopened this Apr 30, 2025
@Kludex
Copy link
Member

Kludex commented Apr 30, 2025

This PR is fine, we need to get around on how to choose this client when passing the model string to the agent.

@DouweM DouweM marked this pull request as draft April 30, 2025 21:52
@RoyLeviLangware
Copy link

For those stuck on this too, here is a temporary solution:

model_obj = AnthropicModel(
        "claude-3-7-sonnet@20250219",
        provider=AnthropicProvider(
            anthropic_client=AsyncAnthropicVertex(
                project_id="PROJECT_ID",
                region="us-east5",
            )  # type: ignore
        ),
    )

@acehand
Copy link

acehand commented May 29, 2025

For those stuck on this too, here is a temporary solution:

model_obj = AnthropicModel(
        "claude-3-7-sonnet@20250219",
        provider=AnthropicProvider(
            anthropic_client=AsyncAnthropicVertex(
                project_id="PROJECT_ID",
                region="us-east5",
            )  # type: ignore
        ),
    )

When i do this, i get cannot import name 'AsyncAnthropicVertex' from 'pydantic_ai.providers.anthropic, am i doing something wrong ? i am loading the latest (0.2.11) pydantic-ai

@DouweM
Copy link
Collaborator

DouweM commented May 29, 2025

@acehand AsyncAnthropicVertex is not provided by pydantic_ai, you'll have to import it from anthropic.

@andaag
Copy link

andaag commented Jun 2, 2025

Worth noting on this that prompt caching does not work with antropic python sdk + python... anthropics/anthropic-sdk-python#653 😢

@DouweM
Copy link
Collaborator

DouweM commented Jul 7, 2025

@Kludex Just putting this back on your radar!

@github-actions
Copy link

This PR is stale, and will be closed in 3 days if no reply is received.

@github-actions github-actions bot added the Stale label Jul 15, 2025
@github-actions
Copy link

Closing this PR as it has been inactive for 10 days.

@github-actions github-actions bot closed this Jul 19, 2025
@Kludex Kludex reopened this Jul 21, 2025
@github-actions github-actions bot removed the Stale label Jul 21, 2025
@github-actions
Copy link

This PR is stale, and will be closed in 3 days if no reply is received.

@github-actions github-actions bot added the Stale label Jul 28, 2025
@github-actions
Copy link

github-actions bot commented Aug 1, 2025

Closing this PR as it has been inactive for 10 days.

@github-actions github-actions bot closed this Aug 1, 2025
@Kludex Kludex reopened this Aug 5, 2025
@github-actions github-actions bot removed the Stale label Aug 5, 2025
@github-actions
Copy link

This PR is stale, and will be closed in 3 days if no reply is received.

@github-actions github-actions bot added the Stale label Aug 13, 2025
@github-actions
Copy link

Closing this PR as it has been inactive for 10 days.

@github-actions github-actions bot closed this Aug 18, 2025
@Kludex Kludex reopened this Aug 18, 2025
@github-actions github-actions bot removed the Stale label Aug 21, 2025
@cristiandley
Copy link

this is my approach just in case anyone finds it useful

import os
from anthropic import AsyncAnthropicVertex
from pydantic_ai.models.anthropic import AnthropicModel


def create_vertex_model(
    model_name: str = "claude-opus-4",
    project_id: str = "app-prod",
    region: str = "us-east5",
    credentials_file: str | None = None
):
    """
    Usage:
        model = create_vertex_model("claude-opus-4")
        agent = Agent(model, system_prompt="You are helpful")
        
        @agent.tool_plain
        def my_tool(x: int): return x * 2
        
        result = await agent.run("Hello")
    """
    
    # Set credentials if provided
    if credentials_file:
        os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = credentials_file
    
    # Create Vertex client
    vertex = AsyncAnthropicVertex(
        project_id=project_id,
        region=region
    )
    
    # Add the missing attributes that AnthropicModel expects
    # This is the key trick - expose vertex itself as 'client'
    vertex.client = vertex
    vertex.model_profile = None  # Default profile
    vertex.name = "anthropic_vertex"  # Provider name
    
    return AnthropicModel(model_name, provider=vertex)

@DouweM
Copy link
Collaborator

DouweM commented Sep 5, 2025

@cristiandley Did you try this approach? #1392 (comment) That shouldn't require manually setting any attributes

@github-actions
Copy link

github-actions bot commented Nov 5, 2025

This PR is stale, and will be closed in 3 days if no reply is received.

@github-actions github-actions bot added the Stale label Nov 5, 2025
@DouweM
Copy link
Collaborator

DouweM commented Nov 5, 2025

Not necessary anymore now that we have #3292

@DouweM DouweM closed this Nov 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants