Skip to main content
Glama
pydantic

mcp-run-python

Official
by pydantic
openai.py6.88 kB
from collections.abc import Sequence from dataclasses import dataclass, field from typing import Literal, cast from pydantic_ai import _utils from pydantic_ai.exceptions import ModelAPIError, ModelHTTPError, UserError from pydantic_ai.providers import Provider, infer_provider from pydantic_ai.usage import RequestUsage from . import OpenAIEmbeddingsCompatibleProvider from .base import EmbeddingModel, EmbedInputType from .result import EmbeddingResult from .settings import EmbeddingSettings try: import tiktoken from openai import APIConnectionError, APIStatusError, AsyncOpenAI from openai.types import EmbeddingModel as LatestOpenAIEmbeddingModelNames from openai.types.create_embedding_response import Usage from pydantic_ai.models.openai import OMIT except ImportError as _import_error: raise ImportError( 'Please install `openai` to use the OpenAI embeddings model, ' 'you can use the `openai` optional group — `pip install "pydantic-ai-slim[openai]"`' ) from _import_error OpenAIEmbeddingModelName = str | LatestOpenAIEmbeddingModelNames """Possible OpenAI embeddings model names. See the [OpenAI embeddings documentation](https://platform.openai.com/docs/guides/embeddings) for available models. """ class OpenAIEmbeddingSettings(EmbeddingSettings, total=False): """Settings used for an OpenAI embedding model request. All fields from [`EmbeddingSettings`][pydantic_ai.embeddings.EmbeddingSettings] are supported. """ # ALL FIELDS MUST BE `openai_` PREFIXED SO YOU CAN MERGE THEM WITH OTHER MODELS. @dataclass(init=False) class OpenAIEmbeddingModel(EmbeddingModel): """OpenAI embedding model implementation. This model works with OpenAI's embeddings API and any [OpenAI-compatible providers](../models/openai.md#openai-compatible-models). Example: ```python from pydantic_ai.embeddings.openai import OpenAIEmbeddingModel from pydantic_ai.providers.openai import OpenAIProvider # Using OpenAI directly model = OpenAIEmbeddingModel('text-embedding-3-small') # Using an OpenAI-compatible provider model = OpenAIEmbeddingModel( 'text-embedding-3-small', provider=OpenAIProvider(base_url='https://my-provider.com/v1'), ) ``` """ _model_name: OpenAIEmbeddingModelName = field(repr=False) _provider: Provider[AsyncOpenAI] = field(repr=False) def __init__( self, model_name: OpenAIEmbeddingModelName, *, provider: OpenAIEmbeddingsCompatibleProvider | Literal['openai'] | Provider[AsyncOpenAI] = 'openai', settings: EmbeddingSettings | None = None, ): """Initialize an OpenAI embedding model. Args: model_name: The name of the OpenAI model to use. See [OpenAI's embedding models](https://platform.openai.com/docs/guides/embeddings) for available options. provider: The provider to use for authentication and API access. Can be: - `'openai'` (default): Uses the standard OpenAI API - A provider name string (e.g., `'azure'`, `'deepseek'`) - A [`Provider`][pydantic_ai.providers.Provider] instance for custom configuration See [OpenAI-compatible providers](../models/openai.md#openai-compatible-models) for a list of supported providers. settings: Model-specific [`EmbeddingSettings`][pydantic_ai.embeddings.EmbeddingSettings] to use as defaults for this model. """ self._model_name = model_name if isinstance(provider, str): provider = infer_provider(provider) self._provider = provider self._client = provider.client super().__init__(settings=settings) @property def base_url(self) -> str: return str(self._client.base_url) @property def model_name(self) -> OpenAIEmbeddingModelName: """The embedding model name.""" return self._model_name @property def system(self) -> str: """The embedding model provider.""" return self._provider.name async def embed( self, inputs: str | Sequence[str], *, input_type: EmbedInputType, settings: EmbeddingSettings | None = None ) -> EmbeddingResult: inputs, settings = self.prepare_embed(inputs, settings) settings = cast(OpenAIEmbeddingSettings, settings) try: response = await self._client.embeddings.create( input=inputs, model=self.model_name, dimensions=settings.get('dimensions') or OMIT, extra_headers=settings.get('extra_headers'), extra_body=settings.get('extra_body'), ) except APIStatusError as e: if (status_code := e.status_code) >= 400: raise ModelHTTPError(status_code=status_code, model_name=self.model_name, body=e.body) from e raise # pragma: lax no cover except APIConnectionError as e: # pragma: no cover raise ModelAPIError(model_name=self.model_name, message=e.message) from e embeddings = [item.embedding for item in response.data] return EmbeddingResult( embeddings=embeddings, inputs=inputs, input_type=input_type, usage=_map_usage(response.usage, self.system, self.base_url, response.model), model_name=response.model, provider_name=self.system, ) async def max_input_tokens(self) -> int | None: if self.system != 'openai': return None # https://platform.openai.com/docs/guides/embeddings#embedding-models return 8192 async def count_tokens(self, text: str) -> int: if self.system != 'openai': raise UserError( 'Counting tokens is not supported for non-OpenAI embedding models', ) try: encoding = await _utils.run_in_executor(tiktoken.encoding_for_model, self.model_name) except KeyError as e: # pragma: no cover raise ValueError( f'The embedding model {self.model_name!r} is not supported by tiktoken', ) from e return len(encoding.encode(text)) def _map_usage( usage: Usage, provider: str, provider_url: str, model: str, ) -> RequestUsage: usage_data = usage.model_dump(exclude_none=True) details = {k: v for k, v in usage_data.items() if k not in {'prompt_tokens', 'total_tokens'} if isinstance(v, int)} response_data = dict(model=model, usage=usage_data) return RequestUsage.extract( response_data, provider=provider, provider_url=provider_url, provider_fallback='openai', api_flavor='embeddings', details=details, )

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/pydantic/pydantic-ai'

If you have feedback or need assistance with the MCP directory API, please join our Discord server