mirror of
https://github.com/GNS3/gns3-server.git
synced 2026-10-24 20:02:35 +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) |
|
| `api_key` | string | API key (auto-encrypted) |
|
||||||
| `max_tokens` | integer | Max tokens for generation |
|
| `max_tokens` | integer | Max tokens for generation |
|
||||||
| `context_strategy` | string | Context trimming strategy: "conservative" (60%), "balanced" (75%), "aggressive" (85%). Default: "balanced" |
|
| `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) |
|
| `is_default` | boolean | Set as default (default: false) |
|
||||||
|
|
||||||
**Important Notes:**
|
**Important Notes:**
|
||||||
@ -235,7 +235,7 @@ curl -X POST http://localhost:3080/v3/access/users/{user_id}/llm-model-configs \
|
|||||||
"context_limit": 128,
|
"context_limit": 128,
|
||||||
"context_strategy": "balanced",
|
"context_strategy": "balanced",
|
||||||
"api_key": "sk-xxx",
|
"api_key": "sk-xxx",
|
||||||
"copilot_mode": "teaching",
|
"copilot_mode": "teaching_assistant",
|
||||||
"is_default": true
|
"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_limit": 200,
|
||||||
"context_strategy": "balanced",
|
"context_strategy": "balanced",
|
||||||
"api_key": "sk-ant-xxx",
|
"api_key": "sk-ant-xxx",
|
||||||
"copilot_mode": "lab_assistant",
|
"copilot_mode": "lab_automation_assistant",
|
||||||
"is_default": true
|
"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_limit": 128,
|
||||||
"context_strategy": "balanced",
|
"context_strategy": "balanced",
|
||||||
"api_key": "sk-xxx",
|
"api_key": "sk-xxx",
|
||||||
"copilot_mode": "lab_assistant"
|
"copilot_mode": "lab_automation_assistant"
|
||||||
},
|
},
|
||||||
"user_id": "uuid-user",
|
"user_id": "uuid-user",
|
||||||
"group_id": null,
|
"group_id": null,
|
||||||
|
|||||||
@ -33,11 +33,15 @@ an AI-powered assistant for GNS3 network automation and management.
|
|||||||
|
|
||||||
The agent provides:
|
The agent provides:
|
||||||
- LangGraph-based state management and workflow
|
- LangGraph-based state management and workflow
|
||||||
- Tool orchestration for GNS3 operations
|
- Mode-aware tool orchestration for GNS3 operations
|
||||||
- Context-aware conversation handling
|
- Context-aware conversation handling
|
||||||
- Automatic conversation title generation
|
- Automatic conversation title generation
|
||||||
- Integration with GNS3 topology management
|
- 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
|
# 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.
|
# 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.
|
# The model_factory module handles model creation with configuration from the database.
|
||||||
|
|
||||||
# Define the available tools for the agent
|
# Define tools for different copilot modes
|
||||||
tools = [
|
# Teaching assistant mode: READ-ONLY diagnostic tools only
|
||||||
|
TEACHING_ASSISTANT_MODE_TOOLS = [
|
||||||
GNS3TemplateTool(), # Get GNS3 node templates
|
GNS3TemplateTool(), # Get GNS3 node templates
|
||||||
GNS3CreateNodeTool(), # Create new nodes in GNS3
|
GNS3CreateNodeTool(), # Create new nodes in GNS3
|
||||||
GNS3LinkTool(), # Create links between nodes
|
GNS3LinkTool(), # Create links between nodes
|
||||||
GNS3StartNodeTool(), # Start GNS3 nodes
|
GNS3StartNodeTool(), # Start GNS3 nodes
|
||||||
GNS3UpdateNodeNameTool(), # Update node name
|
GNS3UpdateNodeNameTool(), # Update node name
|
||||||
ExecuteMultipleDeviceCommands(), # Execute show/display/debug commands on multiple devices (READ-ONLY)
|
ExecuteMultipleDeviceCommands(), # Execute show/display/debug commands (READ-ONLY)
|
||||||
ExecuteMultipleDeviceConfigCommands(), # Execute configuration commands on multiple devices
|
]
|
||||||
|
|
||||||
|
# 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
|
VPCSMultiCommands(), # Execute VPCS commands on multiple devices
|
||||||
]
|
]
|
||||||
# Augment the LLM with tools
|
|
||||||
tools_by_name = {tool.name: tool for tool in tools}
|
# Default tools (legacy support - will be overridden by mode-specific tools)
|
||||||
# Model with tools will be created dynamically by the factory when needed
|
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
|
# Log application startup
|
||||||
logger.info("GNS3-Copilot application starting up")
|
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
|
# Store topology_info in state for pre_model_hook to access
|
||||||
state["topology_info"] = topology_info
|
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
|
# Create pre_model_hook for automatic topology injection and trimming
|
||||||
# Load system prompt based on copilot_mode configuration
|
# Load system prompt based on copilot_mode configuration
|
||||||
system_prompt = load_system_prompt(llm_config)
|
system_prompt = load_system_prompt(llm_config)
|
||||||
@ -210,14 +239,18 @@ def llm_call(state: dict, config: RunnableConfig | None = None):
|
|||||||
system_prompt=system_prompt,
|
system_prompt=system_prompt,
|
||||||
get_topology_func=lambda s: s.get("topology_info"),
|
get_topology_func=lambda s: s.get("topology_info"),
|
||||||
get_llm_config_func=get_current_llm_config,
|
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
|
# Create fresh model with tools for each LLM call
|
||||||
logger.debug(
|
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)
|
# Call pre_hook directly to prepare messages (topology injection + trimming)
|
||||||
# Note: LangGraph's pre_model_hook only works with prebuilt agents, not custom StateGraph
|
# 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:
|
Available prompts:
|
||||||
- base_prompt: Teaching assistant mode (diagnostics only, no configuration)
|
- 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.
|
Supports multiple prompt variants based on LLM model configuration.
|
||||||
|
|
||||||
Available Modes (controlled by config.copilot_mode in llm_model_configs):
|
Available Modes (controlled by config.copilot_mode in llm_model_configs):
|
||||||
- "teaching" (default): Teaching assistant mode - diagnostics only, no configuration
|
- "teaching_assistant" (default): Teaching assistant mode - diagnostics only, no configuration
|
||||||
- "lab_assistant": Full lab assistant mode - diagnostics and configuration enabled
|
- "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.
|
Load the system prompt for GNS3-Copilot.
|
||||||
|
|
||||||
The prompt mode is controlled by the `copilot_mode` field in the LLM model config:
|
The prompt mode is controlled by the `copilot_mode` field in the LLM model config:
|
||||||
- "teaching" (default): Teaching assistant mode - diagnostics only, no configuration
|
- "teaching_assistant" (default): Teaching assistant mode - diagnostics only, no configuration
|
||||||
- "lab_assistant": Full lab assistant mode - diagnostics and configuration enabled
|
- "lab_automation_assistant": Full lab automation assistant mode - diagnostics and configuration enabled
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
llm_config: LLM model configuration dictionary (flattened structure from get_user_llm_config_full)
|
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.
|
str: The system prompt string.
|
||||||
"""
|
"""
|
||||||
if not llm_config:
|
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
|
return SYSTEM_PROMPT
|
||||||
|
|
||||||
# llm_config is a flattened dict with copilot_mode at the top level
|
# llm_config is a flattened dict with copilot_mode at the top level
|
||||||
# Example: {"provider": "...", "model": "...", "copilot_mode": "...", ...}
|
# 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":
|
if mode == "lab_automation_assistant":
|
||||||
logger.info("Using LAB_ASSISTANT prompt mode (diagnostics + configuration)")
|
logger.info("Using LAB_AUTOMATION_ASSISTANT prompt mode (diagnostics + configuration)")
|
||||||
return LAB_ASSISTANT_PROMPT
|
return LAB_ASSISTANT_PROMPT
|
||||||
else:
|
else:
|
||||||
logger.info("Using TEACHING assistant prompt mode (diagnostics only)")
|
logger.info("Using TEACHING_ASSISTANT prompt mode (diagnostics only)")
|
||||||
return SYSTEM_PROMPT
|
return SYSTEM_PROMPT
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class LLMModelConfigData(BaseModel):
|
|||||||
)
|
)
|
||||||
copilot_mode: Optional[str] = Field(
|
copilot_mode: Optional[str] = Field(
|
||||||
None,
|
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
|
# Allow extra fields for extensibility
|
||||||
@ -78,7 +78,7 @@ class LLMModelConfigCreate(BaseModel):
|
|||||||
)
|
)
|
||||||
copilot_mode: Optional[str] = Field(
|
copilot_mode: Optional[str] = Field(
|
||||||
None,
|
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
|
# Allow extra config fields
|
||||||
@ -107,7 +107,7 @@ class LLMModelConfigUpdate(BaseModel):
|
|||||||
)
|
)
|
||||||
copilot_mode: Optional[str] = Field(
|
copilot_mode: Optional[str] = Field(
|
||||||
None,
|
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
|
# Allow extra config fields
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user