feat: add RAG search endpoint with content extraction
Build and Push / build (release) Successful in 1m2s
Build and Push / build (release) Successful in 1m2s
- Add /rag/search endpoint for web, news, and image search via SearXNG - Add /content/extract and /content/extract/batch endpoints - Add ContentExtractor client using Trafilatura for content extraction - Enhance HybridRAG web search with full content extraction - Add Redis caching for search results - Add new configuration options for search and extraction timeouts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -13,12 +13,15 @@ from typing import Annotated
|
||||
from fastapi import Depends
|
||||
import logging
|
||||
|
||||
import redis.asyncio as aioredis
|
||||
|
||||
from src.config import Settings, get_settings
|
||||
from src.clients.neo4j_client import Neo4jClient
|
||||
from src.clients.qdrant_client import QdrantClientWrapper
|
||||
from src.clients.wikijs_client import WikiJSClient
|
||||
from src.clients.searxng_client import SearXNGClient
|
||||
from src.clients.ollama_client import OllamaClient
|
||||
from src.clients.content_extractor import ContentExtractor
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -116,6 +119,43 @@ def get_ollama_client() -> OllamaClient:
|
||||
return client
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_redis_client() -> aioredis.Redis:
|
||||
"""
|
||||
Get Redis client singleton for caching.
|
||||
|
||||
Returns:
|
||||
Async Redis client connected to the configured database
|
||||
|
||||
Note: Uses Redis DB 4 (configured for library-desk)
|
||||
"""
|
||||
settings = get_settings()
|
||||
client = aioredis.from_url(
|
||||
settings.redis_url,
|
||||
encoding="utf-8",
|
||||
decode_responses=True
|
||||
)
|
||||
logger.debug(f"Created Redis client: {settings.redis_url}")
|
||||
return client
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_content_extractor() -> ContentExtractor:
|
||||
"""
|
||||
Get ContentExtractor singleton.
|
||||
|
||||
Returns:
|
||||
Initialized content extraction client using Trafilatura
|
||||
"""
|
||||
settings = get_settings()
|
||||
extractor = ContentExtractor(
|
||||
timeout=settings.content_extraction_timeout,
|
||||
max_length=settings.content_max_length
|
||||
)
|
||||
logger.debug("Created ContentExtractor instance")
|
||||
return extractor
|
||||
|
||||
|
||||
# Type aliases for FastAPI endpoint dependencies
|
||||
# Usage: def my_endpoint(neo4j: Neo4jDep):
|
||||
Neo4jDep = Annotated[Neo4jClient, Depends(get_neo4j_client)]
|
||||
@@ -123,6 +163,8 @@ QdrantDep = Annotated[QdrantClientWrapper, Depends(get_qdrant_client)]
|
||||
WikiJSDep = Annotated[WikiJSClient, Depends(get_wikijs_client)]
|
||||
SearXNGDep = Annotated[SearXNGClient, Depends(get_searxng_client)]
|
||||
OllamaDep = Annotated[OllamaClient, Depends(get_ollama_client)]
|
||||
RedisDep = Annotated[aioredis.Redis, Depends(get_redis_client)]
|
||||
ContentExtractorDep = Annotated[ContentExtractor, Depends(get_content_extractor)]
|
||||
|
||||
|
||||
# Lifecycle management functions
|
||||
@@ -336,6 +378,19 @@ def get_hybrid_rag_service() -> "HybridRAGService":
|
||||
graph_service=get_graph_service(),
|
||||
searxng_client=get_searxng_client(),
|
||||
ollama_client=get_ollama_client(),
|
||||
content_extractor=get_content_extractor(),
|
||||
settings=get_settings()
|
||||
)
|
||||
|
||||
|
||||
@lru_cache
|
||||
def get_rag_search_service() -> "RAGSearchService":
|
||||
"""Get RAGSearchService singleton."""
|
||||
from src.services.rag_search_service import RAGSearchService
|
||||
return RAGSearchService(
|
||||
searxng_client=get_searxng_client(),
|
||||
content_extractor=get_content_extractor(),
|
||||
redis_client=get_redis_client(),
|
||||
settings=get_settings()
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user