49 lines
2.0 KiB
Python
49 lines
2.0 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Body
|
|
from sqlalchemy import or_, text
|
|
from app.db.session import get_db
|
|
from app.pipeline.enricher import Enricher
|
|
|
|
router = APIRouter(prefix="/api")
|
|
enricher = Enricher()
|
|
|
|
@router.get("/search")
|
|
def search(q: str = "", category: str = None, person: str = None,
|
|
date: str = None, page: int = None, job_id: int = None, semantic: bool = False, db=Depends(get_db)):
|
|
from app.db.models import Article
|
|
query = db.query(Article)
|
|
if category: query = query.filter(Article.category == category)
|
|
if date: query = query.filter(Article.date == date)
|
|
if page: query = query.filter(Article.page == page)
|
|
if job_id: query = query.filter(Article.upload_job_id == job_id)
|
|
if person: query = query.filter(Article.persons.any(person))
|
|
if q and not semantic:
|
|
query = query.filter(or_(Article.headline.ilike(f"%{q}%"),
|
|
Article.text.ilike(f"%{q}%")))
|
|
return query.limit(50).all()
|
|
if semantic and q:
|
|
vec = enricher.embed(q)
|
|
# pgvector cosine distance
|
|
return db.execute(text("""
|
|
SELECT * FROM articles ORDER BY embedding <=> :v LIMIT 30
|
|
"""), {"v": str(vec)}).fetchall()
|
|
return query.limit(50).all()
|
|
|
|
@router.put("/articles/{article_id}")
|
|
def update_article(article_id: int, updates: dict = Body(...), db=Depends(get_db)):
|
|
from app.db.models import Article
|
|
article = db.query(Article).filter(Article.id == article_id).first()
|
|
if not article:
|
|
raise HTTPException(status_code=404, detail="Article not found")
|
|
|
|
# Update allowed fields
|
|
allowed = ["headline", "category", "subcategory", "summary", "sentiment", "keywords", "persons", "locations", "organizations"]
|
|
for k, v in updates.items():
|
|
if k in allowed:
|
|
setattr(article, k, v)
|
|
|
|
# Mark as verified for RAG training
|
|
article.human_verified = True
|
|
db.commit()
|
|
db.refresh(article)
|
|
return article
|