Compare commits
No commits in common. "d148b95534585b3c0c45fe5c13e50c5d377b34ec" and "15359e2ae3a6f502e8aa84adb3e456ad7ebd321b" have entirely different histories.
d148b95534
...
15359e2ae3
@ -1,5 +1,4 @@
|
|||||||
ollama
|
ollama
|
||||||
httpx
|
|
||||||
trilium-py
|
trilium-py
|
||||||
gitpython
|
gitpython
|
||||||
PyGithub
|
PyGithub
|
||||||
|
|||||||
@ -4,25 +4,17 @@ Custom CrewAI tool that wraps Ollama's native web search API.
|
|||||||
This tool allows CrewAI agents to perform web searches using an Ollama
|
This tool allows CrewAI agents to perform web searches using an Ollama
|
||||||
subscription instead of third-party services like Serper or EXA.
|
subscription instead of third-party services like Serper or EXA.
|
||||||
|
|
||||||
Uses direct HTTP requests via httpx with explicit Authorization: Bearer
|
|
||||||
header to ensure the OLLAMA_API_KEY is properly passed to the Ollama cloud
|
|
||||||
API endpoint (https://ollama.com/api/web_search).
|
|
||||||
|
|
||||||
Requires:
|
Requires:
|
||||||
- httpx library: pip install httpx (already a transitive dependency of crewai)
|
- Ollama Python library: pip install ollama
|
||||||
- OLLAMA_API_KEY environment variable set with your Ollama API key
|
- OLLAMA_API_KEY environment variable set with your Ollama API key
|
||||||
|
|
||||||
Reference: https://docs.ollama.com/capabilities/web-search
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
import httpx
|
import ollama
|
||||||
from crewai.tools import BaseTool
|
from crewai.tools import BaseTool
|
||||||
from pydantic import BaseModel, Field
|
from pydantic import BaseModel, Field
|
||||||
|
|
||||||
OLLAMA_WEB_SEARCH_URL = "https://ollama.com/api/web_search"
|
|
||||||
|
|
||||||
|
|
||||||
class OllamaWebSearchInput(BaseModel):
|
class OllamaWebSearchInput(BaseModel):
|
||||||
"""Input schema for OllamaWebSearchTool."""
|
"""Input schema for OllamaWebSearchTool."""
|
||||||
@ -50,10 +42,6 @@ class OllamaWebSearchTool(BaseTool):
|
|||||||
The tool requires an Ollama subscription and the OLLAMA_API_KEY environment
|
The tool requires an Ollama subscription and the OLLAMA_API_KEY environment
|
||||||
variable to be set.
|
variable to be set.
|
||||||
|
|
||||||
Authentication is handled by sending the OLLAMA_API_KEY as a Bearer token
|
|
||||||
in the Authorization header, as documented at:
|
|
||||||
https://docs.ollama.com/capabilities/web-search
|
|
||||||
|
|
||||||
Example usage:
|
Example usage:
|
||||||
from ai_generators.tools.ollama_web_search_tool import OllamaWebSearchTool
|
from ai_generators.tools.ollama_web_search_tool import OllamaWebSearchTool
|
||||||
|
|
||||||
@ -77,9 +65,6 @@ class OllamaWebSearchTool(BaseTool):
|
|||||||
"""
|
"""
|
||||||
Execute a web search and return formatted results.
|
Execute a web search and return formatted results.
|
||||||
|
|
||||||
Makes a POST request to https://ollama.com/api/web_search with the
|
|
||||||
OLLAMA_API_KEY as a Bearer token in the Authorization header.
|
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
query: The search query string
|
query: The search query string
|
||||||
max_results: Maximum number of results to return (1-10)
|
max_results: Maximum number of results to return (1-10)
|
||||||
@ -87,40 +72,16 @@ class OllamaWebSearchTool(BaseTool):
|
|||||||
Returns:
|
Returns:
|
||||||
Formatted string with search results, each containing title, URL, and content
|
Formatted string with search results, each containing title, URL, and content
|
||||||
"""
|
"""
|
||||||
api_key = os.environ.get("OLLAMA_API_KEY")
|
|
||||||
if not api_key:
|
|
||||||
return (
|
|
||||||
"Error: OLLAMA_API_KEY environment variable is not set. "
|
|
||||||
"Please set your Ollama API key."
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = httpx.post(
|
# Ensure API key is set
|
||||||
OLLAMA_WEB_SEARCH_URL,
|
if not os.environ.get("OLLAMA_API_KEY"):
|
||||||
json={"query": query, "max_results": max_results},
|
return "Error: OLLAMA_API_KEY environment variable is not set. Please set your Ollama API key."
|
||||||
headers={
|
|
||||||
"Authorization": f"Bearer {api_key}",
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
timeout=30.0,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Raise for HTTP errors so we can catch them with specific messages
|
# Perform the web search
|
||||||
if response.status_code == 401:
|
response = ollama.web_search(query=query, max_results=max_results)
|
||||||
return (
|
|
||||||
"Authentication error: OLLAMA_API_KEY was rejected. "
|
|
||||||
"Your key may be invalid or expired. Please verify it at "
|
|
||||||
"https://ollama.com/settings/keys"
|
|
||||||
)
|
|
||||||
if response.status_code == 429:
|
|
||||||
return (
|
|
||||||
"Rate limit exceeded: Too many search requests. "
|
|
||||||
"Please wait a moment and try again."
|
|
||||||
)
|
|
||||||
response.raise_for_status()
|
|
||||||
|
|
||||||
data = response.json()
|
# Extract and format results
|
||||||
results = data.get("results", [])
|
results = response.get("results", [])
|
||||||
|
|
||||||
if not results:
|
if not results:
|
||||||
return f"No search results found for query: '{query}'"
|
return f"No search results found for query: '{query}'"
|
||||||
@ -137,20 +98,27 @@ class OllamaWebSearchTool(BaseTool):
|
|||||||
|
|
||||||
return "\n".join(formatted_results)
|
return "\n".join(formatted_results)
|
||||||
|
|
||||||
except httpx.TimeoutException:
|
except Exception as exc:
|
||||||
|
return f"Error performing web search: {exc}"
|
||||||
|
|
||||||
|
def _handle_exception(self, exc: Exception) -> str:
|
||||||
|
"""Handle exceptions gracefully and return a user-friendly error message."""
|
||||||
|
error_message = str(exc)
|
||||||
|
|
||||||
|
# Check for common error types
|
||||||
|
if "authentication" in error_message.lower() or "401" in error_message:
|
||||||
return (
|
return (
|
||||||
"Timeout error: The web search request timed out. "
|
"Authentication error: Your OLLAMA_API_KEY may be invalid or expired. "
|
||||||
"Please try again with a simpler query."
|
"Please check your API key and ensure it's set correctly in the environment."
|
||||||
)
|
)
|
||||||
except httpx.ConnectError:
|
elif "rate limit" in error_message.lower() or "429" in error_message:
|
||||||
|
return "Rate limit exceeded: Too many search requests. Please wait a moment and try again."
|
||||||
|
elif (
|
||||||
|
"network" in error_message.lower() or "connection" in error_message.lower()
|
||||||
|
):
|
||||||
return (
|
return (
|
||||||
"Network error: Unable to connect to Ollama's web search service. "
|
"Network error: Unable to connect to Ollama's web search service. "
|
||||||
"Please check your internet connection and try again."
|
"Please check your internet connection and try again."
|
||||||
)
|
)
|
||||||
except httpx.HTTPStatusError as exc:
|
else:
|
||||||
return (
|
return f"Search failed: {error_message}"
|
||||||
f"HTTP error {exc.response.status_code} from Ollama web search API: "
|
|
||||||
f"{exc.response.text}"
|
|
||||||
)
|
|
||||||
except Exception as exc:
|
|
||||||
return f"Error performing web search: {exc}"
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user