Spaces:
Sleeping
Sleeping
from agents import Agent, function_tool | |
from retriever_tool import db | |
from textwrap import dedent | |
from agents import Tool | |
from model import gemini_model, qwen_model | |
def unused_ports() -> str: | |
"""Get information about unused Ethernet interfaces across all network devices. | |
This tool specifically queries for unused/available ports in the network infrastructure | |
by filtering documents with 'Ethernet Interfaces Summary' headers and UNUSED interfaces. | |
Only returns results from leaf switches (devices with 'LEAF' in their name). | |
""" | |
# Use metadata-based filtering instead of similarity search | |
# Get all documents from the vectorstore | |
all_docs_with_scores = db.similarity_search_with_score("", k=db.index.ntotal) | |
# Filter documents by header metadata and device type | |
target_header = "Ethernet Interfaces Summary" | |
matching_docs = [] | |
for doc, score in all_docs_with_scores: | |
# Check if document has the target header | |
section_title = doc.metadata.get('section_title', '') | |
header_path = doc.metadata.get('header_path', '') | |
device_name = doc.metadata.get('device_name', '') | |
# Filter for: | |
# 1. Documents with "Ethernet Interfaces Summary" in header path | |
# 2. Documents from LEAF devices only | |
# 3. Documents that contain UNUSED interfaces | |
is_ethernet_summary = (target_header == section_title or target_header in header_path) | |
is_leaf_device = 'LEAF' in device_name.upper() | |
has_unused = 'UNUSED' in doc.page_content | |
if is_ethernet_summary and is_leaf_device and has_unused: | |
matching_docs.append((doc, score)) | |
response = "" | |
if not matching_docs: | |
return "No unused interface information found in Ethernet Interfaces Summary sections of leaf devices." | |
# Track devices and their unused interfaces | |
device_unused = {} | |
for doc, score in matching_docs: | |
device_name = doc.metadata.get('device_name') | |
source = doc.metadata.get('source', 'Unknown source') | |
header_path = doc.metadata.get('header_path', 'No header path') | |
section_title = doc.metadata.get('section_title', 'No section title') | |
if device_name: | |
# Count UNUSED interfaces in this chunk | |
unused_count = doc.page_content.count('UNUSED') | |
if unused_count > 0: | |
if device_name not in device_unused: | |
device_unused[device_name] = { | |
'total_unused': 0, | |
'sections': [], | |
'source': source | |
} | |
device_unused[device_name]['total_unused'] += unused_count | |
device_unused[device_name]['sections'].append({ | |
'section': section_title, | |
'header_path': header_path, | |
'count': unused_count, | |
'score': score | |
}) | |
# Format the response with enhanced metadata | |
if matching_docs: | |
# Attach the actual sections containing UNUSED interfaces from each document | |
for doc, score in matching_docs: | |
device_name = doc.metadata.get('device_name', 'Unknown device') | |
source = doc.metadata.get('source', 'Unknown source') | |
section_title = doc.metadata.get('section_title', 'No section title') | |
header_path = doc.metadata.get('header_path', 'No header path') | |
response += f"---\n" | |
response += f"Device: {device_name} (Source: {source})\n" | |
response += f"Section: {section_title}\n" | |
response += f"Path: {header_path}\n\n" | |
# Extract and attach only the lines that actually contain UNUSED interfaces | |
for line in doc.page_content.splitlines(): | |
if 'UNUSED' in line: | |
response += line + "\n" | |
response += "\n" | |
else: | |
response += "No leaf devices with unused interfaces found in Ethernet Interfaces Summary sections." | |
print(f"Retrieved {len(matching_docs)} filtered results from Ethernet Interfaces Summary sections on leaf devices") | |
return response | |
# Port recommendation specific instructions | |
port_recommendation_instructions = dedent(""" | |
You are an expert network assistant specialized in port and interface recommendations. | |
Your role is to use the available tools to answer questions about port/interface recommendations for connecting new devices to the network infrastructure. | |
Key responsibilities: | |
- Port and interface are synonymous terms (users may use them interchangeably) | |
- Always use the retrieve_network_information tool to find unused interface ports before making recommendations | |
- Provide specific device names and port numbers in your recommendations | |
- Be detailed and precise in your responses | |
Port Recommendation Rules: | |
1. If not specified otherwise, always recommend TWO ports across different devices for redundancy | |
2. Recommend ports across devices that form a MLAG or LACP group | |
3. Leaf switches are in MLAG pairs: odd-numbered leaf (leaf01, leaf03, etc.) paired with even-numbered leaf (leaf02, leaf04, etc.) | |
4. Try to select the same interface port number across paired devices (e.g., if recommending port 25 on leaf01, also recommend port 25 on leaf02) | |
5. Include device names and specific port identifiers in your response | |
6. If user specifically requests single port or "without redundancy", recommend only one port | |
7. Only recommend ports that have the description "UNUSED". | |
Response Format: | |
- Always query for unused ports first using retrieve_network_information | |
- Provide clear, actionable recommendations with device names and port numbers | |
- Explain the reasoning behind your recommendations when relevant | |
Examples: | |
User: "I need an unused port" | |
Response: After checking available ports, I recommend using Ethernet1/25 on leaf01 and Ethernet1/25 on leaf02 for redundancy. | |
User: "I need an unused port without redundancy" | |
Response: After checking available ports, I recommend using Ethernet1/26 on leaf01. | |
User: "I need to dual connect a server to the network, what ports should I use?" | |
Response: For dual-connecting a server, I recommend using Ethernet1/27 on leaf01 and Ethernet1/27 on leaf02, which will provide MLAG redundancy. | |
User: "I need to connect two servers to the network, what ports should I use?" | |
Response: For connecting two servers, I recommend using Ethernet1/28-29 on leaf01 and Ethernet1/28-29 on leaf02 for redundancy. | |
""") | |
# Create the specialized port recommendations agent | |
port_recommendations_agent = Agent( | |
name="port_recommendations_agent", | |
instructions=port_recommendation_instructions, | |
model=qwen_model, | |
tools=[unused_ports], | |
) |