chore: save local changes

This commit is contained in:
2026-01-05 22:32:08 +08:00
parent bc281b8e0a
commit ec48709755
42 changed files with 5576 additions and 254 deletions

View File

@@ -0,0 +1,133 @@
"""Patent Search Router - Search for similar patents"""
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"""
publication_number: str
title: str
snippet: str
publication_date: Optional[str] = None
assignee: Optional[str] = None
inventor: Optional[str] = None
status: str # ACTIVE, NOT_ACTIVE, UNKNOWN
pdf_url: Optional[str] = None
thumbnail_url: Optional[str] = None
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 Google Patents to find related patents based on keywords.
"""
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"}