You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

121 lines
3.5 KiB

from __future__ import annotations
import asyncio
from datetime import datetime
import httpx
from fastapi import Depends, FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from info import debate_types, explainer, limit_warning, party_colors
from .schemas import (
ChatRequest,
ChatResponse,
FeedbackRequest,
FeedbackResponse,
SearchRequest,
SearchResponse,
TalkHit,
)
from .services import ChatService, SearchService
from backend.routes.chat import router as chat_router
from .services.names_autocomplete import router as names_autocomplete_router
app = FastAPI(title="Riksdagen API", version="0.1.0")
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # tighten for production
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
search_service = SearchService()
chat_service = ChatService()
app.include_router(chat_router)
app.include_router(names_autocomplete_router)
@app.get("/api/meta")
def meta():
return {
"parties": party_colors,
"debate_types": debate_types,
"explainer": explainer,
"limit_warning": limit_warning,
}
@app.post("/api/search", response_model=SearchResponse)
def search(payload: SearchRequest):
print('PAYLOAD IN APP', payload)
results, stats, limit_reached = search_service.search(
payload, include_snippets=payload.include_snippets
)
print(f'Search service returned {len(results)} results')
# Log first result to see structure
if results:
print('First result structure:', results[0].keys() if isinstance(results[0], dict) else 'not a dict')
print('First result _id:', results[0].get('_id') if isinstance(results[0], dict) else 'N/A')
# Try to convert results to TalkHit objects
hits = []
for idx, hit in enumerate(results):
try:
talk_hit = TalkHit(**hit)
hits.append(talk_hit)
except Exception as e:
print(f'Error converting result {idx} to TalkHit: {e}')
print(f'Problematic result: {hit}')
# Continue with other results instead of failing completely
continue
print(f'Successfully converted {len(hits)} results to TalkHit objects')
return SearchResponse(
results=hits,
stats=stats,
active_filters={
"parties": payload.parties,
"people": payload.people,
"debates": payload.debates,
"from_year": payload.from_year,
"to_year": payload.to_year,
"speaker_ids": payload.speaker_ids,
"speaker": payload.speaker,
},
limit_reached=limit_reached,
)
@app.post("/api/chat", response_model=ChatResponse)
def chat(payload: ChatRequest) -> ChatResponse:
"""
Generate a chat answer plus citations via the retrieval-aware ChatService.
Args:
payload (ChatRequest): Chat history, retrieval strategy, and result limit.
Returns:
ChatResponse: Assistant reply and supporting sources.
"""
if not payload.messages:
raise HTTPException(status_code=400, detail="messages cannot be empty")
messages = [message.dict() for message in payload.messages]
limit = getattr(payload, "top_k", None)
if limit is None:
limit = getattr(payload, "limit", None)
top_k = limit or 5
chat_result = chat_service.get_chat_response(
messages=messages,
top_k=top_k,
)
return ChatResponse(answer=chat_result["answer"], sources=chat_result["sources"])