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:
YueGuobin 2026-03-05 21:44:36 +08:00
parent 28f2fe03e6
commit 54775faaf4
5 changed files with 61 additions and 28 deletions

View File

@ -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,

View File

@ -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

View File

@ -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)
"""

View File

@ -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

View File

@ -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