mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-08-27 20:40:13 +03:00
feat(copilot): rename copilot modes for clarity and add mode-specific tools
- Rename "teaching" mode to "teaching_assistant" for better clarity - Rename "lab_assistant" mode to "lab_automation_assistant" to reflect expanded capabilities - Implement mode-specific tool sets: teaching_assistant gets read-only diagnostic tools only, while lab_automation_assistant gets full diagnostic and configuration tools - Update API documentation examples to reflect new mode names - Maintain backward compatibility with default tool set initialization
This commit is contained in:
parent
28f2fe03e6
commit
54775faaf4
@ -124,7 +124,7 @@ The `model_type` field accepts the following values:
|
||||
| `api_key` | string | API key (auto-encrypted) |
|
||||
| `max_tokens` | integer | Max tokens for generation |
|
||||
| `context_strategy` | string | Context trimming strategy: "conservative" (60%), "balanced" (75%), "aggressive" (85%). Default: "balanced" |
|
||||
| `copilot_mode` | string | GNS3-Copilot mode: "teaching" (diagnostics only, default) or "lab_assistant" (full configuration access) |
|
||||
| `copilot_mode` | string | GNS3-Copilot mode: "teaching_assistant" (diagnostics only, default) or "lab_automation_assistant" (full configuration access) |
|
||||
| `is_default` | boolean | Set as default (default: false) |
|
||||
|
||||
**Important Notes:**
|
||||
@ -235,7 +235,7 @@ curl -X POST http://localhost:3080/v3/access/users/{user_id}/llm-model-configs \
|
||||
"context_limit": 128,
|
||||
"context_strategy": "balanced",
|
||||
"api_key": "sk-xxx",
|
||||
"copilot_mode": "teaching",
|
||||
"copilot_mode": "teaching_assistant",
|
||||
"is_default": true
|
||||
}'
|
||||
```
|
||||
@ -285,7 +285,7 @@ curl -X POST http://localhost:3080/v3/access/groups/{group_id}/llm-model-configs
|
||||
"context_limit": 200,
|
||||
"context_strategy": "balanced",
|
||||
"api_key": "sk-ant-xxx",
|
||||
"copilot_mode": "lab_assistant",
|
||||
"copilot_mode": "lab_automation_assistant",
|
||||
"is_default": true
|
||||
}'
|
||||
```
|
||||
@ -313,7 +313,7 @@ curl -X GET http://localhost:3080/v3/access/users/{user_id}/llm-model-configs \
|
||||
"context_limit": 128,
|
||||
"context_strategy": "balanced",
|
||||
"api_key": "sk-xxx",
|
||||
"copilot_mode": "lab_assistant"
|
||||
"copilot_mode": "lab_automation_assistant"
|
||||
},
|
||||
"user_id": "uuid-user",
|
||||
"group_id": null,
|
||||
|
||||
@ -33,11 +33,15 @@ an AI-powered assistant for GNS3 network automation and management.
|
||||
|
||||
The agent provides:
|
||||
- LangGraph-based state management and workflow
|
||||
- Tool orchestration for GNS3 operations
|
||||
- Mode-aware tool orchestration for GNS3 operations
|
||||
- Context-aware conversation handling
|
||||
- Automatic conversation title generation
|
||||
- Integration with GNS3 topology management
|
||||
|
||||
Copilot Modes:
|
||||
- "teaching_assistant" (default): Diagnostic tools only, no configuration changes
|
||||
- "lab_automation_assistant": Full diagnostic and configuration tools
|
||||
|
||||
"""
|
||||
|
||||
# Standard library imports
|
||||
@ -84,20 +88,36 @@ logger = logging.getLogger(__name__)
|
||||
# Note: LLM model configuration is now managed by the new llm_model_configs system.
|
||||
# The model_factory module handles model creation with configuration from the database.
|
||||
|
||||
# Define the available tools for the agent
|
||||
tools = [
|
||||
# Define tools for different copilot modes
|
||||
# Teaching assistant mode: READ-ONLY diagnostic tools only
|
||||
TEACHING_ASSISTANT_MODE_TOOLS = [
|
||||
GNS3TemplateTool(), # Get GNS3 node templates
|
||||
GNS3CreateNodeTool(), # Create new nodes in GNS3
|
||||
GNS3LinkTool(), # Create links between nodes
|
||||
GNS3StartNodeTool(), # Start GNS3 nodes
|
||||
GNS3UpdateNodeNameTool(), # Update node name
|
||||
ExecuteMultipleDeviceCommands(), # Execute show/display/debug commands on multiple devices (READ-ONLY)
|
||||
ExecuteMultipleDeviceConfigCommands(), # Execute configuration commands on multiple devices
|
||||
ExecuteMultipleDeviceCommands(), # Execute show/display/debug commands (READ-ONLY)
|
||||
]
|
||||
|
||||
# Lab automation assistant mode: Full diagnostic AND configuration tools
|
||||
LAB_AUTOMATION_ASSISTANT_MODE_TOOLS = [
|
||||
GNS3TemplateTool(), # Get GNS3 node templates
|
||||
GNS3CreateNodeTool(), # Create new nodes in GNS3
|
||||
GNS3LinkTool(), # Create links between nodes
|
||||
GNS3StartNodeTool(), # Start GNS3 nodes
|
||||
GNS3UpdateNodeNameTool(), # Update node name
|
||||
ExecuteMultipleDeviceCommands(), # Execute show/display/debug commands (READ-ONLY)
|
||||
ExecuteMultipleDeviceConfigCommands(), # Execute configuration commands
|
||||
VPCSMultiCommands(), # Execute VPCS commands on multiple devices
|
||||
]
|
||||
# Augment the LLM with tools
|
||||
tools_by_name = {tool.name: tool for tool in tools}
|
||||
# Model with tools will be created dynamically by the factory when needed
|
||||
|
||||
# Default tools (legacy support - will be overridden by mode-specific tools)
|
||||
tools = LAB_AUTOMATION_ASSISTANT_MODE_TOOLS
|
||||
|
||||
# Create combined tool lookup for tool_node (supports both modes)
|
||||
# tool_node will receive tool calls based on mode-specific tools bound to the model
|
||||
ALL_TOOLS = LAB_AUTOMATION_ASSISTANT_MODE_TOOLS
|
||||
tools_by_name = {tool.name: tool for tool in ALL_TOOLS}
|
||||
|
||||
# Log application startup
|
||||
logger.info("GNS3-Copilot application starting up")
|
||||
@ -203,6 +223,15 @@ def llm_call(state: dict, config: RunnableConfig | None = None):
|
||||
# Store topology_info in state for pre_model_hook to access
|
||||
state["topology_info"] = topology_info
|
||||
|
||||
# Select tools based on copilot_mode
|
||||
copilot_mode = llm_config.get("copilot_mode", "teaching_assistant").lower()
|
||||
if copilot_mode == "lab_automation_assistant":
|
||||
mode_tools = LAB_AUTOMATION_ASSISTANT_MODE_TOOLS
|
||||
logger.info("Using LAB_AUTOMATION_ASSISTANT mode tools (includes configuration tools)")
|
||||
else: # teaching_assistant mode (default)
|
||||
mode_tools = TEACHING_ASSISTANT_MODE_TOOLS
|
||||
logger.info("Using TEACHING_ASSISTANT mode tools (diagnostic tools only)")
|
||||
|
||||
# Create pre_model_hook for automatic topology injection and trimming
|
||||
# Load system prompt based on copilot_mode configuration
|
||||
system_prompt = load_system_prompt(llm_config)
|
||||
@ -210,14 +239,18 @@ def llm_call(state: dict, config: RunnableConfig | None = None):
|
||||
system_prompt=system_prompt,
|
||||
get_topology_func=lambda s: s.get("topology_info"),
|
||||
get_llm_config_func=get_current_llm_config,
|
||||
get_tools_func=lambda: tools, # Pass tools for token estimation
|
||||
get_tools_func=lambda: mode_tools, # Pass mode-specific tools for token estimation
|
||||
)
|
||||
|
||||
# Create fresh model with tools for each LLM call
|
||||
logger.debug(
|
||||
"Creating model with tools: provider=%s, model=%s", llm_config.get("provider"), llm_config.get("model")
|
||||
"Creating model with tools: provider=%s, model=%s, mode=%s, tools=%d",
|
||||
llm_config.get("provider"),
|
||||
llm_config.get("model"),
|
||||
copilot_mode,
|
||||
len(mode_tools),
|
||||
)
|
||||
model_with_tools = create_base_model_with_tools(tools, llm_config=llm_config)
|
||||
model_with_tools = create_base_model_with_tools(mode_tools, llm_config=llm_config)
|
||||
|
||||
# Call pre_hook directly to prepare messages (topology injection + trimming)
|
||||
# Note: LangGraph's pre_model_hook only works with prebuilt agents, not custom StateGraph
|
||||
|
||||
@ -31,7 +31,7 @@ the GNS3-Copilot AI agent.
|
||||
|
||||
Available prompts:
|
||||
- base_prompt: Teaching assistant mode (diagnostics only, no configuration)
|
||||
- lab_assistant_prompt: Full lab assistant mode (diagnostics + configuration)
|
||||
- lab_assistant_prompt: Lab automation assistant mode (diagnostics + configuration)
|
||||
|
||||
"""
|
||||
|
||||
|
||||
@ -30,8 +30,8 @@ This module provides utilities for loading system prompts.
|
||||
Supports multiple prompt variants based on LLM model configuration.
|
||||
|
||||
Available Modes (controlled by config.copilot_mode in llm_model_configs):
|
||||
- "teaching" (default): Teaching assistant mode - diagnostics only, no configuration
|
||||
- "lab_assistant": Full lab assistant mode - diagnostics and configuration enabled
|
||||
- "teaching_assistant" (default): Teaching assistant mode - diagnostics only, no configuration
|
||||
- "lab_automation_assistant": Full lab automation assistant mode - diagnostics and configuration enabled
|
||||
|
||||
"""
|
||||
|
||||
@ -48,8 +48,8 @@ def load_system_prompt(llm_config: dict | None = None) -> str:
|
||||
Load the system prompt for GNS3-Copilot.
|
||||
|
||||
The prompt mode is controlled by the `copilot_mode` field in the LLM model config:
|
||||
- "teaching" (default): Teaching assistant mode - diagnostics only, no configuration
|
||||
- "lab_assistant": Full lab assistant mode - diagnostics and configuration enabled
|
||||
- "teaching_assistant" (default): Teaching assistant mode - diagnostics only, no configuration
|
||||
- "lab_automation_assistant": Full lab automation assistant mode - diagnostics and configuration enabled
|
||||
|
||||
Args:
|
||||
llm_config: LLM model configuration dictionary (flattened structure from get_user_llm_config_full)
|
||||
@ -58,16 +58,16 @@ def load_system_prompt(llm_config: dict | None = None) -> str:
|
||||
str: The system prompt string.
|
||||
"""
|
||||
if not llm_config:
|
||||
logger.info("No LLM config provided, using default TEACHING assistant prompt mode")
|
||||
logger.info("No LLM config provided, using default TEACHING_ASSISTANT prompt mode")
|
||||
return SYSTEM_PROMPT
|
||||
|
||||
# llm_config is a flattened dict with copilot_mode at the top level
|
||||
# Example: {"provider": "...", "model": "...", "copilot_mode": "...", ...}
|
||||
mode = llm_config.get("copilot_mode", "teaching").lower()
|
||||
mode = llm_config.get("copilot_mode", "teaching_assistant").lower()
|
||||
|
||||
if mode == "lab_assistant":
|
||||
logger.info("Using LAB_ASSISTANT prompt mode (diagnostics + configuration)")
|
||||
if mode == "lab_automation_assistant":
|
||||
logger.info("Using LAB_AUTOMATION_ASSISTANT prompt mode (diagnostics + configuration)")
|
||||
return LAB_ASSISTANT_PROMPT
|
||||
else:
|
||||
logger.info("Using TEACHING assistant prompt mode (diagnostics only)")
|
||||
logger.info("Using TEACHING_ASSISTANT prompt mode (diagnostics only)")
|
||||
return SYSTEM_PROMPT
|
||||
|
||||
@ -50,7 +50,7 @@ class LLMModelConfigData(BaseModel):
|
||||
)
|
||||
copilot_mode: Optional[str] = Field(
|
||||
None,
|
||||
description="GNS3-Copilot mode: 'teaching' (diagnostics only) or 'lab_assistant' (full configuration access)"
|
||||
description="GNS3-Copilot mode: 'teaching_assistant' (diagnostics only) or 'lab_automation_assistant' (full configuration access)"
|
||||
)
|
||||
|
||||
# Allow extra fields for extensibility
|
||||
@ -78,7 +78,7 @@ class LLMModelConfigCreate(BaseModel):
|
||||
)
|
||||
copilot_mode: Optional[str] = Field(
|
||||
None,
|
||||
description="GNS3-Copilot mode: 'teaching' (diagnostics only) or 'lab_assistant' (full configuration access)"
|
||||
description="GNS3-Copilot mode: 'teaching_assistant' (diagnostics only) or 'lab_automation_assistant' (full configuration access)"
|
||||
)
|
||||
|
||||
# Allow extra config fields
|
||||
@ -107,7 +107,7 @@ class LLMModelConfigUpdate(BaseModel):
|
||||
)
|
||||
copilot_mode: Optional[str] = Field(
|
||||
None,
|
||||
description="GNS3-Copilot mode: 'teaching' (diagnostics only) or 'lab_assistant' (full configuration access)"
|
||||
description="GNS3-Copilot mode: 'teaching_assistant' (diagnostics only) or 'lab_automation_assistant' (full configuration access)"
|
||||
)
|
||||
|
||||
# Allow extra config fields
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user