Spaces:
Running
Running
File size: 6,318 Bytes
6464d69 01a4095 6464d69 ff707e8 01a4095 ff707e8 6464d69 01a4095 6464d69 ff707e8 2e7e1ce 01a4095 8676c07 01a4095 8676c07 01a4095 8676c07 01a4095 9e25d5f 01a4095 8676c07 6464d69 01a4095 c6bfc2b 01a4095 6464d69 01a4095 c6bfc2b 01a4095 c6bfc2b 01a4095 ff707e8 c6bfc2b 01a4095 9e25d5f 01a4095 6464d69 c6bfc2b 01a4095 6464d69 ff707e8 6464d69 ff707e8 6464d69 ff707e8 6464d69 ff707e8 6464d69 ff707e8 6464d69 ff707e8 6464d69 ff707e8 6464d69 a420a58 6464d69 01a4095 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | """
tools.py
This module contains all available tools for the AI assistant.
Each tool is a function that can be called by the pipeline.
Tools:
- web_search: Google Serper API-based web search
"""
import os
import json
from typing import Dict, Any, Optional, List
# =============================================================================
# AVAILABLE TOOLS REGISTRY
# =============================================================================
# Dictionary mapping tool names to their functions
AVAILABLE_TOOLS = {
"web_search": None # Will be set after function definition
}
# =============================================================================
# SEARCH CONFIGURATION
# =============================================================================
WEB_SEARCH_MAX_QUERY_CHARS = int(os.getenv("WEB_SEARCH_MAX_QUERY_CHARS", "200"))
SEARCH_MAX_RESULTS = int(os.getenv("SEARCH_MAX_RESULTS", "1"))
SEARCH_WORKERS = int(os.getenv("SEARCH_WORKERS", "6"))
try:
from search import run_search
except ImportError as e:
raise ImportError("Could not import run_search from search.py: " + str(e))
# =============================================================================
# TOOL IMPLEMENTATIONS
# =============================================================================
def _format_search_results(structured_results: List[Dict[str, Any]]) -> str:
"""
Format search results from search.py into readable output.
Excludes unnecessary fields and returns full structured data.
Args:
structured_results: List of structured result dictionaries from search.py
Returns:
JSON formatted string with filtered search results
"""
if not structured_results:
print("⚠️ No results found from search")
return json.dumps({"results": [], "count": 0})
# Fields to exclude from each result
exclude_fields = {
"publish_date",
"author",
"fetch_time",
"extraction_status",
"confidence_score",
"content_type",
"cleaned_content",
"first_paragraph",
"quality_signals"
}
# Filter results and remove excluded fields
filtered_results = []
for result in structured_results[:max(1, SEARCH_MAX_RESULTS)]:
filtered_result = {k: v for k, v in result.items() if k not in exclude_fields}
filtered_results.append(filtered_result)
# Format as JSON output
output = {
"query_results": filtered_results,
"total_count": len(filtered_results)
}
result_json = json.dumps(output, indent=2, ensure_ascii=False)
print(f"✅ Got {len(filtered_results)} results from search pipeline")
print(f"📈 Total chars in results from search pipeline after formated( from tools.py): {len(structured_results)}")
return result_json
def web_search(query: str) -> str:
"""
Live web search tool using search.py pipeline.
Args:
query: The search query string
Returns:
Formatted string with search results containing:
- Position (for each result)
- Title
- Link
- Snippet
"""
try:
if not query or not isinstance(query, str):
print("⚠️ Invalid query provided")
return "No results found."
q = query.strip()
if not q:
print("⚠️ Empty query string")
return "No results found."
# Truncate query to max chars
q = q[:WEB_SEARCH_MAX_QUERY_CHARS]
print(f"🔎 Web search initiated for: '{q}' (max results={SEARCH_MAX_RESULTS})")
# Run search pipeline from search.py
structured_results, stats = run_search(q, max_results=SEARCH_MAX_RESULTS, workers=SEARCH_WORKERS)
print(f" Pipeline: {stats['search_engine']['total']} total results, "
f"{stats['cleaner']['successful']} successfully extracted")
print(f"📈 Total chars in results from search pipeline Before formated ( from tools.py ): {len(structured_results)}")
return _format_search_results(structured_results)
except Exception as e:
error_msg = f"Web search failed: {str(e)}"
print(f"❌ {error_msg}")
return f"Search failed: {str(e)}"
def execute_tool(tool_name: str, args: Dict[str, Any]) -> Optional[str]:
"""
Execute a tool by name with the given arguments.
Args:
tool_name: Name of the tool to execute
args: Dictionary of arguments for the tool
Returns:
Tool result as string, or None if tool not found or execution fails
"""
try:
# Validate tool name
if not tool_name:
print("No tool name provided")
return None
# Check if tool exists
if tool_name not in AVAILABLE_TOOLS:
print(f"Unknown tool: '{tool_name}'")
return None
# Get the tool function
tool_func = AVAILABLE_TOOLS.get(tool_name)
if tool_func is None:
print(f"Tool '{tool_name}' not implemented")
return None
print(f"Executing tool: '{tool_name}' with args: {args}")
# Execute the tool
result = tool_func(**args)
print(f"Tool '{tool_name}' executed successfully")
return result
except Exception as e:
print(f"Error executing tool '{tool_name}': {str(e)}")
return None
# =============================================================================
# INITIALIZE TOOL REGISTRY
# =============================================================================
# Register the web_search tool
AVAILABLE_TOOLS["web_search"] = web_search
AVAILABLE_TOOLS["websearch"] = web_search
def get_available_tools() -> list:
"""
Get a list of available tool names.
Returns:
List of tool name strings
"""
return list(AVAILABLE_TOOLS.keys())
def is_tool_available(tool_name: str) -> bool:
"""
Check if a tool is available.
Args:
tool_name: Name of the tool to check
Returns:
True if tool exists, False otherwise
"""
return tool_name in AVAILABLE_TOOLS and AVAILABLE_TOOLS[tool_name] is not None |