autobyteus 1.1.8__py3-none-any.whl → 1.2.0__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.
Files changed (127) hide show
  1. autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +6 -2
  2. autobyteus/agent/handlers/inter_agent_message_event_handler.py +17 -19
  3. autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +6 -3
  4. autobyteus/agent/handlers/tool_result_event_handler.py +61 -18
  5. autobyteus/agent/handlers/user_input_message_event_handler.py +19 -10
  6. autobyteus/agent/hooks/base_phase_hook.py +17 -0
  7. autobyteus/agent/hooks/hook_registry.py +15 -27
  8. autobyteus/agent/input_processor/base_user_input_processor.py +17 -1
  9. autobyteus/agent/input_processor/processor_registry.py +15 -27
  10. autobyteus/agent/llm_response_processor/base_processor.py +17 -1
  11. autobyteus/agent/llm_response_processor/processor_registry.py +15 -24
  12. autobyteus/agent/llm_response_processor/provider_aware_tool_usage_processor.py +14 -0
  13. autobyteus/agent/message/agent_input_user_message.py +15 -2
  14. autobyteus/agent/message/send_message_to.py +1 -1
  15. autobyteus/agent/processor_option.py +17 -0
  16. autobyteus/agent/sender_type.py +1 -0
  17. autobyteus/agent/system_prompt_processor/base_processor.py +17 -1
  18. autobyteus/agent/system_prompt_processor/processor_registry.py +15 -27
  19. autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +10 -0
  20. autobyteus/agent/tool_execution_result_processor/base_processor.py +17 -1
  21. autobyteus/agent/tool_execution_result_processor/processor_registry.py +15 -1
  22. autobyteus/agent/workspace/base_workspace.py +1 -1
  23. autobyteus/agent/workspace/workspace_definition.py +1 -1
  24. autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +1 -1
  25. autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +2 -2
  26. autobyteus/agent_team/task_notification/__init__.py +4 -0
  27. autobyteus/agent_team/task_notification/activation_policy.py +70 -0
  28. autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +56 -122
  29. autobyteus/agent_team/task_notification/task_activator.py +66 -0
  30. autobyteus/cli/agent_team_tui/state.py +17 -20
  31. autobyteus/cli/agent_team_tui/widgets/focus_pane.py +1 -1
  32. autobyteus/cli/agent_team_tui/widgets/task_board_panel.py +1 -1
  33. autobyteus/clients/__init__.py +10 -0
  34. autobyteus/clients/autobyteus_client.py +318 -0
  35. autobyteus/clients/cert_utils.py +105 -0
  36. autobyteus/clients/certificates/cert.pem +34 -0
  37. autobyteus/events/event_types.py +2 -2
  38. autobyteus/llm/api/autobyteus_llm.py +1 -1
  39. autobyteus/llm/api/gemini_llm.py +45 -54
  40. autobyteus/llm/api/qwen_llm.py +25 -0
  41. autobyteus/llm/api/zhipu_llm.py +26 -0
  42. autobyteus/llm/autobyteus_provider.py +9 -3
  43. autobyteus/llm/llm_factory.py +39 -0
  44. autobyteus/llm/ollama_provider_resolver.py +1 -0
  45. autobyteus/llm/providers.py +1 -0
  46. autobyteus/llm/token_counter/token_counter_factory.py +3 -0
  47. autobyteus/llm/token_counter/zhipu_token_counter.py +24 -0
  48. autobyteus/multimedia/audio/api/autobyteus_audio_client.py +5 -2
  49. autobyteus/multimedia/audio/api/gemini_audio_client.py +84 -153
  50. autobyteus/multimedia/audio/audio_client_factory.py +47 -22
  51. autobyteus/multimedia/audio/audio_model.py +13 -6
  52. autobyteus/multimedia/audio/autobyteus_audio_provider.py +9 -3
  53. autobyteus/multimedia/audio/base_audio_client.py +3 -1
  54. autobyteus/multimedia/image/api/autobyteus_image_client.py +13 -6
  55. autobyteus/multimedia/image/api/gemini_image_client.py +72 -130
  56. autobyteus/multimedia/image/api/openai_image_client.py +4 -2
  57. autobyteus/multimedia/image/autobyteus_image_provider.py +9 -3
  58. autobyteus/multimedia/image/base_image_client.py +6 -2
  59. autobyteus/multimedia/image/image_client_factory.py +20 -19
  60. autobyteus/multimedia/image/image_model.py +13 -6
  61. autobyteus/multimedia/providers.py +1 -0
  62. autobyteus/task_management/__init__.py +10 -10
  63. autobyteus/task_management/base_task_board.py +14 -6
  64. autobyteus/task_management/converters/__init__.py +0 -2
  65. autobyteus/task_management/converters/task_board_converter.py +7 -16
  66. autobyteus/task_management/events.py +6 -6
  67. autobyteus/task_management/in_memory_task_board.py +48 -38
  68. autobyteus/task_management/schemas/__init__.py +2 -2
  69. autobyteus/task_management/schemas/{plan_definition.py → task_definition.py} +6 -7
  70. autobyteus/task_management/schemas/task_status_report.py +1 -2
  71. autobyteus/task_management/task.py +60 -0
  72. autobyteus/task_management/tools/__init__.py +6 -2
  73. autobyteus/task_management/tools/assign_task_to.py +125 -0
  74. autobyteus/task_management/tools/get_my_tasks.py +80 -0
  75. autobyteus/task_management/tools/get_task_board_status.py +3 -3
  76. autobyteus/task_management/tools/publish_task.py +77 -0
  77. autobyteus/task_management/tools/publish_tasks.py +74 -0
  78. autobyteus/task_management/tools/update_task_status.py +5 -5
  79. autobyteus/tools/__init__.py +54 -16
  80. autobyteus/tools/base_tool.py +4 -4
  81. autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +1 -1
  82. autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +1 -1
  83. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +1 -1
  84. autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +1 -1
  85. autobyteus/tools/browser/standalone/navigate_to.py +1 -1
  86. autobyteus/tools/browser/standalone/web_page_pdf_generator.py +1 -1
  87. autobyteus/tools/browser/standalone/webpage_image_downloader.py +1 -1
  88. autobyteus/tools/browser/standalone/webpage_reader.py +1 -1
  89. autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +1 -1
  90. autobyteus/tools/download_media_tool.py +136 -0
  91. autobyteus/tools/file/file_editor.py +200 -0
  92. autobyteus/tools/functional_tool.py +1 -1
  93. autobyteus/tools/google_search.py +1 -1
  94. autobyteus/tools/mcp/factory.py +1 -1
  95. autobyteus/tools/mcp/schema_mapper.py +1 -1
  96. autobyteus/tools/mcp/tool.py +1 -1
  97. autobyteus/tools/multimedia/__init__.py +2 -0
  98. autobyteus/tools/multimedia/audio_tools.py +10 -20
  99. autobyteus/tools/multimedia/image_tools.py +21 -22
  100. autobyteus/tools/multimedia/media_reader_tool.py +117 -0
  101. autobyteus/tools/pydantic_schema_converter.py +1 -1
  102. autobyteus/tools/registry/tool_definition.py +1 -1
  103. autobyteus/tools/timer.py +1 -1
  104. autobyteus/tools/tool_meta.py +1 -1
  105. autobyteus/tools/usage/formatters/default_json_example_formatter.py +1 -1
  106. autobyteus/tools/usage/formatters/default_xml_example_formatter.py +1 -1
  107. autobyteus/tools/usage/formatters/default_xml_schema_formatter.py +59 -3
  108. autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +1 -1
  109. autobyteus/tools/usage/formatters/google_json_example_formatter.py +1 -1
  110. autobyteus/tools/usage/formatters/openai_json_example_formatter.py +1 -1
  111. autobyteus/tools/usage/parsers/_string_decoders.py +18 -0
  112. autobyteus/tools/usage/parsers/default_json_tool_usage_parser.py +9 -1
  113. autobyteus/tools/usage/parsers/default_xml_tool_usage_parser.py +15 -1
  114. autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +4 -1
  115. autobyteus/tools/usage/parsers/openai_json_tool_usage_parser.py +4 -1
  116. autobyteus/{tools → utils}/parameter_schema.py +1 -1
  117. {autobyteus-1.1.8.dist-info → autobyteus-1.2.0.dist-info}/METADATA +4 -3
  118. {autobyteus-1.1.8.dist-info → autobyteus-1.2.0.dist-info}/RECORD +122 -108
  119. examples/run_poem_writer.py +1 -1
  120. autobyteus/task_management/converters/task_plan_converter.py +0 -48
  121. autobyteus/task_management/task_plan.py +0 -110
  122. autobyteus/task_management/tools/publish_task_plan.py +0 -101
  123. autobyteus/tools/image_downloader.py +0 -99
  124. autobyteus/tools/pdf_downloader.py +0 -89
  125. {autobyteus-1.1.8.dist-info → autobyteus-1.2.0.dist-info}/WHEEL +0 -0
  126. {autobyteus-1.1.8.dist-info → autobyteus-1.2.0.dist-info}/licenses/LICENSE +0 -0
  127. {autobyteus-1.1.8.dist-info → autobyteus-1.2.0.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  import logging
2
- from typing import Dict, List, AsyncGenerator, Any
3
- import google.generativeai as genai # CHANGED: Using the older 'google.generativeai' library
2
+ from typing import Dict, Optional, List, AsyncGenerator, Any
3
+ from google import genai
4
+ from google.genai import types as genai_types
4
5
  import os
5
6
  from autobyteus.llm.models import LLMModel
6
7
  from autobyteus.llm.base_llm import BaseLLM
@@ -13,66 +14,60 @@ from autobyteus.llm.user_message import LLMUserMessage
13
14
  logger = logging.getLogger(__name__)
14
15
 
15
16
  def _format_gemini_history(messages: List[Message]) -> List[Dict[str, Any]]:
16
- """
17
- Formats internal message history for the Gemini API.
18
- This function remains compatible with the older library.
19
- """
17
+ """Formats internal message history for the Gemini API."""
20
18
  history = []
21
- # System message is handled separately in the model initialization
19
+ # System message is handled separately in the new API
22
20
  for msg in messages:
23
21
  if msg.role in [MessageRole.USER, MessageRole.ASSISTANT]:
22
+ # NOTE: This history conversion will need to be updated for multimodal messages
24
23
  role = 'model' if msg.role == MessageRole.ASSISTANT else 'user'
24
+ # The `parts` must be a list of dictionaries (Part objects), not a list of strings.
25
25
  history.append({"role": role, "parts": [{"text": msg.content}]})
26
26
  return history
27
27
 
28
28
  class GeminiLLM(BaseLLM):
29
29
  def __init__(self, model: LLMModel = None, llm_config: LLMConfig = None):
30
+ self.generation_config_dict = {
31
+ "response_mime_type": "text/plain",
32
+ }
33
+
30
34
  if model is None:
31
- model = LLMModel['gemini-2.5-flash'] # Note: Ensure model name is compatible, e.g., 'gemini-1.5-flash-latest'
35
+ model = LLMModel['gemini-2.5-flash']
32
36
  if llm_config is None:
33
37
  llm_config = LLMConfig()
34
-
38
+
35
39
  super().__init__(model=model, llm_config=llm_config)
36
-
37
- # CHANGED: Initialization flow. Configure API key and then instantiate the model.
38
- self.initialize()
39
-
40
- system_instruction = self.system_message if self.system_message else None
41
-
42
- self.model = genai.GenerativeModel(
43
- model_name=self.model.value,
44
- system_instruction=system_instruction
45
- )
40
+ self.client = self.initialize()
41
+ self.async_client = self.client.aio
46
42
 
47
- @staticmethod
48
- def initialize():
49
- """
50
- CHANGED: This method now configures the genai library with the API key
51
- instead of creating a client instance.
52
- """
43
+ @classmethod
44
+ def initialize(cls) -> genai.client.Client:
53
45
  api_key = os.environ.get("GEMINI_API_KEY")
54
46
  if not api_key:
55
47
  logger.error("GEMINI_API_KEY environment variable is not set.")
56
48
  raise ValueError("GEMINI_API_KEY environment variable is not set.")
57
49
  try:
58
- genai.configure(api_key=api_key)
50
+ return genai.Client()
59
51
  except Exception as e:
60
- logger.error(f"Failed to configure Gemini client: {str(e)}")
61
- raise ValueError(f"Failed to configure Gemini client: {str(e)}")
52
+ logger.error(f"Failed to initialize Gemini client: {str(e)}")
53
+ raise ValueError(f"Failed to initialize Gemini client: {str(e)}")
62
54
 
63
- def _get_generation_config(self) -> Dict[str, Any]:
64
- """
65
- CHANGED: Builds the generation config as a dictionary.
66
- 'thinking_config' is not available in the old library.
67
- 'system_instruction' is passed during model initialization.
68
- """
69
- # Basic configuration, you can expand this with temperature, top_p, etc.
70
- # from self.llm_config if needed.
71
- config = {
72
- "response_mime_type": "text/plain",
73
- # Example: "temperature": self.llm_config.temperature
74
- }
75
- return config
55
+ def _get_generation_config(self) -> genai_types.GenerateContentConfig:
56
+ """Builds the generation config, handling special cases like 'thinking'."""
57
+ config = self.generation_config_dict.copy()
58
+
59
+ thinking_config = None
60
+ if "flash" in self.model.value:
61
+ thinking_config = genai_types.ThinkingConfig(thinking_budget=0)
62
+
63
+ # System instruction is now part of the config
64
+ system_instruction = self.system_message if self.system_message else None
65
+
66
+ return genai_types.GenerateContentConfig(
67
+ **config,
68
+ thinking_config=thinking_config,
69
+ system_instruction=system_instruction
70
+ )
76
71
 
77
72
  async def _send_user_message_to_llm(self, user_message: LLMUserMessage, **kwargs) -> CompleteResponse:
78
73
  self.add_user_message(user_message)
@@ -81,20 +76,19 @@ class GeminiLLM(BaseLLM):
81
76
  history = _format_gemini_history(self.messages)
82
77
  generation_config = self._get_generation_config()
83
78
 
84
- # CHANGED: API call now uses the model instance directly.
85
- response = await self.model.generate_content_async(
79
+ response = await self.async_client.models.generate_content(
80
+ model=f"models/{self.model.value}",
86
81
  contents=history,
87
- generation_config=generation_config,
82
+ config=generation_config,
88
83
  )
89
84
 
90
85
  assistant_message = response.text
91
86
  self.add_assistant_message(assistant_message)
92
87
 
93
- # CHANGED: Token usage is extracted from 'usage_metadata'.
94
88
  token_usage = TokenUsage(
95
- prompt_tokens=response.usage_metadata.prompt_token_count,
96
- completion_tokens=response.usage_metadata.candidates_token_count,
97
- total_tokens=response.usage_metadata.total_token_count
89
+ prompt_tokens=0,
90
+ completion_tokens=0,
91
+ total_tokens=0
98
92
  )
99
93
 
100
94
  return CompleteResponse(
@@ -113,11 +107,10 @@ class GeminiLLM(BaseLLM):
113
107
  history = _format_gemini_history(self.messages)
114
108
  generation_config = self._get_generation_config()
115
109
 
116
- # CHANGED: API call for streaming is now part of generate_content_async.
117
- response_stream = await self.model.generate_content_async(
110
+ response_stream = await self.async_client.models.generate_content_stream(
111
+ model=f"models/{self.model.value}",
118
112
  contents=history,
119
- generation_config=generation_config,
120
- stream=True
113
+ config=generation_config,
121
114
  )
122
115
 
123
116
  async for chunk in response_stream:
@@ -130,8 +123,6 @@ class GeminiLLM(BaseLLM):
130
123
 
131
124
  self.add_assistant_message(complete_response)
132
125
 
133
- # NOTE: The old library's async stream does not easily expose token usage.
134
- # Keeping it at 0, consistent with your original implementation.
135
126
  token_usage = TokenUsage(
136
127
  prompt_tokens=0,
137
128
  completion_tokens=0,
@@ -0,0 +1,25 @@
1
+ import logging
2
+ from typing import Optional
3
+ from autobyteus.llm.models import LLMModel
4
+ from autobyteus.llm.utils.llm_config import LLMConfig
5
+ from autobyteus.llm.api.openai_compatible_llm import OpenAICompatibleLLM
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ class QwenLLM(OpenAICompatibleLLM):
10
+ def __init__(self, model: LLMModel = None, llm_config: LLMConfig = None):
11
+ if model is None:
12
+ model = LLMModel['qwen3-max-preview']
13
+ if llm_config is None:
14
+ llm_config = LLMConfig()
15
+
16
+ super().__init__(
17
+ model=model,
18
+ llm_config=llm_config,
19
+ api_key_env_var="DASHSCOPE_API_KEY",
20
+ base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1"
21
+ )
22
+ logger.info(f"QwenLLM initialized with model: {self.model}")
23
+
24
+ async def cleanup(self):
25
+ await super().cleanup()
@@ -0,0 +1,26 @@
1
+ import logging
2
+ from typing import Optional
3
+ from autobyteus.llm.models import LLMModel
4
+ from autobyteus.llm.utils.llm_config import LLMConfig
5
+ from autobyteus.llm.api.openai_compatible_llm import OpenAICompatibleLLM
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ class ZhipuLLM(OpenAICompatibleLLM):
10
+ def __init__(self, model: LLMModel = None, llm_config: LLMConfig = None):
11
+ # Provide defaults if not specified
12
+ if model is None:
13
+ model = LLMModel['glm-4.6']
14
+ if llm_config is None:
15
+ llm_config = LLMConfig()
16
+
17
+ super().__init__(
18
+ model=model,
19
+ llm_config=llm_config,
20
+ api_key_env_var="ZHIPU_API_KEY",
21
+ base_url="https://open.bigmodel.cn/api/paas/v4/"
22
+ )
23
+ logger.info(f"ZhipuLLM initialized with model: {self.model}")
24
+
25
+ async def cleanup(self):
26
+ await super().cleanup()
@@ -7,7 +7,7 @@ from typing import Dict, Any, TYPE_CHECKING, List, Optional
7
7
  import os
8
8
  import logging
9
9
  from urllib.parse import urlparse
10
- from autobyteus_llm_client import AutobyteusClient
10
+ from autobyteus.clients import AutobyteusClient
11
11
 
12
12
  if TYPE_CHECKING:
13
13
  from autobyteus.llm.llm_factory import LLMFactory
@@ -19,7 +19,9 @@ class AutobyteusModelProvider:
19
19
 
20
20
  @staticmethod
21
21
  def _get_hosts() -> List[str]:
22
- """Gets Autobyteus LLM server hosts from env vars, supporting a comma-separated list."""
22
+ """
23
+ Gets Autobyteus LLM server hosts from env vars. Skips discovery if no host is configured.
24
+ """
23
25
  hosts_str = os.getenv('AUTOBYTEUS_LLM_SERVER_HOSTS')
24
26
  if hosts_str:
25
27
  return [host.strip() for host in hosts_str.split(',')]
@@ -28,7 +30,7 @@ class AutobyteusModelProvider:
28
30
  if legacy_host:
29
31
  return [legacy_host]
30
32
 
31
- return [AutobyteusModelProvider.DEFAULT_SERVER_URL]
33
+ return []
32
34
 
33
35
  @staticmethod
34
36
  def discover_and_register():
@@ -37,6 +39,10 @@ class AutobyteusModelProvider:
37
39
  from autobyteus.llm.llm_factory import LLMFactory
38
40
 
39
41
  hosts = AutobyteusModelProvider._get_hosts()
42
+ if not hosts:
43
+ logger.info("No Autobyteus LLM server hosts configured. Skipping Autobyteus LLM model discovery.")
44
+ return
45
+
40
46
  total_registered_count = 0
41
47
 
42
48
  for host_url in hosts:
@@ -17,6 +17,8 @@ from autobyteus.llm.api.deepseek_llm import DeepSeekLLM
17
17
  from autobyteus.llm.api.gemini_llm import GeminiLLM
18
18
  from autobyteus.llm.api.grok_llm import GrokLLM
19
19
  from autobyteus.llm.api.kimi_llm import KimiLLM
20
+ from autobyteus.llm.api.qwen_llm import QwenLLM
21
+ from autobyteus.llm.api.zhipu_llm import ZhipuLLM
20
22
  from autobyteus.llm.ollama_provider import OllamaModelProvider
21
23
  from autobyteus.llm.lmstudio_provider import LMStudioModelProvider
22
24
  from autobyteus.utils.singleton import SingletonMeta
@@ -344,6 +346,43 @@ class LLMFactory(metaclass=SingletonMeta):
344
346
  pricing_config=TokenPricingConfig(27.59, 27.59)
345
347
  )
346
348
  ),
349
+ # QWEN Provider Models
350
+ LLMModel(
351
+ name="qwen3-max",
352
+ value="qwen-max",
353
+ provider=LLMProvider.QWEN,
354
+ llm_class=QwenLLM,
355
+ canonical_name="qwen3-max",
356
+ default_config=LLMConfig(
357
+ token_limit=262144,
358
+ pricing_config=TokenPricingConfig(
359
+ input_token_pricing=2.4,
360
+ output_token_pricing=12.0
361
+ )
362
+ )
363
+ ),
364
+ # ZHIPU Provider Models
365
+ LLMModel(
366
+ name="glm-4.6",
367
+ value="glm-4.6",
368
+ provider=LLMProvider.ZHIPU,
369
+ llm_class=ZhipuLLM,
370
+ canonical_name="glm-4.6",
371
+ default_config=LLMConfig(
372
+ pricing_config=TokenPricingConfig(13.8, 13.8)
373
+ )
374
+ ),
375
+ LLMModel(
376
+ name="glm-4.6-thinking",
377
+ value="glm-4.6",
378
+ provider=LLMProvider.ZHIPU,
379
+ llm_class=ZhipuLLM,
380
+ canonical_name="glm-4.6-thinking",
381
+ default_config=LLMConfig(
382
+ pricing_config=TokenPricingConfig(13.8, 13.8),
383
+ extra_params={ "extra_body": { "thinking": { "type": "enabled" } } }
384
+ )
385
+ ),
347
386
  ]
348
387
  for model in supported_models:
349
388
  LLMFactory.register_model(model)
@@ -19,6 +19,7 @@ class OllamaProviderResolver:
19
19
  (['mistral'], LLMProvider.MISTRAL),
20
20
  (['deepseek'], LLMProvider.DEEPSEEK),
21
21
  (['qwen'], LLMProvider.QWEN),
22
+ (['glm'], LLMProvider.ZHIPU),
22
23
  ]
23
24
 
24
25
  @staticmethod
@@ -15,3 +15,4 @@ class LLMProvider(Enum):
15
15
  KIMI = "KIMI"
16
16
  QWEN = "QWEN"
17
17
  LMSTUDIO = "LMSTUDIO"
18
+ ZHIPU = "ZHIPU"
@@ -4,6 +4,7 @@ from autobyteus.llm.token_counter.claude_token_counter import ClaudeTokenCounter
4
4
  from autobyteus.llm.token_counter.mistral_token_counter import MistralTokenCounter
5
5
  from autobyteus.llm.token_counter.deepseek_token_counter import DeepSeekTokenCounter
6
6
  from autobyteus.llm.token_counter.kimi_token_counter import KimiTokenCounter
7
+ from autobyteus.llm.token_counter.zhipu_token_counter import ZhipuTokenCounter
7
8
  from autobyteus.llm.token_counter.base_token_counter import BaseTokenCounter
8
9
  from autobyteus.llm.models import LLMModel
9
10
  from autobyteus.llm.providers import LLMProvider
@@ -42,6 +43,8 @@ def get_token_counter(model: LLMModel, llm: 'BaseLLM') -> BaseTokenCounter:
42
43
  return OpenAITokenCounter(model, llm)
43
44
  elif model.provider == LLMProvider.GEMINI:
44
45
  return OpenAITokenCounter(model, llm)
46
+ elif model.provider == LLMProvider.ZHIPU:
47
+ return ZhipuTokenCounter(model, llm)
45
48
  else:
46
49
  # For models that do not have a specialized counter, raise a NotImplementedError
47
50
  raise NotImplementedError(f"No token counter available for model {model.value}")
@@ -0,0 +1,24 @@
1
+ from typing import TYPE_CHECKING
2
+ from autobyteus.llm.token_counter.openai_token_counter import OpenAITokenCounter
3
+ from autobyteus.llm.models import LLMModel
4
+
5
+ if TYPE_CHECKING:
6
+ from autobyteus.llm.base_llm import BaseLLM
7
+
8
+ class ZhipuTokenCounter(OpenAITokenCounter):
9
+ """
10
+ Token counter for Zhipu models. Uses the same token counting implementation as OpenAI.
11
+
12
+ This implementation inherits from OpenAITokenCounter as Zhipu uses a similar tokenization
13
+ approach as OpenAI's models.
14
+ """
15
+
16
+ def __init__(self, model: LLMModel, llm: 'BaseLLM' = None):
17
+ """
18
+ Initialize the Zhipu token counter.
19
+
20
+ Args:
21
+ model (LLMModel): The Zhipu model to count tokens for.
22
+ llm (BaseLLM, optional): The LLM instance. Defaults to None.
23
+ """
24
+ super().__init__(model, llm)
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  from typing import Optional, List, Dict, Any, TYPE_CHECKING
3
- from autobyteus_llm_client import AutobyteusClient
3
+ from autobyteus.clients import AutobyteusClient
4
4
  from autobyteus.multimedia.audio.base_audio_client import BaseAudioClient
5
5
  from autobyteus.multimedia.utils.response_types import SpeechGenerationResponse
6
6
 
@@ -26,7 +26,8 @@ class AutobyteusAudioClient(BaseAudioClient):
26
26
  async def generate_speech(
27
27
  self,
28
28
  prompt: str,
29
- generation_config: Optional[Dict[str, Any]] = None
29
+ generation_config: Optional[Dict[str, Any]] = None,
30
+ **kwargs
30
31
  ) -> SpeechGenerationResponse:
31
32
  """
32
33
  Generates speech by calling the generate_speech endpoint on the remote Autobyteus server.
@@ -36,6 +37,8 @@ class AutobyteusAudioClient(BaseAudioClient):
36
37
 
37
38
  model_name_for_server = self.model.name
38
39
 
40
+ # Note: The underlying autobyteus_client.generate_speech does not currently accept **kwargs.
41
+ # They are accepted here for interface consistency and future-proofing.
39
42
  response_data = await self.autobyteus_client.generate_speech(
40
43
  model_name=model_name_for_server,
41
44
  prompt=prompt,