ag2 0.9.7__py3-none-any.whl → 0.9.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ag2 might be problematic. Click here for more details.
- {ag2-0.9.7.dist-info → ag2-0.9.9.dist-info}/METADATA +102 -75
- ag2-0.9.9.dist-info/RECORD +387 -0
- autogen/__init__.py +1 -2
- autogen/_website/generate_api_references.py +4 -5
- autogen/_website/generate_mkdocs.py +9 -15
- autogen/_website/notebook_processor.py +13 -14
- autogen/_website/process_notebooks.py +10 -10
- autogen/_website/utils.py +5 -4
- autogen/agentchat/agent.py +13 -13
- autogen/agentchat/assistant_agent.py +7 -6
- autogen/agentchat/contrib/agent_eval/agent_eval.py +3 -3
- autogen/agentchat/contrib/agent_eval/critic_agent.py +3 -3
- autogen/agentchat/contrib/agent_eval/quantifier_agent.py +3 -3
- autogen/agentchat/contrib/agent_eval/subcritic_agent.py +3 -3
- autogen/agentchat/contrib/agent_optimizer.py +3 -3
- autogen/agentchat/contrib/capabilities/generate_images.py +11 -11
- autogen/agentchat/contrib/capabilities/teachability.py +15 -15
- autogen/agentchat/contrib/capabilities/transforms.py +17 -18
- autogen/agentchat/contrib/capabilities/transforms_util.py +5 -5
- autogen/agentchat/contrib/capabilities/vision_capability.py +4 -3
- autogen/agentchat/contrib/captainagent/agent_builder.py +30 -30
- autogen/agentchat/contrib/captainagent/captainagent.py +22 -21
- autogen/agentchat/contrib/captainagent/tool_retriever.py +2 -3
- autogen/agentchat/contrib/gpt_assistant_agent.py +9 -9
- autogen/agentchat/contrib/graph_rag/document.py +3 -3
- autogen/agentchat/contrib/graph_rag/falkor_graph_query_engine.py +3 -3
- autogen/agentchat/contrib/graph_rag/falkor_graph_rag_capability.py +6 -6
- autogen/agentchat/contrib/graph_rag/graph_query_engine.py +3 -3
- autogen/agentchat/contrib/graph_rag/neo4j_graph_query_engine.py +5 -11
- autogen/agentchat/contrib/graph_rag/neo4j_graph_rag_capability.py +6 -6
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_query_engine.py +7 -7
- autogen/agentchat/contrib/graph_rag/neo4j_native_graph_rag_capability.py +6 -6
- autogen/agentchat/contrib/img_utils.py +1 -1
- autogen/agentchat/contrib/llamaindex_conversable_agent.py +11 -11
- autogen/agentchat/contrib/llava_agent.py +18 -4
- autogen/agentchat/contrib/math_user_proxy_agent.py +11 -11
- autogen/agentchat/contrib/multimodal_conversable_agent.py +8 -8
- autogen/agentchat/contrib/qdrant_retrieve_user_proxy_agent.py +6 -5
- autogen/agentchat/contrib/rag/chromadb_query_engine.py +22 -26
- autogen/agentchat/contrib/rag/llamaindex_query_engine.py +14 -17
- autogen/agentchat/contrib/rag/mongodb_query_engine.py +27 -37
- autogen/agentchat/contrib/rag/query_engine.py +7 -5
- autogen/agentchat/contrib/retrieve_assistant_agent.py +5 -5
- autogen/agentchat/contrib/retrieve_user_proxy_agent.py +8 -7
- autogen/agentchat/contrib/society_of_mind_agent.py +15 -14
- autogen/agentchat/contrib/swarm_agent.py +76 -98
- autogen/agentchat/contrib/text_analyzer_agent.py +7 -7
- autogen/agentchat/contrib/vectordb/base.py +10 -18
- autogen/agentchat/contrib/vectordb/chromadb.py +2 -1
- autogen/agentchat/contrib/vectordb/couchbase.py +18 -20
- autogen/agentchat/contrib/vectordb/mongodb.py +6 -5
- autogen/agentchat/contrib/vectordb/pgvectordb.py +40 -41
- autogen/agentchat/contrib/vectordb/qdrant.py +5 -5
- autogen/agentchat/contrib/web_surfer.py +20 -19
- autogen/agentchat/conversable_agent.py +292 -290
- autogen/agentchat/group/context_str.py +1 -3
- autogen/agentchat/group/context_variables.py +15 -25
- autogen/agentchat/group/group_tool_executor.py +10 -10
- autogen/agentchat/group/group_utils.py +15 -15
- autogen/agentchat/group/guardrails.py +7 -7
- autogen/agentchat/group/handoffs.py +19 -36
- autogen/agentchat/group/multi_agent_chat.py +7 -7
- autogen/agentchat/group/on_condition.py +4 -7
- autogen/agentchat/group/on_context_condition.py +4 -7
- autogen/agentchat/group/patterns/auto.py +8 -7
- autogen/agentchat/group/patterns/manual.py +7 -6
- autogen/agentchat/group/patterns/pattern.py +13 -12
- autogen/agentchat/group/patterns/random.py +3 -3
- autogen/agentchat/group/patterns/round_robin.py +3 -3
- autogen/agentchat/group/reply_result.py +2 -4
- autogen/agentchat/group/speaker_selection_result.py +5 -5
- autogen/agentchat/group/targets/group_chat_target.py +7 -6
- autogen/agentchat/group/targets/group_manager_target.py +4 -4
- autogen/agentchat/group/targets/transition_target.py +2 -1
- autogen/agentchat/groupchat.py +60 -63
- autogen/agentchat/realtime/experimental/audio_adapters/twilio_audio_adapter.py +4 -4
- autogen/agentchat/realtime/experimental/audio_adapters/websocket_audio_adapter.py +4 -4
- autogen/agentchat/realtime/experimental/clients/gemini/client.py +7 -7
- autogen/agentchat/realtime/experimental/clients/oai/base_client.py +8 -8
- autogen/agentchat/realtime/experimental/clients/oai/rtc_client.py +6 -6
- autogen/agentchat/realtime/experimental/clients/realtime_client.py +10 -9
- autogen/agentchat/realtime/experimental/realtime_agent.py +10 -9
- autogen/agentchat/realtime/experimental/realtime_observer.py +3 -3
- autogen/agentchat/realtime/experimental/realtime_swarm.py +44 -44
- autogen/agentchat/user_proxy_agent.py +10 -9
- autogen/agentchat/utils.py +3 -3
- autogen/agents/contrib/time/time_reply_agent.py +6 -5
- autogen/agents/contrib/time/time_tool_agent.py +2 -1
- autogen/agents/experimental/deep_research/deep_research.py +3 -3
- autogen/agents/experimental/discord/discord.py +2 -2
- autogen/agents/experimental/document_agent/chroma_query_engine.py +29 -44
- autogen/agents/experimental/document_agent/docling_doc_ingest_agent.py +9 -14
- autogen/agents/experimental/document_agent/document_agent.py +15 -16
- autogen/agents/experimental/document_agent/document_conditions.py +3 -3
- autogen/agents/experimental/document_agent/document_utils.py +5 -9
- autogen/agents/experimental/document_agent/inmemory_query_engine.py +14 -20
- autogen/agents/experimental/document_agent/parser_utils.py +4 -4
- autogen/agents/experimental/document_agent/url_utils.py +14 -23
- autogen/agents/experimental/reasoning/reasoning_agent.py +33 -33
- autogen/agents/experimental/slack/slack.py +2 -2
- autogen/agents/experimental/telegram/telegram.py +2 -3
- autogen/agents/experimental/websurfer/websurfer.py +4 -4
- autogen/agents/experimental/wikipedia/wikipedia.py +5 -7
- autogen/browser_utils.py +8 -8
- autogen/cache/abstract_cache_base.py +5 -5
- autogen/cache/cache.py +12 -12
- autogen/cache/cache_factory.py +4 -4
- autogen/cache/cosmos_db_cache.py +9 -9
- autogen/cache/disk_cache.py +6 -6
- autogen/cache/in_memory_cache.py +4 -4
- autogen/cache/redis_cache.py +4 -4
- autogen/code_utils.py +18 -18
- autogen/coding/base.py +6 -6
- autogen/coding/docker_commandline_code_executor.py +9 -9
- autogen/coding/func_with_reqs.py +7 -6
- autogen/coding/jupyter/base.py +3 -3
- autogen/coding/jupyter/docker_jupyter_server.py +3 -4
- autogen/coding/jupyter/import_utils.py +3 -3
- autogen/coding/jupyter/jupyter_client.py +5 -5
- autogen/coding/jupyter/jupyter_code_executor.py +3 -4
- autogen/coding/jupyter/local_jupyter_server.py +2 -6
- autogen/coding/local_commandline_code_executor.py +8 -7
- autogen/coding/markdown_code_extractor.py +1 -2
- autogen/coding/utils.py +1 -2
- autogen/doc_utils.py +3 -2
- autogen/environments/docker_python_environment.py +19 -29
- autogen/environments/python_environment.py +8 -17
- autogen/environments/system_python_environment.py +3 -4
- autogen/environments/venv_python_environment.py +8 -12
- autogen/environments/working_directory.py +1 -2
- autogen/events/agent_events.py +106 -109
- autogen/events/base_event.py +6 -5
- autogen/events/client_events.py +15 -14
- autogen/events/helpers.py +1 -1
- autogen/events/print_event.py +4 -5
- autogen/fast_depends/_compat.py +10 -15
- autogen/fast_depends/core/build.py +17 -36
- autogen/fast_depends/core/model.py +64 -113
- autogen/fast_depends/dependencies/model.py +2 -1
- autogen/fast_depends/dependencies/provider.py +3 -2
- autogen/fast_depends/library/model.py +4 -4
- autogen/fast_depends/schema.py +7 -7
- autogen/fast_depends/use.py +17 -25
- autogen/fast_depends/utils.py +10 -30
- autogen/formatting_utils.py +6 -6
- autogen/graph_utils.py +1 -4
- autogen/import_utils.py +38 -27
- autogen/interop/crewai/crewai.py +2 -2
- autogen/interop/interoperable.py +2 -2
- autogen/interop/langchain/langchain_chat_model_factory.py +3 -2
- autogen/interop/langchain/langchain_tool.py +2 -6
- autogen/interop/litellm/litellm_config_factory.py +6 -7
- autogen/interop/pydantic_ai/pydantic_ai.py +4 -7
- autogen/interop/registry.py +2 -1
- autogen/io/base.py +5 -5
- autogen/io/run_response.py +33 -32
- autogen/io/websockets.py +6 -5
- autogen/json_utils.py +1 -2
- autogen/llm_config/__init__.py +11 -0
- autogen/llm_config/client.py +58 -0
- autogen/llm_config/config.py +384 -0
- autogen/llm_config/entry.py +154 -0
- autogen/logger/base_logger.py +4 -3
- autogen/logger/file_logger.py +2 -1
- autogen/logger/logger_factory.py +2 -2
- autogen/logger/logger_utils.py +2 -2
- autogen/logger/sqlite_logger.py +2 -1
- autogen/math_utils.py +4 -5
- autogen/mcp/__main__.py +6 -6
- autogen/mcp/helpers.py +4 -4
- autogen/mcp/mcp_client.py +170 -29
- autogen/mcp/mcp_proxy/fastapi_code_generator_helpers.py +3 -4
- autogen/mcp/mcp_proxy/mcp_proxy.py +23 -26
- autogen/mcp/mcp_proxy/operation_grouping.py +4 -5
- autogen/mcp/mcp_proxy/operation_renaming.py +6 -10
- autogen/mcp/mcp_proxy/security.py +2 -3
- autogen/messages/agent_messages.py +96 -98
- autogen/messages/base_message.py +6 -5
- autogen/messages/client_messages.py +15 -14
- autogen/messages/print_message.py +4 -5
- autogen/oai/__init__.py +1 -2
- autogen/oai/anthropic.py +42 -41
- autogen/oai/bedrock.py +68 -57
- autogen/oai/cerebras.py +26 -25
- autogen/oai/client.py +113 -139
- autogen/oai/client_utils.py +3 -3
- autogen/oai/cohere.py +34 -11
- autogen/oai/gemini.py +39 -17
- autogen/oai/gemini_types.py +11 -12
- autogen/oai/groq.py +22 -10
- autogen/oai/mistral.py +17 -11
- autogen/oai/oai_models/__init__.py +14 -2
- autogen/oai/oai_models/_models.py +2 -2
- autogen/oai/oai_models/chat_completion.py +13 -14
- autogen/oai/oai_models/chat_completion_message.py +11 -9
- autogen/oai/oai_models/chat_completion_message_tool_call.py +26 -3
- autogen/oai/oai_models/chat_completion_token_logprob.py +3 -4
- autogen/oai/oai_models/completion_usage.py +8 -9
- autogen/oai/ollama.py +19 -9
- autogen/oai/openai_responses.py +40 -17
- autogen/oai/openai_utils.py +48 -38
- autogen/oai/together.py +29 -14
- autogen/retrieve_utils.py +6 -7
- autogen/runtime_logging.py +5 -4
- autogen/token_count_utils.py +7 -4
- autogen/tools/contrib/time/time.py +0 -1
- autogen/tools/dependency_injection.py +5 -6
- autogen/tools/experimental/browser_use/browser_use.py +10 -10
- autogen/tools/experimental/code_execution/python_code_execution.py +5 -7
- autogen/tools/experimental/crawl4ai/crawl4ai.py +12 -15
- autogen/tools/experimental/deep_research/deep_research.py +9 -8
- autogen/tools/experimental/duckduckgo/duckduckgo_search.py +5 -11
- autogen/tools/experimental/firecrawl/firecrawl_tool.py +98 -115
- autogen/tools/experimental/google/authentication/credentials_local_provider.py +1 -1
- autogen/tools/experimental/google/drive/drive_functions.py +4 -4
- autogen/tools/experimental/google/drive/toolkit.py +5 -5
- autogen/tools/experimental/google_search/google_search.py +5 -5
- autogen/tools/experimental/google_search/youtube_search.py +5 -5
- autogen/tools/experimental/messageplatform/discord/discord.py +8 -12
- autogen/tools/experimental/messageplatform/slack/slack.py +14 -20
- autogen/tools/experimental/messageplatform/telegram/telegram.py +8 -12
- autogen/tools/experimental/perplexity/perplexity_search.py +18 -29
- autogen/tools/experimental/reliable/reliable.py +68 -74
- autogen/tools/experimental/searxng/searxng_search.py +20 -19
- autogen/tools/experimental/tavily/tavily_search.py +12 -19
- autogen/tools/experimental/web_search_preview/web_search_preview.py +13 -7
- autogen/tools/experimental/wikipedia/wikipedia.py +7 -10
- autogen/tools/function_utils.py +7 -7
- autogen/tools/tool.py +8 -6
- autogen/types.py +2 -2
- autogen/version.py +1 -1
- ag2-0.9.7.dist-info/RECORD +0 -421
- autogen/llm_config.py +0 -385
- {ag2-0.9.7.dist-info → ag2-0.9.9.dist-info}/WHEEL +0 -0
- {ag2-0.9.7.dist-info → ag2-0.9.9.dist-info}/licenses/LICENSE +0 -0
- {ag2-0.9.7.dist-info → ag2-0.9.9.dist-info}/licenses/NOTICE.md +0 -0
autogen/llm_config.py
DELETED
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2023 - 2025, AG2ai, Inc., AG2ai open-source projects maintainers and core contributors
|
|
2
|
-
#
|
|
3
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
|
|
5
|
-
import functools
|
|
6
|
-
import json
|
|
7
|
-
import re
|
|
8
|
-
from abc import ABC, abstractmethod
|
|
9
|
-
from collections.abc import Iterable
|
|
10
|
-
from contextvars import ContextVar
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
from typing import TYPE_CHECKING, Annotated, Any, Literal, Mapping, Optional, Type, TypeVar, Union
|
|
13
|
-
|
|
14
|
-
from httpx import Client as httpxClient
|
|
15
|
-
from pydantic import BaseModel, ConfigDict, Field, HttpUrl, SecretStr, ValidationInfo, field_serializer, field_validator
|
|
16
|
-
|
|
17
|
-
if TYPE_CHECKING:
|
|
18
|
-
from .oai.client import ModelClient
|
|
19
|
-
|
|
20
|
-
_KT = TypeVar("_KT")
|
|
21
|
-
_VT = TypeVar("_VT")
|
|
22
|
-
|
|
23
|
-
__all__ = [
|
|
24
|
-
"LLMConfig",
|
|
25
|
-
"LLMConfigEntry",
|
|
26
|
-
"register_llm_config",
|
|
27
|
-
]
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def _add_default_api_type(d: dict[str, Any]) -> dict[str, Any]:
|
|
31
|
-
if "api_type" not in d:
|
|
32
|
-
d["api_type"] = "openai"
|
|
33
|
-
return d
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
# Meta class to allow LLMConfig.current and LLMConfig.default to be used as class properties
|
|
37
|
-
class MetaLLMConfig(type):
|
|
38
|
-
def __init__(cls, *args: Any, **kwargs: Any) -> None:
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
@property
|
|
42
|
-
def current(cls) -> "LLMConfig":
|
|
43
|
-
current_llm_config = LLMConfig.get_current_llm_config(llm_config=None)
|
|
44
|
-
if current_llm_config is None:
|
|
45
|
-
raise ValueError("No current LLMConfig set. Are you inside a context block?")
|
|
46
|
-
return current_llm_config # type: ignore[return-value]
|
|
47
|
-
|
|
48
|
-
@property
|
|
49
|
-
def default(cls) -> "LLMConfig":
|
|
50
|
-
return cls.current
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class LLMConfig(metaclass=MetaLLMConfig):
|
|
54
|
-
_current_llm_config: ContextVar["LLMConfig"] = ContextVar("current_llm_config")
|
|
55
|
-
|
|
56
|
-
def __init__(self, **kwargs: Any) -> None:
|
|
57
|
-
outside_properties = list((self._get_base_model_class()).model_json_schema()["properties"].keys())
|
|
58
|
-
outside_properties.remove("config_list")
|
|
59
|
-
|
|
60
|
-
if "config_list" in kwargs and isinstance(kwargs["config_list"], dict):
|
|
61
|
-
kwargs["config_list"] = [kwargs["config_list"]]
|
|
62
|
-
|
|
63
|
-
modified_kwargs = (
|
|
64
|
-
kwargs
|
|
65
|
-
if "config_list" in kwargs
|
|
66
|
-
else {
|
|
67
|
-
**{
|
|
68
|
-
"config_list": [
|
|
69
|
-
{k: v for k, v in kwargs.items() if k not in outside_properties},
|
|
70
|
-
]
|
|
71
|
-
},
|
|
72
|
-
**{k: v for k, v in kwargs.items() if k in outside_properties},
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
|
|
76
|
-
modified_kwargs["config_list"] = [
|
|
77
|
-
_add_default_api_type(v) if isinstance(v, dict) else v for v in modified_kwargs["config_list"]
|
|
78
|
-
]
|
|
79
|
-
for x in ["max_tokens", "top_p"]:
|
|
80
|
-
if x in modified_kwargs:
|
|
81
|
-
modified_kwargs["config_list"] = [{**v, x: modified_kwargs[x]} for v in modified_kwargs["config_list"]]
|
|
82
|
-
modified_kwargs.pop(x)
|
|
83
|
-
|
|
84
|
-
self._model = self._get_base_model_class()(**modified_kwargs)
|
|
85
|
-
|
|
86
|
-
# used by BaseModel to create instance variables
|
|
87
|
-
def __enter__(self) -> "LLMConfig":
|
|
88
|
-
# Store previous context and set self as current
|
|
89
|
-
self._token = LLMConfig._current_llm_config.set(self)
|
|
90
|
-
return self
|
|
91
|
-
|
|
92
|
-
def __exit__(self, exc_type: Type[Exception], exc_val: Exception, exc_tb: Any) -> None:
|
|
93
|
-
LLMConfig._current_llm_config.reset(self._token)
|
|
94
|
-
|
|
95
|
-
@classmethod
|
|
96
|
-
def get_current_llm_config(cls, llm_config: "Optional[LLMConfig]" = None) -> "Optional[LLMConfig]":
|
|
97
|
-
if llm_config is not None:
|
|
98
|
-
return llm_config
|
|
99
|
-
try:
|
|
100
|
-
return (LLMConfig._current_llm_config.get()).copy()
|
|
101
|
-
except LookupError:
|
|
102
|
-
return None
|
|
103
|
-
|
|
104
|
-
def _satisfies_criteria(self, value: Any, criteria_values: Any) -> bool:
|
|
105
|
-
if value is None:
|
|
106
|
-
return False
|
|
107
|
-
|
|
108
|
-
if isinstance(value, list):
|
|
109
|
-
return bool(set(value) & set(criteria_values)) # Non-empty intersection
|
|
110
|
-
else:
|
|
111
|
-
return value in criteria_values
|
|
112
|
-
|
|
113
|
-
@classmethod
|
|
114
|
-
def from_json(
|
|
115
|
-
cls,
|
|
116
|
-
*,
|
|
117
|
-
env: Optional[str] = None,
|
|
118
|
-
path: Optional[Union[str, Path]] = None,
|
|
119
|
-
file_location: Optional[str] = None,
|
|
120
|
-
**kwargs: Any,
|
|
121
|
-
) -> "LLMConfig":
|
|
122
|
-
from .oai.openai_utils import config_list_from_json
|
|
123
|
-
|
|
124
|
-
if env is None and path is None:
|
|
125
|
-
raise ValueError("Either 'env' or 'path' must be provided")
|
|
126
|
-
if env is not None and path is not None:
|
|
127
|
-
raise ValueError("Only one of 'env' or 'path' can be provided")
|
|
128
|
-
|
|
129
|
-
config_list = config_list_from_json(
|
|
130
|
-
env_or_file=env if env is not None else str(path), file_location=file_location
|
|
131
|
-
)
|
|
132
|
-
return LLMConfig(config_list=config_list, **kwargs)
|
|
133
|
-
|
|
134
|
-
def where(self, *, exclude: bool = False, **kwargs: Any) -> "LLMConfig":
|
|
135
|
-
from .oai.openai_utils import filter_config
|
|
136
|
-
|
|
137
|
-
filtered_config_list = filter_config(config_list=self.config_list, filter_dict=kwargs, exclude=exclude)
|
|
138
|
-
if len(filtered_config_list) == 0:
|
|
139
|
-
raise ValueError(f"No config found that satisfies the filter criteria: {kwargs}")
|
|
140
|
-
|
|
141
|
-
kwargs = self.model_dump()
|
|
142
|
-
kwargs["config_list"] = filtered_config_list
|
|
143
|
-
|
|
144
|
-
return LLMConfig(**kwargs)
|
|
145
|
-
|
|
146
|
-
# @functools.wraps(BaseModel.model_dump)
|
|
147
|
-
def model_dump(self, *args: Any, exclude_none: bool = True, **kwargs: Any) -> dict[str, Any]:
|
|
148
|
-
d = self._model.model_dump(*args, exclude_none=exclude_none, **kwargs)
|
|
149
|
-
return {k: v for k, v in d.items() if not (isinstance(v, list) and len(v) == 0)}
|
|
150
|
-
|
|
151
|
-
# @functools.wraps(BaseModel.model_dump_json)
|
|
152
|
-
def model_dump_json(self, *args: Any, exclude_none: bool = True, **kwargs: Any) -> str:
|
|
153
|
-
# return self._model.model_dump_json(*args, exclude_none=exclude_none, **kwargs)
|
|
154
|
-
d = self.model_dump(*args, exclude_none=exclude_none, **kwargs)
|
|
155
|
-
return json.dumps(d)
|
|
156
|
-
|
|
157
|
-
# @functools.wraps(BaseModel.model_validate)
|
|
158
|
-
def model_validate(self, *args: Any, **kwargs: Any) -> Any:
|
|
159
|
-
return self._model.model_validate(*args, **kwargs)
|
|
160
|
-
|
|
161
|
-
@functools.wraps(BaseModel.model_validate_json)
|
|
162
|
-
def model_validate_json(self, *args: Any, **kwargs: Any) -> Any:
|
|
163
|
-
return self._model.model_validate_json(*args, **kwargs)
|
|
164
|
-
|
|
165
|
-
@functools.wraps(BaseModel.model_validate_strings)
|
|
166
|
-
def model_validate_strings(self, *args: Any, **kwargs: Any) -> Any:
|
|
167
|
-
return self._model.model_validate_strings(*args, **kwargs)
|
|
168
|
-
|
|
169
|
-
def __eq__(self, value: Any) -> bool:
|
|
170
|
-
return hasattr(value, "_model") and self._model == value._model
|
|
171
|
-
|
|
172
|
-
def _getattr(self, o: object, name: str) -> Any:
|
|
173
|
-
val = getattr(o, name)
|
|
174
|
-
return val
|
|
175
|
-
|
|
176
|
-
def get(self, key: str, default: Optional[Any] = None) -> Any:
|
|
177
|
-
val = getattr(self._model, key, default)
|
|
178
|
-
return val
|
|
179
|
-
|
|
180
|
-
def __getitem__(self, key: str) -> Any:
|
|
181
|
-
try:
|
|
182
|
-
return self._getattr(self._model, key)
|
|
183
|
-
except AttributeError:
|
|
184
|
-
raise KeyError(f"Key '{key}' not found in {self.__class__.__name__}")
|
|
185
|
-
|
|
186
|
-
def __setitem__(self, key: str, value: Any) -> None:
|
|
187
|
-
try:
|
|
188
|
-
setattr(self._model, key, value)
|
|
189
|
-
except ValueError:
|
|
190
|
-
raise ValueError(f"'{self.__class__.__name__}' object has no field '{key}'")
|
|
191
|
-
|
|
192
|
-
def __getattr__(self, name: Any) -> Any:
|
|
193
|
-
try:
|
|
194
|
-
return self._getattr(self._model, name)
|
|
195
|
-
except AttributeError:
|
|
196
|
-
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
|
|
197
|
-
|
|
198
|
-
def __setattr__(self, name: str, value: Any) -> None:
|
|
199
|
-
if name == "_model":
|
|
200
|
-
object.__setattr__(self, name, value)
|
|
201
|
-
else:
|
|
202
|
-
setattr(self._model, name, value)
|
|
203
|
-
|
|
204
|
-
def __contains__(self, key: str) -> bool:
|
|
205
|
-
return hasattr(self._model, key)
|
|
206
|
-
|
|
207
|
-
def __repr__(self) -> str:
|
|
208
|
-
d = self.model_dump()
|
|
209
|
-
r = [f"{k}={repr(v)}" for k, v in d.items()]
|
|
210
|
-
|
|
211
|
-
s = f"LLMConfig({', '.join(r)})"
|
|
212
|
-
# Replace any keys ending with 'key' or 'token' values with stars for security
|
|
213
|
-
s = re.sub(
|
|
214
|
-
r"(['\"])(\w*(key|token))\1:\s*(['\"])([^'\"]*)(?:\4)", r"\1\2\1: \4**********\4", s, flags=re.IGNORECASE
|
|
215
|
-
)
|
|
216
|
-
return s
|
|
217
|
-
|
|
218
|
-
def __copy__(self) -> "LLMConfig":
|
|
219
|
-
return LLMConfig(**self.model_dump())
|
|
220
|
-
|
|
221
|
-
def __deepcopy__(self, memo: Optional[dict[int, Any]] = None) -> "LLMConfig":
|
|
222
|
-
return self.__copy__()
|
|
223
|
-
|
|
224
|
-
def copy(self) -> "LLMConfig":
|
|
225
|
-
return self.__copy__()
|
|
226
|
-
|
|
227
|
-
def deepcopy(self, memo: Optional[dict[int, Any]] = None) -> "LLMConfig":
|
|
228
|
-
return self.__deepcopy__(memo)
|
|
229
|
-
|
|
230
|
-
def __str__(self) -> str:
|
|
231
|
-
return repr(self)
|
|
232
|
-
|
|
233
|
-
def items(self) -> Iterable[tuple[str, Any]]:
|
|
234
|
-
d = self.model_dump()
|
|
235
|
-
return d.items()
|
|
236
|
-
|
|
237
|
-
def keys(self) -> Iterable[str]:
|
|
238
|
-
d = self.model_dump()
|
|
239
|
-
return d.keys()
|
|
240
|
-
|
|
241
|
-
def values(self) -> Iterable[Any]:
|
|
242
|
-
d = self.model_dump()
|
|
243
|
-
return d.values()
|
|
244
|
-
|
|
245
|
-
_base_model_classes: dict[tuple[Type["LLMConfigEntry"], ...], Type[BaseModel]] = {}
|
|
246
|
-
|
|
247
|
-
@classmethod
|
|
248
|
-
def _get_base_model_class(cls) -> Type["BaseModel"]:
|
|
249
|
-
def _get_cls(llm_config_classes: tuple[Type[LLMConfigEntry], ...]) -> Type[BaseModel]:
|
|
250
|
-
if llm_config_classes in LLMConfig._base_model_classes:
|
|
251
|
-
return LLMConfig._base_model_classes[llm_config_classes]
|
|
252
|
-
|
|
253
|
-
class _LLMConfig(BaseModel):
|
|
254
|
-
temperature: Optional[float] = None
|
|
255
|
-
check_every_ms: Optional[int] = None
|
|
256
|
-
max_new_tokens: Optional[int] = None
|
|
257
|
-
seed: Optional[int] = None
|
|
258
|
-
allow_format_str_template: Optional[bool] = None
|
|
259
|
-
response_format: Optional[Union[str, dict[str, Any], BaseModel, Type[BaseModel]]] = None
|
|
260
|
-
timeout: Optional[int] = None
|
|
261
|
-
cache_seed: Optional[int] = None
|
|
262
|
-
|
|
263
|
-
tools: list[Any] = Field(default_factory=list)
|
|
264
|
-
functions: list[Any] = Field(default_factory=list)
|
|
265
|
-
parallel_tool_calls: Optional[bool] = None
|
|
266
|
-
|
|
267
|
-
config_list: Annotated[ # type: ignore[valid-type]
|
|
268
|
-
list[Annotated[Union[llm_config_classes], Field(discriminator="api_type")]],
|
|
269
|
-
Field(default_factory=list, min_length=1),
|
|
270
|
-
]
|
|
271
|
-
routing_method: Optional[Literal["fixed_order", "round_robin"]] = None
|
|
272
|
-
|
|
273
|
-
# Following field is configuration for pydantic to disallow extra fields
|
|
274
|
-
model_config = ConfigDict(extra="forbid")
|
|
275
|
-
|
|
276
|
-
LLMConfig._base_model_classes[llm_config_classes] = _LLMConfig
|
|
277
|
-
|
|
278
|
-
return _LLMConfig
|
|
279
|
-
|
|
280
|
-
return _get_cls(tuple(_llm_config_classes))
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
class LLMConfigEntry(BaseModel, ABC):
|
|
284
|
-
api_type: str
|
|
285
|
-
model: str = Field(..., min_length=1)
|
|
286
|
-
api_key: Optional[SecretStr] = None
|
|
287
|
-
api_version: Optional[str] = None
|
|
288
|
-
max_tokens: Optional[int] = None
|
|
289
|
-
base_url: Optional[HttpUrl] = None
|
|
290
|
-
voice: Optional[str] = None
|
|
291
|
-
model_client_cls: Optional[str] = None
|
|
292
|
-
http_client: Optional[httpxClient] = None
|
|
293
|
-
response_format: Optional[Union[str, dict[str, Any], BaseModel, Type[BaseModel]]] = None
|
|
294
|
-
default_headers: Optional[Mapping[str, Any]] = None
|
|
295
|
-
tags: list[str] = Field(default_factory=list)
|
|
296
|
-
|
|
297
|
-
# Following field is configuration for pydantic to disallow extra fields
|
|
298
|
-
model_config = ConfigDict(extra="forbid", arbitrary_types_allowed=True)
|
|
299
|
-
|
|
300
|
-
@abstractmethod
|
|
301
|
-
def create_client(self) -> "ModelClient": ...
|
|
302
|
-
|
|
303
|
-
@field_validator("base_url", mode="before")
|
|
304
|
-
@classmethod
|
|
305
|
-
def check_base_url(cls, v: Any, info: ValidationInfo) -> Any:
|
|
306
|
-
if v is None: # Handle None case explicitly
|
|
307
|
-
return None
|
|
308
|
-
if not str(v).startswith("https://") and not str(v).startswith("http://"):
|
|
309
|
-
v = f"http://{str(v)}"
|
|
310
|
-
return v
|
|
311
|
-
|
|
312
|
-
@field_serializer("base_url", when_used="unless-none") # Ensure serializer also respects None
|
|
313
|
-
def serialize_base_url(self, v: Any) -> Any:
|
|
314
|
-
return str(v) if v is not None else None
|
|
315
|
-
|
|
316
|
-
@field_serializer("api_key", when_used="unless-none")
|
|
317
|
-
def serialize_api_key(self, v: SecretStr) -> Any:
|
|
318
|
-
return v.get_secret_value()
|
|
319
|
-
|
|
320
|
-
def model_dump(self, *args: Any, exclude_none: bool = True, **kwargs: Any) -> dict[str, Any]:
|
|
321
|
-
return BaseModel.model_dump(self, exclude_none=exclude_none, *args, **kwargs)
|
|
322
|
-
|
|
323
|
-
def model_dump_json(self, *args: Any, exclude_none: bool = True, **kwargs: Any) -> str:
|
|
324
|
-
return BaseModel.model_dump_json(self, exclude_none=exclude_none, *args, **kwargs)
|
|
325
|
-
|
|
326
|
-
def get(self, key: str, default: Optional[Any] = None) -> Any:
|
|
327
|
-
val = getattr(self, key, default)
|
|
328
|
-
if isinstance(val, SecretStr):
|
|
329
|
-
return val.get_secret_value()
|
|
330
|
-
return val
|
|
331
|
-
|
|
332
|
-
def __getitem__(self, key: str) -> Any:
|
|
333
|
-
try:
|
|
334
|
-
val = getattr(self, key)
|
|
335
|
-
if isinstance(val, SecretStr):
|
|
336
|
-
return val.get_secret_value()
|
|
337
|
-
return val
|
|
338
|
-
except AttributeError:
|
|
339
|
-
raise KeyError(f"Key '{key}' not found in {self.__class__.__name__}")
|
|
340
|
-
|
|
341
|
-
def __setitem__(self, key: str, value: Any) -> None:
|
|
342
|
-
setattr(self, key, value)
|
|
343
|
-
|
|
344
|
-
def __contains__(self, key: str) -> bool:
|
|
345
|
-
return hasattr(self, key)
|
|
346
|
-
|
|
347
|
-
def items(self) -> Iterable[tuple[str, Any]]:
|
|
348
|
-
d = self.model_dump()
|
|
349
|
-
return d.items()
|
|
350
|
-
|
|
351
|
-
def keys(self) -> Iterable[str]:
|
|
352
|
-
d = self.model_dump()
|
|
353
|
-
return d.keys()
|
|
354
|
-
|
|
355
|
-
def values(self) -> Iterable[Any]:
|
|
356
|
-
d = self.model_dump()
|
|
357
|
-
return d.values()
|
|
358
|
-
|
|
359
|
-
def __repr__(self) -> str:
|
|
360
|
-
# Override to eliminate none values from the repr
|
|
361
|
-
d = self.model_dump()
|
|
362
|
-
r = [f"{k}={repr(v)}" for k, v in d.items()]
|
|
363
|
-
|
|
364
|
-
s = f"{self.__class__.__name__}({', '.join(r)})"
|
|
365
|
-
|
|
366
|
-
# Replace any keys ending with '_key' or '_token' values with stars for security
|
|
367
|
-
# This regex will match any key ending with '_key' or '_token' and its value, and replace the value with stars
|
|
368
|
-
# It also captures the type of quote used (single or double) and reuses it in the replacement
|
|
369
|
-
s = re.sub(r'(\w+_(key|token)\s*=\s*)([\'"]).*?\3', r"\1\3**********\3", s, flags=re.IGNORECASE)
|
|
370
|
-
|
|
371
|
-
return s
|
|
372
|
-
|
|
373
|
-
def __str__(self) -> str:
|
|
374
|
-
return repr(self)
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
_llm_config_classes: list[Type[LLMConfigEntry]] = []
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
def register_llm_config(cls: Type[LLMConfigEntry]) -> Type[LLMConfigEntry]:
|
|
381
|
-
if isinstance(cls, type) and issubclass(cls, LLMConfigEntry):
|
|
382
|
-
_llm_config_classes.append(cls)
|
|
383
|
-
else:
|
|
384
|
-
raise TypeError(f"Expected a subclass of LLMConfigEntry, got {cls}")
|
|
385
|
-
return cls
|
|
File without changes
|
|
File without changes
|
|
File without changes
|