api_base fix + litellm update

frdel committed Jul 9, 2025 at 10:30 UTC 3b18b86454715bae7cdb33dd029938f5ecc5b2aa
7 files changed +69 -69
agent.py
+15 -26
@@ -202,25 +202,13 @@ class AgentContext:
202 agent.handle_critical_exception(e)
203
204
205 -@dataclass
206 -class ModelConfig:
207 - provider: models.ModelProvider
208 - name: str
209 - api_base: str = ""
210 - ctx_length: int = 0
211 - limit_requests: int = 0
212 - limit_input: int = 0
213 - limit_output: int = 0
214 - vision: bool = False
215 - kwargs: dict = field(default_factory=dict)
216 -
205
206 @dataclass
207 class AgentConfig:
220 - chat_model: ModelConfig
221 - utility_model: ModelConfig
222 - embeddings_model: ModelConfig
223 - browser_model: ModelConfig
208 + chat_model: models.ModelConfig
209 + utility_model: models.ModelConfig
210 + embeddings_model: models.ModelConfig
211 + browser_model: models.ModelConfig
212 mcp_servers: str
213 prompts_subdir: str = ""
214 memory_subdir: str = ""
@@ -582,29 +570,30 @@ class Agent:
570 return models.get_chat_model(
571 self.config.chat_model.provider,
572 self.config.chat_model.name,
585 - **self._get_model_kwargs(self.config.chat_model),
573 + **self.config.chat_model.build_kwargs(),
574 )
575
576 def get_utility_model(self):
577 return models.get_chat_model(
578 self.config.utility_model.provider,
579 self.config.utility_model.name,
592 - **self._get_model_kwargs(self.config.utility_model),
580 + **self.config.utility_model.build_kwargs(),
581 + )
582 +
583 + def get_browser_model(self):
584 + return models.get_browser_model(
585 + self.config.browser_model.provider,
586 + self.config.browser_model.name,
587 + **self.config.browser_model.build_kwargs(),
588 )
589
590 def get_embedding_model(self):
591 return models.get_embedding_model(
592 self.config.embeddings_model.provider,
593 self.config.embeddings_model.name,
599 - **self._get_model_kwargs(self.config.embeddings_model),
594 + **self.config.embeddings_model.build_kwargs(),
595 )
596
602 - def _get_model_kwargs(self, model_config: ModelConfig):
603 - kwargs = model_config.kwargs.copy() or {}
604 - if model_config.api_base and "api_base" not in kwargs:
605 - kwargs["api_base"] = model_config.api_base
606 - return kwargs
607 -
597 async def call_utility_model(
598 self,
599 system: str,
@@ -670,7 +659,7 @@ class Agent:
659 return response, reasoning
660
661 async def rate_limiter(
673 - self, model_config: ModelConfig, input: str, background: bool = False
662 + self, model_config: models.ModelConfig, input: str, background: bool = False
663 ):
664 # rate limiter log
665 wait_log = None
initialize.py
+9 -5
@@ -1,5 +1,5 @@
1 import models
2 -from agent import AgentConfig, ModelConfig
2 +from agent import AgentConfig
3 from python.helpers import runtime, settings, defer
4 from python.helpers.print_style import PrintStyle
5
@@ -26,7 +26,8 @@ def initialize_agent():
26 return result
27
28 # chat model from user settings
29 - chat_llm = ModelConfig(
29 + chat_llm = models.ModelConfig(
30 + type=models.ModelType.CHAT,
31 provider=models.ModelProvider[current_settings["chat_model_provider"]],
32 name=current_settings["chat_model_name"],
33 api_base=current_settings["chat_model_api_base"],
@@ -39,7 +40,8 @@ def initialize_agent():
40 )
41
42 # utility model from user settings
42 - utility_llm = ModelConfig(
43 + utility_llm = models.ModelConfig(
44 + type=models.ModelType.CHAT,
45 provider=models.ModelProvider[current_settings["util_model_provider"]],
46 name=current_settings["util_model_name"],
47 api_base=current_settings["util_model_api_base"],
@@ -50,7 +52,8 @@ def initialize_agent():
52 kwargs=_normalize_model_kwargs(current_settings["util_model_kwargs"]),
53 )
54 # embedding model from user settings
53 - embedding_llm = ModelConfig(
55 + embedding_llm = models.ModelConfig(
56 + type=models.ModelType.EMBEDDING,
57 provider=models.ModelProvider[current_settings["embed_model_provider"]],
58 name=current_settings["embed_model_name"],
59 api_base=current_settings["embed_model_api_base"],
@@ -58,7 +61,8 @@ def initialize_agent():
61 kwargs=_normalize_model_kwargs(current_settings["embed_model_kwargs"]),
62 )
63 # browser model from user settings
61 - browser_llm = ModelConfig(
64 + browser_llm = models.ModelConfig(
65 + type=models.ModelType.CHAT,
66 provider=models.ModelProvider[current_settings["browser_model_provider"]],
67 name=current_settings["browser_model_name"],
68 api_base=current_settings["browser_model_api_base"],
models.py
+27 -1
@@ -1,3 +1,4 @@
1 +from dataclasses import dataclass, field
2 from enum import Enum
3 import logging
4 import os
@@ -73,6 +74,26 @@ class ModelProvider(Enum):
74 OTHER = "Other OpenAI compatible"
75
76
77 +@dataclass
78 +class ModelConfig:
79 + type: ModelType
80 + provider: ModelProvider
81 + name: str
82 + api_base: str = ""
83 + ctx_length: int = 0
84 + limit_requests: int = 0
85 + limit_input: int = 0
86 + limit_output: int = 0
87 + vision: bool = False
88 + kwargs: dict = field(default_factory=dict)
89 +
90 + def build_kwargs(self):
91 + kwargs = self.kwargs.copy() or {}
92 + if self.api_base and "api_base" not in kwargs:
93 + kwargs["api_base"] = self.api_base
94 + return kwargs
95 +
96 +
97 class ChatChunk(TypedDict):
98 """Simplified response chunk for chat models."""
99
@@ -233,6 +254,9 @@ class LiteLLMChatWrapper(SimpleChatModel):
254 tokens_callback: Callable[[str, int], Awaitable[None]] | None = None,
255 **kwargs: Any,
256 ) -> Tuple[str, str]:
257 +
258 + turn_off_logging()
259 +
260 if not messages:
261 messages = []
262 # construct messages
@@ -408,7 +432,9 @@ def _get_litellm_embedding(model_name: str, provider_name: str, **kwargs: Any):
432
433 def _parse_chunk(chunk: Any) -> ChatChunk:
434 delta = chunk["choices"][0].get("delta", {})
411 - message = chunk["choices"][0].get("model_extra", {}).get("message", {})
435 + message = chunk["choices"][0].get("message", {}) or chunk["choices"][0].get(
436 + "model_extra", {}
437 + ).get("message", {})
438 response_delta = (
439 delta.get("content", "")
440 if isinstance(delta, dict)
python/helpers/memory.py
+3 -10
@@ -28,7 +28,7 @@ import uuid
28 from python.helpers import knowledge_import
29 from python.helpers.log import Log, LogItem
30 from enum import Enum
31 -from agent import Agent, ModelConfig
31 +from agent import Agent
32 import models
33 import logging
34
@@ -96,7 +96,7 @@ class Memory:
96 @staticmethod
97 def initialize(
98 log_item: LogItem | None,
99 - model_config: ModelConfig,
99 + model_config: models.ModelConfig,
100 memory_subdir: str,
101 in_memory=False,
102 ) -> tuple[MyFaiss, bool]:
@@ -120,17 +120,10 @@ class Memory:
120 os.makedirs(em_dir, exist_ok=True)
121 store = LocalFileStore(em_dir)
122
123 - # HOTFIX TODO: unify with agent.py
124 - def _get_model_kwargs(model_config: ModelConfig):
125 - kwargs = model_config.kwargs.copy() or {}
126 - if model_config.api_base and "api_base" not in kwargs:
127 - kwargs["api_base"] = model_config.api_base
128 - return kwargs
129 -
123 embeddings_model = models.get_embedding_model(
124 model_config.provider,
125 model_config.name,
133 - **_get_model_kwargs(model_config),
126 + **model_config.build_kwargs(),
127 )
128 embeddings_model_id = files.safe_file_name(
129 model_config.provider.name + "_" + model_config.name
python/helpers/settings.py
+13 -21
@@ -122,6 +122,7 @@ _settings: Settings | None = None
122
123 def convert_out(settings: Settings) -> SettingsOutput:
124 from models import ModelProvider
125 + default_settings = get_default_settings()
126
127 # main model section
128 chat_model_fields: list[SettingsField] = []
@@ -381,7 +382,7 @@ def convert_out(settings: Settings) -> SettingsOutput:
382 embed_model_section: SettingsSection = {
383 "id": "embed_model",
384 "title": "Embedding Model",
384 - "description": "Settings for the embedding model used by Agent Zero.",
385 + "description": f"Settings for the embedding model used by Agent Zero.<br><h4>⚠️ No need to change</h4>The default HuggingFace model {default_settings['embed_model_name']} is preloaded and runs locally within the docker container and there's no need to change it unless you have a specific requirements for embedding.",
386 "fields": embed_model_fields,
387 "tab": "agent",
388 }
@@ -408,6 +409,16 @@ def convert_out(settings: Settings) -> SettingsOutput:
409 }
410 )
411
412 + browser_model_fields.append(
413 + {
414 + "id": "browser_model_api_base",
415 + "title": "Web Browser model API base URL",
416 + "description": "API base URL for web browser model. Leave empty for default. Only relevant for Azure, local and custom (other) providers.",
417 + "type": "text",
418 + "value": settings["browser_model_api_base"],
419 + }
420 + )
421 +
422 browser_model_fields.append(
423 {
424 "id": "browser_model_vision",
@@ -436,24 +447,6 @@ def convert_out(settings: Settings) -> SettingsOutput:
447 "tab": "agent",
448 }
449
439 - # # Memory settings section
440 - # memory_fields: list[SettingsField] = []
441 - # memory_fields.append(
442 - # {
443 - # "id": "memory_settings",
444 - # "title": "Memory Settings",
445 - # "description": "<settings for memory>",
446 - # "type": "text",
447 - # "value": "",
448 - # }
449 - # )
450 -
451 - # memory_section: SettingsSection = {
452 - # "id": "memory",
453 - # "title": "Memory Settings",
454 - # "description": "<settings for memory management here>",
455 - # "fields": memory_fields,
456 - # }
450
451 # basic auth section
452 auth_fields: list[SettingsField] = []
@@ -829,9 +822,8 @@ def convert_out(settings: Settings) -> SettingsOutput:
822 agent_section,
823 chat_model_section,
824 util_model_section,
832 - embed_model_section,
825 browser_model_section,
834 - # memory_section,
826 + embed_model_section,
827 stt_section,
828 api_keys_section,
829 auth_section,
python/tools/browser_agent.py
+1 -5
@@ -125,11 +125,7 @@ class State:
125 )
126 return result
127
128 - model = models.get_browser_model(
129 - provider=self.agent.config.browser_model.provider,
130 - name=self.agent.config.browser_model.name,
131 - **self.agent._get_model_kwargs(self.agent.config.browser_model),
132 - )
128 + model = self.agent.get_browser_model()
129
130 try:
131 self.use_agent = browser_use.Agent(
requirements.txt
+1 -1
@@ -30,7 +30,7 @@ unstructured-client==0.31.0
30 webcolors==24.6.0
31 nest-asyncio==1.6.0
32 crontab==1.0.1
33 -litellm==1.72.4
33 +litellm==1.74
34 markdownify==1.1.0
35 pymupdf==1.25.3
36 pytesseract==0.3.13