Source code for redis_openai_agents.sdk_tools
"""OpenAI Agents SDK tool integrations for Redis.
This module provides tools that can be used with the OpenAI Agents SDK
to integrate Redis-based search capabilities.
Example:
>>> from redis_openai_agents import HybridSearchService, create_redis_file_search_tool
>>>
>>> # Create the search service
>>> service = HybridSearchService(redis_url="redis://localhost:6379", index_name="docs")
>>>
>>> # Index some documents
>>> await service.index_documents([
... {"content": "Redis is a fast database.", "metadata": {"source": "docs"}},
... ])
>>>
>>> # Create the tool
>>> search_tool = create_redis_file_search_tool(service)
>>>
>>> # Use with an agent
>>> from agents import Agent
>>> agent = Agent(name="Support", tools=[search_tool])
"""
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from .hybrid import HybridSearchService
[docs]
@dataclass
class RedisFileSearchTool:
"""A callable tool for searching documents using Redis hybrid search.
This tool wraps a HybridSearchService to provide RAG capabilities
for OpenAI Agents SDK agents.
Attributes:
name: Tool name for registration with agents.
description: Tool description for LLM context.
parameters: JSON schema for function calling parameters.
default_k: Default number of results to return.
"""
_service: "HybridSearchService"
name: str = "redis_file_search"
description: str = (
"Search documents using semantic similarity and keyword matching. "
"Use this tool to find relevant information from the knowledge base."
)
default_k: int = 5
default_min_score: float = 0.0
parameters: dict[str, Any] = field(default_factory=dict)
def __post_init__(self) -> None:
"""Initialize parameter schema after dataclass init."""
if not self.parameters:
self.parameters = {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "The search query to find relevant documents.",
},
"k": {
"type": "integer",
"description": f"Maximum number of results to return (default: {self.default_k}).",
"default": self.default_k,
},
"min_score": {
"type": "number",
"description": "Minimum similarity score (0-1) for results.",
"default": self.default_min_score,
},
},
"required": ["query"],
}
async def __call__(
self,
query: str,
k: int | None = None,
min_score: float | None = None,
) -> str:
"""Execute the search and return formatted results.
Args:
query: The search query.
k: Maximum number of results (uses default_k if not provided).
min_score: Minimum similarity score for filtering results.
Returns:
Formatted search results as a string for LLM consumption.
"""
k = k if k is not None else self.default_k
min_score = min_score if min_score is not None else self.default_min_score
try:
# Handle empty query
if not query or not query.strip():
return "Please provide a search query."
# Execute search
results = await self._service.search(
query=query,
k=k,
)
# Filter by minimum score
if min_score > 0:
results = [r for r in results if r.score >= min_score]
# Format results for LLM
if not results:
return "No documents found matching your query."
output_parts = [f"Found {len(results)} relevant document(s):\n"]
for i, result in enumerate(results, 1):
output_parts.append(f"\n--- Result {i} (score: {result.score:.2f}) ---")
output_parts.append(f"Content: {result.content}")
if result.metadata:
metadata_str = ", ".join(f"{k}: {v}" for k, v in result.metadata.items())
output_parts.append(f"Metadata: {metadata_str}")
return "\n".join(output_parts)
except Exception as e:
# Return error as string (non-fatal, sent to LLM)
return f"Search error: {str(e)}. Please try a different query."
[docs]
def create_redis_file_search_tool(
service: "HybridSearchService",
name: str = "redis_file_search",
description: str | None = None,
default_k: int = 5,
default_min_score: float = 0.0,
) -> RedisFileSearchTool:
"""Factory function to create a Redis file search tool.
This function creates a callable tool that wraps a HybridSearchService
for use with the OpenAI Agents SDK.
Args:
service: The HybridSearchService instance to use for searching.
name: Custom tool name (default: "redis_file_search").
description: Custom tool description for LLM context.
default_k: Default number of results to return.
default_min_score: Default minimum similarity score for filtering.
Returns:
A RedisFileSearchTool instance that can be used with OpenAI agents.
Example:
>>> service = HybridSearchService(redis_url="redis://localhost:6379", index_name="docs")
>>> tool = create_redis_file_search_tool(service, name="search_docs", default_k=10)
>>> result = await tool(query="Redis performance")
"""
default_description = (
"Search documents using semantic similarity and keyword matching. "
"Use this tool to find relevant information from the knowledge base."
)
return RedisFileSearchTool(
_service=service,
name=name,
description=description or default_description,
default_k=default_k,
default_min_score=default_min_score,
)