autobyteus 1.1.3__py3-none-any.whl → 1.1.5__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.
- autobyteus/agent/agent.py +1 -1
- autobyteus/agent/bootstrap_steps/system_prompt_processing_step.py +4 -2
- autobyteus/agent/context/__init__.py +4 -2
- autobyteus/agent/context/agent_config.py +35 -8
- autobyteus/agent/context/agent_context_registry.py +73 -0
- autobyteus/agent/events/notifiers.py +4 -0
- autobyteus/agent/events/worker_event_dispatcher.py +1 -2
- autobyteus/agent/handlers/inter_agent_message_event_handler.py +8 -3
- autobyteus/agent/handlers/llm_complete_response_received_event_handler.py +19 -19
- autobyteus/agent/handlers/llm_user_message_ready_event_handler.py +2 -2
- autobyteus/agent/handlers/tool_result_event_handler.py +48 -20
- autobyteus/agent/handlers/user_input_message_event_handler.py +16 -1
- autobyteus/agent/input_processor/__init__.py +1 -7
- autobyteus/agent/message/context_file_type.py +6 -0
- autobyteus/agent/message/send_message_to.py +74 -99
- autobyteus/agent/phases/discover.py +2 -1
- autobyteus/agent/runtime/agent_runtime.py +10 -2
- autobyteus/agent/runtime/agent_worker.py +1 -0
- autobyteus/agent/sender_type.py +15 -0
- autobyteus/agent/streaming/agent_event_stream.py +6 -0
- autobyteus/agent/streaming/stream_event_payloads.py +12 -0
- autobyteus/agent/streaming/stream_events.py +3 -0
- autobyteus/agent/system_prompt_processor/tool_manifest_injector_processor.py +7 -4
- autobyteus/agent/tool_execution_result_processor/__init__.py +9 -0
- autobyteus/agent/tool_execution_result_processor/base_processor.py +46 -0
- autobyteus/agent/tool_execution_result_processor/processor_definition.py +36 -0
- autobyteus/agent/tool_execution_result_processor/processor_meta.py +36 -0
- autobyteus/agent/tool_execution_result_processor/processor_registry.py +70 -0
- autobyteus/agent/workspace/base_workspace.py +17 -2
- autobyteus/agent_team/__init__.py +1 -0
- autobyteus/agent_team/agent_team.py +93 -0
- autobyteus/agent_team/agent_team_builder.py +184 -0
- autobyteus/agent_team/base_agent_team.py +86 -0
- autobyteus/agent_team/bootstrap_steps/__init__.py +24 -0
- autobyteus/agent_team/bootstrap_steps/agent_configuration_preparation_step.py +73 -0
- autobyteus/agent_team/bootstrap_steps/agent_team_bootstrapper.py +54 -0
- autobyteus/agent_team/bootstrap_steps/agent_team_runtime_queue_initialization_step.py +25 -0
- autobyteus/agent_team/bootstrap_steps/base_agent_team_bootstrap_step.py +23 -0
- autobyteus/agent_team/bootstrap_steps/coordinator_initialization_step.py +41 -0
- autobyteus/agent_team/bootstrap_steps/coordinator_prompt_preparation_step.py +85 -0
- autobyteus/agent_team/bootstrap_steps/task_notifier_initialization_step.py +51 -0
- autobyteus/agent_team/bootstrap_steps/team_context_initialization_step.py +45 -0
- autobyteus/agent_team/context/__init__.py +17 -0
- autobyteus/agent_team/context/agent_team_config.py +33 -0
- autobyteus/agent_team/context/agent_team_context.py +61 -0
- autobyteus/agent_team/context/agent_team_runtime_state.py +56 -0
- autobyteus/agent_team/context/team_manager.py +147 -0
- autobyteus/agent_team/context/team_node_config.py +76 -0
- autobyteus/agent_team/events/__init__.py +29 -0
- autobyteus/agent_team/events/agent_team_event_dispatcher.py +39 -0
- autobyteus/agent_team/events/agent_team_events.py +53 -0
- autobyteus/agent_team/events/agent_team_input_event_queue_manager.py +21 -0
- autobyteus/agent_team/exceptions.py +8 -0
- autobyteus/agent_team/factory/__init__.py +9 -0
- autobyteus/agent_team/factory/agent_team_factory.py +99 -0
- autobyteus/agent_team/handlers/__init__.py +19 -0
- autobyteus/agent_team/handlers/agent_team_event_handler_registry.py +23 -0
- autobyteus/agent_team/handlers/base_agent_team_event_handler.py +16 -0
- autobyteus/agent_team/handlers/inter_agent_message_request_event_handler.py +61 -0
- autobyteus/agent_team/handlers/lifecycle_agent_team_event_handler.py +27 -0
- autobyteus/agent_team/handlers/process_user_message_event_handler.py +46 -0
- autobyteus/agent_team/handlers/tool_approval_team_event_handler.py +48 -0
- autobyteus/agent_team/phases/__init__.py +11 -0
- autobyteus/agent_team/phases/agent_team_operational_phase.py +19 -0
- autobyteus/agent_team/phases/agent_team_phase_manager.py +48 -0
- autobyteus/agent_team/runtime/__init__.py +13 -0
- autobyteus/agent_team/runtime/agent_team_runtime.py +82 -0
- autobyteus/agent_team/runtime/agent_team_worker.py +117 -0
- autobyteus/agent_team/shutdown_steps/__init__.py +17 -0
- autobyteus/agent_team/shutdown_steps/agent_team_shutdown_orchestrator.py +35 -0
- autobyteus/agent_team/shutdown_steps/agent_team_shutdown_step.py +42 -0
- autobyteus/agent_team/shutdown_steps/base_agent_team_shutdown_step.py +16 -0
- autobyteus/agent_team/shutdown_steps/bridge_cleanup_step.py +28 -0
- autobyteus/agent_team/shutdown_steps/sub_team_shutdown_step.py +41 -0
- autobyteus/agent_team/streaming/__init__.py +26 -0
- autobyteus/agent_team/streaming/agent_event_bridge.py +48 -0
- autobyteus/agent_team/streaming/agent_event_multiplexer.py +70 -0
- autobyteus/agent_team/streaming/agent_team_event_notifier.py +64 -0
- autobyteus/agent_team/streaming/agent_team_event_stream.py +33 -0
- autobyteus/agent_team/streaming/agent_team_stream_event_payloads.py +32 -0
- autobyteus/agent_team/streaming/agent_team_stream_events.py +56 -0
- autobyteus/agent_team/streaming/team_event_bridge.py +50 -0
- autobyteus/agent_team/task_notification/__init__.py +11 -0
- autobyteus/agent_team/task_notification/system_event_driven_agent_task_notifier.py +164 -0
- autobyteus/agent_team/task_notification/task_notification_mode.py +24 -0
- autobyteus/agent_team/utils/__init__.py +9 -0
- autobyteus/agent_team/utils/wait_for_idle.py +46 -0
- autobyteus/cli/__init__.py +1 -1
- autobyteus/cli/agent_team_tui/__init__.py +4 -0
- autobyteus/cli/agent_team_tui/app.py +210 -0
- autobyteus/cli/agent_team_tui/state.py +180 -0
- autobyteus/cli/agent_team_tui/widgets/__init__.py +6 -0
- autobyteus/cli/agent_team_tui/widgets/agent_list_sidebar.py +149 -0
- autobyteus/cli/agent_team_tui/widgets/focus_pane.py +320 -0
- autobyteus/cli/agent_team_tui/widgets/logo.py +20 -0
- autobyteus/cli/agent_team_tui/widgets/renderables.py +77 -0
- autobyteus/cli/agent_team_tui/widgets/shared.py +60 -0
- autobyteus/cli/agent_team_tui/widgets/status_bar.py +14 -0
- autobyteus/cli/agent_team_tui/widgets/task_board_panel.py +82 -0
- autobyteus/cli/cli_display.py +1 -1
- autobyteus/cli/workflow_tui/__init__.py +4 -0
- autobyteus/cli/workflow_tui/app.py +210 -0
- autobyteus/cli/workflow_tui/state.py +189 -0
- autobyteus/cli/workflow_tui/widgets/__init__.py +6 -0
- autobyteus/cli/workflow_tui/widgets/agent_list_sidebar.py +149 -0
- autobyteus/cli/workflow_tui/widgets/focus_pane.py +335 -0
- autobyteus/cli/workflow_tui/widgets/logo.py +27 -0
- autobyteus/cli/workflow_tui/widgets/renderables.py +70 -0
- autobyteus/cli/workflow_tui/widgets/shared.py +51 -0
- autobyteus/cli/workflow_tui/widgets/status_bar.py +14 -0
- autobyteus/events/event_types.py +8 -0
- autobyteus/llm/api/autobyteus_llm.py +11 -12
- autobyteus/llm/api/lmstudio_llm.py +34 -0
- autobyteus/llm/api/ollama_llm.py +8 -13
- autobyteus/llm/api/openai_compatible_llm.py +20 -3
- autobyteus/llm/autobyteus_provider.py +73 -46
- autobyteus/llm/llm_factory.py +103 -139
- autobyteus/llm/lmstudio_provider.py +104 -0
- autobyteus/llm/models.py +83 -53
- autobyteus/llm/ollama_provider.py +69 -61
- autobyteus/llm/ollama_provider_resolver.py +1 -0
- autobyteus/llm/providers.py +13 -12
- autobyteus/llm/runtimes.py +11 -0
- autobyteus/llm/token_counter/token_counter_factory.py +2 -0
- autobyteus/task_management/__init__.py +43 -0
- autobyteus/task_management/base_task_board.py +68 -0
- autobyteus/task_management/converters/__init__.py +11 -0
- autobyteus/task_management/converters/task_board_converter.py +64 -0
- autobyteus/task_management/converters/task_plan_converter.py +48 -0
- autobyteus/task_management/deliverable.py +16 -0
- autobyteus/task_management/deliverables/__init__.py +8 -0
- autobyteus/task_management/deliverables/file_deliverable.py +15 -0
- autobyteus/task_management/events.py +27 -0
- autobyteus/task_management/in_memory_task_board.py +126 -0
- autobyteus/task_management/schemas/__init__.py +15 -0
- autobyteus/task_management/schemas/deliverable_schema.py +13 -0
- autobyteus/task_management/schemas/plan_definition.py +35 -0
- autobyteus/task_management/schemas/task_status_report.py +27 -0
- autobyteus/task_management/task_plan.py +110 -0
- autobyteus/task_management/tools/__init__.py +14 -0
- autobyteus/task_management/tools/get_task_board_status.py +68 -0
- autobyteus/task_management/tools/publish_task_plan.py +113 -0
- autobyteus/task_management/tools/update_task_status.py +135 -0
- autobyteus/tools/__init__.py +2 -0
- autobyteus/tools/ask_user_input.py +2 -1
- autobyteus/tools/bash/bash_executor.py +61 -15
- autobyteus/tools/browser/session_aware/browser_session_aware_navigate_to.py +2 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_web_element_trigger.py +3 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_reader.py +3 -0
- autobyteus/tools/browser/session_aware/browser_session_aware_webpage_screenshot_taker.py +3 -0
- autobyteus/tools/browser/standalone/google_search_ui.py +2 -0
- autobyteus/tools/browser/standalone/navigate_to.py +2 -0
- autobyteus/tools/browser/standalone/web_page_pdf_generator.py +3 -0
- autobyteus/tools/browser/standalone/webpage_image_downloader.py +3 -0
- autobyteus/tools/browser/standalone/webpage_reader.py +2 -0
- autobyteus/tools/browser/standalone/webpage_screenshot_taker.py +3 -0
- autobyteus/tools/file/file_reader.py +36 -9
- autobyteus/tools/file/file_writer.py +37 -9
- autobyteus/tools/functional_tool.py +5 -4
- autobyteus/tools/image_downloader.py +2 -0
- autobyteus/tools/mcp/config_service.py +63 -58
- autobyteus/tools/mcp/server/http_managed_mcp_server.py +14 -2
- autobyteus/tools/mcp/server/stdio_managed_mcp_server.py +14 -2
- autobyteus/tools/mcp/server_instance_manager.py +30 -4
- autobyteus/tools/mcp/tool_registrar.py +106 -51
- autobyteus/tools/parameter_schema.py +17 -11
- autobyteus/tools/pdf_downloader.py +2 -1
- autobyteus/tools/registry/tool_definition.py +36 -37
- autobyteus/tools/registry/tool_registry.py +50 -2
- autobyteus/tools/timer.py +2 -0
- autobyteus/tools/tool_category.py +15 -4
- autobyteus/tools/tool_meta.py +6 -1
- autobyteus/tools/tool_origin.py +10 -0
- autobyteus/tools/usage/formatters/default_json_example_formatter.py +78 -3
- autobyteus/tools/usage/formatters/default_xml_example_formatter.py +23 -3
- autobyteus/tools/usage/formatters/gemini_json_example_formatter.py +6 -0
- autobyteus/tools/usage/formatters/google_json_example_formatter.py +7 -0
- autobyteus/tools/usage/formatters/openai_json_example_formatter.py +6 -4
- autobyteus/tools/usage/parsers/gemini_json_tool_usage_parser.py +23 -7
- autobyteus/tools/usage/parsers/provider_aware_tool_usage_parser.py +14 -25
- autobyteus/tools/usage/providers/__init__.py +2 -12
- autobyteus/tools/usage/providers/tool_manifest_provider.py +36 -29
- autobyteus/tools/usage/registries/__init__.py +7 -12
- autobyteus/tools/usage/registries/tool_formatter_pair.py +15 -0
- autobyteus/tools/usage/registries/tool_formatting_registry.py +58 -0
- autobyteus/tools/usage/registries/tool_usage_parser_registry.py +55 -0
- autobyteus/workflow/agentic_workflow.py +93 -0
- autobyteus/{agent/workflow → workflow}/base_agentic_workflow.py +19 -27
- autobyteus/workflow/bootstrap_steps/__init__.py +20 -0
- autobyteus/workflow/bootstrap_steps/agent_tool_injection_step.py +34 -0
- autobyteus/workflow/bootstrap_steps/base_workflow_bootstrap_step.py +23 -0
- autobyteus/workflow/bootstrap_steps/coordinator_initialization_step.py +41 -0
- autobyteus/workflow/bootstrap_steps/coordinator_prompt_preparation_step.py +108 -0
- autobyteus/workflow/bootstrap_steps/workflow_bootstrapper.py +50 -0
- autobyteus/workflow/bootstrap_steps/workflow_runtime_queue_initialization_step.py +25 -0
- autobyteus/workflow/context/__init__.py +17 -0
- autobyteus/workflow/context/team_manager.py +147 -0
- autobyteus/workflow/context/workflow_config.py +30 -0
- autobyteus/workflow/context/workflow_context.py +61 -0
- autobyteus/workflow/context/workflow_node_config.py +76 -0
- autobyteus/workflow/context/workflow_runtime_state.py +53 -0
- autobyteus/workflow/events/__init__.py +29 -0
- autobyteus/workflow/events/workflow_event_dispatcher.py +39 -0
- autobyteus/workflow/events/workflow_events.py +53 -0
- autobyteus/workflow/events/workflow_input_event_queue_manager.py +21 -0
- autobyteus/workflow/exceptions.py +8 -0
- autobyteus/workflow/factory/__init__.py +9 -0
- autobyteus/workflow/factory/workflow_factory.py +99 -0
- autobyteus/workflow/handlers/__init__.py +19 -0
- autobyteus/workflow/handlers/base_workflow_event_handler.py +16 -0
- autobyteus/workflow/handlers/inter_agent_message_request_event_handler.py +61 -0
- autobyteus/workflow/handlers/lifecycle_workflow_event_handler.py +27 -0
- autobyteus/workflow/handlers/process_user_message_event_handler.py +46 -0
- autobyteus/workflow/handlers/tool_approval_workflow_event_handler.py +39 -0
- autobyteus/workflow/handlers/workflow_event_handler_registry.py +23 -0
- autobyteus/workflow/phases/__init__.py +11 -0
- autobyteus/workflow/phases/workflow_operational_phase.py +19 -0
- autobyteus/workflow/phases/workflow_phase_manager.py +48 -0
- autobyteus/workflow/runtime/__init__.py +13 -0
- autobyteus/workflow/runtime/workflow_runtime.py +82 -0
- autobyteus/workflow/runtime/workflow_worker.py +117 -0
- autobyteus/workflow/shutdown_steps/__init__.py +17 -0
- autobyteus/workflow/shutdown_steps/agent_team_shutdown_step.py +42 -0
- autobyteus/workflow/shutdown_steps/base_workflow_shutdown_step.py +16 -0
- autobyteus/workflow/shutdown_steps/bridge_cleanup_step.py +28 -0
- autobyteus/workflow/shutdown_steps/sub_workflow_shutdown_step.py +41 -0
- autobyteus/workflow/shutdown_steps/workflow_shutdown_orchestrator.py +35 -0
- autobyteus/workflow/streaming/__init__.py +26 -0
- autobyteus/workflow/streaming/agent_event_bridge.py +48 -0
- autobyteus/workflow/streaming/agent_event_multiplexer.py +70 -0
- autobyteus/workflow/streaming/workflow_event_bridge.py +50 -0
- autobyteus/workflow/streaming/workflow_event_notifier.py +83 -0
- autobyteus/workflow/streaming/workflow_event_stream.py +33 -0
- autobyteus/workflow/streaming/workflow_stream_event_payloads.py +28 -0
- autobyteus/workflow/streaming/workflow_stream_events.py +45 -0
- autobyteus/workflow/utils/__init__.py +9 -0
- autobyteus/workflow/utils/wait_for_idle.py +46 -0
- autobyteus/workflow/workflow_builder.py +151 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/METADATA +16 -14
- autobyteus-1.1.5.dist-info/RECORD +455 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/top_level.txt +1 -0
- examples/__init__.py +1 -0
- examples/agent_team/__init__.py +1 -0
- examples/discover_phase_transitions.py +104 -0
- examples/run_browser_agent.py +262 -0
- examples/run_google_slides_agent.py +287 -0
- examples/run_mcp_browser_client.py +174 -0
- examples/run_mcp_google_slides_client.py +270 -0
- examples/run_mcp_list_tools.py +189 -0
- examples/run_poem_writer.py +284 -0
- examples/run_sqlite_agent.py +295 -0
- autobyteus/agent/context/agent_phase_manager.py +0 -264
- autobyteus/agent/context/phases.py +0 -49
- autobyteus/agent/group/__init__.py +0 -0
- autobyteus/agent/group/agent_group.py +0 -164
- autobyteus/agent/group/agent_group_context.py +0 -81
- autobyteus/agent/input_processor/content_prefixing_input_processor.py +0 -41
- autobyteus/agent/input_processor/metadata_appending_input_processor.py +0 -34
- autobyteus/agent/input_processor/passthrough_input_processor.py +0 -33
- autobyteus/agent/workflow/__init__.py +0 -11
- autobyteus/agent/workflow/agentic_workflow.py +0 -89
- autobyteus/tools/mcp/call_handlers/__init__.py +0 -16
- autobyteus/tools/mcp/call_handlers/base_handler.py +0 -40
- autobyteus/tools/mcp/call_handlers/stdio_handler.py +0 -76
- autobyteus/tools/mcp/call_handlers/streamable_http_handler.py +0 -55
- autobyteus/tools/mcp/registrar.py +0 -202
- autobyteus/tools/usage/providers/json_example_provider.py +0 -32
- autobyteus/tools/usage/providers/json_schema_provider.py +0 -35
- autobyteus/tools/usage/providers/json_tool_usage_parser_provider.py +0 -28
- autobyteus/tools/usage/providers/xml_example_provider.py +0 -28
- autobyteus/tools/usage/providers/xml_schema_provider.py +0 -29
- autobyteus/tools/usage/providers/xml_tool_usage_parser_provider.py +0 -26
- autobyteus/tools/usage/registries/json_example_formatter_registry.py +0 -51
- autobyteus/tools/usage/registries/json_schema_formatter_registry.py +0 -51
- autobyteus/tools/usage/registries/json_tool_usage_parser_registry.py +0 -42
- autobyteus/tools/usage/registries/xml_example_formatter_registry.py +0 -30
- autobyteus/tools/usage/registries/xml_schema_formatter_registry.py +0 -33
- autobyteus/tools/usage/registries/xml_tool_usage_parser_registry.py +0 -30
- autobyteus/workflow/simple_task.py +0 -98
- autobyteus/workflow/task.py +0 -147
- autobyteus/workflow/workflow.py +0 -49
- autobyteus-1.1.3.dist-info/RECORD +0 -312
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/WHEEL +0 -0
- {autobyteus-1.1.3.dist-info → autobyteus-1.1.5.dist-info}/licenses/LICENSE +0 -0
autobyteus/events/event_types.py
CHANGED
|
@@ -34,6 +34,7 @@ class EventType(Enum):
|
|
|
34
34
|
AGENT_DATA_ASSISTANT_COMPLETE_RESPONSE = "agent_data_assistant_complete_response"
|
|
35
35
|
AGENT_DATA_TOOL_LOG = "agent_data_tool_log"
|
|
36
36
|
AGENT_DATA_TOOL_LOG_STREAM_END = "agent_data_tool_log_stream_end"
|
|
37
|
+
AGENT_DATA_SYSTEM_TASK_NOTIFICATION_RECEIVED = "agent_data_system_task_notification_received" # NEW
|
|
37
38
|
|
|
38
39
|
# --- Agent Requests for External Interaction ---
|
|
39
40
|
AGENT_REQUEST_TOOL_INVOCATION_APPROVAL = "agent_request_tool_invocation_approval"
|
|
@@ -42,5 +43,12 @@ class EventType(Enum):
|
|
|
42
43
|
# --- Agent Errors (not necessarily phase changes, e.g., error during output generation) ---
|
|
43
44
|
AGENT_ERROR_OUTPUT_GENERATION = "agent_error_output_generation"
|
|
44
45
|
|
|
46
|
+
# --- Agent Team Events ---
|
|
47
|
+
TEAM_STREAM_EVENT = "team_stream_event" # For unified agent team event stream
|
|
48
|
+
|
|
49
|
+
# --- Task Board Events ---
|
|
50
|
+
TASK_BOARD_PLAN_PUBLISHED = "task_board_plan_published"
|
|
51
|
+
TASK_BOARD_STATUS_UPDATED = "task_board_status_updated"
|
|
52
|
+
|
|
45
53
|
def __str__(self):
|
|
46
54
|
return self.value
|
|
@@ -11,18 +11,17 @@ import uuid
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
13
|
class AutobyteusLLM(BaseLLM):
|
|
14
|
-
def __init__(self, model: LLMModel
|
|
15
|
-
#
|
|
16
|
-
if model
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
if llm_config is None:
|
|
20
|
-
llm_config = LLMConfig()
|
|
21
|
-
|
|
14
|
+
def __init__(self, model: LLMModel, llm_config: LLMConfig):
|
|
15
|
+
# The host URL is now passed via the model object.
|
|
16
|
+
if not model.host_url:
|
|
17
|
+
raise ValueError("AutobyteusLLM requires a host_url to be set in its LLMModel object.")
|
|
18
|
+
|
|
22
19
|
super().__init__(model=model, llm_config=llm_config)
|
|
23
|
-
|
|
20
|
+
|
|
21
|
+
# Instantiate the client with the specific host for this model.
|
|
22
|
+
self.client = AutobyteusClient(server_url=self.model.host_url)
|
|
24
23
|
self.conversation_id = str(uuid.uuid4())
|
|
25
|
-
logger.info(f"AutobyteusLLM initialized
|
|
24
|
+
logger.info(f"AutobyteusLLM initialized for model '{self.model.model_identifier}' with conversation ID: {self.conversation_id}")
|
|
26
25
|
|
|
27
26
|
async def _send_user_message_to_llm(
|
|
28
27
|
self,
|
|
@@ -34,7 +33,7 @@ class AutobyteusLLM(BaseLLM):
|
|
|
34
33
|
try:
|
|
35
34
|
response = await self.client.send_message(
|
|
36
35
|
conversation_id=self.conversation_id,
|
|
37
|
-
model_name=self.model.name,
|
|
36
|
+
model_name=self.model.name, # Use `name` as it's the original model name for the API
|
|
38
37
|
user_message=user_message,
|
|
39
38
|
image_urls=image_urls
|
|
40
39
|
)
|
|
@@ -70,7 +69,7 @@ class AutobyteusLLM(BaseLLM):
|
|
|
70
69
|
try:
|
|
71
70
|
async for chunk in self.client.stream_message(
|
|
72
71
|
conversation_id=self.conversation_id,
|
|
73
|
-
model_name=self.model.name,
|
|
72
|
+
model_name=self.model.name, # Use `name` for the API call
|
|
74
73
|
user_message=user_message,
|
|
75
74
|
image_urls=image_urls
|
|
76
75
|
):
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from autobyteus.llm.models import LLMModel
|
|
3
|
+
from autobyteus.llm.utils.llm_config import LLMConfig
|
|
4
|
+
from autobyteus.llm.api.openai_compatible_llm import OpenAICompatibleLLM
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
class LMStudioLLM(OpenAICompatibleLLM):
|
|
10
|
+
"""
|
|
11
|
+
LLM class for models served by a local LM Studio instance.
|
|
12
|
+
This class is now decoupled from environment variables and receives its connection
|
|
13
|
+
details from the LLMModel object.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, model: LLMModel, llm_config: LLMConfig):
|
|
17
|
+
if not model.host_url:
|
|
18
|
+
raise ValueError("LMStudioLLM requires a host_url to be set in its LLMModel object.")
|
|
19
|
+
|
|
20
|
+
base_url = f"{model.host_url}/v1"
|
|
21
|
+
|
|
22
|
+
# The API key is often not needed for LM Studio, but we allow it to be set via env var.
|
|
23
|
+
# It defaults to a dummy value if not set.
|
|
24
|
+
super().__init__(
|
|
25
|
+
model=model,
|
|
26
|
+
llm_config=llm_config,
|
|
27
|
+
api_key_env_var="LMSTUDIO_API_KEY",
|
|
28
|
+
base_url=base_url,
|
|
29
|
+
api_key_default="lm-studio" # Dummy key for LM Studio
|
|
30
|
+
)
|
|
31
|
+
logger.info(f"LMStudioLLM initialized for model '{model.model_identifier}' with base URL: {base_url}")
|
|
32
|
+
|
|
33
|
+
async def cleanup(self):
|
|
34
|
+
await super().cleanup()
|
autobyteus/llm/api/ollama_llm.py
CHANGED
|
@@ -14,22 +14,17 @@ import os
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
|
|
16
16
|
class OllamaLLM(BaseLLM):
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
def __init__(self, model: LLMModel, llm_config: LLMConfig):
|
|
18
|
+
# The host URL is now passed via the model object, decoupling from environment variables here.
|
|
19
|
+
if not model.host_url:
|
|
20
|
+
raise ValueError("OllamaLLM requires a host_url to be set in its LLMModel object.")
|
|
21
|
+
|
|
22
|
+
logger.info(f"Initializing OllamaLLM for model '{model.name}' with host: {model.host_url}")
|
|
22
23
|
|
|
23
|
-
self.client = AsyncClient(host=
|
|
24
|
+
self.client = AsyncClient(host=model.host_url)
|
|
24
25
|
|
|
25
|
-
# Provide defaults if not specified
|
|
26
|
-
if model is None:
|
|
27
|
-
model = LLMModel.OLLAMA_LLAMA_3_2
|
|
28
|
-
if llm_config is None:
|
|
29
|
-
llm_config = LLMConfig()
|
|
30
|
-
|
|
31
26
|
super().__init__(model=model, llm_config=llm_config)
|
|
32
|
-
logger.info(f"OllamaLLM initialized with model: {self.model}")
|
|
27
|
+
logger.info(f"OllamaLLM initialized with model: {self.model.model_identifier}")
|
|
33
28
|
|
|
34
29
|
async def _send_user_message_to_llm(self, user_message: str, image_urls: Optional[List[str]] = None, **kwargs) -> CompleteResponse:
|
|
35
30
|
self.add_user_message(user_message)
|
|
@@ -21,12 +21,29 @@ class OpenAICompatibleLLM(BaseLLM, ABC):
|
|
|
21
21
|
model: LLMModel,
|
|
22
22
|
llm_config: LLMConfig,
|
|
23
23
|
api_key_env_var: str,
|
|
24
|
-
base_url: str
|
|
24
|
+
base_url: str,
|
|
25
|
+
api_key_default: Optional[str] = None
|
|
25
26
|
):
|
|
27
|
+
"""
|
|
28
|
+
Initializes an OpenAI-compatible LLM.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
model (LLMModel): The model to use.
|
|
32
|
+
llm_config (LLMConfig): Configuration for the LLM.
|
|
33
|
+
api_key_env_var (str): The name of the environment variable for the API key.
|
|
34
|
+
base_url (str): The base URL for the API.
|
|
35
|
+
api_key_default (Optional[str], optional): A default API key to use if the
|
|
36
|
+
environment variable is not set.
|
|
37
|
+
Defaults to None.
|
|
38
|
+
"""
|
|
26
39
|
api_key = os.getenv(api_key_env_var)
|
|
27
40
|
if not api_key:
|
|
28
|
-
|
|
29
|
-
|
|
41
|
+
if api_key_default:
|
|
42
|
+
api_key = api_key_default
|
|
43
|
+
logger.info(f"{api_key_env_var} not set, using default key.")
|
|
44
|
+
else:
|
|
45
|
+
logger.error(f"{api_key_env_var} environment variable is not set.")
|
|
46
|
+
raise ValueError(f"{api_key_env_var} environment variable is not set.")
|
|
30
47
|
|
|
31
48
|
self.client = OpenAI(api_key=api_key, base_url=base_url)
|
|
32
49
|
logger.info(f"Initialized OpenAI compatible client with base_url: {base_url}")
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from autobyteus.llm.api.autobyteus_llm import AutobyteusLLM
|
|
2
2
|
from autobyteus.llm.models import LLMModel
|
|
3
3
|
from autobyteus.llm.providers import LLMProvider
|
|
4
|
+
from autobyteus.llm.runtimes import LLMRuntime
|
|
4
5
|
from autobyteus.llm.utils.llm_config import LLMConfig, TokenPricingConfig
|
|
5
|
-
from typing import Dict, Any, TYPE_CHECKING
|
|
6
|
+
from typing import Dict, Any, TYPE_CHECKING, List, Optional
|
|
6
7
|
import os
|
|
7
8
|
import logging
|
|
8
9
|
from urllib.parse import urlparse
|
|
@@ -15,63 +16,89 @@ logger = logging.getLogger(__name__)
|
|
|
15
16
|
|
|
16
17
|
class AutobyteusModelProvider:
|
|
17
18
|
DEFAULT_SERVER_URL = 'https://localhost:8000'
|
|
18
|
-
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def _get_hosts() -> List[str]:
|
|
22
|
+
"""Gets Autobyteus LLM server hosts from env vars, supporting a comma-separated list."""
|
|
23
|
+
hosts_str = os.getenv('AUTOBYTEUS_LLM_SERVER_HOSTS')
|
|
24
|
+
if hosts_str:
|
|
25
|
+
return [host.strip() for host in hosts_str.split(',')]
|
|
26
|
+
|
|
27
|
+
legacy_host = os.getenv('AUTOBYTEUS_LLM_SERVER_URL')
|
|
28
|
+
if legacy_host:
|
|
29
|
+
return [legacy_host]
|
|
30
|
+
|
|
31
|
+
return [AutobyteusModelProvider.DEFAULT_SERVER_URL]
|
|
19
32
|
|
|
20
33
|
@staticmethod
|
|
21
34
|
def discover_and_register():
|
|
22
|
-
"""Discover and register Autobyteus models
|
|
35
|
+
"""Discover and register Autobyteus models from all configured hosts."""
|
|
23
36
|
try:
|
|
24
|
-
from autobyteus.llm.llm_factory import LLMFactory
|
|
25
|
-
|
|
26
|
-
client = None
|
|
27
|
-
try:
|
|
28
|
-
client = AutobyteusClient()
|
|
29
|
-
response = client.get_available_models_sync()
|
|
30
|
-
except Exception as e:
|
|
31
|
-
logger.error(f"Client initialization failed: {str(e)}")
|
|
32
|
-
return
|
|
33
|
-
finally:
|
|
34
|
-
if client:
|
|
35
|
-
client.sync_client.close()
|
|
37
|
+
from autobyteus.llm.llm_factory import LLMFactory
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
hosts = AutobyteusModelProvider._get_hosts()
|
|
40
|
+
total_registered_count = 0
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
for host_url in hosts:
|
|
43
|
+
if not AutobyteusModelProvider.is_valid_url(host_url):
|
|
44
|
+
logger.error(f"Invalid Autobyteus host URL: {host_url}, skipping.")
|
|
45
|
+
continue
|
|
46
|
+
|
|
47
|
+
logger.info(f"Discovering Autobyteus models from host: {host_url}")
|
|
48
|
+
client = None
|
|
44
49
|
try:
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
continue
|
|
49
|
-
|
|
50
|
-
llm_config = AutobyteusModelProvider._parse_llm_config(model_info["config"])
|
|
51
|
-
if not llm_config:
|
|
52
|
-
continue
|
|
53
|
-
|
|
54
|
-
llm_model = LLMModel(
|
|
55
|
-
name=model_info["name"],
|
|
56
|
-
value=model_info["value"],
|
|
57
|
-
provider=LLMProvider(model_info["provider"]), # Convert string to enum
|
|
58
|
-
llm_class=AutobyteusLLM,
|
|
59
|
-
canonical_name=model_info["canonical_name"], # Add canonical_name
|
|
60
|
-
default_config=llm_config
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
LLMFactory.register_model(llm_model)
|
|
64
|
-
registered_count += 1
|
|
65
|
-
logger.debug(f"Registered model: {model_info['name']} with canonical name: {model_info['canonical_name']}")
|
|
66
|
-
|
|
50
|
+
# Instantiate client for this specific host
|
|
51
|
+
client = AutobyteusClient(server_url=host_url)
|
|
52
|
+
response = client.get_available_models_sync()
|
|
67
53
|
except Exception as e:
|
|
68
|
-
logger.
|
|
54
|
+
logger.warning(f"Could not connect or fetch models from Autobyteus server at {host_url}: {e}")
|
|
55
|
+
continue
|
|
56
|
+
finally:
|
|
57
|
+
if client:
|
|
58
|
+
client.sync_client.close()
|
|
59
|
+
|
|
60
|
+
if not AutobyteusModelProvider._validate_server_response(response):
|
|
69
61
|
continue
|
|
62
|
+
|
|
63
|
+
models = response.get('models', [])
|
|
64
|
+
host_registered_count = 0
|
|
65
|
+
for model_info in models:
|
|
66
|
+
try:
|
|
67
|
+
validation_result = AutobyteusModelProvider._validate_model_info(model_info)
|
|
68
|
+
if not validation_result["valid"]:
|
|
69
|
+
logger.warning(validation_result["message"])
|
|
70
|
+
continue
|
|
71
|
+
|
|
72
|
+
llm_config = AutobyteusModelProvider._parse_llm_config(model_info["config"])
|
|
73
|
+
if not llm_config:
|
|
74
|
+
continue
|
|
70
75
|
|
|
71
|
-
|
|
76
|
+
llm_model = LLMModel(
|
|
77
|
+
name=model_info["name"],
|
|
78
|
+
value=model_info["value"],
|
|
79
|
+
provider=LLMProvider(model_info["provider"]),
|
|
80
|
+
llm_class=AutobyteusLLM,
|
|
81
|
+
canonical_name=model_info["canonical_name"],
|
|
82
|
+
runtime=LLMRuntime.AUTOBYTEUS,
|
|
83
|
+
host_url=host_url,
|
|
84
|
+
default_config=llm_config
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
LLMFactory.register_model(llm_model)
|
|
88
|
+
host_registered_count += 1
|
|
89
|
+
|
|
90
|
+
except Exception as e:
|
|
91
|
+
logger.error(f"Failed to register Autobyteus model '{model_info.get('name')}' from {host_url}: {e}")
|
|
92
|
+
|
|
93
|
+
if host_registered_count > 0:
|
|
94
|
+
logger.info(f"Registered {host_registered_count} models from Autobyteus host {host_url}")
|
|
95
|
+
total_registered_count += host_registered_count
|
|
96
|
+
|
|
97
|
+
if total_registered_count > 0:
|
|
98
|
+
logger.info(f"Finished Autobyteus discovery. Total models registered: {total_registered_count}")
|
|
72
99
|
|
|
73
100
|
except Exception as e:
|
|
74
|
-
logger.error(f"
|
|
101
|
+
logger.error(f"An unexpected error occurred during Autobyteus model discovery: {e}", exc_info=True)
|
|
75
102
|
|
|
76
103
|
@staticmethod
|
|
77
104
|
def _validate_server_response(response: Dict[str, Any]) -> bool:
|
autobyteus/llm/llm_factory.py
CHANGED
|
@@ -5,75 +5,48 @@ import inspect
|
|
|
5
5
|
from autobyteus.llm.autobyteus_provider import AutobyteusModelProvider
|
|
6
6
|
from autobyteus.llm.models import LLMModel, ModelInfo, ProviderModelGroup
|
|
7
7
|
from autobyteus.llm.providers import LLMProvider
|
|
8
|
+
from autobyteus.llm.runtimes import LLMRuntime
|
|
8
9
|
from autobyteus.llm.utils.llm_config import LLMConfig, TokenPricingConfig
|
|
9
10
|
from autobyteus.llm.base_llm import BaseLLM
|
|
10
11
|
|
|
11
12
|
from autobyteus.llm.api.claude_llm import ClaudeLLM
|
|
12
13
|
from autobyteus.llm.api.mistral_llm import MistralLLM
|
|
13
14
|
from autobyteus.llm.api.openai_llm import OpenAILLM
|
|
14
|
-
from autobyteus.llm.api.ollama_llm import OllamaLLM
|
|
15
15
|
from autobyteus.llm.api.deepseek_llm import DeepSeekLLM
|
|
16
16
|
from autobyteus.llm.api.grok_llm import GrokLLM
|
|
17
17
|
from autobyteus.llm.api.kimi_llm import KimiLLM
|
|
18
18
|
from autobyteus.llm.ollama_provider import OllamaModelProvider
|
|
19
|
+
from autobyteus.llm.lmstudio_provider import LMStudioModelProvider
|
|
19
20
|
from autobyteus.utils.singleton import SingletonMeta
|
|
20
21
|
|
|
21
22
|
logger = logging.getLogger(__name__)
|
|
22
23
|
|
|
23
24
|
class LLMFactory(metaclass=SingletonMeta):
|
|
24
25
|
_models_by_provider: Dict[LLMProvider, List[LLMModel]] = {}
|
|
26
|
+
_models_by_identifier: Dict[str, LLMModel] = {}
|
|
25
27
|
_initialized = False
|
|
26
28
|
|
|
27
|
-
@staticmethod
|
|
28
|
-
def register(model: LLMModel):
|
|
29
|
-
LLMFactory.register_model(model)
|
|
30
|
-
|
|
31
29
|
@staticmethod
|
|
32
30
|
def ensure_initialized():
|
|
33
|
-
"""
|
|
34
|
-
Ensures the factory is initialized before use.
|
|
35
|
-
"""
|
|
31
|
+
"""Ensures the factory is initialized before use."""
|
|
36
32
|
if not LLMFactory._initialized:
|
|
37
33
|
LLMFactory._initialize_registry()
|
|
38
34
|
LLMFactory._initialized = True
|
|
39
35
|
|
|
40
36
|
@staticmethod
|
|
41
37
|
def reinitialize():
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Returns:
|
|
50
|
-
bool: True if reinitialization was successful, False otherwise.
|
|
51
|
-
"""
|
|
52
|
-
try:
|
|
53
|
-
logger.info("Reinitializing LLM model registry...")
|
|
54
|
-
|
|
55
|
-
# Reset the initialized flag
|
|
56
|
-
LLMFactory._initialized = False
|
|
57
|
-
|
|
58
|
-
# Clear existing models registry
|
|
59
|
-
LLMFactory._models_by_provider = {}
|
|
60
|
-
|
|
61
|
-
# Reinitialize the registry
|
|
62
|
-
LLMFactory.ensure_initialized()
|
|
63
|
-
|
|
64
|
-
logger.info("LLM model registry reinitialized successfully")
|
|
65
|
-
return True
|
|
66
|
-
except Exception as e:
|
|
67
|
-
logger.error(f"Failed to reinitialize LLM model registry: {str(e)}")
|
|
68
|
-
return False
|
|
38
|
+
"""Reinitializes the model registry."""
|
|
39
|
+
logger.info("Reinitializing LLM model registry...")
|
|
40
|
+
LLMFactory._initialized = False
|
|
41
|
+
LLMFactory._models_by_provider.clear()
|
|
42
|
+
LLMFactory._models_by_identifier.clear()
|
|
43
|
+
LLMFactory.ensure_initialized()
|
|
44
|
+
logger.info("LLM model registry reinitialized successfully.")
|
|
69
45
|
|
|
70
46
|
@staticmethod
|
|
71
47
|
def _initialize_registry():
|
|
72
|
-
"""
|
|
73
|
-
|
|
74
|
-
organize models by provider, and assign models as attributes on LLMModel.
|
|
75
|
-
"""
|
|
76
|
-
# Organize supported models by provider sections
|
|
48
|
+
"""Initializes the registry with built-in models and discovers runtime models."""
|
|
49
|
+
# Hardcoded direct-API models. Runtime defaults to API.
|
|
77
50
|
supported_models = [
|
|
78
51
|
# OPENAI Provider Models
|
|
79
52
|
LLMModel(
|
|
@@ -305,133 +278,124 @@ class LLMFactory(metaclass=SingletonMeta):
|
|
|
305
278
|
for model in supported_models:
|
|
306
279
|
LLMFactory.register_model(model)
|
|
307
280
|
|
|
281
|
+
# Discover models from runtimes
|
|
308
282
|
OllamaModelProvider.discover_and_register()
|
|
283
|
+
LMStudioModelProvider.discover_and_register()
|
|
309
284
|
AutobyteusModelProvider.discover_and_register()
|
|
310
285
|
|
|
311
286
|
@staticmethod
|
|
312
287
|
def register_model(model: LLMModel):
|
|
313
|
-
"""
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
# Remove the old model from its provider list
|
|
324
|
-
LLMFactory._models_by_provider[existing_model.provider].remove(existing_model)
|
|
325
|
-
break
|
|
288
|
+
"""Registers a new LLM model."""
|
|
289
|
+
identifier = model.model_identifier
|
|
290
|
+
if identifier in LLMFactory._models_by_identifier:
|
|
291
|
+
logger.debug(f"Redefining model with identifier '{identifier}'.")
|
|
292
|
+
# Remove old model from provider group to replace it
|
|
293
|
+
old_model = LLMFactory._models_by_identifier[identifier]
|
|
294
|
+
if old_model.provider in LLMFactory._models_by_provider:
|
|
295
|
+
# This check is needed because a model might be in _models_by_identifier but not yet in _models_by_provider if re-registering
|
|
296
|
+
if old_model in LLMFactory._models_by_provider[old_model.provider]:
|
|
297
|
+
LLMFactory._models_by_provider[old_model.provider].remove(old_model)
|
|
326
298
|
|
|
327
|
-
|
|
328
|
-
|
|
299
|
+
LLMFactory._models_by_identifier[identifier] = model
|
|
300
|
+
LLMFactory._models_by_provider.setdefault(model.provider, []).append(model)
|
|
329
301
|
|
|
330
302
|
@staticmethod
|
|
331
303
|
def create_llm(model_identifier: str, llm_config: Optional[LLMConfig] = None) -> BaseLLM:
|
|
332
304
|
"""
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
Args:
|
|
336
|
-
model_identifier (str): The model name to create an instance for.
|
|
337
|
-
llm_config (Optional[LLMConfig]): Configuration for the LLM. If None,
|
|
338
|
-
the model's default configuration is used.
|
|
339
|
-
|
|
340
|
-
Returns:
|
|
341
|
-
BaseLLM: An instance of the LLM.
|
|
342
|
-
|
|
343
|
-
Raises:
|
|
344
|
-
ValueError: If the model is not supported.
|
|
305
|
+
Creates an LLM instance for the specified unique model identifier.
|
|
306
|
+
Raises an error if the identifier is not found or if a non-unique name is provided.
|
|
345
307
|
"""
|
|
346
308
|
LLMFactory.ensure_initialized()
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
309
|
+
|
|
310
|
+
# First, try a direct lookup by the unique model_identifier
|
|
311
|
+
model = LLMFactory._models_by_identifier.get(model_identifier)
|
|
312
|
+
if model:
|
|
313
|
+
return model.create_llm(llm_config)
|
|
352
314
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
315
|
+
# If not found, check if the user provided a non-unique name by mistake
|
|
316
|
+
found_by_name = [m for m in LLMFactory._models_by_identifier.values() if m.name == model_identifier]
|
|
317
|
+
if len(found_by_name) > 1:
|
|
318
|
+
identifiers = [m.model_identifier for m in found_by_name]
|
|
319
|
+
raise ValueError(
|
|
320
|
+
f"The model name '{model_identifier}' is ambiguous. Please use one of the unique "
|
|
321
|
+
f"model identifiers: {identifiers}"
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
raise ValueError(f"Model with identifier '{model_identifier}' not found.")
|
|
363
325
|
|
|
364
|
-
|
|
365
|
-
def get_all_providers() -> Set[LLMProvider]:
|
|
366
|
-
"""
|
|
367
|
-
Returns a set of all available LLM providers.
|
|
368
|
-
"""
|
|
369
|
-
LLMFactory.ensure_initialized()
|
|
370
|
-
return set(LLMProvider)
|
|
326
|
+
# --- New Public API ---
|
|
371
327
|
|
|
372
328
|
@staticmethod
|
|
373
|
-
def
|
|
374
|
-
"""
|
|
375
|
-
Returns a list of all model values for a specific provider.
|
|
376
|
-
"""
|
|
329
|
+
def list_available_models() -> List[ModelInfo]:
|
|
330
|
+
"""Returns a list of all available models with their detailed info."""
|
|
377
331
|
LLMFactory.ensure_initialized()
|
|
378
|
-
|
|
332
|
+
models = sorted(LLMFactory._models_by_identifier.values(), key=lambda m: m.model_identifier)
|
|
333
|
+
return [
|
|
334
|
+
ModelInfo(
|
|
335
|
+
model_identifier=m.model_identifier,
|
|
336
|
+
display_name=m.name,
|
|
337
|
+
value=m.value,
|
|
338
|
+
canonical_name=m.canonical_name,
|
|
339
|
+
provider=m.provider.value,
|
|
340
|
+
runtime=m.runtime.value,
|
|
341
|
+
host_url=m.host_url
|
|
342
|
+
)
|
|
343
|
+
for m in models
|
|
344
|
+
]
|
|
379
345
|
|
|
380
346
|
@staticmethod
|
|
381
|
-
def
|
|
382
|
-
"""
|
|
383
|
-
Returns a list of LLMModel instances for a specific provider.
|
|
384
|
-
"""
|
|
347
|
+
def list_models_by_provider(provider: LLMProvider) -> List[ModelInfo]:
|
|
348
|
+
"""Returns a list of available models for a specific provider."""
|
|
385
349
|
LLMFactory.ensure_initialized()
|
|
386
|
-
|
|
350
|
+
provider_models = sorted(
|
|
351
|
+
[m for m in LLMFactory._models_by_identifier.values() if m.provider == provider],
|
|
352
|
+
key=lambda m: m.model_identifier
|
|
353
|
+
)
|
|
354
|
+
return [
|
|
355
|
+
ModelInfo(
|
|
356
|
+
model_identifier=m.model_identifier,
|
|
357
|
+
display_name=m.name,
|
|
358
|
+
value=m.value,
|
|
359
|
+
canonical_name=m.canonical_name,
|
|
360
|
+
provider=m.provider.value,
|
|
361
|
+
runtime=m.runtime.value,
|
|
362
|
+
host_url=m.host_url
|
|
363
|
+
)
|
|
364
|
+
for m in provider_models
|
|
365
|
+
]
|
|
387
366
|
|
|
388
367
|
@staticmethod
|
|
389
|
-
def
|
|
390
|
-
"""
|
|
391
|
-
Get the canonical name for a model by its name.
|
|
392
|
-
|
|
393
|
-
Args:
|
|
394
|
-
model_name (str): The model name (e.g., "gpt_4o")
|
|
395
|
-
|
|
396
|
-
Returns:
|
|
397
|
-
Optional[str]: The canonical name if found, None otherwise
|
|
398
|
-
"""
|
|
368
|
+
def list_models_by_runtime(runtime: LLMRuntime) -> List[ModelInfo]:
|
|
369
|
+
"""Returns a list of available models for a specific runtime."""
|
|
399
370
|
LLMFactory.ensure_initialized()
|
|
400
|
-
|
|
401
|
-
for
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return
|
|
371
|
+
runtime_models = sorted(
|
|
372
|
+
[m for m in LLMFactory._models_by_identifier.values() if m.runtime == runtime],
|
|
373
|
+
key=lambda m: m.model_identifier
|
|
374
|
+
)
|
|
375
|
+
return [
|
|
376
|
+
ModelInfo(
|
|
377
|
+
model_identifier=m.model_identifier,
|
|
378
|
+
display_name=m.name,
|
|
379
|
+
value=m.value,
|
|
380
|
+
canonical_name=m.canonical_name,
|
|
381
|
+
provider=m.provider.value,
|
|
382
|
+
runtime=m.runtime.value,
|
|
383
|
+
host_url=m.host_url
|
|
384
|
+
)
|
|
385
|
+
for m in runtime_models
|
|
386
|
+
]
|
|
405
387
|
|
|
406
388
|
@staticmethod
|
|
407
|
-
def
|
|
389
|
+
def get_canonical_name(model_identifier: str) -> Optional[str]:
|
|
408
390
|
"""
|
|
409
|
-
|
|
410
|
-
sorted by provider name and model name. Providers with no models are included
|
|
411
|
-
with an empty model list.
|
|
391
|
+
Retrieves the canonical name for a given model identifier.
|
|
412
392
|
"""
|
|
413
393
|
LLMFactory.ensure_initialized()
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
394
|
+
model = LLMFactory._models_by_identifier.get(model_identifier)
|
|
395
|
+
if model:
|
|
396
|
+
return model.canonical_name
|
|
417
397
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
models = LLMFactory._models_by_provider.get(provider, [])
|
|
421
|
-
|
|
422
|
-
# Sort the models for this provider by name
|
|
423
|
-
sorted_models = sorted(models, key=lambda model: model.name)
|
|
424
|
-
|
|
425
|
-
model_infos = [
|
|
426
|
-
ModelInfo(name=model.name, canonical_name=model.canonical_name)
|
|
427
|
-
for model in sorted_models
|
|
428
|
-
]
|
|
429
|
-
|
|
430
|
-
result.append(ProviderModelGroup(
|
|
431
|
-
provider=provider.name,
|
|
432
|
-
models=model_infos
|
|
433
|
-
))
|
|
434
|
-
|
|
435
|
-
return result
|
|
398
|
+
logger.warning(f"Could not find model with identifier '{model_identifier}' to get its canonical name.")
|
|
399
|
+
return None
|
|
436
400
|
|
|
437
401
|
default_llm_factory = LLMFactory()
|