- Improve patent search service with expanded functionality - Update PatentSearchPanel UI component - Add new research_report.md - Update experimental protocol, literature review, paper outline, and theoretical framework Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
138 lines
3.9 KiB
Python
138 lines
3.9 KiB
Python
"""Patent Search Router - Search for similar patents using Lens.org API"""
|
|
|
|
import logging
|
|
from typing import Optional, List
|
|
|
|
from fastapi import APIRouter
|
|
from pydantic import BaseModel
|
|
|
|
from ..services.patent_search_service import patent_search_service
|
|
|
|
logger = logging.getLogger(__name__)
|
|
router = APIRouter(prefix="/api/patent", tags=["patent"])
|
|
|
|
|
|
# ===== Request/Response Models =====
|
|
|
|
class PatentSearchRequest(BaseModel):
|
|
"""Patent search request"""
|
|
query: str # Search query (description or keywords)
|
|
max_results: int = 10 # Maximum results to return (1-20)
|
|
|
|
|
|
class PatentResult(BaseModel):
|
|
"""Single patent result from Lens.org"""
|
|
lens_id: str
|
|
doc_number: str
|
|
jurisdiction: str
|
|
kind: str
|
|
title: str
|
|
abstract: Optional[str] = None
|
|
date_published: Optional[str] = None
|
|
applicants: List[str] = []
|
|
inventors: List[str] = []
|
|
legal_status: Optional[str] = None
|
|
classifications_cpc: List[str] = []
|
|
families_simple: List[str] = []
|
|
url: str
|
|
|
|
|
|
class PatentSearchResponse(BaseModel):
|
|
"""Patent search response"""
|
|
query: str
|
|
total_results: int
|
|
patents: List[PatentResult]
|
|
error: Optional[str] = None
|
|
|
|
|
|
class BatchPatentSearchRequest(BaseModel):
|
|
"""Batch patent search request - search multiple descriptions"""
|
|
queries: List[str] # List of descriptions to search
|
|
max_results_per_query: int = 5 # Max results per query
|
|
|
|
|
|
class BatchPatentSearchResult(BaseModel):
|
|
"""Results for a single query in batch search"""
|
|
query: str
|
|
total_results: int
|
|
patents: List[PatentResult]
|
|
error: Optional[str] = None
|
|
|
|
|
|
class BatchPatentSearchResponse(BaseModel):
|
|
"""Batch patent search response"""
|
|
results: List[BatchPatentSearchResult]
|
|
total_queries: int
|
|
|
|
|
|
# ===== Endpoints =====
|
|
|
|
@router.post("/search", response_model=PatentSearchResponse)
|
|
async def search_patents(request: PatentSearchRequest):
|
|
"""
|
|
Search for patents similar to the given description/query.
|
|
|
|
Uses Lens.org API to find related patents based on title, abstract, and claims.
|
|
"""
|
|
logger.info(f"Patent search request: {request.query[:100]}...")
|
|
|
|
# Limit max_results to reasonable range
|
|
max_results = min(max(1, request.max_results), 20)
|
|
|
|
result = await patent_search_service.search(
|
|
query=request.query,
|
|
max_results=max_results,
|
|
)
|
|
|
|
return PatentSearchResponse(
|
|
query=request.query,
|
|
total_results=result.get("total_results", 0),
|
|
patents=[PatentResult(**p) for p in result.get("patents", [])],
|
|
error=result.get("error"),
|
|
)
|
|
|
|
|
|
@router.post("/search/batch", response_model=BatchPatentSearchResponse)
|
|
async def batch_search_patents(request: BatchPatentSearchRequest):
|
|
"""
|
|
Search for patents for multiple descriptions at once.
|
|
|
|
Useful for checking multiple creative descriptions against patents.
|
|
"""
|
|
logger.info(f"Batch patent search: {len(request.queries)} queries")
|
|
|
|
# Limit results per query
|
|
max_per_query = min(max(1, request.max_results_per_query), 10)
|
|
|
|
results: List[BatchPatentSearchResult] = []
|
|
|
|
for query in request.queries:
|
|
result = await patent_search_service.search(
|
|
query=query,
|
|
max_results=max_per_query,
|
|
)
|
|
|
|
results.append(BatchPatentSearchResult(
|
|
query=query,
|
|
total_results=result.get("total_results", 0),
|
|
patents=[PatentResult(**p) for p in result.get("patents", [])],
|
|
error=result.get("error"),
|
|
))
|
|
|
|
return BatchPatentSearchResponse(
|
|
results=results,
|
|
total_queries=len(request.queries),
|
|
)
|
|
|
|
|
|
@router.get("/health")
|
|
async def patent_search_health():
|
|
"""Check if patent search service is working"""
|
|
# Do a simple test search
|
|
result = await patent_search_service.search("test", max_results=1)
|
|
|
|
if result.get("error"):
|
|
return {"status": "unhealthy", "error": result["error"]}
|
|
|
|
return {"status": "healthy"}
|